Completed
Branch master (8de7dd)
by
unknown
06:29
created
libraries/form_sections/inputs/EE_Form_Input_With_Options_Base.input.php 2 patches
Indentation   +322 added lines, -322 removed lines patch added patch discarded remove patch
@@ -11,328 +11,328 @@
 block discarded – undo
11 11
  */
12 12
 class EE_Form_Input_With_Options_Base extends EE_Form_Input_Base
13 13
 {
14
-    /**
15
-     * array of available options to choose as an answer
16
-     *
17
-     * @var array
18
-     */
19
-    protected $_options = array();
20
-
21
-    /**
22
-     * whether to display the html_label_text above the checkbox/radio button options
23
-     *
24
-     * @var boolean
25
-     */
26
-    protected $_display_html_label_text = true;
27
-
28
-    /**
29
-     * whether to display an question option description as part of the input label
30
-     *
31
-     * @var boolean
32
-     */
33
-    protected $_use_desc_in_label = true;
34
-
35
-    /**
36
-     * strlen() result for the longest input value (what gets displayed in the label)
37
-     * this is used to apply a css class to the input label
38
-     *
39
-     * @var int
40
-     */
41
-    protected $_label_size = 0;
42
-
43
-    /**
44
-     * whether to enforce the label size value passed in the constructor
45
-     *
46
-     * @var boolean
47
-     */
48
-    protected $_enforce_label_size = false;
49
-
50
-    /**
51
-     * whether to allow multiple selections (ie, the value of this input should be an array)
52
-     * or not (ie, the value should be a simple int, string, etc)
53
-     *
54
-     * @var boolean
55
-     */
56
-    protected $_multiple_selections = false;
57
-
58
-
59
-
60
-    /**
61
-     * @param array     $answer_options
62
-     * @param array     $input_settings {
63
-     * @type int|string $label_size
64
-     * @type boolean    $display_html_label_text
65
-     *                                  }
66
-     *                                  And all the options accepted by EE_Form_Input_Base
67
-     */
68
-    public function __construct($answer_options = array(), $input_settings = array())
69
-    {
70
-        if (isset($input_settings['label_size'])) {
71
-            $this->_set_label_size($input_settings['label_size']);
72
-            if (isset($input_settings['enforce_label_size']) && $input_settings['enforce_label_size']) {
73
-                $this->_enforce_label_size = true;
74
-            }
75
-        }
76
-        if (isset($input_settings['display_html_label_text'])) {
77
-            $this->set_display_html_label_text($input_settings['display_html_label_text']);
78
-        }
79
-        $this->set_select_options($answer_options);
80
-        parent::__construct($input_settings);
81
-    }
82
-
83
-
84
-
85
-    /**
86
-     * Sets the allowed options for this input. Also has the side effect of
87
-     * updating the normalization strategy to match the keys provided in the array
88
-     *
89
-     * @param array $answer_options
90
-     * @return void  just has the side effect of setting the options for this input
91
-     */
92
-    public function set_select_options($answer_options = array())
93
-    {
94
-        $answer_options = is_array($answer_options) ? $answer_options : array($answer_options);
95
-        // get the first item in the select options and check its type
96
-        $this->_options = reset($answer_options) instanceof EE_Question_Option
97
-            ? $this->_process_question_options($answer_options)
98
-            : $answer_options;
99
-        // d( $this->_options );
100
-        $select_option_keys = array_keys($this->_options);
101
-        // attempt to determine data type for values in order to set normalization type
102
-        // purposefully only
103
-        if (
104
-            count($this->_options) === 2
105
-            && (
106
-                (in_array(true, $select_option_keys, true) && in_array(false, $select_option_keys, true))
107
-                || (in_array(1, $select_option_keys, true) && in_array(0, $select_option_keys, true))
108
-            )
109
-        ) {
110
-            // values appear to be boolean, like TRUE, FALSE, 1, 0
111
-            $normalization = new EE_Boolean_Normalization();
112
-        } else {
113
-            // are ALL the options integers (even if we're using a multidimensional array)? If so use int validation
114
-            $all_integers = true;
115
-            array_walk_recursive(
116
-                $this->_options,
117
-                function ($value, $key) use (&$all_integers) {
118
-                    // is this a top-level key? ignore it
119
-                    if (
120
-                        ! is_array($value)
121
-                        && ! is_int($key)
122
-                        && $key !== ''
123
-                        && $key !== null
124
-                    ) {
125
-                        $all_integers = false;
126
-                    }
127
-                }
128
-            );
129
-            $normalization = $all_integers ? new EE_Int_Normalization() : new EE_Text_Normalization();
130
-        }
131
-        // does input type have multiple options ?
132
-        if ($this->_multiple_selections) {
133
-            $this->_set_normalization_strategy(new EE_Many_Valued_Normalization($normalization));
134
-        } else {
135
-            $this->_set_normalization_strategy($normalization);
136
-        }
137
-    }
138
-
139
-
140
-
141
-    /**
142
-     * @return array
143
-     */
144
-    public function options()
145
-    {
146
-        return $this->_options;
147
-    }
148
-
149
-
150
-
151
-    /**
152
-     * Returns an array which is guaranteed to not be multidimensional
153
-     *
154
-     * @return array
155
-     */
156
-    public function flat_options()
157
-    {
158
-        return $this->_flatten_select_options($this->options());
159
-    }
160
-
161
-
162
-
163
-    /**
164
-     * Makes sure $arr is a flat array, not a multidimensional one
165
-     *
166
-     * @param array $arr
167
-     * @return array
168
-     */
169
-    protected function _flatten_select_options($arr)
170
-    {
171
-        $flat_array = array();
172
-        if (EEH_Array::is_multi_dimensional_array($arr)) {
173
-            foreach ($arr as $sub_array) {
174
-                foreach ((array) $sub_array as $key => $value) {
175
-                    $flat_array[ $key ] = $value;
176
-                    $this->_set_label_size($value);
177
-                }
178
-            }
179
-        } else {
180
-            foreach ($arr as $key => $value) {
181
-                $flat_array[ $key ] = $value;
182
-                $this->_set_label_size($value);
183
-            }
184
-        }
185
-        return $flat_array;
186
-    }
187
-
188
-
189
-
190
-    /**
191
-     * @param EE_Question_Option[] $question_options_array
192
-     * @return array
193
-     */
194
-    protected function _process_question_options($question_options_array = array())
195
-    {
196
-        $flat_array = array();
197
-        foreach ($question_options_array as $question_option) {
198
-            if ($question_option instanceof EE_Question_Option) {
199
-                $desc = '';
200
-                if ($this->_use_desc_in_label) {
201
-                    $desc = $question_option->desc();
202
-                    $desc = ! empty($desc) ? '<span class="ee-question-option-desc">' . $desc . '</span>' : '';
203
-                }
204
-                $value = $question_option->value();
205
-                // add value even if it's empty
206
-                $flat_array[ $value ] = $value;
207
-                // if both value and desc are not empty, then separate with a dash
208
-                if (! empty($value) && ! empty($desc)) {
209
-                    $flat_array[ $value ] .= ' - ' . $desc;
210
-                } else {
211
-                    // otherwise, just add desc, since either or both of the vars is empty, and no dash is necessary
212
-                    $flat_array[ $value ] .= $desc;
213
-                }
214
-            } elseif (is_array($question_option)) {
215
-                $flat_array += $this->_flatten_select_options($question_option);
216
-            }
217
-        }
218
-        return $flat_array;
219
-    }
220
-
221
-
222
-
223
-    /**
224
-     *    set_label_sizes
225
-     *
226
-     * @return void
227
-     */
228
-    public function set_label_sizes()
229
-    {
230
-        // did the input settings specifically say to NOT set the label size dynamically ?
231
-        if (! $this->_enforce_label_size) {
232
-            foreach ($this->_options as $option) {
233
-                // calculate the strlen of the label
234
-                $this->_set_label_size($option);
235
-            }
236
-        }
237
-    }
238
-
239
-
240
-
241
-    /**
242
-     *    _set_label_size_class
243
-     *
244
-     * @param int|string $value
245
-     * @return void
246
-     */
247
-    private function _set_label_size($value = '')
248
-    {
249
-        // don't change label size if it has already been set and is being enforced
250
-        if ($this->_enforce_label_size && $this->_label_size >  0) {
251
-            return;
252
-        }
253
-        // determine length of option value
254
-        $val_size = is_int($value) ? $value : strlen($value);
255
-        // use new value if bigger than existing
256
-        $this->_label_size = $val_size > $this->_label_size ? $val_size : $this->_label_size;
257
-    }
258
-
259
-
260
-
261
-    /**
262
-     *    get_label_size_class
263
-     *
264
-     * @return string
265
-     */
266
-    public function get_label_size_class()
267
-    {
268
-        $size = ' medium-lbl';
269
-        // use maximum option value length to determine label size
270
-        if ($this->_label_size < 3) {
271
-            $size = ' nano-lbl';
272
-        } elseif ($this->_label_size < 6) {
273
-            $size = ' micro-lbl';
274
-        } elseif ($this->_label_size < 12) {
275
-            $size = ' tiny-lbl';
276
-        } elseif ($this->_label_size < 25) {
277
-            $size = ' small-lbl';
278
-        } elseif ($this->_label_size < 50) {
279
-            $size = ' medium-lbl';
280
-        } elseif ($this->_label_size >= 100) {
281
-            $size = ' big-lbl';
282
-        }
283
-        return $size;
284
-    }
285
-
286
-
287
-
288
-    /**
289
-     * Returns the pretty value for the normalized value
290
-     *
291
-     * @return string
292
-     */
293
-    public function pretty_value()
294
-    {
295
-        $options = $this->flat_options();
296
-        $unnormalized_value_choices = $this->get_normalization_strategy()->unnormalize($this->_normalized_value);
297
-        if (! $this->_multiple_selections) {
298
-            $unnormalized_value_choices = array($unnormalized_value_choices);
299
-        }
300
-        $pretty_strings = array();
301
-        foreach ((array) $unnormalized_value_choices as $unnormalized_value_choice) {
302
-            if (isset($options[ $unnormalized_value_choice ])) {
303
-                $pretty_strings[] = $options[ $unnormalized_value_choice ];
304
-            } else {
305
-                $pretty_strings[] = $this->normalized_value();
306
-            }
307
-        }
308
-        return implode(', ', $pretty_strings);
309
-    }
310
-
311
-
312
-
313
-    /**
314
-     * @return boolean
315
-     */
316
-    public function display_html_label_text()
317
-    {
318
-        return $this->_display_html_label_text;
319
-    }
320
-
321
-
322
-
323
-    /**
324
-     * @param boolean $display_html_label_text
325
-     */
326
-    public function set_display_html_label_text($display_html_label_text)
327
-    {
328
-        $this->_display_html_label_text = filter_var($display_html_label_text, FILTER_VALIDATE_BOOLEAN);
329
-    }
330
-
331
-
332
-    public function hasMultipleSelections(): bool
333
-    {
334
-        return $this->_multiple_selections;
335
-    }
14
+	/**
15
+	 * array of available options to choose as an answer
16
+	 *
17
+	 * @var array
18
+	 */
19
+	protected $_options = array();
20
+
21
+	/**
22
+	 * whether to display the html_label_text above the checkbox/radio button options
23
+	 *
24
+	 * @var boolean
25
+	 */
26
+	protected $_display_html_label_text = true;
27
+
28
+	/**
29
+	 * whether to display an question option description as part of the input label
30
+	 *
31
+	 * @var boolean
32
+	 */
33
+	protected $_use_desc_in_label = true;
34
+
35
+	/**
36
+	 * strlen() result for the longest input value (what gets displayed in the label)
37
+	 * this is used to apply a css class to the input label
38
+	 *
39
+	 * @var int
40
+	 */
41
+	protected $_label_size = 0;
42
+
43
+	/**
44
+	 * whether to enforce the label size value passed in the constructor
45
+	 *
46
+	 * @var boolean
47
+	 */
48
+	protected $_enforce_label_size = false;
49
+
50
+	/**
51
+	 * whether to allow multiple selections (ie, the value of this input should be an array)
52
+	 * or not (ie, the value should be a simple int, string, etc)
53
+	 *
54
+	 * @var boolean
55
+	 */
56
+	protected $_multiple_selections = false;
57
+
58
+
59
+
60
+	/**
61
+	 * @param array     $answer_options
62
+	 * @param array     $input_settings {
63
+	 * @type int|string $label_size
64
+	 * @type boolean    $display_html_label_text
65
+	 *                                  }
66
+	 *                                  And all the options accepted by EE_Form_Input_Base
67
+	 */
68
+	public function __construct($answer_options = array(), $input_settings = array())
69
+	{
70
+		if (isset($input_settings['label_size'])) {
71
+			$this->_set_label_size($input_settings['label_size']);
72
+			if (isset($input_settings['enforce_label_size']) && $input_settings['enforce_label_size']) {
73
+				$this->_enforce_label_size = true;
74
+			}
75
+		}
76
+		if (isset($input_settings['display_html_label_text'])) {
77
+			$this->set_display_html_label_text($input_settings['display_html_label_text']);
78
+		}
79
+		$this->set_select_options($answer_options);
80
+		parent::__construct($input_settings);
81
+	}
82
+
83
+
84
+
85
+	/**
86
+	 * Sets the allowed options for this input. Also has the side effect of
87
+	 * updating the normalization strategy to match the keys provided in the array
88
+	 *
89
+	 * @param array $answer_options
90
+	 * @return void  just has the side effect of setting the options for this input
91
+	 */
92
+	public function set_select_options($answer_options = array())
93
+	{
94
+		$answer_options = is_array($answer_options) ? $answer_options : array($answer_options);
95
+		// get the first item in the select options and check its type
96
+		$this->_options = reset($answer_options) instanceof EE_Question_Option
97
+			? $this->_process_question_options($answer_options)
98
+			: $answer_options;
99
+		// d( $this->_options );
100
+		$select_option_keys = array_keys($this->_options);
101
+		// attempt to determine data type for values in order to set normalization type
102
+		// purposefully only
103
+		if (
104
+			count($this->_options) === 2
105
+			&& (
106
+				(in_array(true, $select_option_keys, true) && in_array(false, $select_option_keys, true))
107
+				|| (in_array(1, $select_option_keys, true) && in_array(0, $select_option_keys, true))
108
+			)
109
+		) {
110
+			// values appear to be boolean, like TRUE, FALSE, 1, 0
111
+			$normalization = new EE_Boolean_Normalization();
112
+		} else {
113
+			// are ALL the options integers (even if we're using a multidimensional array)? If so use int validation
114
+			$all_integers = true;
115
+			array_walk_recursive(
116
+				$this->_options,
117
+				function ($value, $key) use (&$all_integers) {
118
+					// is this a top-level key? ignore it
119
+					if (
120
+						! is_array($value)
121
+						&& ! is_int($key)
122
+						&& $key !== ''
123
+						&& $key !== null
124
+					) {
125
+						$all_integers = false;
126
+					}
127
+				}
128
+			);
129
+			$normalization = $all_integers ? new EE_Int_Normalization() : new EE_Text_Normalization();
130
+		}
131
+		// does input type have multiple options ?
132
+		if ($this->_multiple_selections) {
133
+			$this->_set_normalization_strategy(new EE_Many_Valued_Normalization($normalization));
134
+		} else {
135
+			$this->_set_normalization_strategy($normalization);
136
+		}
137
+	}
138
+
139
+
140
+
141
+	/**
142
+	 * @return array
143
+	 */
144
+	public function options()
145
+	{
146
+		return $this->_options;
147
+	}
148
+
149
+
150
+
151
+	/**
152
+	 * Returns an array which is guaranteed to not be multidimensional
153
+	 *
154
+	 * @return array
155
+	 */
156
+	public function flat_options()
157
+	{
158
+		return $this->_flatten_select_options($this->options());
159
+	}
160
+
161
+
162
+
163
+	/**
164
+	 * Makes sure $arr is a flat array, not a multidimensional one
165
+	 *
166
+	 * @param array $arr
167
+	 * @return array
168
+	 */
169
+	protected function _flatten_select_options($arr)
170
+	{
171
+		$flat_array = array();
172
+		if (EEH_Array::is_multi_dimensional_array($arr)) {
173
+			foreach ($arr as $sub_array) {
174
+				foreach ((array) $sub_array as $key => $value) {
175
+					$flat_array[ $key ] = $value;
176
+					$this->_set_label_size($value);
177
+				}
178
+			}
179
+		} else {
180
+			foreach ($arr as $key => $value) {
181
+				$flat_array[ $key ] = $value;
182
+				$this->_set_label_size($value);
183
+			}
184
+		}
185
+		return $flat_array;
186
+	}
187
+
188
+
189
+
190
+	/**
191
+	 * @param EE_Question_Option[] $question_options_array
192
+	 * @return array
193
+	 */
194
+	protected function _process_question_options($question_options_array = array())
195
+	{
196
+		$flat_array = array();
197
+		foreach ($question_options_array as $question_option) {
198
+			if ($question_option instanceof EE_Question_Option) {
199
+				$desc = '';
200
+				if ($this->_use_desc_in_label) {
201
+					$desc = $question_option->desc();
202
+					$desc = ! empty($desc) ? '<span class="ee-question-option-desc">' . $desc . '</span>' : '';
203
+				}
204
+				$value = $question_option->value();
205
+				// add value even if it's empty
206
+				$flat_array[ $value ] = $value;
207
+				// if both value and desc are not empty, then separate with a dash
208
+				if (! empty($value) && ! empty($desc)) {
209
+					$flat_array[ $value ] .= ' - ' . $desc;
210
+				} else {
211
+					// otherwise, just add desc, since either or both of the vars is empty, and no dash is necessary
212
+					$flat_array[ $value ] .= $desc;
213
+				}
214
+			} elseif (is_array($question_option)) {
215
+				$flat_array += $this->_flatten_select_options($question_option);
216
+			}
217
+		}
218
+		return $flat_array;
219
+	}
220
+
221
+
222
+
223
+	/**
224
+	 *    set_label_sizes
225
+	 *
226
+	 * @return void
227
+	 */
228
+	public function set_label_sizes()
229
+	{
230
+		// did the input settings specifically say to NOT set the label size dynamically ?
231
+		if (! $this->_enforce_label_size) {
232
+			foreach ($this->_options as $option) {
233
+				// calculate the strlen of the label
234
+				$this->_set_label_size($option);
235
+			}
236
+		}
237
+	}
238
+
239
+
240
+
241
+	/**
242
+	 *    _set_label_size_class
243
+	 *
244
+	 * @param int|string $value
245
+	 * @return void
246
+	 */
247
+	private function _set_label_size($value = '')
248
+	{
249
+		// don't change label size if it has already been set and is being enforced
250
+		if ($this->_enforce_label_size && $this->_label_size >  0) {
251
+			return;
252
+		}
253
+		// determine length of option value
254
+		$val_size = is_int($value) ? $value : strlen($value);
255
+		// use new value if bigger than existing
256
+		$this->_label_size = $val_size > $this->_label_size ? $val_size : $this->_label_size;
257
+	}
258
+
259
+
260
+
261
+	/**
262
+	 *    get_label_size_class
263
+	 *
264
+	 * @return string
265
+	 */
266
+	public function get_label_size_class()
267
+	{
268
+		$size = ' medium-lbl';
269
+		// use maximum option value length to determine label size
270
+		if ($this->_label_size < 3) {
271
+			$size = ' nano-lbl';
272
+		} elseif ($this->_label_size < 6) {
273
+			$size = ' micro-lbl';
274
+		} elseif ($this->_label_size < 12) {
275
+			$size = ' tiny-lbl';
276
+		} elseif ($this->_label_size < 25) {
277
+			$size = ' small-lbl';
278
+		} elseif ($this->_label_size < 50) {
279
+			$size = ' medium-lbl';
280
+		} elseif ($this->_label_size >= 100) {
281
+			$size = ' big-lbl';
282
+		}
283
+		return $size;
284
+	}
285
+
286
+
287
+
288
+	/**
289
+	 * Returns the pretty value for the normalized value
290
+	 *
291
+	 * @return string
292
+	 */
293
+	public function pretty_value()
294
+	{
295
+		$options = $this->flat_options();
296
+		$unnormalized_value_choices = $this->get_normalization_strategy()->unnormalize($this->_normalized_value);
297
+		if (! $this->_multiple_selections) {
298
+			$unnormalized_value_choices = array($unnormalized_value_choices);
299
+		}
300
+		$pretty_strings = array();
301
+		foreach ((array) $unnormalized_value_choices as $unnormalized_value_choice) {
302
+			if (isset($options[ $unnormalized_value_choice ])) {
303
+				$pretty_strings[] = $options[ $unnormalized_value_choice ];
304
+			} else {
305
+				$pretty_strings[] = $this->normalized_value();
306
+			}
307
+		}
308
+		return implode(', ', $pretty_strings);
309
+	}
310
+
311
+
312
+
313
+	/**
314
+	 * @return boolean
315
+	 */
316
+	public function display_html_label_text()
317
+	{
318
+		return $this->_display_html_label_text;
319
+	}
320
+
321
+
322
+
323
+	/**
324
+	 * @param boolean $display_html_label_text
325
+	 */
326
+	public function set_display_html_label_text($display_html_label_text)
327
+	{
328
+		$this->_display_html_label_text = filter_var($display_html_label_text, FILTER_VALIDATE_BOOLEAN);
329
+	}
330
+
331
+
332
+	public function hasMultipleSelections(): bool
333
+	{
334
+		return $this->_multiple_selections;
335
+	}
336 336
 
337 337
 
338 338
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
             $all_integers = true;
115 115
             array_walk_recursive(
116 116
                 $this->_options,
117
-                function ($value, $key) use (&$all_integers) {
117
+                function($value, $key) use (&$all_integers) {
118 118
                     // is this a top-level key? ignore it
119 119
                     if (
120 120
                         ! is_array($value)
@@ -172,13 +172,13 @@  discard block
 block discarded – undo
172 172
         if (EEH_Array::is_multi_dimensional_array($arr)) {
173 173
             foreach ($arr as $sub_array) {
174 174
                 foreach ((array) $sub_array as $key => $value) {
175
-                    $flat_array[ $key ] = $value;
175
+                    $flat_array[$key] = $value;
176 176
                     $this->_set_label_size($value);
177 177
                 }
178 178
             }
179 179
         } else {
180 180
             foreach ($arr as $key => $value) {
181
-                $flat_array[ $key ] = $value;
181
+                $flat_array[$key] = $value;
182 182
                 $this->_set_label_size($value);
183 183
             }
184 184
         }
@@ -199,17 +199,17 @@  discard block
 block discarded – undo
199 199
                 $desc = '';
200 200
                 if ($this->_use_desc_in_label) {
201 201
                     $desc = $question_option->desc();
202
-                    $desc = ! empty($desc) ? '<span class="ee-question-option-desc">' . $desc . '</span>' : '';
202
+                    $desc = ! empty($desc) ? '<span class="ee-question-option-desc">'.$desc.'</span>' : '';
203 203
                 }
204 204
                 $value = $question_option->value();
205 205
                 // add value even if it's empty
206
-                $flat_array[ $value ] = $value;
206
+                $flat_array[$value] = $value;
207 207
                 // if both value and desc are not empty, then separate with a dash
208
-                if (! empty($value) && ! empty($desc)) {
209
-                    $flat_array[ $value ] .= ' - ' . $desc;
208
+                if ( ! empty($value) && ! empty($desc)) {
209
+                    $flat_array[$value] .= ' - '.$desc;
210 210
                 } else {
211 211
                     // otherwise, just add desc, since either or both of the vars is empty, and no dash is necessary
212
-                    $flat_array[ $value ] .= $desc;
212
+                    $flat_array[$value] .= $desc;
213 213
                 }
214 214
             } elseif (is_array($question_option)) {
215 215
                 $flat_array += $this->_flatten_select_options($question_option);
@@ -228,7 +228,7 @@  discard block
 block discarded – undo
228 228
     public function set_label_sizes()
229 229
     {
230 230
         // did the input settings specifically say to NOT set the label size dynamically ?
231
-        if (! $this->_enforce_label_size) {
231
+        if ( ! $this->_enforce_label_size) {
232 232
             foreach ($this->_options as $option) {
233 233
                 // calculate the strlen of the label
234 234
                 $this->_set_label_size($option);
@@ -247,7 +247,7 @@  discard block
 block discarded – undo
247 247
     private function _set_label_size($value = '')
248 248
     {
249 249
         // don't change label size if it has already been set and is being enforced
250
-        if ($this->_enforce_label_size && $this->_label_size >  0) {
250
+        if ($this->_enforce_label_size && $this->_label_size > 0) {
251 251
             return;
252 252
         }
253 253
         // determine length of option value
@@ -294,13 +294,13 @@  discard block
 block discarded – undo
294 294
     {
295 295
         $options = $this->flat_options();
296 296
         $unnormalized_value_choices = $this->get_normalization_strategy()->unnormalize($this->_normalized_value);
297
-        if (! $this->_multiple_selections) {
297
+        if ( ! $this->_multiple_selections) {
298 298
             $unnormalized_value_choices = array($unnormalized_value_choices);
299 299
         }
300 300
         $pretty_strings = array();
301 301
         foreach ((array) $unnormalized_value_choices as $unnormalized_value_choice) {
302
-            if (isset($options[ $unnormalized_value_choice ])) {
303
-                $pretty_strings[] = $options[ $unnormalized_value_choice ];
302
+            if (isset($options[$unnormalized_value_choice])) {
303
+                $pretty_strings[] = $options[$unnormalized_value_choice];
304 304
             } else {
305 305
                 $pretty_strings[] = $this->normalized_value();
306 306
             }
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_Datepicker_Input.php 1 patch
Indentation   +66 added lines, -66 removed lines patch added patch discarded remove patch
@@ -9,77 +9,77 @@
 block discarded – undo
9 9
  */
10 10
 class EE_Datepicker_Input extends EE_Form_Input_Base
11 11
 {
12
-    private bool $use_jquery_ui;
12
+	private bool $use_jquery_ui;
13 13
 
14 14
 
15
-    /**
16
-     * @param array $input_settings
17
-     */
18
-    public function __construct($input_settings = [], $use_jquery_ui = false)
19
-    {
20
-        $this->use_jquery_ui = (bool) apply_filters('FHEE__EE_Datepicker_Input__use_jquery_ui', $use_jquery_ui);
21
-        $type                = $this->use_jquery_ui ? 'datepicker' : 'date';
22
-        $this->_set_display_strategy(new EE_Text_Input_Display_Strategy($type));
23
-        $this->_set_normalization_strategy(new EE_Text_Normalization());
24
-        // we could do better for validation, but at least verify its plaintext
25
-        $this->_add_validation_strategy(
26
-            new EE_Plaintext_Validation_Strategy($input_settings['validation_error_message'] ?? null)
27
-        );
28
-        parent::__construct($input_settings);
29
-        $this->set_html_class($this->html_class() . " $type");
15
+	/**
16
+	 * @param array $input_settings
17
+	 */
18
+	public function __construct($input_settings = [], $use_jquery_ui = false)
19
+	{
20
+		$this->use_jquery_ui = (bool) apply_filters('FHEE__EE_Datepicker_Input__use_jquery_ui', $use_jquery_ui);
21
+		$type                = $this->use_jquery_ui ? 'datepicker' : 'date';
22
+		$this->_set_display_strategy(new EE_Text_Input_Display_Strategy($type));
23
+		$this->_set_normalization_strategy(new EE_Text_Normalization());
24
+		// we could do better for validation, but at least verify its plaintext
25
+		$this->_add_validation_strategy(
26
+			new EE_Plaintext_Validation_Strategy($input_settings['validation_error_message'] ?? null)
27
+		);
28
+		parent::__construct($input_settings);
29
+		$this->set_html_class($this->html_class() . " $type");
30 30
 
31
-        if ($this->use_jquery_ui) {
32
-            // add some style and make it dance
33
-            add_action('wp_enqueue_scripts', ['EE_Datepicker_Input', 'enqueue_styles_and_scripts']);
34
-            add_action('admin_enqueue_scripts', ['EE_Datepicker_Input', 'enqueue_styles_and_scripts']);
35
-        }
36
-    }
31
+		if ($this->use_jquery_ui) {
32
+			// add some style and make it dance
33
+			add_action('wp_enqueue_scripts', ['EE_Datepicker_Input', 'enqueue_styles_and_scripts']);
34
+			add_action('admin_enqueue_scripts', ['EE_Datepicker_Input', 'enqueue_styles_and_scripts']);
35
+		}
36
+	}
37 37
 
38 38
 
39
-    /**
40
-     * @return void
41
-     * @deprecated 5.0.30.p
42
-     */
43
-    public static function enqueue_styles_and_scripts()
44
-    {
45
-        // load css
46
-        wp_register_style(
47
-            'espresso-ui-theme',
48
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
49
-            [],
50
-            EVENT_ESPRESSO_VERSION
51
-        );
52
-        wp_enqueue_style('espresso-ui-theme');
53
-    }
39
+	/**
40
+	 * @return void
41
+	 * @deprecated 5.0.30.p
42
+	 */
43
+	public static function enqueue_styles_and_scripts()
44
+	{
45
+		// load css
46
+		wp_register_style(
47
+			'espresso-ui-theme',
48
+			EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
49
+			[],
50
+			EVENT_ESPRESSO_VERSION
51
+		);
52
+		wp_enqueue_style('espresso-ui-theme');
53
+	}
54 54
 
55 55
 
56
-    /**
57
-     * converts the raw value into a date strimg in the format Y-m-d
58
-     * unless we're using jquery ui, in which case we just return the raw value
59
-     *
60
-     * @return string
61
-     * @throws Exception
62
-     */
63
-    public function raw_value_in_form(): string
64
-    {
65
-        $raw_value = $this->raw_value();
66
-        if ($this->use_jquery_ui || ! $raw_value) {
67
-            return parent::raw_value_in_form();
68
-        }
69
-        // load the CURRENT WordPress date format and try that
70
-        $date = DateTime::createFromFormat(get_option('date_format', 'Y-m-d'), $raw_value);
71
-        if ($date instanceof DateTime) {
72
-            return $date->format('Y-m-d');
73
-        }
74
-        // nope? ok check if date format can just be parsed as is
75
-        $timestamp = strtotime($raw_value);
76
-        if ($timestamp) {
77
-            $date = date('Y-m-d', $timestamp);
78
-            if ($date) {
79
-                return $date;
80
-            }
81
-        }
82
-        // ... errr... ok... just return the raw value
83
-        return $raw_value;
84
-    }
56
+	/**
57
+	 * converts the raw value into a date strimg in the format Y-m-d
58
+	 * unless we're using jquery ui, in which case we just return the raw value
59
+	 *
60
+	 * @return string
61
+	 * @throws Exception
62
+	 */
63
+	public function raw_value_in_form(): string
64
+	{
65
+		$raw_value = $this->raw_value();
66
+		if ($this->use_jquery_ui || ! $raw_value) {
67
+			return parent::raw_value_in_form();
68
+		}
69
+		// load the CURRENT WordPress date format and try that
70
+		$date = DateTime::createFromFormat(get_option('date_format', 'Y-m-d'), $raw_value);
71
+		if ($date instanceof DateTime) {
72
+			return $date->format('Y-m-d');
73
+		}
74
+		// nope? ok check if date format can just be parsed as is
75
+		$timestamp = strtotime($raw_value);
76
+		if ($timestamp) {
77
+			$date = date('Y-m-d', $timestamp);
78
+			if ($date) {
79
+				return $date;
80
+			}
81
+		}
82
+		// ... errr... ok... just return the raw value
83
+		return $raw_value;
84
+	}
85 85
 }
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_Form_Input_Base.input.php 2 patches
Indentation   +1290 added lines, -1290 removed lines patch added patch discarded remove patch
@@ -14,1294 +14,1294 @@
 block discarded – undo
14 14
  */
15 15
 abstract class EE_Form_Input_Base extends EE_Form_Section_Validatable
16 16
 {
17
-    /**
18
-     * the input's name attribute
19
-     *
20
-     * @var string|null
21
-     */
22
-    protected ?string $_html_name = null;
23
-
24
-    /**
25
-     * id for the html label tag
26
-     *
27
-     * @var string
28
-     */
29
-    protected $_html_label_id;
30
-
31
-    /**
32
-     * class for teh html label tag
33
-     *
34
-     * @var string
35
-     */
36
-    protected $_html_label_class;
37
-
38
-    /**
39
-     * style for teh html label tag
40
-     *
41
-     * @var string
42
-     */
43
-    protected $_html_label_style;
44
-
45
-    /**
46
-     * text to be placed in the html label
47
-     *
48
-     * @var string
49
-     */
50
-    protected $_html_label_text;
51
-
52
-    /**
53
-     * the full html label. If used, all other html_label_* properties are invalid
54
-     *
55
-     * @var string
56
-     */
57
-    protected $_html_label;
58
-
59
-    /**
60
-     * HTML to use for help text (normally placed below form input), in a span which normally
61
-     * has a class of 'description'
62
-     *
63
-     * @var string
64
-     */
65
-    protected $_html_help_text;
66
-
67
-    /**
68
-     * CSS classes for displaying the help span
69
-     *
70
-     * @var string
71
-     */
72
-    protected $_html_help_class = 'description';
73
-
74
-    /**
75
-     * CSS to put in the style attribute on the help span
76
-     *
77
-     * @var string
78
-     */
79
-    protected $_html_help_style;
80
-
81
-    /**
82
-     * Stores whether or not this input's response is required.
83
-     * Because certain styling elements may also want to know that this
84
-     * input is required etc.
85
-     *
86
-     * @var boolean
87
-     */
88
-    protected $_required;
89
-
90
-    /**
91
-     * css class added to required inputs
92
-     *
93
-     * @var string
94
-     */
95
-    protected $_required_css_class = 'ee-required';
96
-
97
-    /**
98
-     * css styles applied to button type inputs
99
-     *
100
-     * @var string
101
-     */
102
-    protected $_button_css_attributes;
103
-
104
-    /**
105
-     * The raw post data submitted for this
106
-     * Generally unsafe for usage in client code
107
-     *
108
-     * @var mixed string or array
109
-     */
110
-    protected $_raw_value;
111
-
112
-    /**
113
-     * Value normalized according to the input's normalization strategy.
114
-     * The normalization strategy dictates whether this is a string, int, float,
115
-     * boolean, or array of any of those.
116
-     *
117
-     * @var mixed
118
-     */
119
-    protected $_normalized_value;
120
-
121
-
122
-    /**
123
-     * Normalized default value either initially set on the input, or provided by calling
124
-     * set_default().
125
-     *
126
-     * @var mixed
127
-     */
128
-    protected $_default;
129
-
130
-    /**
131
-     * Strategy used for displaying this field.
132
-     * Child classes must use _get_display_strategy to access it.
133
-     *
134
-     * @var EE_Display_Strategy_Base
135
-     */
136
-    private $_display_strategy;
137
-
138
-    /**
139
-     * Gets all the validation strategies used on this field
140
-     *
141
-     * @var EE_Validation_Strategy_Base[]
142
-     */
143
-    private $_validation_strategies = [];
144
-
145
-    /**
146
-     * The normalization strategy for this field
147
-     *
148
-     * @var EE_Normalization_Strategy_Base
149
-     */
150
-    private $_normalization_strategy;
151
-
152
-    /**
153
-     * Strategy for removing sensitive data after we're done with the form input
154
-     *
155
-     * @var EE_Sensitive_Data_Removal_Base
156
-     */
157
-    protected $_sensitive_data_removal_strategy;
158
-
159
-    /**
160
-     * Whether this input has been disabled or not.
161
-     * If it's disabled while rendering, an extra hidden input is added that indicates it has been knowingly disabled.
162
-     * (Client-side code that wants to dynamically disable it must also add this hidden input).
163
-     * When the form is submitted, if the input is disabled in the PHP form section, then input is ignored.
164
-     * If the input is missing from the request data but the hidden input indicating the input is disabled, then the
165
-     * input is again ignored.
166
-     *
167
-     * @var boolean
168
-     */
169
-    protected $disabled = false;
170
-
171
-    protected array $_data_attributes = [];
172
-
173
-    protected bool $_no_label = false; // if true, then no html label will be displayed for this input
174
-
175
-    /**
176
-     * adds a class to the input's container
177
-     *
178
-     * @var string
179
-     */
180
-    protected string $_layout_container_class = '';
181
-
182
-    /**
183
-     * additional HTML to inject into the input's container
184
-     *
185
-     * @var string
186
-     */
187
-    protected string $_extra_container_html = '';
188
-
189
-
190
-    /**
191
-     * @param array                         $input_args       {
192
-     * @type string                         $html_name        the html name for the input
193
-     * @type string                         $html_label_id    the id attribute to give to the html label tag
194
-     * @type string                         $html_label_class the class attribute to give to the html label tag
195
-     * @type string                         $html_label_style the style attribute to give ot teh label tag
196
-     * @type string                         $html_label_text  the text to put in the label tag
197
-     * @type string                         $html_label       the full html label. If used,
198
-     *                                                        all other html_label_* args are invalid
199
-     * @type string                         $html_help_text   text to put in help element
200
-     * @type string                         $html_help_style  style attribute to give to teh help element
201
-     * @type string                         $html_help_class  class attribute to give to the help element
202
-     * @type string                         $default          default value NORMALIZED (eg, if providing the default
203
-     *                                                        for a Yes_No_Input, you should provide TRUE or FALSE, not
204
-     *                                                        '1' or '0')
205
-     * @type EE_Display_Strategy_Base       $display          strategy
206
-     * @type EE_Normalization_Strategy_Base $normalization_strategy
207
-     * @type EE_Validation_Strategy_Base[]  $validation_strategies
208
-     * @type boolean                        $ignore_input     special argument which can be used to avoid adding any
209
-     *                                                        validation strategies, and sets the normalization
210
-     *                                                        strategy to the Null normalization. This is good when you
211
-     *                                                        want the input to be totally ignored server-side (like
212
-     *                                                        when using React.js form inputs)
213
-     *                                                        }
214
-     */
215
-    public function __construct($input_args = [])
216
-    {
217
-        $input_args = (array) apply_filters('FHEE__EE_Form_Input_Base___construct__input_args', $input_args, $this);
218
-        // the following properties must be cast as arrays
219
-        if (isset($input_args['validation_strategies'])) {
220
-            foreach ((array) $input_args['validation_strategies'] as $validation_strategy) {
221
-                if ($validation_strategy instanceof EE_Validation_Strategy_Base && empty($input_args['ignore_input'])) {
222
-                    $this->_validation_strategies[ get_class($validation_strategy) ] = $validation_strategy;
223
-                }
224
-            }
225
-            unset($input_args['validation_strategies']);
226
-        }
227
-        if (isset($input_args['ignore_input'])) {
228
-            $this->_validation_strategies = [];
229
-        }
230
-        // loop thru incoming options
231
-        foreach ($input_args as $key => $value) {
232
-            if ($key === 'disabled') {
233
-                $this->disable($value);
234
-                continue;
235
-            }
236
-            $setter = 'set_' . $key;
237
-            if (method_exists($this, $setter)) {
238
-                $this->$setter($value);
239
-                unset($input_args[ $key ]);
240
-                continue;
241
-            }
242
-            // add underscore to $key to match property names
243
-            $_key = "_$key";
244
-            if (property_exists($this, $_key)) {
245
-                $this->{$_key} = $value;
246
-                unset($input_args[ $key ]);
247
-            }
248
-        }
249
-        // ensure that "required" is set correctly
250
-        $this->set_required(
251
-            $this->_required,
252
-            $input_args['required_validation_error_message'] ?? null
253
-        );
254
-        // $this->_html_name_specified = isset( $input_args['html_name'] ) ? TRUE : FALSE;
255
-        $this->_display_strategy->_construct_finalize($this);
256
-        foreach ($this->_validation_strategies as $validation_strategy) {
257
-            $validation_strategy->_construct_finalize($this);
258
-        }
259
-        if (isset($input_args['ignore_input'])) {
260
-            $this->_normalization_strategy = new EE_Null_Normalization();
261
-        }
262
-        if (! $this->_normalization_strategy) {
263
-            $this->_normalization_strategy = new EE_Text_Normalization();
264
-        }
265
-        $this->_normalization_strategy->_construct_finalize($this);
266
-        // at least we can use the normalization strategy to populate the default
267
-        if (isset($input_args['default'])) {
268
-            $this->set_default($input_args['default']);
269
-            unset($input_args['default']);
270
-        }
271
-        if (! $this->_sensitive_data_removal_strategy) {
272
-            $this->_sensitive_data_removal_strategy = new EE_No_Sensitive_Data_Removal();
273
-        }
274
-        $this->_sensitive_data_removal_strategy->_construct_finalize($this);
275
-        parent::__construct($input_args);
276
-    }
277
-
278
-
279
-    /**
280
-     * Sets the html_name to its default value, if none was specified in teh constructor.
281
-     * Calculation involves using the name and the parent's html_name
282
-     *
283
-     * @throws EE_Error
284
-     */
285
-    protected function _set_default_html_name_if_empty()
286
-    {
287
-        if (! $this->_html_name) {
288
-            $this->_html_name = $this->name();
289
-            if ($this->_parent_section instanceof EE_Form_Section_Proper) {
290
-                $this->_html_name = $this->_parent_section->html_name_prefix() . "[{$this->name()}]";
291
-            }
292
-        }
293
-    }
294
-
295
-
296
-    /**
297
-     * @param $parent_form_section
298
-     * @param $name
299
-     * @throws EE_Error
300
-     */
301
-    public function _construct_finalize($parent_form_section, $name)
302
-    {
303
-        parent::_construct_finalize($parent_form_section, $name);
304
-        if ($this->_html_label === null && $this->_html_label_text === null && ! $this->_no_label) {
305
-            $this->_html_label_text = ucwords(str_replace("_", " ", $name));
306
-        }
307
-        do_action('AHEE__EE_Form_Input_Base___construct_finalize__end', $this, $parent_form_section, $name);
308
-    }
309
-
310
-
311
-    /**
312
-     * Returns the strategy for displaying this form input. If none is set, throws an exception.
313
-     *
314
-     * @return EE_Display_Strategy_Base
315
-     * @throws EE_Error
316
-     */
317
-    protected function _get_display_strategy()
318
-    {
319
-        $this->ensure_construct_finalized_called();
320
-        if (! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
321
-            throw new EE_Error(
322
-                sprintf(
323
-                    esc_html__(
324
-                        "Cannot get display strategy for form input with name %s and id %s, because it has not been set in the constructor",
325
-                        "event_espresso"
326
-                    ),
327
-                    $this->html_name(),
328
-                    $this->html_id()
329
-                )
330
-            );
331
-        } else {
332
-            return $this->_display_strategy;
333
-        }
334
-    }
335
-
336
-
337
-    /**
338
-     * Sets the display strategy.
339
-     *
340
-     * @param EE_Display_Strategy_Base $strategy
341
-     */
342
-    protected function _set_display_strategy(EE_Display_Strategy_Base $strategy)
343
-    {
344
-        $this->_display_strategy = $strategy;
345
-    }
346
-
347
-
348
-    /**
349
-     * Sets the sanitization strategy
350
-     *
351
-     * @param EE_Normalization_Strategy_Base $strategy
352
-     */
353
-    protected function _set_normalization_strategy(EE_Normalization_Strategy_Base $strategy)
354
-    {
355
-        $this->_normalization_strategy = $strategy;
356
-    }
357
-
358
-
359
-    /**
360
-     * Gets sensitive_data_removal_strategy
361
-     *
362
-     * @return EE_Sensitive_Data_Removal_Base
363
-     */
364
-    public function get_sensitive_data_removal_strategy()
365
-    {
366
-        return $this->_sensitive_data_removal_strategy;
367
-    }
368
-
369
-
370
-    /**
371
-     * Sets sensitive_data_removal_strategy
372
-     *
373
-     * @param EE_Sensitive_Data_Removal_Base $sensitive_data_removal_strategy
374
-     * @return void
375
-     */
376
-    public function set_sensitive_data_removal_strategy($sensitive_data_removal_strategy)
377
-    {
378
-        $this->_sensitive_data_removal_strategy = $sensitive_data_removal_strategy;
379
-    }
380
-
381
-
382
-    /**
383
-     * Gets the display strategy for this input
384
-     *
385
-     * @return EE_Display_Strategy_Base
386
-     */
387
-    public function get_display_strategy()
388
-    {
389
-        return $this->_display_strategy;
390
-    }
391
-
392
-
393
-    /**
394
-     * Overwrites the display strategy
395
-     *
396
-     * @param EE_Display_Strategy_Base $display_strategy
397
-     */
398
-    public function set_display_strategy($display_strategy)
399
-    {
400
-        $this->_display_strategy = $display_strategy;
401
-        $this->_display_strategy->_construct_finalize($this);
402
-    }
403
-
404
-
405
-    /**
406
-     * Gets the normalization strategy set on this input
407
-     *
408
-     * @return EE_Normalization_Strategy_Base
409
-     */
410
-    public function get_normalization_strategy()
411
-    {
412
-        return $this->_normalization_strategy;
413
-    }
414
-
415
-
416
-    /**
417
-     * Overwrites the normalization strategy
418
-     *
419
-     * @param EE_Normalization_Strategy_Base $normalization_strategy
420
-     */
421
-    public function set_normalization_strategy($normalization_strategy)
422
-    {
423
-        $this->_normalization_strategy = $normalization_strategy;
424
-        $this->_normalization_strategy->_construct_finalize($this);
425
-    }
426
-
427
-
428
-    /**
429
-     * Returns all teh validation strategies which apply to this field, numerically indexed
430
-     *
431
-     * @return EE_Validation_Strategy_Base[]
432
-     */
433
-    public function get_validation_strategies()
434
-    {
435
-        return $this->_validation_strategies;
436
-    }
437
-
438
-
439
-    /**
440
-     * Adds this strategy to the field so it will be used in both JS validation and server-side validation
441
-     *
442
-     * @param EE_Validation_Strategy_Base $validation_strategy
443
-     * @return void
444
-     */
445
-    protected function _add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
446
-    {
447
-        $validation_strategy->_construct_finalize($this);
448
-        $this->_validation_strategies[] = $validation_strategy;
449
-    }
450
-
451
-
452
-    /**
453
-     * Adds a new validation strategy onto the form input
454
-     *
455
-     * @param EE_Validation_Strategy_Base $validation_strategy
456
-     * @return void
457
-     */
458
-    public function add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
459
-    {
460
-        $this->_add_validation_strategy($validation_strategy);
461
-    }
462
-
463
-
464
-    /**
465
-     * The classname of the validation strategy to remove
466
-     *
467
-     * @param string $validation_strategy_classname
468
-     */
469
-    public function remove_validation_strategy($validation_strategy_classname)
470
-    {
471
-        foreach ($this->_validation_strategies as $key => $validation_strategy) {
472
-            if (
473
-                $validation_strategy instanceof $validation_strategy_classname
474
-                || is_subclass_of($validation_strategy, $validation_strategy_classname)
475
-            ) {
476
-                unset($this->_validation_strategies[ $key ]);
477
-            }
478
-        }
479
-    }
480
-
481
-
482
-    public function removeAllValidationStrategies()
483
-    {
484
-        $this->_validation_strategies = [];
485
-    }
486
-
487
-
488
-    /**
489
-     * returns true if input employs any of the validation strategy defined by the supplied array of classnames
490
-     *
491
-     * @param array $validation_strategy_classnames
492
-     * @return bool
493
-     */
494
-    public function has_validation_strategy($validation_strategy_classnames)
495
-    {
496
-        $validation_strategy_classnames = is_array($validation_strategy_classnames)
497
-            ? $validation_strategy_classnames
498
-            : [$validation_strategy_classnames];
499
-        foreach ($this->_validation_strategies as $key => $validation_strategy) {
500
-            if (in_array($key, $validation_strategy_classnames)) {
501
-                return true;
502
-            }
503
-        }
504
-        return false;
505
-    }
506
-
507
-
508
-    /**
509
-     * Gets the HTML
510
-     *
511
-     * @return string
512
-     */
513
-    public function get_html()
514
-    {
515
-        return $this->_parent_section->get_html_for_input($this);
516
-    }
517
-
518
-
519
-    /**
520
-     * Gets the HTML for the input itself (no label or errors) according to the
521
-     * input's display strategy
522
-     * Makes sure the JS and CSS are enqueued for it
523
-     *
524
-     * @return string
525
-     * @throws EE_Error
526
-     */
527
-    public function get_html_for_input()
528
-    {
529
-        return $this->_form_html_filter
530
-            ? $this->_form_html_filter->filterHtml(
531
-                $this->_get_display_strategy()->display(),
532
-                $this
533
-            )
534
-            : $this->_get_display_strategy()->display();
535
-    }
536
-
537
-
538
-    /**
539
-     * @return string
540
-     */
541
-    public function html_other_attributes()
542
-    {
543
-        EE_Error::doing_it_wrong(
544
-            __METHOD__,
545
-            sprintf(
546
-                esc_html__(
547
-                    'This method is no longer in use. You should replace it by %s',
548
-                    'event_espresso'
549
-                ),
550
-                'EE_Form_Section_Base::other_html_attributes()'
551
-            ),
552
-            '4.10.2.p'
553
-        );
554
-
555
-        return $this->other_html_attributes();
556
-    }
557
-
558
-
559
-    /**
560
-     * @param string $html_other_attributes
561
-     */
562
-    public function set_html_other_attributes($html_other_attributes)
563
-    {
564
-        EE_Error::doing_it_wrong(
565
-            __METHOD__,
566
-            sprintf(
567
-                esc_html__(
568
-                    'This method is no longer in use. You should replace it by %s',
569
-                    'event_espresso'
570
-                ),
571
-                'EE_Form_Section_Base::set_other_html_attributes()'
572
-            ),
573
-            '4.10.2.p'
574
-        );
575
-
576
-        $this->set_other_html_attributes($html_other_attributes);
577
-    }
578
-
579
-
580
-    /**
581
-     * Gets the HTML for displaying the label for this form input
582
-     * according to the form section's layout strategy
583
-     *
584
-     * @return string
585
-     * @throws EE_Error
586
-     */
587
-    public function get_html_for_label()
588
-    {
589
-        return $this->_parent_section->get_layout_strategy()->display_label($this);
590
-    }
591
-
592
-
593
-    /**
594
-     * Gets the HTML for displaying the errors section for this form input
595
-     * according to the form section's layout strategy
596
-     *
597
-     * @return string
598
-     * @throws EE_Error
599
-     */
600
-    public function get_html_for_errors()
601
-    {
602
-        return $this->_parent_section->get_layout_strategy()->display_errors($this);
603
-    }
604
-
605
-
606
-    /**
607
-     * Gets the HTML for displaying the help text for this form input
608
-     * according to the form section's layout strategy
609
-     *
610
-     * @return string
611
-     * @throws EE_Error
612
-     */
613
-    public function get_html_for_help()
614
-    {
615
-        return $this->_parent_section->get_layout_strategy()->display_help_text($this);
616
-    }
617
-
618
-
619
-    /**
620
-     * Validates the input's sanitized value (assumes _sanitize() has already been called)
621
-     * and returns whether or not the form input's submitted value is value
622
-     *
623
-     * @return boolean
624
-     */
625
-    protected function _validate()
626
-    {
627
-        if ($this->isDisabled()) {
628
-            return true;
629
-        }
630
-        foreach ($this->_validation_strategies as $validation_strategy) {
631
-            if ($validation_strategy instanceof EE_Validation_Strategy_Base) {
632
-                try {
633
-                    $validation_strategy->validate($this->normalized_value());
634
-                } catch (EE_Validation_Error $e) {
635
-                    $this->add_validation_error($e);
636
-                }
637
-            }
638
-        }
639
-        if ($this->get_validation_errors()) {
640
-            return false;
641
-        } else {
642
-            return true;
643
-        }
644
-    }
645
-
646
-
647
-    /**
648
-     * Performs basic sanitization on this value. But what sanitization can be performed anyways?
649
-     * This value MIGHT be allowed to have tags, so we can't really remove them.
650
-     *
651
-     * @param string $value
652
-     * @return null|string
653
-     */
654
-    protected function _sanitize($value)
655
-    {
656
-        return $value !== null
657
-            ? stripslashes(html_entity_decode(trim((string) $value)))
658
-            : null;
659
-    }
660
-
661
-
662
-    /**
663
-     * Picks out the form value that relates to this form input,
664
-     * and stores it as the sanitized value on the form input, and sets the normalized value.
665
-     * Returns whether or not any validation errors occurred
666
-     *
667
-     * @param array $req_data
668
-     * @return boolean whether or not there was an error
669
-     * @throws EE_Error
670
-     */
671
-    protected function _normalize($req_data)
672
-    {
673
-        // any existing validation errors don't apply so clear them
674
-        $this->_validation_errors = [];
675
-        // if the input is disabled, ignore whatever input was sent in
676
-        if ($this->isDisabled()) {
677
-            $this->_set_raw_value(null);
678
-            $this->_set_normalized_value($this->get_default());
679
-            return false;
680
-        }
681
-        try {
682
-            $raw_input = $this->find_form_data_for_this_section($req_data);
683
-            // super simple sanitization for now
684
-            if (is_array($raw_input)) {
685
-                $raw_value = [];
686
-                foreach ($raw_input as $key => $value) {
687
-                    $raw_value[ $key ] = $this->_sanitize($value);
688
-                }
689
-                $this->_set_raw_value($raw_value);
690
-            } else {
691
-                $this->_set_raw_value($this->_sanitize($raw_input));
692
-            }
693
-            // we want to mostly leave the input alone in case we need to re-display it to the user
694
-            $this->_set_normalized_value($this->_normalization_strategy->normalize($this->raw_value()));
695
-            return false;
696
-        } catch (EE_Validation_Error $e) {
697
-            $this->add_validation_error($e);
698
-            return true;
699
-        }
700
-    }
701
-
702
-
703
-    /**
704
-     * @return string
705
-     * @throws EE_Error
706
-     */
707
-    public function html_name()
708
-    {
709
-        $this->_set_default_html_name_if_empty();
710
-        return $this->_html_name ?? '';
711
-    }
712
-
713
-
714
-    /**
715
-     * @param string $html_label_id
716
-     */
717
-    public function set_html_label_id(string $html_label_id)
718
-    {
719
-        // if the html_label_id doesn't end in -lbl, then add it
720
-        if (strpos($html_label_id, '-lbl') !== (strlen($html_label_id) - 4)) {
721
-            $html_label_id .= '-lbl';
722
-        }
723
-        $this->_html_label_id = $html_label_id;
724
-    }
725
-
726
-
727
-    /**
728
-     * @return string
729
-     * @throws EE_Error
730
-     */
731
-    public function html_label_id()
732
-    {
733
-        if (empty($this->_html_label_id)) {
734
-            $this->set_html_label_id($this->html_id());
735
-        }
736
-        return $this->_html_label_id;
737
-    }
738
-
739
-
740
-    /**
741
-     * @return string
742
-     */
743
-    public function html_label_class()
744
-    {
745
-        return $this->_html_label_class ?? '';
746
-    }
747
-
748
-
749
-    /**
750
-     * @param string $html_class
751
-     */
752
-    public function add_html_label_class(string $html_class)
753
-    {
754
-        $this->_html_label_class .= ' ' . trim($html_class);
755
-    }
756
-
757
-
758
-    /**
759
-     * @return string
760
-     */
761
-    public function html_label_style()
762
-    {
763
-        return $this->_html_label_style ?? '';
764
-    }
765
-
766
-
767
-    /**
768
-     * @return string
769
-     */
770
-    public function html_label_text()
771
-    {
772
-        return $this->_html_label_text ?? '';
773
-    }
774
-
775
-
776
-    /**
777
-     * @return string
778
-     */
779
-    public function html_help_text()
780
-    {
781
-        return $this->_html_help_text ?? '';
782
-    }
783
-
784
-
785
-    /**
786
-     * @return string
787
-     */
788
-    public function html_help_class()
789
-    {
790
-        return $this->_html_help_class ?? '';
791
-    }
792
-
793
-
794
-    /**
795
-     * @return string
796
-     */
797
-    public function html_help_style()
798
-    {
799
-        return $this->_html_style ?? '';
800
-    }
801
-
802
-
803
-    /**
804
-     * returns the raw, UNSAFE, input, almost exactly as the user submitted it.
805
-     * Please note that almost all client code should instead use the normalized_value;
806
-     * or possibly raw_value_in_form (which prepares the string for displaying in an HTML attribute on a tag,
807
-     * mostly by escaping quotes)
808
-     * Note, we do not store the exact original value sent in the user's request because
809
-     * it may have malicious content, and we MIGHT want to store the form input in a transient or something...
810
-     * in which case, we would have stored the malicious content to our database.
811
-     *
812
-     * @return mixed
813
-     */
814
-    public function raw_value()
815
-    {
816
-        return $this->_raw_value;
817
-    }
818
-
819
-
820
-    /**
821
-     * Returns a string safe to usage in form inputs when displaying, because
822
-     * it escapes all html entities
823
-     *
824
-     * @return string
825
-     */
826
-    public function raw_value_in_form(): string
827
-    {
828
-        return htmlentities((string) $this->raw_value(), ENT_QUOTES, 'UTF-8');
829
-    }
830
-
831
-
832
-    /**
833
-     * returns the value after it's been sanitized, and then converted into it's proper type
834
-     * in PHP. Eg, a string, an int, an array,
835
-     *
836
-     * @return mixed
837
-     */
838
-    public function normalized_value()
839
-    {
840
-        return $this->_normalized_value;
841
-    }
842
-
843
-
844
-    /**
845
-     * Returns the normalized value is a presentable way. By default this is just
846
-     * the normalized value by itself, but it can be overridden for when that's not
847
-     * the best thing to display
848
-     *
849
-     * @return mixed
850
-     */
851
-    public function pretty_value()
852
-    {
853
-        return $this->_normalized_value;
854
-    }
855
-
856
-
857
-    /**
858
-     * When generating the JS for the jquery validation rules like<br>
859
-     * <code>$( "#myform" ).validate({
860
-     * rules: {
861
-     * password: "required",
862
-     * password_again: {
863
-     * equalTo: "#password"
864
-     * }
865
-     * }
866
-     * });</code>
867
-     * if this field had the name 'password_again', it should return
868
-     * <br><code>password_again: {
869
-     * equalTo: "#password"
870
-     * }</code>
871
-     *
872
-     * @return array
873
-     * @throws EE_Error
874
-     */
875
-    public function get_jquery_validation_rules(): array
876
-    {
877
-        $jquery_validation_js    = [];
878
-        $jquery_validation_rules = [];
879
-        foreach ($this->get_validation_strategies() as $validation_strategy) {
880
-            $jquery_validation_rules = array_replace_recursive(
881
-                $jquery_validation_rules,
882
-                $validation_strategy->get_jquery_validation_rule_array()
883
-            );
884
-        }
885
-        if (! empty($jquery_validation_rules)) {
886
-            foreach ($this->get_display_strategy()->get_html_input_ids(true) as $html_id_with_pound_sign) {
887
-                $jquery_validation_js[ $html_id_with_pound_sign ] = $jquery_validation_rules;
888
-            }
889
-        }
890
-        return $jquery_validation_js;
891
-    }
892
-
893
-
894
-    /**
895
-     * Sets the input's default value for use in displaying in the form. Note: value should be
896
-     * normalized (Eg, if providing a default of ra Yes_NO_Input you would provide TRUE or FALSE, not '1' or '0')
897
-     *
898
-     * @param mixed $value
899
-     * @return void
900
-     */
901
-    public function set_default($value)
902
-    {
903
-        $this->_default = $value;
904
-        $this->_set_normalized_value($value);
905
-        $this->_set_raw_value($value);
906
-    }
907
-
908
-
909
-    /**
910
-     * Sets the normalized value on this input
911
-     *
912
-     * @param mixed $value
913
-     */
914
-    protected function _set_normalized_value($value)
915
-    {
916
-        $this->_normalized_value = $value;
917
-    }
918
-
919
-
920
-    /**
921
-     * Sets the raw value on this input (ie, exactly as the user submitted it)
922
-     *
923
-     * @param mixed $value
924
-     */
925
-    protected function _set_raw_value($value)
926
-    {
927
-        $this->_raw_value = $this->_normalization_strategy->unnormalize($value);
928
-    }
929
-
930
-
931
-    /**
932
-     * Sets the HTML label text after it has already been defined
933
-     *
934
-     * @param string $label
935
-     * @return void
936
-     */
937
-    public function set_html_label_text($label)
938
-    {
939
-        $this->_html_label_text = $label;
940
-    }
941
-
942
-
943
-    /**
944
-     * Sets whether or not this field is required, and adjusts the validation strategy.
945
-     * If you want to use the EE_Conditionally_Required_Validation_Strategy,
946
-     * please add it as a validation strategy using add_validation_strategy as normal
947
-     *
948
-     * @param boolean $required boolean
949
-     * @param null    $required_text
950
-     */
951
-    public function set_required($required = true, $required_text = null)
952
-    {
953
-        $required = filter_var($required, FILTER_VALIDATE_BOOLEAN);
954
-        // whether $required is a string or a boolean, we want to add a required validation strategy
955
-        if ($required) {
956
-            $this->_add_validation_strategy(new EE_Required_Validation_Strategy($required_text));
957
-        } else {
958
-            $this->remove_validation_strategy('EE_Required_Validation_Strategy');
959
-        }
960
-        $this->_required = $required;
961
-    }
962
-
963
-
964
-    /**
965
-     * Returns whether or not this field is required
966
-     *
967
-     * @return boolean
968
-     */
969
-    public function required()
970
-    {
971
-        return $this->_required;
972
-    }
973
-
974
-
975
-    /**
976
-     * @param string $required_css_class
977
-     */
978
-    public function set_required_css_class($required_css_class)
979
-    {
980
-        $this->_required_css_class = $required_css_class;
981
-    }
982
-
983
-
984
-    /**
985
-     * @return string
986
-     */
987
-    public function required_css_class()
988
-    {
989
-        return $this->_required_css_class;
990
-    }
991
-
992
-
993
-    /**
994
-     * @param bool $add_required
995
-     * @return string
996
-     */
997
-    public function html_class($add_required = false)
998
-    {
999
-        return $add_required && $this->required()
1000
-            ? $this->required_css_class() . ' ' . $this->_html_class
1001
-            : $this->_html_class;
1002
-    }
1003
-
1004
-
1005
-    /**
1006
-     * Sets the help text, in case
1007
-     *
1008
-     * @param string $text
1009
-     */
1010
-    public function set_html_help_text($text)
1011
-    {
1012
-        $this->_html_help_text = $text;
1013
-    }
1014
-
1015
-
1016
-    /**
1017
-     * Uses the sensitive data removal strategy to remove the sensitive data from this
1018
-     * input. If there is any kind of sensitive data removal on this input, we clear
1019
-     * out the raw value completely
1020
-     *
1021
-     * @return void
1022
-     */
1023
-    public function clean_sensitive_data()
1024
-    {
1025
-        // if we do ANY kind of sensitive data removal on this, then just clear out the raw value
1026
-        // if we need more logic than this we'll make a strategy for it
1027
-        if (
1028
-            $this->_sensitive_data_removal_strategy
1029
-            && ! $this->_sensitive_data_removal_strategy instanceof EE_No_Sensitive_Data_Removal
1030
-        ) {
1031
-            $this->_set_raw_value(null);
1032
-        }
1033
-        // and clean the normalized value according to the appropriate strategy
1034
-        $this->_set_normalized_value(
1035
-            $this->get_sensitive_data_removal_strategy()->remove_sensitive_data(
1036
-                $this->_normalized_value
1037
-            )
1038
-        );
1039
-    }
1040
-
1041
-
1042
-    /**
1043
-     * @param bool   $primary
1044
-     * @param string $button_size
1045
-     * @param string $other_attributes
1046
-     */
1047
-    public function set_button_css_attributes($primary = true, $button_size = '', $other_attributes = '')
1048
-    {
1049
-        $button_css_attributes = 'button';
1050
-        $button_css_attributes .= $primary === true
1051
-            ? ' button--primary'
1052
-            : ' button--secondary';
1053
-        switch ($button_size) {
1054
-            case 'xs':
1055
-            case 'extra-small':
1056
-                $button_css_attributes .= ' button-xs';
1057
-                break;
1058
-            case 'sm':
1059
-            case 'small':
1060
-                $button_css_attributes .= ' button-sm';
1061
-                break;
1062
-            case 'lg':
1063
-            case 'large':
1064
-                $button_css_attributes .= ' button-lg';
1065
-                break;
1066
-            case 'block':
1067
-                $button_css_attributes .= ' button-block';
1068
-                break;
1069
-            case 'md':
1070
-            case 'medium':
1071
-            default:
1072
-                $button_css_attributes .= '';
1073
-        }
1074
-        $this->_button_css_attributes .= ! empty($other_attributes)
1075
-            ? $button_css_attributes . ' ' . $other_attributes
1076
-            : $button_css_attributes;
1077
-    }
1078
-
1079
-
1080
-    /**
1081
-     * @return string
1082
-     */
1083
-    public function button_css_attributes()
1084
-    {
1085
-        if (empty($this->_button_css_attributes)) {
1086
-            $this->set_button_css_attributes();
1087
-        }
1088
-        return $this->_button_css_attributes;
1089
-    }
1090
-
1091
-
1092
-    /**
1093
-     * find_form_data_for_this_section
1094
-     * using this section's name and its parents, finds the value of the form data that corresponds to it.
1095
-     * For example, if this form section's HTML name is my_form[subform][form_input_1],
1096
-     * then it's value should be in request at request['my_form']['subform']['form_input_1'].
1097
-     * (If that doesn't exist, we also check for this subsection's name
1098
-     * at the TOP LEVEL of the request data. Eg request['form_input_1'].)
1099
-     * This function finds its value in the form.
1100
-     *
1101
-     * @param array $req_data
1102
-     * @return mixed whatever the raw value of this form section is in the request data
1103
-     * @throws EE_Error
1104
-     */
1105
-    public function find_form_data_for_this_section($req_data)
1106
-    {
1107
-        $name_parts = $this->getInputNameParts();
1108
-        // now get the value for the input
1109
-        $value = $this->findRequestForSectionUsingNameParts($name_parts, $req_data);
1110
-        // check if this thing's name is at the TOP level of the request data
1111
-        if ($value === null && isset($req_data[ $this->name() ])) {
1112
-            $value = $req_data[ $this->name() ];
1113
-        }
1114
-        return $value;
1115
-    }
1116
-
1117
-
1118
-    /**
1119
-     * If this input's name is something like "foo[bar][baz]"
1120
-     * returns an array like `array('foo','bar',baz')`
1121
-     *
1122
-     * @return array
1123
-     * @throws EE_Error
1124
-     */
1125
-    protected function getInputNameParts()
1126
-    {
1127
-        // break up the html name by "[]"
1128
-        if (strpos($this->html_name(), '[') !== false) {
1129
-            $before_any_brackets = substr($this->html_name(), 0, strpos($this->html_name(), '['));
1130
-        } else {
1131
-            $before_any_brackets = $this->html_name();
1132
-        }
1133
-        // grab all of the segments
1134
-        preg_match_all('~\[([^]]*)\]~', $this->html_name(), $matches);
1135
-        if (isset($matches[1]) && is_array($matches[1])) {
1136
-            $name_parts = $matches[1];
1137
-            array_unshift($name_parts, $before_any_brackets);
1138
-        } else {
1139
-            $name_parts = [$before_any_brackets];
1140
-        }
1141
-        return $name_parts;
1142
-    }
1143
-
1144
-
1145
-    /**
1146
-     * @param array $html_name_parts
1147
-     * @param array $req_data
1148
-     * @return array | NULL
1149
-     */
1150
-    public function findRequestForSectionUsingNameParts($html_name_parts, $req_data)
1151
-    {
1152
-        $first_part_to_consider = array_shift($html_name_parts);
1153
-        if (isset($req_data[ $first_part_to_consider ])) {
1154
-            if (empty($html_name_parts)) {
1155
-                return $req_data[ $first_part_to_consider ];
1156
-            } else {
1157
-                return $this->findRequestForSectionUsingNameParts(
1158
-                    $html_name_parts,
1159
-                    $req_data[ $first_part_to_consider ]
1160
-                );
1161
-            }
1162
-        }
1163
-        return null;
1164
-    }
1165
-
1166
-
1167
-    /**
1168
-     * Checks if this form input's data is in the request data
1169
-     *
1170
-     * @param array $req_data
1171
-     * @return boolean
1172
-     * @throws EE_Error
1173
-     */
1174
-    public function form_data_present_in($req_data = null)
1175
-    {
1176
-        if ($req_data === null) {
1177
-            /** @var RequestInterface $request */
1178
-            $request  = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1179
-            $req_data = $request->postParams();
1180
-        }
1181
-
1182
-        return $this->find_form_data_for_this_section($req_data) !== null;
1183
-    }
1184
-
1185
-
1186
-    /**
1187
-     * Overrides parent to add js data from validation and display strategies
1188
-     *
1189
-     * @param array $form_other_js_data
1190
-     * @return array
1191
-     */
1192
-    public function get_other_js_data($form_other_js_data = [])
1193
-    {
1194
-        return $this->get_other_js_data_from_strategies($form_other_js_data);
1195
-    }
1196
-
1197
-
1198
-    /**
1199
-     * Gets other JS data for localization from this input's strategies, like
1200
-     * the validation strategies and the display strategy
1201
-     *
1202
-     * @param array $form_other_js_data
1203
-     * @return array
1204
-     */
1205
-    public function get_other_js_data_from_strategies($form_other_js_data = [])
1206
-    {
1207
-        $form_other_js_data = $this->get_display_strategy()->get_other_js_data($form_other_js_data);
1208
-        foreach ($this->get_validation_strategies() as $validation_strategy) {
1209
-            $form_other_js_data = $validation_strategy->get_other_js_data($form_other_js_data);
1210
-        }
1211
-        return $form_other_js_data;
1212
-    }
1213
-
1214
-
1215
-    /**
1216
-     * Override parent because we want to give our strategies an opportunity to enqueue some js and css
1217
-     *
1218
-     * @return void
1219
-     */
1220
-    public function enqueue_js()
1221
-    {
1222
-        // ask our display strategy and validation strategies if they have js to enqueue
1223
-        $this->enqueue_js_from_strategies();
1224
-    }
1225
-
1226
-
1227
-    /**
1228
-     * Tells strategies when its ok to enqueue their js and css
1229
-     *
1230
-     * @return void
1231
-     */
1232
-    public function enqueue_js_from_strategies()
1233
-    {
1234
-        $this->get_display_strategy()->enqueue_js();
1235
-        foreach ($this->get_validation_strategies() as $validation_strategy) {
1236
-            $validation_strategy->enqueue_js();
1237
-        }
1238
-    }
1239
-
1240
-
1241
-    /**
1242
-     * Gets the default value set on the input (not the current value, which may have been
1243
-     * changed because of a form submission). If no default was set, this us null.
1244
-     *
1245
-     * @return mixed
1246
-     */
1247
-    public function get_default()
1248
-    {
1249
-        return $this->_default;
1250
-    }
1251
-
1252
-
1253
-    /**
1254
-     * Makes this input disabled. That means it will have the HTML attribute 'disabled="disabled"',
1255
-     * and server-side if any input was received it will be ignored
1256
-     */
1257
-    public function disable($disable = true)
1258
-    {
1259
-        $disabled_attribute = ' disabled="disabled"';
1260
-        $this->disabled     = filter_var($disable, FILTER_VALIDATE_BOOLEAN);
1261
-        if ($this->disabled) {
1262
-            if (strpos($this->_other_html_attributes, $disabled_attribute) === false) {
1263
-                $this->_other_html_attributes .= $disabled_attribute;
1264
-            }
1265
-            $this->_set_normalized_value($this->get_default());
1266
-        } else {
1267
-            $this->_other_html_attributes = str_replace($disabled_attribute, '', $this->_other_html_attributes);
1268
-        }
1269
-    }
1270
-
1271
-
1272
-    /**
1273
-     * Returns whether this input is currently disabled.
1274
-     *
1275
-     * @return bool
1276
-     */
1277
-    public function isDisabled(): bool
1278
-    {
1279
-        return $this->disabled;
1280
-    }
1281
-
1282
-
1283
-    public function dataAttributes(): array
1284
-    {
1285
-        return $this->_data_attributes;
1286
-    }
1287
-
1288
-
1289
-    public function layoutContainerClass(): string
1290
-    {
1291
-        return $this->_layout_container_class;
1292
-    }
1293
-
1294
-
1295
-    public function extraContainerHtml(): string
1296
-    {
1297
-        return $this->_extra_container_html;
1298
-    }
1299
-
1300
-
1301
-    public function hasLabel(): bool
1302
-    {
1303
-        return ! $this->_no_label
1304
-            && $this->html_label_text()
1305
-            && ! $this->get_display_strategy() instanceof EE_Hidden_Display_Strategy;
1306
-    }
17
+	/**
18
+	 * the input's name attribute
19
+	 *
20
+	 * @var string|null
21
+	 */
22
+	protected ?string $_html_name = null;
23
+
24
+	/**
25
+	 * id for the html label tag
26
+	 *
27
+	 * @var string
28
+	 */
29
+	protected $_html_label_id;
30
+
31
+	/**
32
+	 * class for teh html label tag
33
+	 *
34
+	 * @var string
35
+	 */
36
+	protected $_html_label_class;
37
+
38
+	/**
39
+	 * style for teh html label tag
40
+	 *
41
+	 * @var string
42
+	 */
43
+	protected $_html_label_style;
44
+
45
+	/**
46
+	 * text to be placed in the html label
47
+	 *
48
+	 * @var string
49
+	 */
50
+	protected $_html_label_text;
51
+
52
+	/**
53
+	 * the full html label. If used, all other html_label_* properties are invalid
54
+	 *
55
+	 * @var string
56
+	 */
57
+	protected $_html_label;
58
+
59
+	/**
60
+	 * HTML to use for help text (normally placed below form input), in a span which normally
61
+	 * has a class of 'description'
62
+	 *
63
+	 * @var string
64
+	 */
65
+	protected $_html_help_text;
66
+
67
+	/**
68
+	 * CSS classes for displaying the help span
69
+	 *
70
+	 * @var string
71
+	 */
72
+	protected $_html_help_class = 'description';
73
+
74
+	/**
75
+	 * CSS to put in the style attribute on the help span
76
+	 *
77
+	 * @var string
78
+	 */
79
+	protected $_html_help_style;
80
+
81
+	/**
82
+	 * Stores whether or not this input's response is required.
83
+	 * Because certain styling elements may also want to know that this
84
+	 * input is required etc.
85
+	 *
86
+	 * @var boolean
87
+	 */
88
+	protected $_required;
89
+
90
+	/**
91
+	 * css class added to required inputs
92
+	 *
93
+	 * @var string
94
+	 */
95
+	protected $_required_css_class = 'ee-required';
96
+
97
+	/**
98
+	 * css styles applied to button type inputs
99
+	 *
100
+	 * @var string
101
+	 */
102
+	protected $_button_css_attributes;
103
+
104
+	/**
105
+	 * The raw post data submitted for this
106
+	 * Generally unsafe for usage in client code
107
+	 *
108
+	 * @var mixed string or array
109
+	 */
110
+	protected $_raw_value;
111
+
112
+	/**
113
+	 * Value normalized according to the input's normalization strategy.
114
+	 * The normalization strategy dictates whether this is a string, int, float,
115
+	 * boolean, or array of any of those.
116
+	 *
117
+	 * @var mixed
118
+	 */
119
+	protected $_normalized_value;
120
+
121
+
122
+	/**
123
+	 * Normalized default value either initially set on the input, or provided by calling
124
+	 * set_default().
125
+	 *
126
+	 * @var mixed
127
+	 */
128
+	protected $_default;
129
+
130
+	/**
131
+	 * Strategy used for displaying this field.
132
+	 * Child classes must use _get_display_strategy to access it.
133
+	 *
134
+	 * @var EE_Display_Strategy_Base
135
+	 */
136
+	private $_display_strategy;
137
+
138
+	/**
139
+	 * Gets all the validation strategies used on this field
140
+	 *
141
+	 * @var EE_Validation_Strategy_Base[]
142
+	 */
143
+	private $_validation_strategies = [];
144
+
145
+	/**
146
+	 * The normalization strategy for this field
147
+	 *
148
+	 * @var EE_Normalization_Strategy_Base
149
+	 */
150
+	private $_normalization_strategy;
151
+
152
+	/**
153
+	 * Strategy for removing sensitive data after we're done with the form input
154
+	 *
155
+	 * @var EE_Sensitive_Data_Removal_Base
156
+	 */
157
+	protected $_sensitive_data_removal_strategy;
158
+
159
+	/**
160
+	 * Whether this input has been disabled or not.
161
+	 * If it's disabled while rendering, an extra hidden input is added that indicates it has been knowingly disabled.
162
+	 * (Client-side code that wants to dynamically disable it must also add this hidden input).
163
+	 * When the form is submitted, if the input is disabled in the PHP form section, then input is ignored.
164
+	 * If the input is missing from the request data but the hidden input indicating the input is disabled, then the
165
+	 * input is again ignored.
166
+	 *
167
+	 * @var boolean
168
+	 */
169
+	protected $disabled = false;
170
+
171
+	protected array $_data_attributes = [];
172
+
173
+	protected bool $_no_label = false; // if true, then no html label will be displayed for this input
174
+
175
+	/**
176
+	 * adds a class to the input's container
177
+	 *
178
+	 * @var string
179
+	 */
180
+	protected string $_layout_container_class = '';
181
+
182
+	/**
183
+	 * additional HTML to inject into the input's container
184
+	 *
185
+	 * @var string
186
+	 */
187
+	protected string $_extra_container_html = '';
188
+
189
+
190
+	/**
191
+	 * @param array                         $input_args       {
192
+	 * @type string                         $html_name        the html name for the input
193
+	 * @type string                         $html_label_id    the id attribute to give to the html label tag
194
+	 * @type string                         $html_label_class the class attribute to give to the html label tag
195
+	 * @type string                         $html_label_style the style attribute to give ot teh label tag
196
+	 * @type string                         $html_label_text  the text to put in the label tag
197
+	 * @type string                         $html_label       the full html label. If used,
198
+	 *                                                        all other html_label_* args are invalid
199
+	 * @type string                         $html_help_text   text to put in help element
200
+	 * @type string                         $html_help_style  style attribute to give to teh help element
201
+	 * @type string                         $html_help_class  class attribute to give to the help element
202
+	 * @type string                         $default          default value NORMALIZED (eg, if providing the default
203
+	 *                                                        for a Yes_No_Input, you should provide TRUE or FALSE, not
204
+	 *                                                        '1' or '0')
205
+	 * @type EE_Display_Strategy_Base       $display          strategy
206
+	 * @type EE_Normalization_Strategy_Base $normalization_strategy
207
+	 * @type EE_Validation_Strategy_Base[]  $validation_strategies
208
+	 * @type boolean                        $ignore_input     special argument which can be used to avoid adding any
209
+	 *                                                        validation strategies, and sets the normalization
210
+	 *                                                        strategy to the Null normalization. This is good when you
211
+	 *                                                        want the input to be totally ignored server-side (like
212
+	 *                                                        when using React.js form inputs)
213
+	 *                                                        }
214
+	 */
215
+	public function __construct($input_args = [])
216
+	{
217
+		$input_args = (array) apply_filters('FHEE__EE_Form_Input_Base___construct__input_args', $input_args, $this);
218
+		// the following properties must be cast as arrays
219
+		if (isset($input_args['validation_strategies'])) {
220
+			foreach ((array) $input_args['validation_strategies'] as $validation_strategy) {
221
+				if ($validation_strategy instanceof EE_Validation_Strategy_Base && empty($input_args['ignore_input'])) {
222
+					$this->_validation_strategies[ get_class($validation_strategy) ] = $validation_strategy;
223
+				}
224
+			}
225
+			unset($input_args['validation_strategies']);
226
+		}
227
+		if (isset($input_args['ignore_input'])) {
228
+			$this->_validation_strategies = [];
229
+		}
230
+		// loop thru incoming options
231
+		foreach ($input_args as $key => $value) {
232
+			if ($key === 'disabled') {
233
+				$this->disable($value);
234
+				continue;
235
+			}
236
+			$setter = 'set_' . $key;
237
+			if (method_exists($this, $setter)) {
238
+				$this->$setter($value);
239
+				unset($input_args[ $key ]);
240
+				continue;
241
+			}
242
+			// add underscore to $key to match property names
243
+			$_key = "_$key";
244
+			if (property_exists($this, $_key)) {
245
+				$this->{$_key} = $value;
246
+				unset($input_args[ $key ]);
247
+			}
248
+		}
249
+		// ensure that "required" is set correctly
250
+		$this->set_required(
251
+			$this->_required,
252
+			$input_args['required_validation_error_message'] ?? null
253
+		);
254
+		// $this->_html_name_specified = isset( $input_args['html_name'] ) ? TRUE : FALSE;
255
+		$this->_display_strategy->_construct_finalize($this);
256
+		foreach ($this->_validation_strategies as $validation_strategy) {
257
+			$validation_strategy->_construct_finalize($this);
258
+		}
259
+		if (isset($input_args['ignore_input'])) {
260
+			$this->_normalization_strategy = new EE_Null_Normalization();
261
+		}
262
+		if (! $this->_normalization_strategy) {
263
+			$this->_normalization_strategy = new EE_Text_Normalization();
264
+		}
265
+		$this->_normalization_strategy->_construct_finalize($this);
266
+		// at least we can use the normalization strategy to populate the default
267
+		if (isset($input_args['default'])) {
268
+			$this->set_default($input_args['default']);
269
+			unset($input_args['default']);
270
+		}
271
+		if (! $this->_sensitive_data_removal_strategy) {
272
+			$this->_sensitive_data_removal_strategy = new EE_No_Sensitive_Data_Removal();
273
+		}
274
+		$this->_sensitive_data_removal_strategy->_construct_finalize($this);
275
+		parent::__construct($input_args);
276
+	}
277
+
278
+
279
+	/**
280
+	 * Sets the html_name to its default value, if none was specified in teh constructor.
281
+	 * Calculation involves using the name and the parent's html_name
282
+	 *
283
+	 * @throws EE_Error
284
+	 */
285
+	protected function _set_default_html_name_if_empty()
286
+	{
287
+		if (! $this->_html_name) {
288
+			$this->_html_name = $this->name();
289
+			if ($this->_parent_section instanceof EE_Form_Section_Proper) {
290
+				$this->_html_name = $this->_parent_section->html_name_prefix() . "[{$this->name()}]";
291
+			}
292
+		}
293
+	}
294
+
295
+
296
+	/**
297
+	 * @param $parent_form_section
298
+	 * @param $name
299
+	 * @throws EE_Error
300
+	 */
301
+	public function _construct_finalize($parent_form_section, $name)
302
+	{
303
+		parent::_construct_finalize($parent_form_section, $name);
304
+		if ($this->_html_label === null && $this->_html_label_text === null && ! $this->_no_label) {
305
+			$this->_html_label_text = ucwords(str_replace("_", " ", $name));
306
+		}
307
+		do_action('AHEE__EE_Form_Input_Base___construct_finalize__end', $this, $parent_form_section, $name);
308
+	}
309
+
310
+
311
+	/**
312
+	 * Returns the strategy for displaying this form input. If none is set, throws an exception.
313
+	 *
314
+	 * @return EE_Display_Strategy_Base
315
+	 * @throws EE_Error
316
+	 */
317
+	protected function _get_display_strategy()
318
+	{
319
+		$this->ensure_construct_finalized_called();
320
+		if (! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
321
+			throw new EE_Error(
322
+				sprintf(
323
+					esc_html__(
324
+						"Cannot get display strategy for form input with name %s and id %s, because it has not been set in the constructor",
325
+						"event_espresso"
326
+					),
327
+					$this->html_name(),
328
+					$this->html_id()
329
+				)
330
+			);
331
+		} else {
332
+			return $this->_display_strategy;
333
+		}
334
+	}
335
+
336
+
337
+	/**
338
+	 * Sets the display strategy.
339
+	 *
340
+	 * @param EE_Display_Strategy_Base $strategy
341
+	 */
342
+	protected function _set_display_strategy(EE_Display_Strategy_Base $strategy)
343
+	{
344
+		$this->_display_strategy = $strategy;
345
+	}
346
+
347
+
348
+	/**
349
+	 * Sets the sanitization strategy
350
+	 *
351
+	 * @param EE_Normalization_Strategy_Base $strategy
352
+	 */
353
+	protected function _set_normalization_strategy(EE_Normalization_Strategy_Base $strategy)
354
+	{
355
+		$this->_normalization_strategy = $strategy;
356
+	}
357
+
358
+
359
+	/**
360
+	 * Gets sensitive_data_removal_strategy
361
+	 *
362
+	 * @return EE_Sensitive_Data_Removal_Base
363
+	 */
364
+	public function get_sensitive_data_removal_strategy()
365
+	{
366
+		return $this->_sensitive_data_removal_strategy;
367
+	}
368
+
369
+
370
+	/**
371
+	 * Sets sensitive_data_removal_strategy
372
+	 *
373
+	 * @param EE_Sensitive_Data_Removal_Base $sensitive_data_removal_strategy
374
+	 * @return void
375
+	 */
376
+	public function set_sensitive_data_removal_strategy($sensitive_data_removal_strategy)
377
+	{
378
+		$this->_sensitive_data_removal_strategy = $sensitive_data_removal_strategy;
379
+	}
380
+
381
+
382
+	/**
383
+	 * Gets the display strategy for this input
384
+	 *
385
+	 * @return EE_Display_Strategy_Base
386
+	 */
387
+	public function get_display_strategy()
388
+	{
389
+		return $this->_display_strategy;
390
+	}
391
+
392
+
393
+	/**
394
+	 * Overwrites the display strategy
395
+	 *
396
+	 * @param EE_Display_Strategy_Base $display_strategy
397
+	 */
398
+	public function set_display_strategy($display_strategy)
399
+	{
400
+		$this->_display_strategy = $display_strategy;
401
+		$this->_display_strategy->_construct_finalize($this);
402
+	}
403
+
404
+
405
+	/**
406
+	 * Gets the normalization strategy set on this input
407
+	 *
408
+	 * @return EE_Normalization_Strategy_Base
409
+	 */
410
+	public function get_normalization_strategy()
411
+	{
412
+		return $this->_normalization_strategy;
413
+	}
414
+
415
+
416
+	/**
417
+	 * Overwrites the normalization strategy
418
+	 *
419
+	 * @param EE_Normalization_Strategy_Base $normalization_strategy
420
+	 */
421
+	public function set_normalization_strategy($normalization_strategy)
422
+	{
423
+		$this->_normalization_strategy = $normalization_strategy;
424
+		$this->_normalization_strategy->_construct_finalize($this);
425
+	}
426
+
427
+
428
+	/**
429
+	 * Returns all teh validation strategies which apply to this field, numerically indexed
430
+	 *
431
+	 * @return EE_Validation_Strategy_Base[]
432
+	 */
433
+	public function get_validation_strategies()
434
+	{
435
+		return $this->_validation_strategies;
436
+	}
437
+
438
+
439
+	/**
440
+	 * Adds this strategy to the field so it will be used in both JS validation and server-side validation
441
+	 *
442
+	 * @param EE_Validation_Strategy_Base $validation_strategy
443
+	 * @return void
444
+	 */
445
+	protected function _add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
446
+	{
447
+		$validation_strategy->_construct_finalize($this);
448
+		$this->_validation_strategies[] = $validation_strategy;
449
+	}
450
+
451
+
452
+	/**
453
+	 * Adds a new validation strategy onto the form input
454
+	 *
455
+	 * @param EE_Validation_Strategy_Base $validation_strategy
456
+	 * @return void
457
+	 */
458
+	public function add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
459
+	{
460
+		$this->_add_validation_strategy($validation_strategy);
461
+	}
462
+
463
+
464
+	/**
465
+	 * The classname of the validation strategy to remove
466
+	 *
467
+	 * @param string $validation_strategy_classname
468
+	 */
469
+	public function remove_validation_strategy($validation_strategy_classname)
470
+	{
471
+		foreach ($this->_validation_strategies as $key => $validation_strategy) {
472
+			if (
473
+				$validation_strategy instanceof $validation_strategy_classname
474
+				|| is_subclass_of($validation_strategy, $validation_strategy_classname)
475
+			) {
476
+				unset($this->_validation_strategies[ $key ]);
477
+			}
478
+		}
479
+	}
480
+
481
+
482
+	public function removeAllValidationStrategies()
483
+	{
484
+		$this->_validation_strategies = [];
485
+	}
486
+
487
+
488
+	/**
489
+	 * returns true if input employs any of the validation strategy defined by the supplied array of classnames
490
+	 *
491
+	 * @param array $validation_strategy_classnames
492
+	 * @return bool
493
+	 */
494
+	public function has_validation_strategy($validation_strategy_classnames)
495
+	{
496
+		$validation_strategy_classnames = is_array($validation_strategy_classnames)
497
+			? $validation_strategy_classnames
498
+			: [$validation_strategy_classnames];
499
+		foreach ($this->_validation_strategies as $key => $validation_strategy) {
500
+			if (in_array($key, $validation_strategy_classnames)) {
501
+				return true;
502
+			}
503
+		}
504
+		return false;
505
+	}
506
+
507
+
508
+	/**
509
+	 * Gets the HTML
510
+	 *
511
+	 * @return string
512
+	 */
513
+	public function get_html()
514
+	{
515
+		return $this->_parent_section->get_html_for_input($this);
516
+	}
517
+
518
+
519
+	/**
520
+	 * Gets the HTML for the input itself (no label or errors) according to the
521
+	 * input's display strategy
522
+	 * Makes sure the JS and CSS are enqueued for it
523
+	 *
524
+	 * @return string
525
+	 * @throws EE_Error
526
+	 */
527
+	public function get_html_for_input()
528
+	{
529
+		return $this->_form_html_filter
530
+			? $this->_form_html_filter->filterHtml(
531
+				$this->_get_display_strategy()->display(),
532
+				$this
533
+			)
534
+			: $this->_get_display_strategy()->display();
535
+	}
536
+
537
+
538
+	/**
539
+	 * @return string
540
+	 */
541
+	public function html_other_attributes()
542
+	{
543
+		EE_Error::doing_it_wrong(
544
+			__METHOD__,
545
+			sprintf(
546
+				esc_html__(
547
+					'This method is no longer in use. You should replace it by %s',
548
+					'event_espresso'
549
+				),
550
+				'EE_Form_Section_Base::other_html_attributes()'
551
+			),
552
+			'4.10.2.p'
553
+		);
554
+
555
+		return $this->other_html_attributes();
556
+	}
557
+
558
+
559
+	/**
560
+	 * @param string $html_other_attributes
561
+	 */
562
+	public function set_html_other_attributes($html_other_attributes)
563
+	{
564
+		EE_Error::doing_it_wrong(
565
+			__METHOD__,
566
+			sprintf(
567
+				esc_html__(
568
+					'This method is no longer in use. You should replace it by %s',
569
+					'event_espresso'
570
+				),
571
+				'EE_Form_Section_Base::set_other_html_attributes()'
572
+			),
573
+			'4.10.2.p'
574
+		);
575
+
576
+		$this->set_other_html_attributes($html_other_attributes);
577
+	}
578
+
579
+
580
+	/**
581
+	 * Gets the HTML for displaying the label for this form input
582
+	 * according to the form section's layout strategy
583
+	 *
584
+	 * @return string
585
+	 * @throws EE_Error
586
+	 */
587
+	public function get_html_for_label()
588
+	{
589
+		return $this->_parent_section->get_layout_strategy()->display_label($this);
590
+	}
591
+
592
+
593
+	/**
594
+	 * Gets the HTML for displaying the errors section for this form input
595
+	 * according to the form section's layout strategy
596
+	 *
597
+	 * @return string
598
+	 * @throws EE_Error
599
+	 */
600
+	public function get_html_for_errors()
601
+	{
602
+		return $this->_parent_section->get_layout_strategy()->display_errors($this);
603
+	}
604
+
605
+
606
+	/**
607
+	 * Gets the HTML for displaying the help text for this form input
608
+	 * according to the form section's layout strategy
609
+	 *
610
+	 * @return string
611
+	 * @throws EE_Error
612
+	 */
613
+	public function get_html_for_help()
614
+	{
615
+		return $this->_parent_section->get_layout_strategy()->display_help_text($this);
616
+	}
617
+
618
+
619
+	/**
620
+	 * Validates the input's sanitized value (assumes _sanitize() has already been called)
621
+	 * and returns whether or not the form input's submitted value is value
622
+	 *
623
+	 * @return boolean
624
+	 */
625
+	protected function _validate()
626
+	{
627
+		if ($this->isDisabled()) {
628
+			return true;
629
+		}
630
+		foreach ($this->_validation_strategies as $validation_strategy) {
631
+			if ($validation_strategy instanceof EE_Validation_Strategy_Base) {
632
+				try {
633
+					$validation_strategy->validate($this->normalized_value());
634
+				} catch (EE_Validation_Error $e) {
635
+					$this->add_validation_error($e);
636
+				}
637
+			}
638
+		}
639
+		if ($this->get_validation_errors()) {
640
+			return false;
641
+		} else {
642
+			return true;
643
+		}
644
+	}
645
+
646
+
647
+	/**
648
+	 * Performs basic sanitization on this value. But what sanitization can be performed anyways?
649
+	 * This value MIGHT be allowed to have tags, so we can't really remove them.
650
+	 *
651
+	 * @param string $value
652
+	 * @return null|string
653
+	 */
654
+	protected function _sanitize($value)
655
+	{
656
+		return $value !== null
657
+			? stripslashes(html_entity_decode(trim((string) $value)))
658
+			: null;
659
+	}
660
+
661
+
662
+	/**
663
+	 * Picks out the form value that relates to this form input,
664
+	 * and stores it as the sanitized value on the form input, and sets the normalized value.
665
+	 * Returns whether or not any validation errors occurred
666
+	 *
667
+	 * @param array $req_data
668
+	 * @return boolean whether or not there was an error
669
+	 * @throws EE_Error
670
+	 */
671
+	protected function _normalize($req_data)
672
+	{
673
+		// any existing validation errors don't apply so clear them
674
+		$this->_validation_errors = [];
675
+		// if the input is disabled, ignore whatever input was sent in
676
+		if ($this->isDisabled()) {
677
+			$this->_set_raw_value(null);
678
+			$this->_set_normalized_value($this->get_default());
679
+			return false;
680
+		}
681
+		try {
682
+			$raw_input = $this->find_form_data_for_this_section($req_data);
683
+			// super simple sanitization for now
684
+			if (is_array($raw_input)) {
685
+				$raw_value = [];
686
+				foreach ($raw_input as $key => $value) {
687
+					$raw_value[ $key ] = $this->_sanitize($value);
688
+				}
689
+				$this->_set_raw_value($raw_value);
690
+			} else {
691
+				$this->_set_raw_value($this->_sanitize($raw_input));
692
+			}
693
+			// we want to mostly leave the input alone in case we need to re-display it to the user
694
+			$this->_set_normalized_value($this->_normalization_strategy->normalize($this->raw_value()));
695
+			return false;
696
+		} catch (EE_Validation_Error $e) {
697
+			$this->add_validation_error($e);
698
+			return true;
699
+		}
700
+	}
701
+
702
+
703
+	/**
704
+	 * @return string
705
+	 * @throws EE_Error
706
+	 */
707
+	public function html_name()
708
+	{
709
+		$this->_set_default_html_name_if_empty();
710
+		return $this->_html_name ?? '';
711
+	}
712
+
713
+
714
+	/**
715
+	 * @param string $html_label_id
716
+	 */
717
+	public function set_html_label_id(string $html_label_id)
718
+	{
719
+		// if the html_label_id doesn't end in -lbl, then add it
720
+		if (strpos($html_label_id, '-lbl') !== (strlen($html_label_id) - 4)) {
721
+			$html_label_id .= '-lbl';
722
+		}
723
+		$this->_html_label_id = $html_label_id;
724
+	}
725
+
726
+
727
+	/**
728
+	 * @return string
729
+	 * @throws EE_Error
730
+	 */
731
+	public function html_label_id()
732
+	{
733
+		if (empty($this->_html_label_id)) {
734
+			$this->set_html_label_id($this->html_id());
735
+		}
736
+		return $this->_html_label_id;
737
+	}
738
+
739
+
740
+	/**
741
+	 * @return string
742
+	 */
743
+	public function html_label_class()
744
+	{
745
+		return $this->_html_label_class ?? '';
746
+	}
747
+
748
+
749
+	/**
750
+	 * @param string $html_class
751
+	 */
752
+	public function add_html_label_class(string $html_class)
753
+	{
754
+		$this->_html_label_class .= ' ' . trim($html_class);
755
+	}
756
+
757
+
758
+	/**
759
+	 * @return string
760
+	 */
761
+	public function html_label_style()
762
+	{
763
+		return $this->_html_label_style ?? '';
764
+	}
765
+
766
+
767
+	/**
768
+	 * @return string
769
+	 */
770
+	public function html_label_text()
771
+	{
772
+		return $this->_html_label_text ?? '';
773
+	}
774
+
775
+
776
+	/**
777
+	 * @return string
778
+	 */
779
+	public function html_help_text()
780
+	{
781
+		return $this->_html_help_text ?? '';
782
+	}
783
+
784
+
785
+	/**
786
+	 * @return string
787
+	 */
788
+	public function html_help_class()
789
+	{
790
+		return $this->_html_help_class ?? '';
791
+	}
792
+
793
+
794
+	/**
795
+	 * @return string
796
+	 */
797
+	public function html_help_style()
798
+	{
799
+		return $this->_html_style ?? '';
800
+	}
801
+
802
+
803
+	/**
804
+	 * returns the raw, UNSAFE, input, almost exactly as the user submitted it.
805
+	 * Please note that almost all client code should instead use the normalized_value;
806
+	 * or possibly raw_value_in_form (which prepares the string for displaying in an HTML attribute on a tag,
807
+	 * mostly by escaping quotes)
808
+	 * Note, we do not store the exact original value sent in the user's request because
809
+	 * it may have malicious content, and we MIGHT want to store the form input in a transient or something...
810
+	 * in which case, we would have stored the malicious content to our database.
811
+	 *
812
+	 * @return mixed
813
+	 */
814
+	public function raw_value()
815
+	{
816
+		return $this->_raw_value;
817
+	}
818
+
819
+
820
+	/**
821
+	 * Returns a string safe to usage in form inputs when displaying, because
822
+	 * it escapes all html entities
823
+	 *
824
+	 * @return string
825
+	 */
826
+	public function raw_value_in_form(): string
827
+	{
828
+		return htmlentities((string) $this->raw_value(), ENT_QUOTES, 'UTF-8');
829
+	}
830
+
831
+
832
+	/**
833
+	 * returns the value after it's been sanitized, and then converted into it's proper type
834
+	 * in PHP. Eg, a string, an int, an array,
835
+	 *
836
+	 * @return mixed
837
+	 */
838
+	public function normalized_value()
839
+	{
840
+		return $this->_normalized_value;
841
+	}
842
+
843
+
844
+	/**
845
+	 * Returns the normalized value is a presentable way. By default this is just
846
+	 * the normalized value by itself, but it can be overridden for when that's not
847
+	 * the best thing to display
848
+	 *
849
+	 * @return mixed
850
+	 */
851
+	public function pretty_value()
852
+	{
853
+		return $this->_normalized_value;
854
+	}
855
+
856
+
857
+	/**
858
+	 * When generating the JS for the jquery validation rules like<br>
859
+	 * <code>$( "#myform" ).validate({
860
+	 * rules: {
861
+	 * password: "required",
862
+	 * password_again: {
863
+	 * equalTo: "#password"
864
+	 * }
865
+	 * }
866
+	 * });</code>
867
+	 * if this field had the name 'password_again', it should return
868
+	 * <br><code>password_again: {
869
+	 * equalTo: "#password"
870
+	 * }</code>
871
+	 *
872
+	 * @return array
873
+	 * @throws EE_Error
874
+	 */
875
+	public function get_jquery_validation_rules(): array
876
+	{
877
+		$jquery_validation_js    = [];
878
+		$jquery_validation_rules = [];
879
+		foreach ($this->get_validation_strategies() as $validation_strategy) {
880
+			$jquery_validation_rules = array_replace_recursive(
881
+				$jquery_validation_rules,
882
+				$validation_strategy->get_jquery_validation_rule_array()
883
+			);
884
+		}
885
+		if (! empty($jquery_validation_rules)) {
886
+			foreach ($this->get_display_strategy()->get_html_input_ids(true) as $html_id_with_pound_sign) {
887
+				$jquery_validation_js[ $html_id_with_pound_sign ] = $jquery_validation_rules;
888
+			}
889
+		}
890
+		return $jquery_validation_js;
891
+	}
892
+
893
+
894
+	/**
895
+	 * Sets the input's default value for use in displaying in the form. Note: value should be
896
+	 * normalized (Eg, if providing a default of ra Yes_NO_Input you would provide TRUE or FALSE, not '1' or '0')
897
+	 *
898
+	 * @param mixed $value
899
+	 * @return void
900
+	 */
901
+	public function set_default($value)
902
+	{
903
+		$this->_default = $value;
904
+		$this->_set_normalized_value($value);
905
+		$this->_set_raw_value($value);
906
+	}
907
+
908
+
909
+	/**
910
+	 * Sets the normalized value on this input
911
+	 *
912
+	 * @param mixed $value
913
+	 */
914
+	protected function _set_normalized_value($value)
915
+	{
916
+		$this->_normalized_value = $value;
917
+	}
918
+
919
+
920
+	/**
921
+	 * Sets the raw value on this input (ie, exactly as the user submitted it)
922
+	 *
923
+	 * @param mixed $value
924
+	 */
925
+	protected function _set_raw_value($value)
926
+	{
927
+		$this->_raw_value = $this->_normalization_strategy->unnormalize($value);
928
+	}
929
+
930
+
931
+	/**
932
+	 * Sets the HTML label text after it has already been defined
933
+	 *
934
+	 * @param string $label
935
+	 * @return void
936
+	 */
937
+	public function set_html_label_text($label)
938
+	{
939
+		$this->_html_label_text = $label;
940
+	}
941
+
942
+
943
+	/**
944
+	 * Sets whether or not this field is required, and adjusts the validation strategy.
945
+	 * If you want to use the EE_Conditionally_Required_Validation_Strategy,
946
+	 * please add it as a validation strategy using add_validation_strategy as normal
947
+	 *
948
+	 * @param boolean $required boolean
949
+	 * @param null    $required_text
950
+	 */
951
+	public function set_required($required = true, $required_text = null)
952
+	{
953
+		$required = filter_var($required, FILTER_VALIDATE_BOOLEAN);
954
+		// whether $required is a string or a boolean, we want to add a required validation strategy
955
+		if ($required) {
956
+			$this->_add_validation_strategy(new EE_Required_Validation_Strategy($required_text));
957
+		} else {
958
+			$this->remove_validation_strategy('EE_Required_Validation_Strategy');
959
+		}
960
+		$this->_required = $required;
961
+	}
962
+
963
+
964
+	/**
965
+	 * Returns whether or not this field is required
966
+	 *
967
+	 * @return boolean
968
+	 */
969
+	public function required()
970
+	{
971
+		return $this->_required;
972
+	}
973
+
974
+
975
+	/**
976
+	 * @param string $required_css_class
977
+	 */
978
+	public function set_required_css_class($required_css_class)
979
+	{
980
+		$this->_required_css_class = $required_css_class;
981
+	}
982
+
983
+
984
+	/**
985
+	 * @return string
986
+	 */
987
+	public function required_css_class()
988
+	{
989
+		return $this->_required_css_class;
990
+	}
991
+
992
+
993
+	/**
994
+	 * @param bool $add_required
995
+	 * @return string
996
+	 */
997
+	public function html_class($add_required = false)
998
+	{
999
+		return $add_required && $this->required()
1000
+			? $this->required_css_class() . ' ' . $this->_html_class
1001
+			: $this->_html_class;
1002
+	}
1003
+
1004
+
1005
+	/**
1006
+	 * Sets the help text, in case
1007
+	 *
1008
+	 * @param string $text
1009
+	 */
1010
+	public function set_html_help_text($text)
1011
+	{
1012
+		$this->_html_help_text = $text;
1013
+	}
1014
+
1015
+
1016
+	/**
1017
+	 * Uses the sensitive data removal strategy to remove the sensitive data from this
1018
+	 * input. If there is any kind of sensitive data removal on this input, we clear
1019
+	 * out the raw value completely
1020
+	 *
1021
+	 * @return void
1022
+	 */
1023
+	public function clean_sensitive_data()
1024
+	{
1025
+		// if we do ANY kind of sensitive data removal on this, then just clear out the raw value
1026
+		// if we need more logic than this we'll make a strategy for it
1027
+		if (
1028
+			$this->_sensitive_data_removal_strategy
1029
+			&& ! $this->_sensitive_data_removal_strategy instanceof EE_No_Sensitive_Data_Removal
1030
+		) {
1031
+			$this->_set_raw_value(null);
1032
+		}
1033
+		// and clean the normalized value according to the appropriate strategy
1034
+		$this->_set_normalized_value(
1035
+			$this->get_sensitive_data_removal_strategy()->remove_sensitive_data(
1036
+				$this->_normalized_value
1037
+			)
1038
+		);
1039
+	}
1040
+
1041
+
1042
+	/**
1043
+	 * @param bool   $primary
1044
+	 * @param string $button_size
1045
+	 * @param string $other_attributes
1046
+	 */
1047
+	public function set_button_css_attributes($primary = true, $button_size = '', $other_attributes = '')
1048
+	{
1049
+		$button_css_attributes = 'button';
1050
+		$button_css_attributes .= $primary === true
1051
+			? ' button--primary'
1052
+			: ' button--secondary';
1053
+		switch ($button_size) {
1054
+			case 'xs':
1055
+			case 'extra-small':
1056
+				$button_css_attributes .= ' button-xs';
1057
+				break;
1058
+			case 'sm':
1059
+			case 'small':
1060
+				$button_css_attributes .= ' button-sm';
1061
+				break;
1062
+			case 'lg':
1063
+			case 'large':
1064
+				$button_css_attributes .= ' button-lg';
1065
+				break;
1066
+			case 'block':
1067
+				$button_css_attributes .= ' button-block';
1068
+				break;
1069
+			case 'md':
1070
+			case 'medium':
1071
+			default:
1072
+				$button_css_attributes .= '';
1073
+		}
1074
+		$this->_button_css_attributes .= ! empty($other_attributes)
1075
+			? $button_css_attributes . ' ' . $other_attributes
1076
+			: $button_css_attributes;
1077
+	}
1078
+
1079
+
1080
+	/**
1081
+	 * @return string
1082
+	 */
1083
+	public function button_css_attributes()
1084
+	{
1085
+		if (empty($this->_button_css_attributes)) {
1086
+			$this->set_button_css_attributes();
1087
+		}
1088
+		return $this->_button_css_attributes;
1089
+	}
1090
+
1091
+
1092
+	/**
1093
+	 * find_form_data_for_this_section
1094
+	 * using this section's name and its parents, finds the value of the form data that corresponds to it.
1095
+	 * For example, if this form section's HTML name is my_form[subform][form_input_1],
1096
+	 * then it's value should be in request at request['my_form']['subform']['form_input_1'].
1097
+	 * (If that doesn't exist, we also check for this subsection's name
1098
+	 * at the TOP LEVEL of the request data. Eg request['form_input_1'].)
1099
+	 * This function finds its value in the form.
1100
+	 *
1101
+	 * @param array $req_data
1102
+	 * @return mixed whatever the raw value of this form section is in the request data
1103
+	 * @throws EE_Error
1104
+	 */
1105
+	public function find_form_data_for_this_section($req_data)
1106
+	{
1107
+		$name_parts = $this->getInputNameParts();
1108
+		// now get the value for the input
1109
+		$value = $this->findRequestForSectionUsingNameParts($name_parts, $req_data);
1110
+		// check if this thing's name is at the TOP level of the request data
1111
+		if ($value === null && isset($req_data[ $this->name() ])) {
1112
+			$value = $req_data[ $this->name() ];
1113
+		}
1114
+		return $value;
1115
+	}
1116
+
1117
+
1118
+	/**
1119
+	 * If this input's name is something like "foo[bar][baz]"
1120
+	 * returns an array like `array('foo','bar',baz')`
1121
+	 *
1122
+	 * @return array
1123
+	 * @throws EE_Error
1124
+	 */
1125
+	protected function getInputNameParts()
1126
+	{
1127
+		// break up the html name by "[]"
1128
+		if (strpos($this->html_name(), '[') !== false) {
1129
+			$before_any_brackets = substr($this->html_name(), 0, strpos($this->html_name(), '['));
1130
+		} else {
1131
+			$before_any_brackets = $this->html_name();
1132
+		}
1133
+		// grab all of the segments
1134
+		preg_match_all('~\[([^]]*)\]~', $this->html_name(), $matches);
1135
+		if (isset($matches[1]) && is_array($matches[1])) {
1136
+			$name_parts = $matches[1];
1137
+			array_unshift($name_parts, $before_any_brackets);
1138
+		} else {
1139
+			$name_parts = [$before_any_brackets];
1140
+		}
1141
+		return $name_parts;
1142
+	}
1143
+
1144
+
1145
+	/**
1146
+	 * @param array $html_name_parts
1147
+	 * @param array $req_data
1148
+	 * @return array | NULL
1149
+	 */
1150
+	public function findRequestForSectionUsingNameParts($html_name_parts, $req_data)
1151
+	{
1152
+		$first_part_to_consider = array_shift($html_name_parts);
1153
+		if (isset($req_data[ $first_part_to_consider ])) {
1154
+			if (empty($html_name_parts)) {
1155
+				return $req_data[ $first_part_to_consider ];
1156
+			} else {
1157
+				return $this->findRequestForSectionUsingNameParts(
1158
+					$html_name_parts,
1159
+					$req_data[ $first_part_to_consider ]
1160
+				);
1161
+			}
1162
+		}
1163
+		return null;
1164
+	}
1165
+
1166
+
1167
+	/**
1168
+	 * Checks if this form input's data is in the request data
1169
+	 *
1170
+	 * @param array $req_data
1171
+	 * @return boolean
1172
+	 * @throws EE_Error
1173
+	 */
1174
+	public function form_data_present_in($req_data = null)
1175
+	{
1176
+		if ($req_data === null) {
1177
+			/** @var RequestInterface $request */
1178
+			$request  = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1179
+			$req_data = $request->postParams();
1180
+		}
1181
+
1182
+		return $this->find_form_data_for_this_section($req_data) !== null;
1183
+	}
1184
+
1185
+
1186
+	/**
1187
+	 * Overrides parent to add js data from validation and display strategies
1188
+	 *
1189
+	 * @param array $form_other_js_data
1190
+	 * @return array
1191
+	 */
1192
+	public function get_other_js_data($form_other_js_data = [])
1193
+	{
1194
+		return $this->get_other_js_data_from_strategies($form_other_js_data);
1195
+	}
1196
+
1197
+
1198
+	/**
1199
+	 * Gets other JS data for localization from this input's strategies, like
1200
+	 * the validation strategies and the display strategy
1201
+	 *
1202
+	 * @param array $form_other_js_data
1203
+	 * @return array
1204
+	 */
1205
+	public function get_other_js_data_from_strategies($form_other_js_data = [])
1206
+	{
1207
+		$form_other_js_data = $this->get_display_strategy()->get_other_js_data($form_other_js_data);
1208
+		foreach ($this->get_validation_strategies() as $validation_strategy) {
1209
+			$form_other_js_data = $validation_strategy->get_other_js_data($form_other_js_data);
1210
+		}
1211
+		return $form_other_js_data;
1212
+	}
1213
+
1214
+
1215
+	/**
1216
+	 * Override parent because we want to give our strategies an opportunity to enqueue some js and css
1217
+	 *
1218
+	 * @return void
1219
+	 */
1220
+	public function enqueue_js()
1221
+	{
1222
+		// ask our display strategy and validation strategies if they have js to enqueue
1223
+		$this->enqueue_js_from_strategies();
1224
+	}
1225
+
1226
+
1227
+	/**
1228
+	 * Tells strategies when its ok to enqueue their js and css
1229
+	 *
1230
+	 * @return void
1231
+	 */
1232
+	public function enqueue_js_from_strategies()
1233
+	{
1234
+		$this->get_display_strategy()->enqueue_js();
1235
+		foreach ($this->get_validation_strategies() as $validation_strategy) {
1236
+			$validation_strategy->enqueue_js();
1237
+		}
1238
+	}
1239
+
1240
+
1241
+	/**
1242
+	 * Gets the default value set on the input (not the current value, which may have been
1243
+	 * changed because of a form submission). If no default was set, this us null.
1244
+	 *
1245
+	 * @return mixed
1246
+	 */
1247
+	public function get_default()
1248
+	{
1249
+		return $this->_default;
1250
+	}
1251
+
1252
+
1253
+	/**
1254
+	 * Makes this input disabled. That means it will have the HTML attribute 'disabled="disabled"',
1255
+	 * and server-side if any input was received it will be ignored
1256
+	 */
1257
+	public function disable($disable = true)
1258
+	{
1259
+		$disabled_attribute = ' disabled="disabled"';
1260
+		$this->disabled     = filter_var($disable, FILTER_VALIDATE_BOOLEAN);
1261
+		if ($this->disabled) {
1262
+			if (strpos($this->_other_html_attributes, $disabled_attribute) === false) {
1263
+				$this->_other_html_attributes .= $disabled_attribute;
1264
+			}
1265
+			$this->_set_normalized_value($this->get_default());
1266
+		} else {
1267
+			$this->_other_html_attributes = str_replace($disabled_attribute, '', $this->_other_html_attributes);
1268
+		}
1269
+	}
1270
+
1271
+
1272
+	/**
1273
+	 * Returns whether this input is currently disabled.
1274
+	 *
1275
+	 * @return bool
1276
+	 */
1277
+	public function isDisabled(): bool
1278
+	{
1279
+		return $this->disabled;
1280
+	}
1281
+
1282
+
1283
+	public function dataAttributes(): array
1284
+	{
1285
+		return $this->_data_attributes;
1286
+	}
1287
+
1288
+
1289
+	public function layoutContainerClass(): string
1290
+	{
1291
+		return $this->_layout_container_class;
1292
+	}
1293
+
1294
+
1295
+	public function extraContainerHtml(): string
1296
+	{
1297
+		return $this->_extra_container_html;
1298
+	}
1299
+
1300
+
1301
+	public function hasLabel(): bool
1302
+	{
1303
+		return ! $this->_no_label
1304
+			&& $this->html_label_text()
1305
+			&& ! $this->get_display_strategy() instanceof EE_Hidden_Display_Strategy;
1306
+	}
1307 1307
 }
Please login to merge, or discard this patch.
Spacing   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -219,7 +219,7 @@  discard block
 block discarded – undo
219 219
         if (isset($input_args['validation_strategies'])) {
220 220
             foreach ((array) $input_args['validation_strategies'] as $validation_strategy) {
221 221
                 if ($validation_strategy instanceof EE_Validation_Strategy_Base && empty($input_args['ignore_input'])) {
222
-                    $this->_validation_strategies[ get_class($validation_strategy) ] = $validation_strategy;
222
+                    $this->_validation_strategies[get_class($validation_strategy)] = $validation_strategy;
223 223
                 }
224 224
             }
225 225
             unset($input_args['validation_strategies']);
@@ -233,17 +233,17 @@  discard block
 block discarded – undo
233 233
                 $this->disable($value);
234 234
                 continue;
235 235
             }
236
-            $setter = 'set_' . $key;
236
+            $setter = 'set_'.$key;
237 237
             if (method_exists($this, $setter)) {
238 238
                 $this->$setter($value);
239
-                unset($input_args[ $key ]);
239
+                unset($input_args[$key]);
240 240
                 continue;
241 241
             }
242 242
             // add underscore to $key to match property names
243 243
             $_key = "_$key";
244 244
             if (property_exists($this, $_key)) {
245 245
                 $this->{$_key} = $value;
246
-                unset($input_args[ $key ]);
246
+                unset($input_args[$key]);
247 247
             }
248 248
         }
249 249
         // ensure that "required" is set correctly
@@ -259,7 +259,7 @@  discard block
 block discarded – undo
259 259
         if (isset($input_args['ignore_input'])) {
260 260
             $this->_normalization_strategy = new EE_Null_Normalization();
261 261
         }
262
-        if (! $this->_normalization_strategy) {
262
+        if ( ! $this->_normalization_strategy) {
263 263
             $this->_normalization_strategy = new EE_Text_Normalization();
264 264
         }
265 265
         $this->_normalization_strategy->_construct_finalize($this);
@@ -268,7 +268,7 @@  discard block
 block discarded – undo
268 268
             $this->set_default($input_args['default']);
269 269
             unset($input_args['default']);
270 270
         }
271
-        if (! $this->_sensitive_data_removal_strategy) {
271
+        if ( ! $this->_sensitive_data_removal_strategy) {
272 272
             $this->_sensitive_data_removal_strategy = new EE_No_Sensitive_Data_Removal();
273 273
         }
274 274
         $this->_sensitive_data_removal_strategy->_construct_finalize($this);
@@ -284,10 +284,10 @@  discard block
 block discarded – undo
284 284
      */
285 285
     protected function _set_default_html_name_if_empty()
286 286
     {
287
-        if (! $this->_html_name) {
287
+        if ( ! $this->_html_name) {
288 288
             $this->_html_name = $this->name();
289 289
             if ($this->_parent_section instanceof EE_Form_Section_Proper) {
290
-                $this->_html_name = $this->_parent_section->html_name_prefix() . "[{$this->name()}]";
290
+                $this->_html_name = $this->_parent_section->html_name_prefix()."[{$this->name()}]";
291 291
             }
292 292
         }
293 293
     }
@@ -317,7 +317,7 @@  discard block
 block discarded – undo
317 317
     protected function _get_display_strategy()
318 318
     {
319 319
         $this->ensure_construct_finalized_called();
320
-        if (! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
320
+        if ( ! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
321 321
             throw new EE_Error(
322 322
                 sprintf(
323 323
                     esc_html__(
@@ -473,7 +473,7 @@  discard block
 block discarded – undo
473 473
                 $validation_strategy instanceof $validation_strategy_classname
474 474
                 || is_subclass_of($validation_strategy, $validation_strategy_classname)
475 475
             ) {
476
-                unset($this->_validation_strategies[ $key ]);
476
+                unset($this->_validation_strategies[$key]);
477 477
             }
478 478
         }
479 479
     }
@@ -684,7 +684,7 @@  discard block
 block discarded – undo
684 684
             if (is_array($raw_input)) {
685 685
                 $raw_value = [];
686 686
                 foreach ($raw_input as $key => $value) {
687
-                    $raw_value[ $key ] = $this->_sanitize($value);
687
+                    $raw_value[$key] = $this->_sanitize($value);
688 688
                 }
689 689
                 $this->_set_raw_value($raw_value);
690 690
             } else {
@@ -751,7 +751,7 @@  discard block
 block discarded – undo
751 751
      */
752 752
     public function add_html_label_class(string $html_class)
753 753
     {
754
-        $this->_html_label_class .= ' ' . trim($html_class);
754
+        $this->_html_label_class .= ' '.trim($html_class);
755 755
     }
756 756
 
757 757
 
@@ -882,9 +882,9 @@  discard block
 block discarded – undo
882 882
                 $validation_strategy->get_jquery_validation_rule_array()
883 883
             );
884 884
         }
885
-        if (! empty($jquery_validation_rules)) {
885
+        if ( ! empty($jquery_validation_rules)) {
886 886
             foreach ($this->get_display_strategy()->get_html_input_ids(true) as $html_id_with_pound_sign) {
887
-                $jquery_validation_js[ $html_id_with_pound_sign ] = $jquery_validation_rules;
887
+                $jquery_validation_js[$html_id_with_pound_sign] = $jquery_validation_rules;
888 888
             }
889 889
         }
890 890
         return $jquery_validation_js;
@@ -997,7 +997,7 @@  discard block
 block discarded – undo
997 997
     public function html_class($add_required = false)
998 998
     {
999 999
         return $add_required && $this->required()
1000
-            ? $this->required_css_class() . ' ' . $this->_html_class
1000
+            ? $this->required_css_class().' '.$this->_html_class
1001 1001
             : $this->_html_class;
1002 1002
     }
1003 1003
 
@@ -1072,7 +1072,7 @@  discard block
 block discarded – undo
1072 1072
                 $button_css_attributes .= '';
1073 1073
         }
1074 1074
         $this->_button_css_attributes .= ! empty($other_attributes)
1075
-            ? $button_css_attributes . ' ' . $other_attributes
1075
+            ? $button_css_attributes.' '.$other_attributes
1076 1076
             : $button_css_attributes;
1077 1077
     }
1078 1078
 
@@ -1108,8 +1108,8 @@  discard block
 block discarded – undo
1108 1108
         // now get the value for the input
1109 1109
         $value = $this->findRequestForSectionUsingNameParts($name_parts, $req_data);
1110 1110
         // check if this thing's name is at the TOP level of the request data
1111
-        if ($value === null && isset($req_data[ $this->name() ])) {
1112
-            $value = $req_data[ $this->name() ];
1111
+        if ($value === null && isset($req_data[$this->name()])) {
1112
+            $value = $req_data[$this->name()];
1113 1113
         }
1114 1114
         return $value;
1115 1115
     }
@@ -1150,13 +1150,13 @@  discard block
 block discarded – undo
1150 1150
     public function findRequestForSectionUsingNameParts($html_name_parts, $req_data)
1151 1151
     {
1152 1152
         $first_part_to_consider = array_shift($html_name_parts);
1153
-        if (isset($req_data[ $first_part_to_consider ])) {
1153
+        if (isset($req_data[$first_part_to_consider])) {
1154 1154
             if (empty($html_name_parts)) {
1155
-                return $req_data[ $first_part_to_consider ];
1155
+                return $req_data[$first_part_to_consider];
1156 1156
             } else {
1157 1157
                 return $this->findRequestForSectionUsingNameParts(
1158 1158
                     $html_name_parts,
1159
-                    $req_data[ $first_part_to_consider ]
1159
+                    $req_data[$first_part_to_consider]
1160 1160
                 );
1161 1161
             }
1162 1162
         }
Please login to merge, or discard this patch.
core/helpers/EEH_Template.helper.php 2 patches
Indentation   +957 added lines, -957 removed lines patch added patch discarded remove patch
@@ -9,36 +9,36 @@  discard block
 block discarded – undo
9 9
 use EventEspresso\core\services\request\sanitizers\AllowedTags;
10 10
 
11 11
 if (! function_exists('espresso_get_template_part')) {
12
-    /**
13
-     * espresso_get_template_part
14
-     * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead, and doesn't add base versions of files
15
-     * so not a very useful function at all except that it adds familiarity PLUS filtering based off of the entire template part name
16
-     *
17
-     * @param string $slug The slug name for the generic template.
18
-     * @param string $name The name of the specialised template.
19
-     */
20
-    function espresso_get_template_part($slug = '', $name = '')
21
-    {
22
-        EEH_Template::get_template_part($slug, $name);
23
-    }
12
+	/**
13
+	 * espresso_get_template_part
14
+	 * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead, and doesn't add base versions of files
15
+	 * so not a very useful function at all except that it adds familiarity PLUS filtering based off of the entire template part name
16
+	 *
17
+	 * @param string $slug The slug name for the generic template.
18
+	 * @param string $name The name of the specialised template.
19
+	 */
20
+	function espresso_get_template_part($slug = '', $name = '')
21
+	{
22
+		EEH_Template::get_template_part($slug, $name);
23
+	}
24 24
 }
25 25
 
26 26
 
27 27
 if (! function_exists('espresso_get_object_css_class')) {
28
-    /**
29
-     * espresso_get_object_css_class - attempts to generate a css class based on the type of EE object passed
30
-     *
31
-     * @param EE_Base_Class $object the EE object the css class is being generated for
32
-     * @param string        $prefix added to the beginning of the generated class
33
-     * @param string        $suffix added to the end of the generated class
34
-     * @return string
35
-     * @throws EE_Error
36
-     * @throws ReflectionException
37
-     */
38
-    function espresso_get_object_css_class($object = null, $prefix = '', $suffix = '')
39
-    {
40
-        return EEH_Template::get_object_css_class($object, $prefix, $suffix);
41
-    }
28
+	/**
29
+	 * espresso_get_object_css_class - attempts to generate a css class based on the type of EE object passed
30
+	 *
31
+	 * @param EE_Base_Class $object the EE object the css class is being generated for
32
+	 * @param string        $prefix added to the beginning of the generated class
33
+	 * @param string        $suffix added to the end of the generated class
34
+	 * @return string
35
+	 * @throws EE_Error
36
+	 * @throws ReflectionException
37
+	 */
38
+	function espresso_get_object_css_class($object = null, $prefix = '', $suffix = '')
39
+	{
40
+		return EEH_Template::get_object_css_class($object, $prefix, $suffix);
41
+	}
42 42
 }
43 43
 
44 44
 
@@ -52,665 +52,665 @@  discard block
 block discarded – undo
52 52
  */
53 53
 class EEH_Template
54 54
 {
55
-    private static array $_espresso_themes = [];
56
-
57
-
58
-    /**
59
-     *    is_espresso_theme - returns TRUE or FALSE on whether the currently active WP theme is an espresso theme
60
-     *
61
-     * @return boolean
62
-     */
63
-    public static function is_espresso_theme()
64
-    {
65
-        return wp_get_theme()->get('TextDomain') === 'event_espresso';
66
-    }
67
-
68
-
69
-    /**
70
-     *    load_espresso_theme_functions - if current theme is an espresso theme, or uses ee theme template parts, then
71
-     *    load its functions.php file ( if not already loaded )
72
-     *
73
-     * @return void
74
-     */
75
-    public static function load_espresso_theme_functions()
76
-    {
77
-        if (! defined('EE_THEME_FUNCTIONS_LOADED')) {
78
-            if (is_readable(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php')) {
79
-                require_once(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php');
80
-            }
81
-        }
82
-    }
83
-
84
-
85
-    /**
86
-     *    get_espresso_themes - returns an array of Espresso Child themes located in the /templates/ directory
87
-     *
88
-     * @return array
89
-     */
90
-    public static function get_espresso_themes(): array
91
-    {
92
-        if (empty(EEH_Template::$_espresso_themes)) {
93
-            $espresso_themes = glob(EE_PUBLIC . '*', GLOB_ONLYDIR);
94
-            if (empty($espresso_themes)) {
95
-                return [];
96
-            }
97
-            if (($key = array_search('global_assets', $espresso_themes)) !== false) {
98
-                unset($espresso_themes[ $key ]);
99
-            }
100
-            EEH_Template::$_espresso_themes = [];
101
-            foreach ($espresso_themes as $espresso_theme) {
102
-                EEH_Template::$_espresso_themes[ basename($espresso_theme) ] = $espresso_theme;
103
-            }
104
-        }
105
-        return EEH_Template::$_espresso_themes;
106
-    }
107
-
108
-
109
-    /**
110
-     * EEH_Template::get_template_part
111
-     * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead,
112
-     * and doesn't add base versions of files so not a very useful function at all except that it adds familiarity PLUS
113
-     * filtering based off of the entire template part name
114
-     *
115
-     * @param string $slug The slug name for the generic template.
116
-     * @param string $name The name of the specialised template.
117
-     * @param array  $template_args
118
-     * @param bool   $return_string
119
-     * @return string        the html output for the formatted money value
120
-     */
121
-    public static function get_template_part(
122
-        $slug = '',
123
-        $name = '',
124
-        $template_args = [],
125
-        $return_string = false
126
-    ) {
127
-        do_action("get_template_part_$slug-$name", $slug, $name);
128
-        $template = $slug;
129
-        $name      = (string) $name;
130
-        if ($name != '') {
131
-            $template .= "-$name";
132
-        }
133
-        $template .= ".php";
134
-        // allow template parts to be turned off via something like:
135
-        // add_filter( 'FHEE__content_espresso_events_tickets_template__display_datetimes', '__return_false' );
136
-        if (apply_filters("FHEE__EEH_Template__get_template_part__display__{$slug}_$name", true)) {
137
-            return EEH_Template::locate_template($template, $template_args, true, $return_string);
138
-        }
139
-        return '';
140
-    }
141
-
142
-
143
-    /**
144
-     *    locate_template
145
-     *    locate a template file by looking in the following places, in the following order:
146
-     *        <server path up to>/wp-content/themes/<current active WordPress theme>/
147
-     *        <assumed full absolute server path>
148
-     *        <server path up to>/wp-content/uploads/espresso/templates/<current EE theme>/
149
-     *        <server path up to>/wp-content/uploads/espresso/templates/
150
-     *        <server path up to>/wp-content/plugins/<EE4 folder>/public/<current EE theme>/
151
-     *        <server path up to>/wp-content/plugins/<EE4 folder>/core/templates/<current EE theme>/
152
-     *        <server path up to>/wp-content/plugins/<EE4 folder>/
153
-     *    as soon as the template is found in one of these locations, it will be returned or loaded
154
-     *        Example:
155
-     *          You are using the WordPress Twenty Sixteen theme,
156
-     *        and you want to customize the "some-event.template.php" template,
157
-     *          which is located in the "/relative/path/to/" folder relative to the main EE plugin folder.
158
-     *          Assuming WP is installed on your server in the "/home/public_html/" folder,
159
-     *        EEH_Template::locate_template() will look at the following paths in order until the template is found:
160
-     *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
161
-     *        /relative/path/to/some-event.template.php
162
-     *        /home/public_html/wp-content/uploads/espresso/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
163
-     *        /home/public_html/wp-content/uploads/espresso/templates/relative/path/to/some-event.template.php
164
-     *        /home/public_html/wp-content/plugins/event-espresso-core-reg/public/Espresso_Arabica_2014/relative/path/to/some-event.template.php
165
-     *        /home/public_html/wp-content/plugins/event-espresso-core-reg/core/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
166
-     *        /home/public_html/wp-content/plugins/event-espresso-core-reg/relative/path/to/some-event.template.php
167
-     *          Had you passed an absolute path to your template that was in some other location,
168
-     *        ie: "/absolute/path/to/some-event.template.php"
169
-     *          then the search would have been :
170
-     *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
171
-     *        /absolute/path/to/some-event.template.php
172
-     *          and stopped there upon finding it in the second location
173
-     *
174
-     * @param array|string $templates       array of template file names including extension (or just a single string)
175
-     * @param array        $template_args   an array of arguments to be extracted for use in the template
176
-     * @param boolean      $load            whether to pass the located template path on to the
177
-     *                                      EEH_Template::display_template() method or simply return it
178
-     * @param boolean      $return_string   whether to send output immediately to screen, or capture and return as a
179
-     *                                      string
180
-     * @param boolean      $check_if_custom If TRUE, this flags this method to return boolean for whether this will
181
-     *                                      generate a custom template or not. Used in places where you don't actually
182
-     *                                      load the template, you just want to know if there's a custom version of it.
183
-     * @return string|true
184
-     * @throws DomainException
185
-     * @throws InvalidArgumentException
186
-     * @throws InvalidDataTypeException
187
-     * @throws InvalidInterfaceException
188
-     */
189
-    public static function locate_template(
190
-        $templates = [],
191
-        array $template_args = [],
192
-        bool $load = true,
193
-        bool $return_string = true,
194
-        bool $check_if_custom = false
195
-    ) {
196
-        $cache_id      = TemplateCache::generateCacheID(__FUNCTION__, func_get_args());
197
-        $template_path = TemplateCache::get($cache_id);
198
-        $template_path = $template_path ?: self::resolveTemplatePath($cache_id, (array) $templates, $check_if_custom);
199
-
200
-        if ($check_if_custom && ! empty($template_path)) {
201
-            return true;
202
-        }
203
-
204
-        // if we got it and you want to see it...
205
-        if ($template_path && $load && ! $check_if_custom) {
206
-            if ($return_string) {
207
-                return EEH_Template::display_template($template_path, $template_args, true);
208
-            }
209
-            EEH_Template::display_template($template_path, $template_args);
210
-        }
211
-        return $check_if_custom && ! empty($template_path) ? true : $template_path;
212
-    }
213
-
214
-
215
-    /**
216
-     * Resolves the path of a template by checking various possible locations.
217
-     *
218
-     * This method checks for the existence of a template in several locations,
219
-     * including the current theme folder, the uploads directory, and the plugin's own template directory.
220
-     * It uses the provided cache ID to store and retrieve the resolved path from a cache for performance.
221
-     * If the template is not found in any of the checked locations, an empty string is returned.
222
-     *
223
-     * @param string $cache_id        The ID used for caching the resolved path.
224
-     * @param array  $templates       An array of template file names to search for.
225
-     * @param bool $check_if_custom   If true, the method will only check if a custom template exists
226
-     *                                and won't include core plugin folders.
227
-     * @return string The resolved template path, or an empty string if the template was not found.
228
-     * @since 5.0.21.p
229
-     */
230
-    private static function resolveTemplatePath(string $cache_id, array $templates, bool $check_if_custom): string
231
-    {
232
-        // first use WP locate_template to check for template in the current theme folder
233
-        $template_path = $templates ? locate_template($templates) : '';
234
-        // not in the theme
235
-        if (empty($template_path)) {
236
-            // not even a template to look for ?
237
-            if (empty($templates)) {
238
-                $loader = LoaderFactory::getLoader();
239
-                /** @var RequestInterface $request */
240
-                $request = $loader->getShared(RequestInterface::class);
241
-                // get post_type
242
-                $post_type = $request->getRequestParam('post_type');
243
-                /** @var CustomPostTypeDefinitions $custom_post_types */
244
-                $custom_post_types = $loader->getShared(CustomPostTypeDefinitions::class);
245
-                // get array of EE Custom Post Types
246
-                $EE_CPTs = $custom_post_types->getDefinitions();
247
-                // build template name based on request
248
-                if (isset($EE_CPTs[ $post_type ])) {
249
-                    $archive_or_single = is_archive() ? 'archive' : '';
250
-                    $archive_or_single = is_single() ? 'single' : $archive_or_single;
251
-                    $templates[]       = $archive_or_single . '-' . $post_type . '.php';
252
-                }
253
-            }
254
-            // currently active EE template theme
255
-            $current_theme = EE_Config::get_current_theme();
256
-            // array of paths to folders that may contain templates
257
-            $template_folder_paths = [];
258
-
259
-            // add core plugin folders for checking only if we're not $check_if_custom
260
-            if (! $check_if_custom) {
261
-                $core_paths            = [
262
-                    // in the  /wp-content/plugins/(EE4 folder)/public/(current EE theme)/ folder within the plugin
263
-                    EE_PUBLIC . $current_theme,
264
-                    // in the  /wp-content/plugins/(EE4 folder)/core/templates/(current EE theme)/ folder within the plugin
265
-                    EE_TEMPLATES . $current_theme,
266
-                    // or maybe relative from the plugin root: /wp-content/plugins/(EE4 folder)/
267
-                    EE_PLUGIN_DIR_PATH,
268
-                ];
269
-                $template_folder_paths = array_merge($template_folder_paths, $core_paths);
270
-            }
271
-
272
-            // now filter that array
273
-            $template_folder_paths = (array) apply_filters(
274
-                'FHEE__EEH_Template__locate_template__template_folder_paths',
275
-                $template_folder_paths
276
-            );
277
-
278
-            // array to hold all possible template paths
279
-            $full_template_paths = [];
280
-            $file_name           = '';
281
-
282
-            // loop through $templates
283
-            foreach ($templates as $template) {
284
-                // normalize directory separators
285
-                $template                      = EEH_File::standardise_directory_separators($template);
286
-                $file_name                     = basename($template);
287
-                $template_path_minus_file_name = substr($template, 0, (strlen($file_name) * -1));
288
-                // while looping through all template folder paths
289
-                foreach ($template_folder_paths as $template_folder_path) {
290
-                    // normalize directory separators
291
-                    $template_folder_path = EEH_File::standardise_directory_separators($template_folder_path);
292
-                    // determine if any common base path exists between the two paths
293
-                    $common_base_path = EEH_Template::_find_common_base_path(
294
-                        [$template_folder_path, $template_path_minus_file_name]
295
-                    );
296
-                    if ($common_base_path !== '') {
297
-                        // both paths have a common base, so just tack the filename onto our search path
298
-                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $file_name;
299
-                    } else {
300
-                        // no common base path, so let's just concatenate
301
-                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $template;
302
-                    }
303
-                    // build up our template locations array by adding our resolved paths
304
-                    $full_template_paths[] = $resolved_path;
305
-                }
306
-                // if $template is an absolute path, then we'll tack it onto the start of our array so that it gets searched first
307
-                array_unshift($full_template_paths, $template);
308
-                // path to the directory of the current theme: /wp-content/themes/(current WP theme)/
309
-                array_unshift($full_template_paths, get_stylesheet_directory() . '/' . $file_name);
310
-            }
311
-            // filter final array of full template paths
312
-            $full_template_paths = apply_filters(
313
-                'FHEE__EEH_Template__locate_template__full_template_paths',
314
-                $full_template_paths,
315
-                $file_name
316
-            );
317
-            // now loop through our final array of template location paths and check each location
318
-            foreach ((array) $full_template_paths as $full_template_path) {
319
-                if (is_readable($full_template_path)) {
320
-                    $template_path = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $full_template_path);
321
-                    TemplateCache::set($cache_id, $template_path);
322
-                    break;
323
-                }
324
-            }
325
-        }
326
-
327
-        // Display a deprecated notice if the template file is located in the WordPress uploads directory
328
-        if (strpos($template_path, 'wp-content/uploads/espresso') !== false) {
329
-            EE_Error::doing_it_wrong(
330
-                __CLASS__,
331
-                esc_html__(
332
-                    'The use of the WordPress uploads directory as a location to override template files has been deprecated.',
333
-                    'event_espresso'
334
-                ),
335
-                '5.0.0'
336
-            );
337
-        }
338
-
339
-        // hook that can be used to display the full template path that will be used
340
-        do_action('AHEE__EEH_Template__locate_template__full_template_path', $template_path);
341
-
342
-        return $template_path;
343
-    }
344
-
345
-
346
-    /**
347
-     * _find_common_base_path
348
-     * given two paths, this determines if there is a common base path between the two
349
-     *
350
-     * @param array $paths
351
-     * @return string
352
-     */
353
-    protected static function _find_common_base_path($paths)
354
-    {
355
-        $last_offset      = 0;
356
-        $common_base_path = '';
357
-        while (($index = strpos($paths[0], '/', $last_offset)) !== false) {
358
-            $dir_length = $index - $last_offset + 1;
359
-            $directory  = substr($paths[0], $last_offset, $dir_length);
360
-            foreach ($paths as $path) {
361
-                if (substr($path, $last_offset, $dir_length) != $directory) {
362
-                    return $common_base_path;
363
-                }
364
-            }
365
-            $common_base_path .= $directory;
366
-            $last_offset      = $index + 1;
367
-        }
368
-        return substr($common_base_path, 0, -1);
369
-    }
370
-
371
-
372
-    /**
373
-     * load and display a template
374
-     *
375
-     * @param bool|string $template_path    server path to the file to be loaded, including file name and extension
376
-     * @param array       $template_args    an array of arguments to be extracted for use in the template
377
-     * @param boolean     $return_string    whether to send output immediately to screen, or capture and return as a
378
-     *                                      string
379
-     * @param bool        $throw_exceptions if set to true, will throw an exception if the template is either
380
-     *                                      not found or is not readable
381
-     * @return string
382
-     * @throws DomainException
383
-     */
384
-    public static function display_template(
385
-        $template_path = '',
386
-        $template_args = [],
387
-        $return_string = false,
388
-        $throw_exceptions = false
389
-    ) {
390
-        /**
391
-         * These two filters are intended for last minute changes to templates being loaded and/or template arg
392
-         * modifications.  NOTE... modifying these things can cause breakage as most templates running through
393
-         * the display_template method are templates we DON'T want modified (usually because of js
394
-         * dependencies etc).  So unless you know what you are doing, do NOT filter templates or template args
395
-         * using this.
396
-         *
397
-         * @since 4.6.0
398
-         */
399
-        $template_path = (string) apply_filters('FHEE__EEH_Template__display_template__template_path', $template_path);
400
-        $template_args = (array) apply_filters(
401
-            'FHEE__EEH_Template__display_template__template_args',
402
-            $template_args,
403
-            $template_path
404
-        );
405
-
406
-        // you gimme nuttin - YOU GET NUTTIN !!
407
-        if (! $template_path || ! is_readable($template_path)) {
408
-            // ignore whether template is accessible ?
409
-            if ($throw_exceptions) {
410
-                throw new DomainException(
411
-                    esc_html__('Invalid, unreadable, or missing file.', 'event_espresso')
412
-                );
413
-            }
414
-            return '';
415
-        }
416
-
417
-        extract($template_args, EXTR_SKIP);
418
-        // because we might want to return a string, we are going to capture the output
419
-        ob_start();
420
-        include($template_path);
421
-        $template = ob_get_clean();
422
-
423
-        if ($return_string) {
424
-            return $template;
425
-        }
426
-        echo wp_kses($template, AllowedTags::getWithFullTags());
427
-        return '';
428
-    }
429
-
430
-
431
-    /**
432
-     * get_object_css_class - attempts to generate a css class based on the type of EE object passed
433
-     *
434
-     * @param EE_Base_Class $object the EE object the css class is being generated for
435
-     * @param string        $prefix added to the beginning of the generated class
436
-     * @param string        $suffix added to the end of the generated class
437
-     * @return string
438
-     * @throws EE_Error
439
-     * @throws ReflectionException
440
-     */
441
-    public static function get_object_css_class($object = null, $prefix = '', $suffix = '')
442
-    {
443
-        // in the beginning...
444
-        $prefix = ! empty($prefix) ? rtrim($prefix, '-') . '-' : '';
445
-        // da muddle
446
-        $class = '';
447
-        // the end
448
-        $suffix = ! empty($suffix) ? '-' . ltrim($suffix, '-') : '';
449
-        // is the passed object an EE object ?
450
-        if ($object instanceof EE_Base_Class) {
451
-            // grab the exact type of object
452
-            $obj_class = get_class($object);
453
-            // depending on the type of object...
454
-            // no specifics just yet...
455
-            $class = strtolower(str_replace('_', '-', $obj_class));
456
-            $class .= method_exists($obj_class, 'name') ? '-' . sanitize_title($object->name()) : '';
457
-        }
458
-        return $prefix . $class . $suffix;
459
-    }
460
-
461
-
462
-    /**
463
-     * EEH_Template::format_currency
464
-     * This helper takes a raw float value and formats it according to the default config country currency settings, or
465
-     * the country currency settings from the supplied country ISO code
466
-     *
467
-     * @param float   $amount       raw money value
468
-     * @param boolean $return_raw   whether to return the formatted float value only with no currency sign or code
469
-     * @param boolean $display_code whether to display the country code (USD). Default = TRUE
470
-     * @param string  $CNT_ISO      2-letter ISO code for a country
471
-     * @param string  $cur_code_span_class
472
-     * @return string        the html output for the formatted money value
473
-     */
474
-    public static function format_currency(
475
-        $amount = null,
476
-        $return_raw = false,
477
-        $display_code = true,
478
-        $CNT_ISO = '',
479
-        $cur_code_span_class = 'currency-code'
480
-    ) {
481
-        // ensure amount was received
482
-        if ($amount === null) {
483
-            $msg = esc_html__('In order to format currency, an amount needs to be passed.', 'event_espresso');
484
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
485
-            return '';
486
-        }
487
-        // ensure amount is float
488
-        $amount  = (float) apply_filters('FHEE__EEH_Template__format_currency__raw_amount', (float) $amount);
489
-        $CNT_ISO = apply_filters('FHEE__EEH_Template__format_currency__CNT_ISO', $CNT_ISO, $amount);
490
-        // filter raw amount (allows 0.00 to be changed to "free" for example)
491
-        $amount_formatted = apply_filters('FHEE__EEH_Template__format_currency__amount', $amount, $return_raw);
492
-        // still a number, or was amount converted to a string like "free" ?
493
-        if (! is_float($amount_formatted)) {
494
-            return esc_html($amount_formatted);
495
-        }
496
-        try {
497
-            // was a country ISO code passed ? if so generate currency config object for that country
498
-            $mny = $CNT_ISO !== '' ? new EE_Currency_Config($CNT_ISO) : null;
499
-        } catch (Exception $e) {
500
-            // eat exception
501
-            $mny = null;
502
-        }
503
-        // verify results
504
-        if (! $mny instanceof EE_Currency_Config) {
505
-            // set default config country currency settings
506
-            $mny = EE_Registry::instance()->CFG->currency instanceof EE_Currency_Config
507
-                ? EE_Registry::instance()->CFG->currency
508
-                : new EE_Currency_Config();
509
-        }
510
-        // format float
511
-        $amount_formatted = number_format($amount, $mny->dec_plc, $mny->dec_mrk, $mny->thsnds);
512
-        // add formatting ?
513
-        if (! $return_raw) {
514
-            // add currency sign
515
-            if ($mny->sign_b4) {
516
-                if ($amount >= 0) {
517
-                    $amount_formatted = $mny->sign . $amount_formatted;
518
-                } else {
519
-                    $amount_formatted = '-' . $mny->sign . str_replace('-', '', $amount_formatted);
520
-                }
521
-            } else {
522
-                $amount_formatted = $amount_formatted . $mny->sign;
523
-            }
524
-
525
-            // filter to allow global setting of display_code
526
-            $display_code = (bool) apply_filters(
527
-                'FHEE__EEH_Template__format_currency__display_code',
528
-                $display_code
529
-            );
530
-
531
-            // add currency code ?
532
-            $amount_formatted = $display_code
533
-                ? $amount_formatted . ' <span class="' . $cur_code_span_class . '">' . $mny->code . '</span>'
534
-                : $amount_formatted;
535
-        }
536
-        // filter results
537
-        $amount_formatted = apply_filters(
538
-            'FHEE__EEH_Template__format_currency__amount_formatted',
539
-            $amount_formatted,
540
-            $mny,
541
-            $return_raw
542
-        );
543
-        // clean up vars
544
-        unset($mny);
545
-        // return formatted currency amount
546
-        return $amount_formatted;
547
-    }
548
-
549
-
550
-    /**
551
-     * This function is used for outputting the localized label for a given status id in the schema requested (and
552
-     * possibly plural).  The intended use of this function is only for cases where wanting a label outside of a
553
-     * related status model or model object (i.e. in documentation etc.)
554
-     *
555
-     * @param string  $status_id  Status ID matching a registered status in the esp_status table.  If there is no
556
-     *                            match, then 'Unknown' will be returned.
557
-     * @param boolean $plural     Whether to return plural or not
558
-     * @param string  $schema     'UPPER', 'lower', or 'Sentence'
559
-     * @return string             The localized label for the status id.
560
-     * @throws EE_Error
561
-     */
562
-    public static function pretty_status($status_id, $plural = false, $schema = 'upper')
563
-    {
564
-        $status = EEM_Status::instance()->localized_status(
565
-            [$status_id => esc_html__('unknown', 'event_espresso')],
566
-            $plural,
567
-            $schema
568
-        );
569
-        return $status[ $status_id ];
570
-    }
571
-
572
-
573
-    /**
574
-     * This helper just returns a button or link for the given parameters
575
-     *
576
-     * @param string $url   the url for the link, note that `esc_url` will be called on it
577
-     * @param string $label What is the label you want displayed for the button
578
-     * @param string $class what class is used for the button (defaults to 'button--primary')
579
-     * @param string $icon
580
-     * @param string $title
581
-     * @return string the html output for the button
582
-     */
583
-    public static function get_button_or_link($url, $label, $class = 'button button--primary', $icon = '', $title = '')
584
-    {
585
-        $icon_html = '';
586
-        if (! empty($icon)) {
587
-            $dashicons = preg_split("(ee-icon |dashicons )", $icon);
588
-            $dashicons = array_filter($dashicons);
589
-            $count     = count($dashicons);
590
-            $icon_html .= $count > 1 ? '<span class="ee-composite-dashicon">' : '';
591
-            foreach ($dashicons as $dashicon) {
592
-                $type      = strpos($dashicon, 'ee-icon') !== false ? 'ee-icon ' : 'dashicons ';
593
-                $icon_html .= '<span class="' . $type . $dashicon . '"></span>';
594
-            }
595
-            $icon_html .= $count > 1 ? '</span>' : '';
596
-        }
597
-        // sanitize & escape
598
-        $id    = sanitize_title_with_dashes($label);
599
-        $url   = esc_url_raw($url);
600
-        $class = esc_attr($class);
601
-        $title = esc_attr($title);
602
-        $class .= $title ? ' ee-aria-tooltip' : '';
603
-        $title = $title ? " aria-label='{$title}'" : '';
604
-        $label = esc_html($label);
605
-        return "<a id='{$id}' href='{$url}' class='{$class}'{$title}>{$icon_html}{$label}</a>";
606
-    }
607
-
608
-
609
-    /**
610
-     * This returns a generated link that will load the related help tab on admin pages.
611
-     *
612
-     * @param string      $help_tab_id the id for the connected help tab
613
-     * @param bool|string $page        The page identifier for the page the help tab is on
614
-     * @param bool|string $action      The action (route) for the admin page the help tab is on.
615
-     * @param bool|string $icon_style  (optional) include css class for the style you want to use for the help icon.
616
-     * @param bool|string $help_text   (optional) send help text you want to use for the link if default not to be used
617
-     * @return string              generated link
618
-     */
619
-    public static function get_help_tab_link(
620
-        $help_tab_id,
621
-        $page = false,
622
-        $action = false,
623
-        $icon_style = false,
624
-        $help_text = false
625
-    ) {
626
-        /** @var RequestInterface $request */
627
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
628
-        $page    = $page ?: $request->getRequestParam('page', '', 'key');
629
-        $action  = $action ?: $request->getRequestParam('action', 'default', 'key');
630
-
631
-
632
-        $help_tab_lnk = $page . '-' . $action . '-' . $help_tab_id;
633
-        $icon         = ! $icon_style ? 'dashicons-editor-help' : $icon_style;
634
-        $help_text    = ! $help_text ? '' : $help_text;
635
-        return '
55
+	private static array $_espresso_themes = [];
56
+
57
+
58
+	/**
59
+	 *    is_espresso_theme - returns TRUE or FALSE on whether the currently active WP theme is an espresso theme
60
+	 *
61
+	 * @return boolean
62
+	 */
63
+	public static function is_espresso_theme()
64
+	{
65
+		return wp_get_theme()->get('TextDomain') === 'event_espresso';
66
+	}
67
+
68
+
69
+	/**
70
+	 *    load_espresso_theme_functions - if current theme is an espresso theme, or uses ee theme template parts, then
71
+	 *    load its functions.php file ( if not already loaded )
72
+	 *
73
+	 * @return void
74
+	 */
75
+	public static function load_espresso_theme_functions()
76
+	{
77
+		if (! defined('EE_THEME_FUNCTIONS_LOADED')) {
78
+			if (is_readable(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php')) {
79
+				require_once(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php');
80
+			}
81
+		}
82
+	}
83
+
84
+
85
+	/**
86
+	 *    get_espresso_themes - returns an array of Espresso Child themes located in the /templates/ directory
87
+	 *
88
+	 * @return array
89
+	 */
90
+	public static function get_espresso_themes(): array
91
+	{
92
+		if (empty(EEH_Template::$_espresso_themes)) {
93
+			$espresso_themes = glob(EE_PUBLIC . '*', GLOB_ONLYDIR);
94
+			if (empty($espresso_themes)) {
95
+				return [];
96
+			}
97
+			if (($key = array_search('global_assets', $espresso_themes)) !== false) {
98
+				unset($espresso_themes[ $key ]);
99
+			}
100
+			EEH_Template::$_espresso_themes = [];
101
+			foreach ($espresso_themes as $espresso_theme) {
102
+				EEH_Template::$_espresso_themes[ basename($espresso_theme) ] = $espresso_theme;
103
+			}
104
+		}
105
+		return EEH_Template::$_espresso_themes;
106
+	}
107
+
108
+
109
+	/**
110
+	 * EEH_Template::get_template_part
111
+	 * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead,
112
+	 * and doesn't add base versions of files so not a very useful function at all except that it adds familiarity PLUS
113
+	 * filtering based off of the entire template part name
114
+	 *
115
+	 * @param string $slug The slug name for the generic template.
116
+	 * @param string $name The name of the specialised template.
117
+	 * @param array  $template_args
118
+	 * @param bool   $return_string
119
+	 * @return string        the html output for the formatted money value
120
+	 */
121
+	public static function get_template_part(
122
+		$slug = '',
123
+		$name = '',
124
+		$template_args = [],
125
+		$return_string = false
126
+	) {
127
+		do_action("get_template_part_$slug-$name", $slug, $name);
128
+		$template = $slug;
129
+		$name      = (string) $name;
130
+		if ($name != '') {
131
+			$template .= "-$name";
132
+		}
133
+		$template .= ".php";
134
+		// allow template parts to be turned off via something like:
135
+		// add_filter( 'FHEE__content_espresso_events_tickets_template__display_datetimes', '__return_false' );
136
+		if (apply_filters("FHEE__EEH_Template__get_template_part__display__{$slug}_$name", true)) {
137
+			return EEH_Template::locate_template($template, $template_args, true, $return_string);
138
+		}
139
+		return '';
140
+	}
141
+
142
+
143
+	/**
144
+	 *    locate_template
145
+	 *    locate a template file by looking in the following places, in the following order:
146
+	 *        <server path up to>/wp-content/themes/<current active WordPress theme>/
147
+	 *        <assumed full absolute server path>
148
+	 *        <server path up to>/wp-content/uploads/espresso/templates/<current EE theme>/
149
+	 *        <server path up to>/wp-content/uploads/espresso/templates/
150
+	 *        <server path up to>/wp-content/plugins/<EE4 folder>/public/<current EE theme>/
151
+	 *        <server path up to>/wp-content/plugins/<EE4 folder>/core/templates/<current EE theme>/
152
+	 *        <server path up to>/wp-content/plugins/<EE4 folder>/
153
+	 *    as soon as the template is found in one of these locations, it will be returned or loaded
154
+	 *        Example:
155
+	 *          You are using the WordPress Twenty Sixteen theme,
156
+	 *        and you want to customize the "some-event.template.php" template,
157
+	 *          which is located in the "/relative/path/to/" folder relative to the main EE plugin folder.
158
+	 *          Assuming WP is installed on your server in the "/home/public_html/" folder,
159
+	 *        EEH_Template::locate_template() will look at the following paths in order until the template is found:
160
+	 *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
161
+	 *        /relative/path/to/some-event.template.php
162
+	 *        /home/public_html/wp-content/uploads/espresso/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
163
+	 *        /home/public_html/wp-content/uploads/espresso/templates/relative/path/to/some-event.template.php
164
+	 *        /home/public_html/wp-content/plugins/event-espresso-core-reg/public/Espresso_Arabica_2014/relative/path/to/some-event.template.php
165
+	 *        /home/public_html/wp-content/plugins/event-espresso-core-reg/core/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
166
+	 *        /home/public_html/wp-content/plugins/event-espresso-core-reg/relative/path/to/some-event.template.php
167
+	 *          Had you passed an absolute path to your template that was in some other location,
168
+	 *        ie: "/absolute/path/to/some-event.template.php"
169
+	 *          then the search would have been :
170
+	 *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
171
+	 *        /absolute/path/to/some-event.template.php
172
+	 *          and stopped there upon finding it in the second location
173
+	 *
174
+	 * @param array|string $templates       array of template file names including extension (or just a single string)
175
+	 * @param array        $template_args   an array of arguments to be extracted for use in the template
176
+	 * @param boolean      $load            whether to pass the located template path on to the
177
+	 *                                      EEH_Template::display_template() method or simply return it
178
+	 * @param boolean      $return_string   whether to send output immediately to screen, or capture and return as a
179
+	 *                                      string
180
+	 * @param boolean      $check_if_custom If TRUE, this flags this method to return boolean for whether this will
181
+	 *                                      generate a custom template or not. Used in places where you don't actually
182
+	 *                                      load the template, you just want to know if there's a custom version of it.
183
+	 * @return string|true
184
+	 * @throws DomainException
185
+	 * @throws InvalidArgumentException
186
+	 * @throws InvalidDataTypeException
187
+	 * @throws InvalidInterfaceException
188
+	 */
189
+	public static function locate_template(
190
+		$templates = [],
191
+		array $template_args = [],
192
+		bool $load = true,
193
+		bool $return_string = true,
194
+		bool $check_if_custom = false
195
+	) {
196
+		$cache_id      = TemplateCache::generateCacheID(__FUNCTION__, func_get_args());
197
+		$template_path = TemplateCache::get($cache_id);
198
+		$template_path = $template_path ?: self::resolveTemplatePath($cache_id, (array) $templates, $check_if_custom);
199
+
200
+		if ($check_if_custom && ! empty($template_path)) {
201
+			return true;
202
+		}
203
+
204
+		// if we got it and you want to see it...
205
+		if ($template_path && $load && ! $check_if_custom) {
206
+			if ($return_string) {
207
+				return EEH_Template::display_template($template_path, $template_args, true);
208
+			}
209
+			EEH_Template::display_template($template_path, $template_args);
210
+		}
211
+		return $check_if_custom && ! empty($template_path) ? true : $template_path;
212
+	}
213
+
214
+
215
+	/**
216
+	 * Resolves the path of a template by checking various possible locations.
217
+	 *
218
+	 * This method checks for the existence of a template in several locations,
219
+	 * including the current theme folder, the uploads directory, and the plugin's own template directory.
220
+	 * It uses the provided cache ID to store and retrieve the resolved path from a cache for performance.
221
+	 * If the template is not found in any of the checked locations, an empty string is returned.
222
+	 *
223
+	 * @param string $cache_id        The ID used for caching the resolved path.
224
+	 * @param array  $templates       An array of template file names to search for.
225
+	 * @param bool $check_if_custom   If true, the method will only check if a custom template exists
226
+	 *                                and won't include core plugin folders.
227
+	 * @return string The resolved template path, or an empty string if the template was not found.
228
+	 * @since 5.0.21.p
229
+	 */
230
+	private static function resolveTemplatePath(string $cache_id, array $templates, bool $check_if_custom): string
231
+	{
232
+		// first use WP locate_template to check for template in the current theme folder
233
+		$template_path = $templates ? locate_template($templates) : '';
234
+		// not in the theme
235
+		if (empty($template_path)) {
236
+			// not even a template to look for ?
237
+			if (empty($templates)) {
238
+				$loader = LoaderFactory::getLoader();
239
+				/** @var RequestInterface $request */
240
+				$request = $loader->getShared(RequestInterface::class);
241
+				// get post_type
242
+				$post_type = $request->getRequestParam('post_type');
243
+				/** @var CustomPostTypeDefinitions $custom_post_types */
244
+				$custom_post_types = $loader->getShared(CustomPostTypeDefinitions::class);
245
+				// get array of EE Custom Post Types
246
+				$EE_CPTs = $custom_post_types->getDefinitions();
247
+				// build template name based on request
248
+				if (isset($EE_CPTs[ $post_type ])) {
249
+					$archive_or_single = is_archive() ? 'archive' : '';
250
+					$archive_or_single = is_single() ? 'single' : $archive_or_single;
251
+					$templates[]       = $archive_or_single . '-' . $post_type . '.php';
252
+				}
253
+			}
254
+			// currently active EE template theme
255
+			$current_theme = EE_Config::get_current_theme();
256
+			// array of paths to folders that may contain templates
257
+			$template_folder_paths = [];
258
+
259
+			// add core plugin folders for checking only if we're not $check_if_custom
260
+			if (! $check_if_custom) {
261
+				$core_paths            = [
262
+					// in the  /wp-content/plugins/(EE4 folder)/public/(current EE theme)/ folder within the plugin
263
+					EE_PUBLIC . $current_theme,
264
+					// in the  /wp-content/plugins/(EE4 folder)/core/templates/(current EE theme)/ folder within the plugin
265
+					EE_TEMPLATES . $current_theme,
266
+					// or maybe relative from the plugin root: /wp-content/plugins/(EE4 folder)/
267
+					EE_PLUGIN_DIR_PATH,
268
+				];
269
+				$template_folder_paths = array_merge($template_folder_paths, $core_paths);
270
+			}
271
+
272
+			// now filter that array
273
+			$template_folder_paths = (array) apply_filters(
274
+				'FHEE__EEH_Template__locate_template__template_folder_paths',
275
+				$template_folder_paths
276
+			);
277
+
278
+			// array to hold all possible template paths
279
+			$full_template_paths = [];
280
+			$file_name           = '';
281
+
282
+			// loop through $templates
283
+			foreach ($templates as $template) {
284
+				// normalize directory separators
285
+				$template                      = EEH_File::standardise_directory_separators($template);
286
+				$file_name                     = basename($template);
287
+				$template_path_minus_file_name = substr($template, 0, (strlen($file_name) * -1));
288
+				// while looping through all template folder paths
289
+				foreach ($template_folder_paths as $template_folder_path) {
290
+					// normalize directory separators
291
+					$template_folder_path = EEH_File::standardise_directory_separators($template_folder_path);
292
+					// determine if any common base path exists between the two paths
293
+					$common_base_path = EEH_Template::_find_common_base_path(
294
+						[$template_folder_path, $template_path_minus_file_name]
295
+					);
296
+					if ($common_base_path !== '') {
297
+						// both paths have a common base, so just tack the filename onto our search path
298
+						$resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $file_name;
299
+					} else {
300
+						// no common base path, so let's just concatenate
301
+						$resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $template;
302
+					}
303
+					// build up our template locations array by adding our resolved paths
304
+					$full_template_paths[] = $resolved_path;
305
+				}
306
+				// if $template is an absolute path, then we'll tack it onto the start of our array so that it gets searched first
307
+				array_unshift($full_template_paths, $template);
308
+				// path to the directory of the current theme: /wp-content/themes/(current WP theme)/
309
+				array_unshift($full_template_paths, get_stylesheet_directory() . '/' . $file_name);
310
+			}
311
+			// filter final array of full template paths
312
+			$full_template_paths = apply_filters(
313
+				'FHEE__EEH_Template__locate_template__full_template_paths',
314
+				$full_template_paths,
315
+				$file_name
316
+			);
317
+			// now loop through our final array of template location paths and check each location
318
+			foreach ((array) $full_template_paths as $full_template_path) {
319
+				if (is_readable($full_template_path)) {
320
+					$template_path = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $full_template_path);
321
+					TemplateCache::set($cache_id, $template_path);
322
+					break;
323
+				}
324
+			}
325
+		}
326
+
327
+		// Display a deprecated notice if the template file is located in the WordPress uploads directory
328
+		if (strpos($template_path, 'wp-content/uploads/espresso') !== false) {
329
+			EE_Error::doing_it_wrong(
330
+				__CLASS__,
331
+				esc_html__(
332
+					'The use of the WordPress uploads directory as a location to override template files has been deprecated.',
333
+					'event_espresso'
334
+				),
335
+				'5.0.0'
336
+			);
337
+		}
338
+
339
+		// hook that can be used to display the full template path that will be used
340
+		do_action('AHEE__EEH_Template__locate_template__full_template_path', $template_path);
341
+
342
+		return $template_path;
343
+	}
344
+
345
+
346
+	/**
347
+	 * _find_common_base_path
348
+	 * given two paths, this determines if there is a common base path between the two
349
+	 *
350
+	 * @param array $paths
351
+	 * @return string
352
+	 */
353
+	protected static function _find_common_base_path($paths)
354
+	{
355
+		$last_offset      = 0;
356
+		$common_base_path = '';
357
+		while (($index = strpos($paths[0], '/', $last_offset)) !== false) {
358
+			$dir_length = $index - $last_offset + 1;
359
+			$directory  = substr($paths[0], $last_offset, $dir_length);
360
+			foreach ($paths as $path) {
361
+				if (substr($path, $last_offset, $dir_length) != $directory) {
362
+					return $common_base_path;
363
+				}
364
+			}
365
+			$common_base_path .= $directory;
366
+			$last_offset      = $index + 1;
367
+		}
368
+		return substr($common_base_path, 0, -1);
369
+	}
370
+
371
+
372
+	/**
373
+	 * load and display a template
374
+	 *
375
+	 * @param bool|string $template_path    server path to the file to be loaded, including file name and extension
376
+	 * @param array       $template_args    an array of arguments to be extracted for use in the template
377
+	 * @param boolean     $return_string    whether to send output immediately to screen, or capture and return as a
378
+	 *                                      string
379
+	 * @param bool        $throw_exceptions if set to true, will throw an exception if the template is either
380
+	 *                                      not found or is not readable
381
+	 * @return string
382
+	 * @throws DomainException
383
+	 */
384
+	public static function display_template(
385
+		$template_path = '',
386
+		$template_args = [],
387
+		$return_string = false,
388
+		$throw_exceptions = false
389
+	) {
390
+		/**
391
+		 * These two filters are intended for last minute changes to templates being loaded and/or template arg
392
+		 * modifications.  NOTE... modifying these things can cause breakage as most templates running through
393
+		 * the display_template method are templates we DON'T want modified (usually because of js
394
+		 * dependencies etc).  So unless you know what you are doing, do NOT filter templates or template args
395
+		 * using this.
396
+		 *
397
+		 * @since 4.6.0
398
+		 */
399
+		$template_path = (string) apply_filters('FHEE__EEH_Template__display_template__template_path', $template_path);
400
+		$template_args = (array) apply_filters(
401
+			'FHEE__EEH_Template__display_template__template_args',
402
+			$template_args,
403
+			$template_path
404
+		);
405
+
406
+		// you gimme nuttin - YOU GET NUTTIN !!
407
+		if (! $template_path || ! is_readable($template_path)) {
408
+			// ignore whether template is accessible ?
409
+			if ($throw_exceptions) {
410
+				throw new DomainException(
411
+					esc_html__('Invalid, unreadable, or missing file.', 'event_espresso')
412
+				);
413
+			}
414
+			return '';
415
+		}
416
+
417
+		extract($template_args, EXTR_SKIP);
418
+		// because we might want to return a string, we are going to capture the output
419
+		ob_start();
420
+		include($template_path);
421
+		$template = ob_get_clean();
422
+
423
+		if ($return_string) {
424
+			return $template;
425
+		}
426
+		echo wp_kses($template, AllowedTags::getWithFullTags());
427
+		return '';
428
+	}
429
+
430
+
431
+	/**
432
+	 * get_object_css_class - attempts to generate a css class based on the type of EE object passed
433
+	 *
434
+	 * @param EE_Base_Class $object the EE object the css class is being generated for
435
+	 * @param string        $prefix added to the beginning of the generated class
436
+	 * @param string        $suffix added to the end of the generated class
437
+	 * @return string
438
+	 * @throws EE_Error
439
+	 * @throws ReflectionException
440
+	 */
441
+	public static function get_object_css_class($object = null, $prefix = '', $suffix = '')
442
+	{
443
+		// in the beginning...
444
+		$prefix = ! empty($prefix) ? rtrim($prefix, '-') . '-' : '';
445
+		// da muddle
446
+		$class = '';
447
+		// the end
448
+		$suffix = ! empty($suffix) ? '-' . ltrim($suffix, '-') : '';
449
+		// is the passed object an EE object ?
450
+		if ($object instanceof EE_Base_Class) {
451
+			// grab the exact type of object
452
+			$obj_class = get_class($object);
453
+			// depending on the type of object...
454
+			// no specifics just yet...
455
+			$class = strtolower(str_replace('_', '-', $obj_class));
456
+			$class .= method_exists($obj_class, 'name') ? '-' . sanitize_title($object->name()) : '';
457
+		}
458
+		return $prefix . $class . $suffix;
459
+	}
460
+
461
+
462
+	/**
463
+	 * EEH_Template::format_currency
464
+	 * This helper takes a raw float value and formats it according to the default config country currency settings, or
465
+	 * the country currency settings from the supplied country ISO code
466
+	 *
467
+	 * @param float   $amount       raw money value
468
+	 * @param boolean $return_raw   whether to return the formatted float value only with no currency sign or code
469
+	 * @param boolean $display_code whether to display the country code (USD). Default = TRUE
470
+	 * @param string  $CNT_ISO      2-letter ISO code for a country
471
+	 * @param string  $cur_code_span_class
472
+	 * @return string        the html output for the formatted money value
473
+	 */
474
+	public static function format_currency(
475
+		$amount = null,
476
+		$return_raw = false,
477
+		$display_code = true,
478
+		$CNT_ISO = '',
479
+		$cur_code_span_class = 'currency-code'
480
+	) {
481
+		// ensure amount was received
482
+		if ($amount === null) {
483
+			$msg = esc_html__('In order to format currency, an amount needs to be passed.', 'event_espresso');
484
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
485
+			return '';
486
+		}
487
+		// ensure amount is float
488
+		$amount  = (float) apply_filters('FHEE__EEH_Template__format_currency__raw_amount', (float) $amount);
489
+		$CNT_ISO = apply_filters('FHEE__EEH_Template__format_currency__CNT_ISO', $CNT_ISO, $amount);
490
+		// filter raw amount (allows 0.00 to be changed to "free" for example)
491
+		$amount_formatted = apply_filters('FHEE__EEH_Template__format_currency__amount', $amount, $return_raw);
492
+		// still a number, or was amount converted to a string like "free" ?
493
+		if (! is_float($amount_formatted)) {
494
+			return esc_html($amount_formatted);
495
+		}
496
+		try {
497
+			// was a country ISO code passed ? if so generate currency config object for that country
498
+			$mny = $CNT_ISO !== '' ? new EE_Currency_Config($CNT_ISO) : null;
499
+		} catch (Exception $e) {
500
+			// eat exception
501
+			$mny = null;
502
+		}
503
+		// verify results
504
+		if (! $mny instanceof EE_Currency_Config) {
505
+			// set default config country currency settings
506
+			$mny = EE_Registry::instance()->CFG->currency instanceof EE_Currency_Config
507
+				? EE_Registry::instance()->CFG->currency
508
+				: new EE_Currency_Config();
509
+		}
510
+		// format float
511
+		$amount_formatted = number_format($amount, $mny->dec_plc, $mny->dec_mrk, $mny->thsnds);
512
+		// add formatting ?
513
+		if (! $return_raw) {
514
+			// add currency sign
515
+			if ($mny->sign_b4) {
516
+				if ($amount >= 0) {
517
+					$amount_formatted = $mny->sign . $amount_formatted;
518
+				} else {
519
+					$amount_formatted = '-' . $mny->sign . str_replace('-', '', $amount_formatted);
520
+				}
521
+			} else {
522
+				$amount_formatted = $amount_formatted . $mny->sign;
523
+			}
524
+
525
+			// filter to allow global setting of display_code
526
+			$display_code = (bool) apply_filters(
527
+				'FHEE__EEH_Template__format_currency__display_code',
528
+				$display_code
529
+			);
530
+
531
+			// add currency code ?
532
+			$amount_formatted = $display_code
533
+				? $amount_formatted . ' <span class="' . $cur_code_span_class . '">' . $mny->code . '</span>'
534
+				: $amount_formatted;
535
+		}
536
+		// filter results
537
+		$amount_formatted = apply_filters(
538
+			'FHEE__EEH_Template__format_currency__amount_formatted',
539
+			$amount_formatted,
540
+			$mny,
541
+			$return_raw
542
+		);
543
+		// clean up vars
544
+		unset($mny);
545
+		// return formatted currency amount
546
+		return $amount_formatted;
547
+	}
548
+
549
+
550
+	/**
551
+	 * This function is used for outputting the localized label for a given status id in the schema requested (and
552
+	 * possibly plural).  The intended use of this function is only for cases where wanting a label outside of a
553
+	 * related status model or model object (i.e. in documentation etc.)
554
+	 *
555
+	 * @param string  $status_id  Status ID matching a registered status in the esp_status table.  If there is no
556
+	 *                            match, then 'Unknown' will be returned.
557
+	 * @param boolean $plural     Whether to return plural or not
558
+	 * @param string  $schema     'UPPER', 'lower', or 'Sentence'
559
+	 * @return string             The localized label for the status id.
560
+	 * @throws EE_Error
561
+	 */
562
+	public static function pretty_status($status_id, $plural = false, $schema = 'upper')
563
+	{
564
+		$status = EEM_Status::instance()->localized_status(
565
+			[$status_id => esc_html__('unknown', 'event_espresso')],
566
+			$plural,
567
+			$schema
568
+		);
569
+		return $status[ $status_id ];
570
+	}
571
+
572
+
573
+	/**
574
+	 * This helper just returns a button or link for the given parameters
575
+	 *
576
+	 * @param string $url   the url for the link, note that `esc_url` will be called on it
577
+	 * @param string $label What is the label you want displayed for the button
578
+	 * @param string $class what class is used for the button (defaults to 'button--primary')
579
+	 * @param string $icon
580
+	 * @param string $title
581
+	 * @return string the html output for the button
582
+	 */
583
+	public static function get_button_or_link($url, $label, $class = 'button button--primary', $icon = '', $title = '')
584
+	{
585
+		$icon_html = '';
586
+		if (! empty($icon)) {
587
+			$dashicons = preg_split("(ee-icon |dashicons )", $icon);
588
+			$dashicons = array_filter($dashicons);
589
+			$count     = count($dashicons);
590
+			$icon_html .= $count > 1 ? '<span class="ee-composite-dashicon">' : '';
591
+			foreach ($dashicons as $dashicon) {
592
+				$type      = strpos($dashicon, 'ee-icon') !== false ? 'ee-icon ' : 'dashicons ';
593
+				$icon_html .= '<span class="' . $type . $dashicon . '"></span>';
594
+			}
595
+			$icon_html .= $count > 1 ? '</span>' : '';
596
+		}
597
+		// sanitize & escape
598
+		$id    = sanitize_title_with_dashes($label);
599
+		$url   = esc_url_raw($url);
600
+		$class = esc_attr($class);
601
+		$title = esc_attr($title);
602
+		$class .= $title ? ' ee-aria-tooltip' : '';
603
+		$title = $title ? " aria-label='{$title}'" : '';
604
+		$label = esc_html($label);
605
+		return "<a id='{$id}' href='{$url}' class='{$class}'{$title}>{$icon_html}{$label}</a>";
606
+	}
607
+
608
+
609
+	/**
610
+	 * This returns a generated link that will load the related help tab on admin pages.
611
+	 *
612
+	 * @param string      $help_tab_id the id for the connected help tab
613
+	 * @param bool|string $page        The page identifier for the page the help tab is on
614
+	 * @param bool|string $action      The action (route) for the admin page the help tab is on.
615
+	 * @param bool|string $icon_style  (optional) include css class for the style you want to use for the help icon.
616
+	 * @param bool|string $help_text   (optional) send help text you want to use for the link if default not to be used
617
+	 * @return string              generated link
618
+	 */
619
+	public static function get_help_tab_link(
620
+		$help_tab_id,
621
+		$page = false,
622
+		$action = false,
623
+		$icon_style = false,
624
+		$help_text = false
625
+	) {
626
+		/** @var RequestInterface $request */
627
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
628
+		$page    = $page ?: $request->getRequestParam('page', '', 'key');
629
+		$action  = $action ?: $request->getRequestParam('action', 'default', 'key');
630
+
631
+
632
+		$help_tab_lnk = $page . '-' . $action . '-' . $help_tab_id;
633
+		$icon         = ! $icon_style ? 'dashicons-editor-help' : $icon_style;
634
+		$help_text    = ! $help_text ? '' : $help_text;
635
+		return '
636 636
             <a id="' . esc_attr($help_tab_lnk) . '"
637 637
                class="espresso-help-tab-lnk ee-help-btn ee-aria-tooltip dashicons ' . esc_attr($icon) . '"
638 638
                aria-label="' . esc_attr__(
639
-                   'Click to open the \'Help\' tab for more information about this feature.',
640
-                   'event_espresso'
641
-               ) . '"
639
+				   'Click to open the \'Help\' tab for more information about this feature.',
640
+				   'event_espresso'
641
+			   ) . '"
642 642
             >
643 643
                 ' . wp_kses($help_text, AllowedTags::getAllowedTags()) . '
644 644
             </a>';
645
-    }
646
-
647
-
648
-    /**
649
-     * This is a helper method to generate a status legend for a given status array.
650
-     * Note this will only work if the incoming statuses have a key in the EEM_Status->localized_status() methods
651
-     * status_array.
652
-     *
653
-     * @param array  $status_array   array of statuses that will make up the legend. In format:
654
-     *                               array(
655
-     *                               'status_item' => 'status_name'
656
-     *                               )
657
-     * @param string $active_status  This is used to indicate what the active status is IF that is to be highlighted in
658
-     *                               the legend.
659
-     * @return string               html structure for status.
660
-     * @throws EE_Error
661
-     */
662
-    public static function status_legend($status_array, $active_status = '')
663
-    {
664
-        if (! is_array($status_array)) {
665
-            throw new EE_Error(
666
-                esc_html__(
667
-                    'The EEH_Template::status_legend helper required the incoming status_array argument to be an array!',
668
-                    'event_espresso'
669
-                )
670
-            );
671
-        }
672
-
673
-        $content = '
645
+	}
646
+
647
+
648
+	/**
649
+	 * This is a helper method to generate a status legend for a given status array.
650
+	 * Note this will only work if the incoming statuses have a key in the EEM_Status->localized_status() methods
651
+	 * status_array.
652
+	 *
653
+	 * @param array  $status_array   array of statuses that will make up the legend. In format:
654
+	 *                               array(
655
+	 *                               'status_item' => 'status_name'
656
+	 *                               )
657
+	 * @param string $active_status  This is used to indicate what the active status is IF that is to be highlighted in
658
+	 *                               the legend.
659
+	 * @return string               html structure for status.
660
+	 * @throws EE_Error
661
+	 */
662
+	public static function status_legend($status_array, $active_status = '')
663
+	{
664
+		if (! is_array($status_array)) {
665
+			throw new EE_Error(
666
+				esc_html__(
667
+					'The EEH_Template::status_legend helper required the incoming status_array argument to be an array!',
668
+					'event_espresso'
669
+				)
670
+			);
671
+		}
672
+
673
+		$content = '
674 674
             <div class="ee-list-table-legend-container">
675 675
                 <h4 class="status-legend-title">
676 676
                     ' . esc_html__('Status Legend', 'event_espresso') . '
677 677
                 </h4>
678 678
                 <dl class="ee-list-table-legend">';
679 679
 
680
-        foreach ($status_array as $item => $status) {
681
-            $active_class = $active_status == $status ? 'class="ee-is-active-status"' : '';
682
-            $content      .= '
680
+		foreach ($status_array as $item => $status) {
681
+			$active_class = $active_status == $status ? 'class="ee-is-active-status"' : '';
682
+			$content      .= '
683 683
                     <dt id="' . esc_attr('ee-legend-item-tooltip-' . $item) . '" ' . $active_class . '>
684 684
                         <span class="' . esc_attr('ee-status-legend ee-status-bg--' . $status) . '"></span>
685 685
                         <span class="ee-legend-description">
686 686
                             ' . EEH_Template::pretty_status($status, false, 'sentence') . '
687 687
                         </span>
688 688
                     </dt>';
689
-        }
689
+		}
690 690
 
691
-        $content .= '
691
+		$content .= '
692 692
                 </dl>
693 693
             </div>
694 694
 ';
695
-        return $content;
696
-    }
697
-
698
-
699
-    /**
700
-     * Gets HTML for laying out a deeply-nested array (and objects) in a format
701
-     * that's nice for presenting in the wp admin
702
-     *
703
-     * @param mixed $data
704
-     * @return string
705
-     */
706
-    public static function layout_array_as_table($data)
707
-    {
708
-        if (is_object($data) || $data instanceof __PHP_Incomplete_Class) {
709
-            $data = (array) $data;
710
-        }
711
-        ob_start();
712
-        if (is_array($data)) {
713
-            if (EEH_Array::is_associative_array($data)) { ?>
695
+		return $content;
696
+	}
697
+
698
+
699
+	/**
700
+	 * Gets HTML for laying out a deeply-nested array (and objects) in a format
701
+	 * that's nice for presenting in the wp admin
702
+	 *
703
+	 * @param mixed $data
704
+	 * @return string
705
+	 */
706
+	public static function layout_array_as_table($data)
707
+	{
708
+		if (is_object($data) || $data instanceof __PHP_Incomplete_Class) {
709
+			$data = (array) $data;
710
+		}
711
+		ob_start();
712
+		if (is_array($data)) {
713
+			if (EEH_Array::is_associative_array($data)) { ?>
714 714
                 <table class="widefat">
715 715
                     <tbody>
716 716
                         <?php foreach ($data as $data_key => $data_values) { ?>
@@ -728,304 +728,304 @@  discard block
 block discarded – undo
728 728
             <?php } else { ?>
729 729
                 <ul>
730 730
                     <?php
731
-                    foreach ($data as $datum) {
732
-                        echo "<li>";
733
-                        echo self::layout_array_as_table($datum);
734
-                        echo "</li>";
735
-                    } ?>
731
+					foreach ($data as $datum) {
732
+						echo "<li>";
733
+						echo self::layout_array_as_table($datum);
734
+						echo "</li>";
735
+					} ?>
736 736
                 </ul>
737 737
             <?php }
738
-        } else {
739
-            // simple value
740
-            echo esc_html($data);
741
-        }
742
-        return ob_get_clean();
743
-    }
744
-
745
-
746
-    /**
747
-     * wrapper for self::get_paging_html() that simply echos the generated paging html
748
-     *
749
-     * @param        $total_items
750
-     * @param        $current
751
-     * @param        $per_page
752
-     * @param        $url
753
-     * @param bool   $show_num_field
754
-     * @param string $paged_arg_name
755
-     * @param array  $items_label
756
-     * @see   self:get_paging_html() for argument docs.
757
-     * @since 4.4.0
758
-     */
759
-    public static function paging_html(
760
-        $total_items,
761
-        $current,
762
-        $per_page,
763
-        $url,
764
-        $show_num_field = true,
765
-        $paged_arg_name = 'paged',
766
-        $items_label = []
767
-    ) {
768
-        echo self::get_paging_html(
769
-            $total_items,
770
-            $current,
771
-            $per_page,
772
-            $url,
773
-            $show_num_field,
774
-            $paged_arg_name,
775
-            $items_label
776
-        );
777
-    }
778
-
779
-
780
-    /**
781
-     * A method for generating paging similar to WP_List_Table
782
-     *
783
-     * @param int    $total_items       How many total items there are to page.
784
-     * @param int    $current           What the current page is.
785
-     * @param int    $per_page          How many items per page.
786
-     * @param string $url               What the base url for page links is.
787
-     * @param bool   $show_num_field    Whether to show the input for changing page number.
788
-     * @param string $paged_arg_name    The name of the key for the paged query argument.
789
-     * @param array  $items_label       An array of singular/plural values for the items label:
790
-     *                                  array(
791
-     *                                  'single' => 'item',
792
-     *                                  'plural' => 'items'
793
-     *                                  )
794
-     * @return  string
795
-     * @since    4.4.0
796
-     * @see      wp-admin/includes/class-wp-list-table.php WP_List_Table::pagination()
797
-     */
798
-    public static function get_paging_html(
799
-        int $total_items,
800
-        int $current,
801
-        int $per_page,
802
-        string $url,
803
-        bool $show_num_field = true,
804
-        string $paged_arg_name = 'paged',
805
-        array $items_label = [],
806
-        string $button_size = 'small'
807
-    ): string {
808
-        $page_links     = [];
809
-        $paged_arg_name = empty($paged_arg_name) ? 'paged' : sanitize_key($paged_arg_name);
810
-
811
-        // filter items_label
812
-        $items_label = apply_filters(
813
-            'FHEE__EEH_Template__get_paging_html__items_label',
814
-            $items_label
815
-        );
816
-
817
-        if (
818
-            empty($items_label)
819
-            || ! is_array($items_label)
820
-            || ! isset($items_label['single'])
821
-            || ! isset($items_label['plural'])
822
-        ) {
823
-            $items_label = [
824
-                'single' => esc_html__('1 item', 'event_espresso'),
825
-                'plural' => esc_html__('%s items', 'event_espresso'),
826
-            ];
827
-        } else {
828
-            $items_label = [
829
-                'single' => '1 ' . esc_html($items_label['single']),
830
-                'plural' => '%s ' . esc_html($items_label['plural']),
831
-            ];
832
-        }
833
-
834
-        $total_pages = (int) ceil($total_items / $per_page);
835
-
836
-        if ($total_pages <= 1) {
837
-            return '';
838
-        }
839
-
840
-        $item_label = $total_items > 1 ? sprintf($items_label['plural'], $total_items) : $items_label['single'];
841
-
842
-        $output = '<span class="displaying-num">' . $item_label . '</span>';
843
-
844
-        $disable_first = $current === 1 ? 'disabled' : '';
845
-        $disable_last  = $current === $total_pages ? 'disabled' : '';
846
-
847
-        $button_size    = in_array($button_size, ['tiny', 'small', 'default', 'big']) ? $button_size : 'small';
848
-        $button_classes = "button button--secondary button--icon-only button--$button_size";
849
-
850
-        $page_links[] = sprintf(
851
-            '<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
852
-            esc_attr("first-page $button_classes $disable_first"),
853
-            esc_attr__('Go to the first page', 'event_espresso'),
854
-            esc_url_raw(remove_query_arg($paged_arg_name, $url)),
855
-            '&laquo;'
856
-        );
857
-
858
-        $page_links[] = sprintf(
859
-            '<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
860
-            esc_attr("prev-page $button_classes $disable_first"),
861
-            esc_attr__('Go to the previous page', 'event_espresso'),
862
-            esc_url_raw(add_query_arg($paged_arg_name, max(1, $current - 1), $url)),
863
-            '&lsaquo;'
864
-        );
865
-
866
-        $html_current_page = $show_num_field
867
-            ? sprintf(
868
-                "<input class='current-page ee-input-size--small' title='%s' type='text' name=$paged_arg_name value='%s' size='%d' />",
869
-                esc_attr__('Current page', 'event_espresso'),
870
-                esc_attr($current),
871
-                strlen($total_pages)
872
-            )
873
-            : $current;
874
-
875
-        $html_total_pages = sprintf(
876
-            '<span class="total-pages">%s</span>',
877
-            number_format_i18n($total_pages)
878
-        );
879
-        $page_links[]     = sprintf(
880
-            _x('%3$s%1$s of %2$s%4$s', 'paging', 'event_espresso'),
881
-            "{$html_current_page}<span class='paging-input-of'>",
882
-            "</span>{$html_total_pages}",
883
-            '<span class="paging-input">',
884
-            '</span>'
885
-        );
886
-
887
-        $page_links[] = sprintf(
888
-            '<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
889
-            esc_attr("next-page $button_classes $disable_last"),
890
-            esc_attr__('Go to the next page', 'event_espresso'),
891
-            esc_url_raw(add_query_arg($paged_arg_name, min($total_pages, $current + 1), $url)),
892
-            '&rsaquo;'
893
-        );
894
-
895
-        $page_links[] = sprintf(
896
-            '<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
897
-            esc_attr("last-page $button_classes $disable_last"),
898
-            esc_attr__('Go to the last page', 'event_espresso'),
899
-            esc_url_raw(add_query_arg($paged_arg_name, $total_pages, $url)),
900
-            '&raquo;'
901
-        );
902
-
903
-        $output .= "\n" . '<span class="pagination-links">' . join("\n", $page_links) . '</span>';
904
-
905
-        $page_class = ' no-pages';
906
-        if ($total_pages) {
907
-            $page_class = $total_pages < 2 ? ' one-page' : '';
908
-        }
909
-
910
-        return '<div class="tablenav"><div class="tablenav-pages' . $page_class . '">' . $output . '</div></div>';
911
-    }
912
-
913
-
914
-    /**
915
-     * @param string|null $wrap_class
916
-     * @param string|null $wrap_id
917
-     * @param array       $query_args
918
-     * @return string
919
-     */
920
-    public static function powered_by_event_espresso(
921
-        ?string $wrap_class = '',
922
-        ?string $wrap_id = '',
923
-        array $query_args = []
924
-    ): string {
925
-        $request = LoaderFactory::getShared(RequestInterface::class);
926
-        if (
927
-            $request->isActivation()
928
-            || strpos($request->requestUri(true), 'wp-admin/update.php') !== false
929
-        ) {
930
-            return '';
931
-        }
932
-        $cache_id = TemplateCache::generateCacheID(__FUNCTION__, func_get_args());
933
-        $cache    = TemplateCache::get($cache_id);
934
-        if ($cache) {
935
-            return $cache;
936
-        }
937
-
938
-        $admin = is_admin() && ! (defined('DOING_AJAX') && DOING_AJAX);
939
-        if (
940
-            ! $admin
941
-            && ! apply_filters(
942
-                'FHEE__EEH_Template__powered_by_event_espresso__show_reg_footer',
943
-                EE_Registry::instance()->CFG->admin->show_reg_footer
944
-            )
945
-        ) {
946
-            return '';
947
-        }
948
-        $tag        = $admin ? 'span' : 'div';
949
-        $attributes = ! empty($wrap_id) ? " id='$wrap_id'" : '';
950
-        $wrap_class = $admin ? "$wrap_class ee-layout-row ee-layout-row--inline" : $wrap_class;
951
-        $attributes .= ! empty($wrap_class)
952
-            ? " class='$wrap_class powered-by-event-espresso-credit'"
953
-            : ' class="powered-by-event-espresso-credit"';
954
-        $query_args = array_merge(
955
-            [
956
-                'ap_id'        => EE_Registry::instance()->CFG->admin->affiliate_id(),
957
-                'utm_source'   => 'powered_by_event_espresso',
958
-                'utm_medium'   => 'link',
959
-                'utm_campaign' => 'powered_by',
960
-            ],
961
-            $query_args
962
-        );
963
-        $powered_by = apply_filters(
964
-            'FHEE__EEH_Template__powered_by_event_espresso_text',
965
-            $admin ? 'Event Espresso - ' . EVENT_ESPRESSO_VERSION : 'Event Espresso'
966
-        );
967
-        $url        = add_query_arg($query_args, 'https://eventespresso.com/');
968
-        $url        = apply_filters('FHEE__EEH_Template__powered_by_event_espresso__url', $url);
969
-        $template   = (string) apply_filters(
970
-            'FHEE__EEH_Template__powered_by_event_espresso__html',
971
-            sprintf(
972
-                esc_html_x(
973
-                    '%3$s%1$sOnline event registration and ticketing powered by %2$s%3$s',
974
-                    'Online event registration and ticketing powered by [link to eventespresso.com]',
975
-                    'event_espresso'
976
-                ),
977
-                "<$tag$attributes style='margin-inline:.5rem;'>",
978
-                " <a href='$url' target='_blank' rel='nofollow' style='margin-inline: .25rem;'>$powered_by</a></$tag> ",
979
-                $admin ? '' : '<br />'
980
-            ),
981
-            $wrap_class,
982
-            $wrap_id
983
-        );
984
-        TemplateCache::set($cache_id, $template);
985
-        return $template;
986
-    }
987
-
988
-
989
-    /**
990
-     * @param string $image_name
991
-     * @return string|null
992
-     * @since   4.10.14.p
993
-     */
994
-    public static function getScreenshotUrl($image_name)
995
-    {
996
-        return esc_url_raw(EE_GLOBAL_ASSETS_URL . 'images/screenshots/' . $image_name . '.jpg');
997
-    }
738
+		} else {
739
+			// simple value
740
+			echo esc_html($data);
741
+		}
742
+		return ob_get_clean();
743
+	}
744
+
745
+
746
+	/**
747
+	 * wrapper for self::get_paging_html() that simply echos the generated paging html
748
+	 *
749
+	 * @param        $total_items
750
+	 * @param        $current
751
+	 * @param        $per_page
752
+	 * @param        $url
753
+	 * @param bool   $show_num_field
754
+	 * @param string $paged_arg_name
755
+	 * @param array  $items_label
756
+	 * @see   self:get_paging_html() for argument docs.
757
+	 * @since 4.4.0
758
+	 */
759
+	public static function paging_html(
760
+		$total_items,
761
+		$current,
762
+		$per_page,
763
+		$url,
764
+		$show_num_field = true,
765
+		$paged_arg_name = 'paged',
766
+		$items_label = []
767
+	) {
768
+		echo self::get_paging_html(
769
+			$total_items,
770
+			$current,
771
+			$per_page,
772
+			$url,
773
+			$show_num_field,
774
+			$paged_arg_name,
775
+			$items_label
776
+		);
777
+	}
778
+
779
+
780
+	/**
781
+	 * A method for generating paging similar to WP_List_Table
782
+	 *
783
+	 * @param int    $total_items       How many total items there are to page.
784
+	 * @param int    $current           What the current page is.
785
+	 * @param int    $per_page          How many items per page.
786
+	 * @param string $url               What the base url for page links is.
787
+	 * @param bool   $show_num_field    Whether to show the input for changing page number.
788
+	 * @param string $paged_arg_name    The name of the key for the paged query argument.
789
+	 * @param array  $items_label       An array of singular/plural values for the items label:
790
+	 *                                  array(
791
+	 *                                  'single' => 'item',
792
+	 *                                  'plural' => 'items'
793
+	 *                                  )
794
+	 * @return  string
795
+	 * @since    4.4.0
796
+	 * @see      wp-admin/includes/class-wp-list-table.php WP_List_Table::pagination()
797
+	 */
798
+	public static function get_paging_html(
799
+		int $total_items,
800
+		int $current,
801
+		int $per_page,
802
+		string $url,
803
+		bool $show_num_field = true,
804
+		string $paged_arg_name = 'paged',
805
+		array $items_label = [],
806
+		string $button_size = 'small'
807
+	): string {
808
+		$page_links     = [];
809
+		$paged_arg_name = empty($paged_arg_name) ? 'paged' : sanitize_key($paged_arg_name);
810
+
811
+		// filter items_label
812
+		$items_label = apply_filters(
813
+			'FHEE__EEH_Template__get_paging_html__items_label',
814
+			$items_label
815
+		);
816
+
817
+		if (
818
+			empty($items_label)
819
+			|| ! is_array($items_label)
820
+			|| ! isset($items_label['single'])
821
+			|| ! isset($items_label['plural'])
822
+		) {
823
+			$items_label = [
824
+				'single' => esc_html__('1 item', 'event_espresso'),
825
+				'plural' => esc_html__('%s items', 'event_espresso'),
826
+			];
827
+		} else {
828
+			$items_label = [
829
+				'single' => '1 ' . esc_html($items_label['single']),
830
+				'plural' => '%s ' . esc_html($items_label['plural']),
831
+			];
832
+		}
833
+
834
+		$total_pages = (int) ceil($total_items / $per_page);
835
+
836
+		if ($total_pages <= 1) {
837
+			return '';
838
+		}
839
+
840
+		$item_label = $total_items > 1 ? sprintf($items_label['plural'], $total_items) : $items_label['single'];
841
+
842
+		$output = '<span class="displaying-num">' . $item_label . '</span>';
843
+
844
+		$disable_first = $current === 1 ? 'disabled' : '';
845
+		$disable_last  = $current === $total_pages ? 'disabled' : '';
846
+
847
+		$button_size    = in_array($button_size, ['tiny', 'small', 'default', 'big']) ? $button_size : 'small';
848
+		$button_classes = "button button--secondary button--icon-only button--$button_size";
849
+
850
+		$page_links[] = sprintf(
851
+			'<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
852
+			esc_attr("first-page $button_classes $disable_first"),
853
+			esc_attr__('Go to the first page', 'event_espresso'),
854
+			esc_url_raw(remove_query_arg($paged_arg_name, $url)),
855
+			'&laquo;'
856
+		);
857
+
858
+		$page_links[] = sprintf(
859
+			'<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
860
+			esc_attr("prev-page $button_classes $disable_first"),
861
+			esc_attr__('Go to the previous page', 'event_espresso'),
862
+			esc_url_raw(add_query_arg($paged_arg_name, max(1, $current - 1), $url)),
863
+			'&lsaquo;'
864
+		);
865
+
866
+		$html_current_page = $show_num_field
867
+			? sprintf(
868
+				"<input class='current-page ee-input-size--small' title='%s' type='text' name=$paged_arg_name value='%s' size='%d' />",
869
+				esc_attr__('Current page', 'event_espresso'),
870
+				esc_attr($current),
871
+				strlen($total_pages)
872
+			)
873
+			: $current;
874
+
875
+		$html_total_pages = sprintf(
876
+			'<span class="total-pages">%s</span>',
877
+			number_format_i18n($total_pages)
878
+		);
879
+		$page_links[]     = sprintf(
880
+			_x('%3$s%1$s of %2$s%4$s', 'paging', 'event_espresso'),
881
+			"{$html_current_page}<span class='paging-input-of'>",
882
+			"</span>{$html_total_pages}",
883
+			'<span class="paging-input">',
884
+			'</span>'
885
+		);
886
+
887
+		$page_links[] = sprintf(
888
+			'<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
889
+			esc_attr("next-page $button_classes $disable_last"),
890
+			esc_attr__('Go to the next page', 'event_espresso'),
891
+			esc_url_raw(add_query_arg($paged_arg_name, min($total_pages, $current + 1), $url)),
892
+			'&rsaquo;'
893
+		);
894
+
895
+		$page_links[] = sprintf(
896
+			'<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
897
+			esc_attr("last-page $button_classes $disable_last"),
898
+			esc_attr__('Go to the last page', 'event_espresso'),
899
+			esc_url_raw(add_query_arg($paged_arg_name, $total_pages, $url)),
900
+			'&raquo;'
901
+		);
902
+
903
+		$output .= "\n" . '<span class="pagination-links">' . join("\n", $page_links) . '</span>';
904
+
905
+		$page_class = ' no-pages';
906
+		if ($total_pages) {
907
+			$page_class = $total_pages < 2 ? ' one-page' : '';
908
+		}
909
+
910
+		return '<div class="tablenav"><div class="tablenav-pages' . $page_class . '">' . $output . '</div></div>';
911
+	}
912
+
913
+
914
+	/**
915
+	 * @param string|null $wrap_class
916
+	 * @param string|null $wrap_id
917
+	 * @param array       $query_args
918
+	 * @return string
919
+	 */
920
+	public static function powered_by_event_espresso(
921
+		?string $wrap_class = '',
922
+		?string $wrap_id = '',
923
+		array $query_args = []
924
+	): string {
925
+		$request = LoaderFactory::getShared(RequestInterface::class);
926
+		if (
927
+			$request->isActivation()
928
+			|| strpos($request->requestUri(true), 'wp-admin/update.php') !== false
929
+		) {
930
+			return '';
931
+		}
932
+		$cache_id = TemplateCache::generateCacheID(__FUNCTION__, func_get_args());
933
+		$cache    = TemplateCache::get($cache_id);
934
+		if ($cache) {
935
+			return $cache;
936
+		}
937
+
938
+		$admin = is_admin() && ! (defined('DOING_AJAX') && DOING_AJAX);
939
+		if (
940
+			! $admin
941
+			&& ! apply_filters(
942
+				'FHEE__EEH_Template__powered_by_event_espresso__show_reg_footer',
943
+				EE_Registry::instance()->CFG->admin->show_reg_footer
944
+			)
945
+		) {
946
+			return '';
947
+		}
948
+		$tag        = $admin ? 'span' : 'div';
949
+		$attributes = ! empty($wrap_id) ? " id='$wrap_id'" : '';
950
+		$wrap_class = $admin ? "$wrap_class ee-layout-row ee-layout-row--inline" : $wrap_class;
951
+		$attributes .= ! empty($wrap_class)
952
+			? " class='$wrap_class powered-by-event-espresso-credit'"
953
+			: ' class="powered-by-event-espresso-credit"';
954
+		$query_args = array_merge(
955
+			[
956
+				'ap_id'        => EE_Registry::instance()->CFG->admin->affiliate_id(),
957
+				'utm_source'   => 'powered_by_event_espresso',
958
+				'utm_medium'   => 'link',
959
+				'utm_campaign' => 'powered_by',
960
+			],
961
+			$query_args
962
+		);
963
+		$powered_by = apply_filters(
964
+			'FHEE__EEH_Template__powered_by_event_espresso_text',
965
+			$admin ? 'Event Espresso - ' . EVENT_ESPRESSO_VERSION : 'Event Espresso'
966
+		);
967
+		$url        = add_query_arg($query_args, 'https://eventespresso.com/');
968
+		$url        = apply_filters('FHEE__EEH_Template__powered_by_event_espresso__url', $url);
969
+		$template   = (string) apply_filters(
970
+			'FHEE__EEH_Template__powered_by_event_espresso__html',
971
+			sprintf(
972
+				esc_html_x(
973
+					'%3$s%1$sOnline event registration and ticketing powered by %2$s%3$s',
974
+					'Online event registration and ticketing powered by [link to eventespresso.com]',
975
+					'event_espresso'
976
+				),
977
+				"<$tag$attributes style='margin-inline:.5rem;'>",
978
+				" <a href='$url' target='_blank' rel='nofollow' style='margin-inline: .25rem;'>$powered_by</a></$tag> ",
979
+				$admin ? '' : '<br />'
980
+			),
981
+			$wrap_class,
982
+			$wrap_id
983
+		);
984
+		TemplateCache::set($cache_id, $template);
985
+		return $template;
986
+	}
987
+
988
+
989
+	/**
990
+	 * @param string $image_name
991
+	 * @return string|null
992
+	 * @since   4.10.14.p
993
+	 */
994
+	public static function getScreenshotUrl($image_name)
995
+	{
996
+		return esc_url_raw(EE_GLOBAL_ASSETS_URL . 'images/screenshots/' . $image_name . '.jpg');
997
+	}
998 998
 }
999 999
 
1000 1000
 
1001 1001
 if (! function_exists('espresso_pagination')) {
1002
-    /**
1003
-     *    espresso_pagination
1004
-     *
1005
-     * @access    public
1006
-     * @return    void
1007
-     */
1008
-    function espresso_pagination()
1009
-    {
1010
-        global $wp_query;
1011
-        $big        = 999999999; // need an unlikely integer
1012
-        $pagination = paginate_links(
1013
-            [
1014
-                'base'         => str_replace($big, '%#%', esc_url(get_pagenum_link($big))),
1015
-                'format'       => '?paged=%#%',
1016
-                'current'      => max(1, get_query_var('paged')),
1017
-                'total'        => $wp_query->max_num_pages,
1018
-                'show_all'     => true,
1019
-                'end_size'     => 10,
1020
-                'mid_size'     => 6,
1021
-                'prev_next'    => true,
1022
-                'prev_text'    => esc_html__('&lsaquo; PREV', 'event_espresso'),
1023
-                'next_text'    => esc_html__('NEXT &rsaquo;', 'event_espresso'),
1024
-                'type'         => 'plain',
1025
-                'add_args'     => false,
1026
-                'add_fragment' => '',
1027
-            ]
1028
-        );
1029
-        echo ! empty($pagination) ? '<div class="ee-pagination-dv ee-clear-float">' . $pagination . '</div>' : '';
1030
-    }
1002
+	/**
1003
+	 *    espresso_pagination
1004
+	 *
1005
+	 * @access    public
1006
+	 * @return    void
1007
+	 */
1008
+	function espresso_pagination()
1009
+	{
1010
+		global $wp_query;
1011
+		$big        = 999999999; // need an unlikely integer
1012
+		$pagination = paginate_links(
1013
+			[
1014
+				'base'         => str_replace($big, '%#%', esc_url(get_pagenum_link($big))),
1015
+				'format'       => '?paged=%#%',
1016
+				'current'      => max(1, get_query_var('paged')),
1017
+				'total'        => $wp_query->max_num_pages,
1018
+				'show_all'     => true,
1019
+				'end_size'     => 10,
1020
+				'mid_size'     => 6,
1021
+				'prev_next'    => true,
1022
+				'prev_text'    => esc_html__('&lsaquo; PREV', 'event_espresso'),
1023
+				'next_text'    => esc_html__('NEXT &rsaquo;', 'event_espresso'),
1024
+				'type'         => 'plain',
1025
+				'add_args'     => false,
1026
+				'add_fragment' => '',
1027
+			]
1028
+		);
1029
+		echo ! empty($pagination) ? '<div class="ee-pagination-dv ee-clear-float">' . $pagination . '</div>' : '';
1030
+	}
1031 1031
 }
Please login to merge, or discard this patch.
Spacing   +56 added lines, -56 removed lines patch added patch discarded remove patch
@@ -8,7 +8,7 @@  discard block
 block discarded – undo
8 8
 use EventEspresso\core\services\request\RequestInterface;
9 9
 use EventEspresso\core\services\request\sanitizers\AllowedTags;
10 10
 
11
-if (! function_exists('espresso_get_template_part')) {
11
+if ( ! function_exists('espresso_get_template_part')) {
12 12
     /**
13 13
      * espresso_get_template_part
14 14
      * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead, and doesn't add base versions of files
@@ -24,7 +24,7 @@  discard block
 block discarded – undo
24 24
 }
25 25
 
26 26
 
27
-if (! function_exists('espresso_get_object_css_class')) {
27
+if ( ! function_exists('espresso_get_object_css_class')) {
28 28
     /**
29 29
      * espresso_get_object_css_class - attempts to generate a css class based on the type of EE object passed
30 30
      *
@@ -74,9 +74,9 @@  discard block
 block discarded – undo
74 74
      */
75 75
     public static function load_espresso_theme_functions()
76 76
     {
77
-        if (! defined('EE_THEME_FUNCTIONS_LOADED')) {
78
-            if (is_readable(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php')) {
79
-                require_once(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php');
77
+        if ( ! defined('EE_THEME_FUNCTIONS_LOADED')) {
78
+            if (is_readable(EE_PUBLIC.EE_Config::get_current_theme().'/functions.php')) {
79
+                require_once(EE_PUBLIC.EE_Config::get_current_theme().'/functions.php');
80 80
             }
81 81
         }
82 82
     }
@@ -90,16 +90,16 @@  discard block
 block discarded – undo
90 90
     public static function get_espresso_themes(): array
91 91
     {
92 92
         if (empty(EEH_Template::$_espresso_themes)) {
93
-            $espresso_themes = glob(EE_PUBLIC . '*', GLOB_ONLYDIR);
93
+            $espresso_themes = glob(EE_PUBLIC.'*', GLOB_ONLYDIR);
94 94
             if (empty($espresso_themes)) {
95 95
                 return [];
96 96
             }
97 97
             if (($key = array_search('global_assets', $espresso_themes)) !== false) {
98
-                unset($espresso_themes[ $key ]);
98
+                unset($espresso_themes[$key]);
99 99
             }
100 100
             EEH_Template::$_espresso_themes = [];
101 101
             foreach ($espresso_themes as $espresso_theme) {
102
-                EEH_Template::$_espresso_themes[ basename($espresso_theme) ] = $espresso_theme;
102
+                EEH_Template::$_espresso_themes[basename($espresso_theme)] = $espresso_theme;
103 103
             }
104 104
         }
105 105
         return EEH_Template::$_espresso_themes;
@@ -126,7 +126,7 @@  discard block
 block discarded – undo
126 126
     ) {
127 127
         do_action("get_template_part_$slug-$name", $slug, $name);
128 128
         $template = $slug;
129
-        $name      = (string) $name;
129
+        $name = (string) $name;
130 130
         if ($name != '') {
131 131
             $template .= "-$name";
132 132
         }
@@ -245,10 +245,10 @@  discard block
 block discarded – undo
245 245
                 // get array of EE Custom Post Types
246 246
                 $EE_CPTs = $custom_post_types->getDefinitions();
247 247
                 // build template name based on request
248
-                if (isset($EE_CPTs[ $post_type ])) {
248
+                if (isset($EE_CPTs[$post_type])) {
249 249
                     $archive_or_single = is_archive() ? 'archive' : '';
250 250
                     $archive_or_single = is_single() ? 'single' : $archive_or_single;
251
-                    $templates[]       = $archive_or_single . '-' . $post_type . '.php';
251
+                    $templates[]       = $archive_or_single.'-'.$post_type.'.php';
252 252
                 }
253 253
             }
254 254
             // currently active EE template theme
@@ -257,12 +257,12 @@  discard block
 block discarded – undo
257 257
             $template_folder_paths = [];
258 258
 
259 259
             // add core plugin folders for checking only if we're not $check_if_custom
260
-            if (! $check_if_custom) {
261
-                $core_paths            = [
260
+            if ( ! $check_if_custom) {
261
+                $core_paths = [
262 262
                     // in the  /wp-content/plugins/(EE4 folder)/public/(current EE theme)/ folder within the plugin
263
-                    EE_PUBLIC . $current_theme,
263
+                    EE_PUBLIC.$current_theme,
264 264
                     // in the  /wp-content/plugins/(EE4 folder)/core/templates/(current EE theme)/ folder within the plugin
265
-                    EE_TEMPLATES . $current_theme,
265
+                    EE_TEMPLATES.$current_theme,
266 266
                     // or maybe relative from the plugin root: /wp-content/plugins/(EE4 folder)/
267 267
                     EE_PLUGIN_DIR_PATH,
268 268
                 ];
@@ -295,10 +295,10 @@  discard block
 block discarded – undo
295 295
                     );
296 296
                     if ($common_base_path !== '') {
297 297
                         // both paths have a common base, so just tack the filename onto our search path
298
-                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $file_name;
298
+                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path).$file_name;
299 299
                     } else {
300 300
                         // no common base path, so let's just concatenate
301
-                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $template;
301
+                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path).$template;
302 302
                     }
303 303
                     // build up our template locations array by adding our resolved paths
304 304
                     $full_template_paths[] = $resolved_path;
@@ -306,7 +306,7 @@  discard block
 block discarded – undo
306 306
                 // if $template is an absolute path, then we'll tack it onto the start of our array so that it gets searched first
307 307
                 array_unshift($full_template_paths, $template);
308 308
                 // path to the directory of the current theme: /wp-content/themes/(current WP theme)/
309
-                array_unshift($full_template_paths, get_stylesheet_directory() . '/' . $file_name);
309
+                array_unshift($full_template_paths, get_stylesheet_directory().'/'.$file_name);
310 310
             }
311 311
             // filter final array of full template paths
312 312
             $full_template_paths = apply_filters(
@@ -363,7 +363,7 @@  discard block
 block discarded – undo
363 363
                 }
364 364
             }
365 365
             $common_base_path .= $directory;
366
-            $last_offset      = $index + 1;
366
+            $last_offset = $index + 1;
367 367
         }
368 368
         return substr($common_base_path, 0, -1);
369 369
     }
@@ -404,7 +404,7 @@  discard block
 block discarded – undo
404 404
         );
405 405
 
406 406
         // you gimme nuttin - YOU GET NUTTIN !!
407
-        if (! $template_path || ! is_readable($template_path)) {
407
+        if ( ! $template_path || ! is_readable($template_path)) {
408 408
             // ignore whether template is accessible ?
409 409
             if ($throw_exceptions) {
410 410
                 throw new DomainException(
@@ -441,11 +441,11 @@  discard block
 block discarded – undo
441 441
     public static function get_object_css_class($object = null, $prefix = '', $suffix = '')
442 442
     {
443 443
         // in the beginning...
444
-        $prefix = ! empty($prefix) ? rtrim($prefix, '-') . '-' : '';
444
+        $prefix = ! empty($prefix) ? rtrim($prefix, '-').'-' : '';
445 445
         // da muddle
446 446
         $class = '';
447 447
         // the end
448
-        $suffix = ! empty($suffix) ? '-' . ltrim($suffix, '-') : '';
448
+        $suffix = ! empty($suffix) ? '-'.ltrim($suffix, '-') : '';
449 449
         // is the passed object an EE object ?
450 450
         if ($object instanceof EE_Base_Class) {
451 451
             // grab the exact type of object
@@ -453,9 +453,9 @@  discard block
 block discarded – undo
453 453
             // depending on the type of object...
454 454
             // no specifics just yet...
455 455
             $class = strtolower(str_replace('_', '-', $obj_class));
456
-            $class .= method_exists($obj_class, 'name') ? '-' . sanitize_title($object->name()) : '';
456
+            $class .= method_exists($obj_class, 'name') ? '-'.sanitize_title($object->name()) : '';
457 457
         }
458
-        return $prefix . $class . $suffix;
458
+        return $prefix.$class.$suffix;
459 459
     }
460 460
 
461 461
 
@@ -490,7 +490,7 @@  discard block
 block discarded – undo
490 490
         // filter raw amount (allows 0.00 to be changed to "free" for example)
491 491
         $amount_formatted = apply_filters('FHEE__EEH_Template__format_currency__amount', $amount, $return_raw);
492 492
         // still a number, or was amount converted to a string like "free" ?
493
-        if (! is_float($amount_formatted)) {
493
+        if ( ! is_float($amount_formatted)) {
494 494
             return esc_html($amount_formatted);
495 495
         }
496 496
         try {
@@ -501,7 +501,7 @@  discard block
 block discarded – undo
501 501
             $mny = null;
502 502
         }
503 503
         // verify results
504
-        if (! $mny instanceof EE_Currency_Config) {
504
+        if ( ! $mny instanceof EE_Currency_Config) {
505 505
             // set default config country currency settings
506 506
             $mny = EE_Registry::instance()->CFG->currency instanceof EE_Currency_Config
507 507
                 ? EE_Registry::instance()->CFG->currency
@@ -510,16 +510,16 @@  discard block
 block discarded – undo
510 510
         // format float
511 511
         $amount_formatted = number_format($amount, $mny->dec_plc, $mny->dec_mrk, $mny->thsnds);
512 512
         // add formatting ?
513
-        if (! $return_raw) {
513
+        if ( ! $return_raw) {
514 514
             // add currency sign
515 515
             if ($mny->sign_b4) {
516 516
                 if ($amount >= 0) {
517
-                    $amount_formatted = $mny->sign . $amount_formatted;
517
+                    $amount_formatted = $mny->sign.$amount_formatted;
518 518
                 } else {
519
-                    $amount_formatted = '-' . $mny->sign . str_replace('-', '', $amount_formatted);
519
+                    $amount_formatted = '-'.$mny->sign.str_replace('-', '', $amount_formatted);
520 520
                 }
521 521
             } else {
522
-                $amount_formatted = $amount_formatted . $mny->sign;
522
+                $amount_formatted = $amount_formatted.$mny->sign;
523 523
             }
524 524
 
525 525
             // filter to allow global setting of display_code
@@ -530,7 +530,7 @@  discard block
 block discarded – undo
530 530
 
531 531
             // add currency code ?
532 532
             $amount_formatted = $display_code
533
-                ? $amount_formatted . ' <span class="' . $cur_code_span_class . '">' . $mny->code . '</span>'
533
+                ? $amount_formatted.' <span class="'.$cur_code_span_class.'">'.$mny->code.'</span>'
534 534
                 : $amount_formatted;
535 535
         }
536 536
         // filter results
@@ -566,7 +566,7 @@  discard block
 block discarded – undo
566 566
             $plural,
567 567
             $schema
568 568
         );
569
-        return $status[ $status_id ];
569
+        return $status[$status_id];
570 570
     }
571 571
 
572 572
 
@@ -583,14 +583,14 @@  discard block
 block discarded – undo
583 583
     public static function get_button_or_link($url, $label, $class = 'button button--primary', $icon = '', $title = '')
584 584
     {
585 585
         $icon_html = '';
586
-        if (! empty($icon)) {
586
+        if ( ! empty($icon)) {
587 587
             $dashicons = preg_split("(ee-icon |dashicons )", $icon);
588 588
             $dashicons = array_filter($dashicons);
589 589
             $count     = count($dashicons);
590 590
             $icon_html .= $count > 1 ? '<span class="ee-composite-dashicon">' : '';
591 591
             foreach ($dashicons as $dashicon) {
592
-                $type      = strpos($dashicon, 'ee-icon') !== false ? 'ee-icon ' : 'dashicons ';
593
-                $icon_html .= '<span class="' . $type . $dashicon . '"></span>';
592
+                $type = strpos($dashicon, 'ee-icon') !== false ? 'ee-icon ' : 'dashicons ';
593
+                $icon_html .= '<span class="'.$type.$dashicon.'"></span>';
594 594
             }
595 595
             $icon_html .= $count > 1 ? '</span>' : '';
596 596
         }
@@ -629,18 +629,18 @@  discard block
 block discarded – undo
629 629
         $action  = $action ?: $request->getRequestParam('action', 'default', 'key');
630 630
 
631 631
 
632
-        $help_tab_lnk = $page . '-' . $action . '-' . $help_tab_id;
632
+        $help_tab_lnk = $page.'-'.$action.'-'.$help_tab_id;
633 633
         $icon         = ! $icon_style ? 'dashicons-editor-help' : $icon_style;
634 634
         $help_text    = ! $help_text ? '' : $help_text;
635 635
         return '
636
-            <a id="' . esc_attr($help_tab_lnk) . '"
637
-               class="espresso-help-tab-lnk ee-help-btn ee-aria-tooltip dashicons ' . esc_attr($icon) . '"
636
+            <a id="' . esc_attr($help_tab_lnk).'"
637
+               class="espresso-help-tab-lnk ee-help-btn ee-aria-tooltip dashicons ' . esc_attr($icon).'"
638 638
                aria-label="' . esc_attr__(
639 639
                    'Click to open the \'Help\' tab for more information about this feature.',
640 640
                    'event_espresso'
641
-               ) . '"
641
+               ).'"
642 642
             >
643
-                ' . wp_kses($help_text, AllowedTags::getAllowedTags()) . '
643
+                ' . wp_kses($help_text, AllowedTags::getAllowedTags()).'
644 644
             </a>';
645 645
     }
646 646
 
@@ -661,7 +661,7 @@  discard block
 block discarded – undo
661 661
      */
662 662
     public static function status_legend($status_array, $active_status = '')
663 663
     {
664
-        if (! is_array($status_array)) {
664
+        if ( ! is_array($status_array)) {
665 665
             throw new EE_Error(
666 666
                 esc_html__(
667 667
                     'The EEH_Template::status_legend helper required the incoming status_array argument to be an array!',
@@ -673,17 +673,17 @@  discard block
 block discarded – undo
673 673
         $content = '
674 674
             <div class="ee-list-table-legend-container">
675 675
                 <h4 class="status-legend-title">
676
-                    ' . esc_html__('Status Legend', 'event_espresso') . '
676
+                    ' . esc_html__('Status Legend', 'event_espresso').'
677 677
                 </h4>
678 678
                 <dl class="ee-list-table-legend">';
679 679
 
680 680
         foreach ($status_array as $item => $status) {
681 681
             $active_class = $active_status == $status ? 'class="ee-is-active-status"' : '';
682
-            $content      .= '
683
-                    <dt id="' . esc_attr('ee-legend-item-tooltip-' . $item) . '" ' . $active_class . '>
684
-                        <span class="' . esc_attr('ee-status-legend ee-status-bg--' . $status) . '"></span>
682
+            $content .= '
683
+                    <dt id="' . esc_attr('ee-legend-item-tooltip-'.$item).'" '.$active_class.'>
684
+                        <span class="' . esc_attr('ee-status-legend ee-status-bg--'.$status).'"></span>
685 685
                         <span class="ee-legend-description">
686
-                            ' . EEH_Template::pretty_status($status, false, 'sentence') . '
686
+                            ' . EEH_Template::pretty_status($status, false, 'sentence').'
687 687
                         </span>
688 688
                     </dt>';
689 689
         }
@@ -826,8 +826,8 @@  discard block
 block discarded – undo
826 826
             ];
827 827
         } else {
828 828
             $items_label = [
829
-                'single' => '1 ' . esc_html($items_label['single']),
830
-                'plural' => '%s ' . esc_html($items_label['plural']),
829
+                'single' => '1 '.esc_html($items_label['single']),
830
+                'plural' => '%s '.esc_html($items_label['plural']),
831 831
             ];
832 832
         }
833 833
 
@@ -839,7 +839,7 @@  discard block
 block discarded – undo
839 839
 
840 840
         $item_label = $total_items > 1 ? sprintf($items_label['plural'], $total_items) : $items_label['single'];
841 841
 
842
-        $output = '<span class="displaying-num">' . $item_label . '</span>';
842
+        $output = '<span class="displaying-num">'.$item_label.'</span>';
843 843
 
844 844
         $disable_first = $current === 1 ? 'disabled' : '';
845 845
         $disable_last  = $current === $total_pages ? 'disabled' : '';
@@ -876,7 +876,7 @@  discard block
 block discarded – undo
876 876
             '<span class="total-pages">%s</span>',
877 877
             number_format_i18n($total_pages)
878 878
         );
879
-        $page_links[]     = sprintf(
879
+        $page_links[] = sprintf(
880 880
             _x('%3$s%1$s of %2$s%4$s', 'paging', 'event_espresso'),
881 881
             "{$html_current_page}<span class='paging-input-of'>",
882 882
             "</span>{$html_total_pages}",
@@ -900,14 +900,14 @@  discard block
 block discarded – undo
900 900
             '&raquo;'
901 901
         );
902 902
 
903
-        $output .= "\n" . '<span class="pagination-links">' . join("\n", $page_links) . '</span>';
903
+        $output .= "\n".'<span class="pagination-links">'.join("\n", $page_links).'</span>';
904 904
 
905 905
         $page_class = ' no-pages';
906 906
         if ($total_pages) {
907 907
             $page_class = $total_pages < 2 ? ' one-page' : '';
908 908
         }
909 909
 
910
-        return '<div class="tablenav"><div class="tablenav-pages' . $page_class . '">' . $output . '</div></div>';
910
+        return '<div class="tablenav"><div class="tablenav-pages'.$page_class.'">'.$output.'</div></div>';
911 911
     }
912 912
 
913 913
 
@@ -962,7 +962,7 @@  discard block
 block discarded – undo
962 962
         );
963 963
         $powered_by = apply_filters(
964 964
             'FHEE__EEH_Template__powered_by_event_espresso_text',
965
-            $admin ? 'Event Espresso - ' . EVENT_ESPRESSO_VERSION : 'Event Espresso'
965
+            $admin ? 'Event Espresso - '.EVENT_ESPRESSO_VERSION : 'Event Espresso'
966 966
         );
967 967
         $url        = add_query_arg($query_args, 'https://eventespresso.com/');
968 968
         $url        = apply_filters('FHEE__EEH_Template__powered_by_event_espresso__url', $url);
@@ -993,12 +993,12 @@  discard block
 block discarded – undo
993 993
      */
994 994
     public static function getScreenshotUrl($image_name)
995 995
     {
996
-        return esc_url_raw(EE_GLOBAL_ASSETS_URL . 'images/screenshots/' . $image_name . '.jpg');
996
+        return esc_url_raw(EE_GLOBAL_ASSETS_URL.'images/screenshots/'.$image_name.'.jpg');
997 997
     }
998 998
 }
999 999
 
1000 1000
 
1001
-if (! function_exists('espresso_pagination')) {
1001
+if ( ! function_exists('espresso_pagination')) {
1002 1002
     /**
1003 1003
      *    espresso_pagination
1004 1004
      *
@@ -1026,6 +1026,6 @@  discard block
 block discarded – undo
1026 1026
                 'add_fragment' => '',
1027 1027
             ]
1028 1028
         );
1029
-        echo ! empty($pagination) ? '<div class="ee-pagination-dv ee-clear-float">' . $pagination . '</div>' : '';
1029
+        echo ! empty($pagination) ? '<div class="ee-pagination-dv ee-clear-float">'.$pagination.'</div>' : '';
1030 1030
     }
1031 1031
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Array.helper.php 1 patch
Indentation   +315 added lines, -315 removed lines patch added patch discarded remove patch
@@ -11,345 +11,345 @@
 block discarded – undo
11 11
  */
12 12
 class EEH_Array extends EEH_Base
13 13
 {
14
-    /**
15
-     * This method basically works the same as the PHP core function array_diff except it allows you to compare arrays
16
-     * of EE_Base_Class objects NOTE: This will ONLY work on an array of EE_Base_Class objects
17
-     *
18
-     * @param array $array1 an array of objects
19
-     * @param array $array2 an array of objects
20
-     * @return array         an array of objects found in array 1 that aren't found in array 2.
21
-     * @uses self::_compare_objects as the custom method for array_udiff
22
-     * @uses array_udiff core php function for setting up our own array comparison
23
-     */
24
-    public static function object_array_diff(array $array1, array $array2): array
25
-    {
26
-        return array_udiff($array1, $array2, ['self', '_compare_objects']);
27
-    }
14
+	/**
15
+	 * This method basically works the same as the PHP core function array_diff except it allows you to compare arrays
16
+	 * of EE_Base_Class objects NOTE: This will ONLY work on an array of EE_Base_Class objects
17
+	 *
18
+	 * @param array $array1 an array of objects
19
+	 * @param array $array2 an array of objects
20
+	 * @return array         an array of objects found in array 1 that aren't found in array 2.
21
+	 * @uses self::_compare_objects as the custom method for array_udiff
22
+	 * @uses array_udiff core php function for setting up our own array comparison
23
+	 */
24
+	public static function object_array_diff(array $array1, array $array2): array
25
+	{
26
+		return array_udiff($array1, $array2, ['self', '_compare_objects']);
27
+	}
28 28
 
29 29
 
30
-    /**
31
-     * Given that $array is an array, determines if it's associative or numerically AND sequentially indexed
32
-     *
33
-     * @param array $array
34
-     * @return boolean
35
-     */
36
-    public static function is_associative_array(array $array): bool
37
-    {
38
-        return ! empty($array) && array_keys($array) !== range(0, count($array) - 1);
39
-    }
30
+	/**
31
+	 * Given that $array is an array, determines if it's associative or numerically AND sequentially indexed
32
+	 *
33
+	 * @param array $array
34
+	 * @return boolean
35
+	 */
36
+	public static function is_associative_array(array $array): bool
37
+	{
38
+		return ! empty($array) && array_keys($array) !== range(0, count($array) - 1);
39
+	}
40 40
 
41 41
 
42
-    /**
43
-     * Gets an item from the array and leave the array intact. Use in place of end()
44
-     * when you don't want to change the array
45
-     *
46
-     * @param array $array
47
-     * @return mixed what ever is in the array
48
-     */
49
-    public static function get_one_item_from_array(array $array)
50
-    {
51
-        $item = end($array);
52
-        reset($array);
53
-        return $item;
54
-    }
42
+	/**
43
+	 * Gets an item from the array and leave the array intact. Use in place of end()
44
+	 * when you don't want to change the array
45
+	 *
46
+	 * @param array $array
47
+	 * @return mixed what ever is in the array
48
+	 */
49
+	public static function get_one_item_from_array(array $array)
50
+	{
51
+		$item = end($array);
52
+		reset($array);
53
+		return $item;
54
+	}
55 55
 
56 56
 
57
-    /**
58
-     * Detects if this is a multidimensional array
59
-     * meaning that at least one top-level value is an array. Eg [ [], ...]
60
-     *
61
-     * @param mixed $array
62
-     * @return boolean
63
-     */
64
-    public static function is_multi_dimensional_array($array): bool
65
-    {
66
-        if (is_array($array)) {
67
-            foreach ($array as $item) {
68
-                if (is_array($item)) {
69
-                    return true; // yep, there's at least 2 levels to this array
70
-                }
71
-            }
72
-        }
73
-        return false; // there's only 1 level, or it's not an array at all!
74
-    }
57
+	/**
58
+	 * Detects if this is a multidimensional array
59
+	 * meaning that at least one top-level value is an array. Eg [ [], ...]
60
+	 *
61
+	 * @param mixed $array
62
+	 * @return boolean
63
+	 */
64
+	public static function is_multi_dimensional_array($array): bool
65
+	{
66
+		if (is_array($array)) {
67
+			foreach ($array as $item) {
68
+				if (is_array($item)) {
69
+					return true; // yep, there's at least 2 levels to this array
70
+				}
71
+			}
72
+		}
73
+		return false; // there's only 1 level, or it's not an array at all!
74
+	}
75 75
 
76 76
 
77
-    /**
78
-     * Shorthand for isset( $array[ $index ] ) ? $array[ $index ] : $default
79
-     *
80
-     * @param array $array
81
-     * @param mixed $index
82
-     * @param mixed $default
83
-     * @return mixed
84
-     */
85
-    public static function is_set(array $array, $index, $default)
86
-    {
87
-        return $array[ $index ] ?? $default;
88
-    }
77
+	/**
78
+	 * Shorthand for isset( $array[ $index ] ) ? $array[ $index ] : $default
79
+	 *
80
+	 * @param array $array
81
+	 * @param mixed $index
82
+	 * @param mixed $default
83
+	 * @return mixed
84
+	 */
85
+	public static function is_set(array $array, $index, $default)
86
+	{
87
+		return $array[ $index ] ?? $default;
88
+	}
89 89
 
90 90
 
91
-    /**
92
-     * Exactly like `maybe_unserialize`, but also accounts for a WP bug: http://core.trac.wordpress.org/ticket/26118
93
-     *
94
-     * @param mixed $value usually a string, but could be an array or object
95
-     * @return mixed the UN-serialized data
96
-     */
97
-    public static function maybe_unserialize($value)
98
-    {
99
-        $data = maybe_unserialize($value);
100
-        // it's possible that this still has serialized data if it's the session.
101
-        //  WP has a bug, http://core.trac.wordpress.org/ticket/26118 that doesn't unserialize this automatically.
102
-        $token = 'C';
103
-        $data  = is_string($data) ? trim($data) : $data;
104
-        if (is_string($data) && strlen($data) > 1 && $data[0] == $token && preg_match("/^$token:[0-9]+:/s", $data)) {
105
-            return unserialize($data);
106
-        }
107
-        return $data;
108
-    }
91
+	/**
92
+	 * Exactly like `maybe_unserialize`, but also accounts for a WP bug: http://core.trac.wordpress.org/ticket/26118
93
+	 *
94
+	 * @param mixed $value usually a string, but could be an array or object
95
+	 * @return mixed the UN-serialized data
96
+	 */
97
+	public static function maybe_unserialize($value)
98
+	{
99
+		$data = maybe_unserialize($value);
100
+		// it's possible that this still has serialized data if it's the session.
101
+		//  WP has a bug, http://core.trac.wordpress.org/ticket/26118 that doesn't unserialize this automatically.
102
+		$token = 'C';
103
+		$data  = is_string($data) ? trim($data) : $data;
104
+		if (is_string($data) && strlen($data) > 1 && $data[0] == $token && preg_match("/^$token:[0-9]+:/s", $data)) {
105
+			return unserialize($data);
106
+		}
107
+		return $data;
108
+	}
109 109
 
110 110
 
111
-    /**
112
-     * insert_into_array
113
-     *
114
-     * @param array           $target_array    the array to insert new data into
115
-     * @param array           $array_to_insert the new data to be inserted
116
-     * @param int|string|null $offset          a known key within $target_array where new data will be inserted
117
-     * @param bool            $add_before      whether to add new data before or after the offset key
118
-     * @param bool            $preserve_keys   whether to reset numerically indexed arrays
119
-     * @return array
120
-     */
121
-    public static function insert_into_array(
122
-        array $target_array = [],
123
-        array $array_to_insert = [],
124
-        $offset = null,
125
-        bool $add_before = true,
126
-        bool $preserve_keys = true
127
-    ): array {
128
-        $target_array_keys = array_keys($target_array);
129
-        // if no offset key was supplied
130
-        if (empty($offset)) {
131
-            // use start or end of $target_array based on whether we are adding before or not
132
-            $offset = $add_before ? 0 : count($target_array);
133
-        }
134
-        // if offset key is a string, then find the corresponding numeric location for that element
135
-        $offset = is_int($offset) ? $offset : array_search($offset, $target_array_keys, true);
136
-        // add one to the offset if adding after
137
-        $offset = $add_before ? $offset : $offset + 1;
138
-        // but ensure offset does not exceed the length of the array
139
-        $offset = $offset > count($target_array) ? count($target_array) : $offset;
140
-        // reindex array ???
141
-        if ($preserve_keys) {
142
-            // take a slice of the target array from the beginning till the offset,
143
-            // then add the new data
144
-            // then add another slice that starts at the offset and goes till the end
145
-            return array_slice($target_array, 0, $offset, true)
146
-                + $array_to_insert
147
-                + array_slice($target_array, $offset, null, true);
148
-        }
149
-        // since we don't want to preserve keys, we can use array_splice
150
-        array_splice($target_array, $offset, 0, $array_to_insert);
151
-        return $target_array;
152
-    }
111
+	/**
112
+	 * insert_into_array
113
+	 *
114
+	 * @param array           $target_array    the array to insert new data into
115
+	 * @param array           $array_to_insert the new data to be inserted
116
+	 * @param int|string|null $offset          a known key within $target_array where new data will be inserted
117
+	 * @param bool            $add_before      whether to add new data before or after the offset key
118
+	 * @param bool            $preserve_keys   whether to reset numerically indexed arrays
119
+	 * @return array
120
+	 */
121
+	public static function insert_into_array(
122
+		array $target_array = [],
123
+		array $array_to_insert = [],
124
+		$offset = null,
125
+		bool $add_before = true,
126
+		bool $preserve_keys = true
127
+	): array {
128
+		$target_array_keys = array_keys($target_array);
129
+		// if no offset key was supplied
130
+		if (empty($offset)) {
131
+			// use start or end of $target_array based on whether we are adding before or not
132
+			$offset = $add_before ? 0 : count($target_array);
133
+		}
134
+		// if offset key is a string, then find the corresponding numeric location for that element
135
+		$offset = is_int($offset) ? $offset : array_search($offset, $target_array_keys, true);
136
+		// add one to the offset if adding after
137
+		$offset = $add_before ? $offset : $offset + 1;
138
+		// but ensure offset does not exceed the length of the array
139
+		$offset = $offset > count($target_array) ? count($target_array) : $offset;
140
+		// reindex array ???
141
+		if ($preserve_keys) {
142
+			// take a slice of the target array from the beginning till the offset,
143
+			// then add the new data
144
+			// then add another slice that starts at the offset and goes till the end
145
+			return array_slice($target_array, 0, $offset, true)
146
+				+ $array_to_insert
147
+				+ array_slice($target_array, $offset, null, true);
148
+		}
149
+		// since we don't want to preserve keys, we can use array_splice
150
+		array_splice($target_array, $offset, 0, $array_to_insert);
151
+		return $target_array;
152
+	}
153 153
 
154 154
 
155
-    /**
156
-     * array_merge() is slow and should never be used while looping over data
157
-     * if you don't need to preserve keys from all arrays, then using a foreach loop is much faster
158
-     * so really this acts more like array_replace( $array1, $array2 )
159
-     * or a union with the arrays flipped ( $array2 + $array1 )
160
-     * this saves a few lines of code and improves readability
161
-     *
162
-     * @param array $array1
163
-     * @param array $array2
164
-     * @return array
165
-     */
166
-    public static function merge_arrays_and_overwrite_keys(array $array1, array $array2): array
167
-    {
168
-        foreach ($array2 as $key => $value) {
169
-            $array1[ $key ] = $value;
170
-        }
171
-        return $array1;
172
-    }
155
+	/**
156
+	 * array_merge() is slow and should never be used while looping over data
157
+	 * if you don't need to preserve keys from all arrays, then using a foreach loop is much faster
158
+	 * so really this acts more like array_replace( $array1, $array2 )
159
+	 * or a union with the arrays flipped ( $array2 + $array1 )
160
+	 * this saves a few lines of code and improves readability
161
+	 *
162
+	 * @param array $array1
163
+	 * @param array $array2
164
+	 * @return array
165
+	 */
166
+	public static function merge_arrays_and_overwrite_keys(array $array1, array $array2): array
167
+	{
168
+		foreach ($array2 as $key => $value) {
169
+			$array1[ $key ] = $value;
170
+		}
171
+		return $array1;
172
+	}
173 173
 
174 174
 
175
-    /**
176
-     * given a flat array like $array = array('A', 'B', 'C')
177
-     * will convert into a multidimensional array like $array[A][B][C]
178
-     * if $final_value is provided and is anything other than null,
179
-     * then that will be set as the value for the innermost array key
180
-     * like so: $array[A][B][C] = $final_value
181
-     *
182
-     * @param array $flat_array
183
-     * @param mixed $final_value
184
-     * @return array
185
-     */
186
-    public static function convert_array_values_to_keys(array $flat_array, $final_value = null): array
187
-    {
188
-        $multidimensional = [];
189
-        $reference        = &$multidimensional;
190
-        foreach ($flat_array as $key) {
191
-            $reference[ $key ] = [];
192
-            $reference         = &$reference[ $key ];
193
-        }
194
-        if ($final_value !== null) {
195
-            $reference = $final_value;
196
-        }
197
-        return $multidimensional;
198
-    }
175
+	/**
176
+	 * given a flat array like $array = array('A', 'B', 'C')
177
+	 * will convert into a multidimensional array like $array[A][B][C]
178
+	 * if $final_value is provided and is anything other than null,
179
+	 * then that will be set as the value for the innermost array key
180
+	 * like so: $array[A][B][C] = $final_value
181
+	 *
182
+	 * @param array $flat_array
183
+	 * @param mixed $final_value
184
+	 * @return array
185
+	 */
186
+	public static function convert_array_values_to_keys(array $flat_array, $final_value = null): array
187
+	{
188
+		$multidimensional = [];
189
+		$reference        = &$multidimensional;
190
+		foreach ($flat_array as $key) {
191
+			$reference[ $key ] = [];
192
+			$reference         = &$reference[ $key ];
193
+		}
194
+		if ($final_value !== null) {
195
+			$reference = $final_value;
196
+		}
197
+		return $multidimensional;
198
+	}
199 199
 
200 200
 
201
-    /**
202
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
203
-     * @param array $array
204
-     * @return bool
205
-     */
206
-    public static function is_array_numerically_and_sequentially_indexed(array $array): bool
207
-    {
208
-        return empty($array) || array_keys($array) === range(0, count($array) - 1);
209
-    }
201
+	/**
202
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
203
+	 * @param array $array
204
+	 * @return bool
205
+	 */
206
+	public static function is_array_numerically_and_sequentially_indexed(array $array): bool
207
+	{
208
+		return empty($array) || array_keys($array) === range(0, count($array) - 1);
209
+	}
210 210
 
211 211
 
212
-    /**
213
-     * recursively walks through an array and adds slashes to all no array elements
214
-     *
215
-     * @param mixed $element
216
-     * @return array|string
217
-     * @since   4.10.29.p
218
-     */
219
-    public static function addSlashesRecursively($element)
220
-    {
221
-        if (is_array($element)) {
222
-            foreach ($element as $key => $value) {
223
-                $element[ $key ] = EEH_Array::addSlashesRecursively($value);
224
-            }
225
-            return $element;
226
-        }
227
-        return is_string($element) ? addslashes($element) : $element;
228
-    }
212
+	/**
213
+	 * recursively walks through an array and adds slashes to all no array elements
214
+	 *
215
+	 * @param mixed $element
216
+	 * @return array|string
217
+	 * @since   4.10.29.p
218
+	 */
219
+	public static function addSlashesRecursively($element)
220
+	{
221
+		if (is_array($element)) {
222
+			foreach ($element as $key => $value) {
223
+				$element[ $key ] = EEH_Array::addSlashesRecursively($value);
224
+			}
225
+			return $element;
226
+		}
227
+		return is_string($element) ? addslashes($element) : $element;
228
+	}
229 229
 
230 230
 
231
-    /**
232
-     * link https://stackoverflow.com/a/3877494
233
-     *
234
-     * @param array $array_1
235
-     * @param array $array_2
236
-     * @return array
237
-     * @since   5.0.0.p
238
-     */
239
-    public static function array_diff_recursive(array $array_1, array $array_2): array
240
-    {
241
-        $diff = [];
242
-        foreach ($array_1 as $key => $value) {
243
-            if (array_key_exists($key, $array_2)) {
244
-                if (is_array($value)) {
245
-                    $inner_diff = EEH_Array::array_diff_recursive($value, $array_2[ $key ]);
246
-                    if (count($inner_diff)) {
247
-                        $diff[ $key ] = $inner_diff;
248
-                    }
249
-                } else {
250
-                    if ($value != $array_2[ $key ]) {
251
-                        $diff[ $key ] = $value;
252
-                    }
253
-                }
254
-            } else {
255
-                $diff[ $key ] = $value;
256
-            }
257
-        }
258
-        return $diff;
259
-    }
231
+	/**
232
+	 * link https://stackoverflow.com/a/3877494
233
+	 *
234
+	 * @param array $array_1
235
+	 * @param array $array_2
236
+	 * @return array
237
+	 * @since   5.0.0.p
238
+	 */
239
+	public static function array_diff_recursive(array $array_1, array $array_2): array
240
+	{
241
+		$diff = [];
242
+		foreach ($array_1 as $key => $value) {
243
+			if (array_key_exists($key, $array_2)) {
244
+				if (is_array($value)) {
245
+					$inner_diff = EEH_Array::array_diff_recursive($value, $array_2[ $key ]);
246
+					if (count($inner_diff)) {
247
+						$diff[ $key ] = $inner_diff;
248
+					}
249
+				} else {
250
+					if ($value != $array_2[ $key ]) {
251
+						$diff[ $key ] = $value;
252
+					}
253
+				}
254
+			} else {
255
+				$diff[ $key ] = $value;
256
+			}
257
+		}
258
+		return $diff;
259
+	}
260 260
 
261 261
 
262
-    /**
263
-     * converts multidimensional arrays into a single depth associative array
264
-     * or converts arrays of any depth into a readable string representation
265
-     *
266
-     *  $example = [
267
-     *      'a' => 'A',
268
-     *      'b' => 'B',
269
-     *      'c' => [
270
-     *          'd' => 'D',
271
-     *          'e' => 'E',
272
-     *          'f' => [ 'G', 'H', 'I' ],
273
-     *      ],
274
-     *      [ 'J', 'K' ],
275
-     *      'L',
276
-     *      'M',
277
-     *      'n' => [
278
-     *          'o' => 'P'
279
-     *      ],
280
-     *  ];
281
-     *
282
-     *  print_r( EEH_Array::flattenArray($example) );
283
-     *
284
-     *  Array (
285
-     *      [a] => A
286
-     *      [b] => B
287
-     *      [c] => [ d:D, e:E, f:[ G, H, I ] ]
288
-     *      [0] => [ J, K ]
289
-     *      [1] => L
290
-     *      [2] => M
291
-     *      [n] => [ o:P ]
292
-     *  )
293
-     *
294
-     *  print_r( EEH_Array::flattenArray($example, true) );
295
-     *
296
-     *  "a:A, b:B, c:[ d:D, e:E, f:[ G, H, I ] ], [ J, K ], L, M, n:[ o:P ]"
297
-     *
298
-     * @param array $array      the array to be flattened
299
-     * @param bool  $to_string  [true] will flatten the entire array down into a string
300
-     *                          [false] will only flatten sub-arrays down into strings and return an array
301
-     * @param bool  $top_level  used for formatting purposes only, best to leave this alone as it's set internally
302
-     * @return array|false|string
303
-     * @since 5.0.0.p
304
-     */
305
-    public static function flattenArray(array $array, bool $to_string = false, bool $top_level = true)
306
-    {
307
-        $flat_array = [];
308
-        foreach ($array as $key => $value) {
309
-            $flat_array[ $key ] = is_array($value)
310
-                ? EEH_Array::flattenArray($value, true, false)
311
-                : $value;
312
-        }
313
-        if (! $to_string) {
314
-            return $flat_array;
315
-        }
316
-        $flat = '';
317
-        foreach ($flat_array as $key => $value) {
318
-            $flat .= is_int($key) ? "$value, " : "$key:$value, ";
319
-        }
320
-        $flat = substr($flat, 0, -2);
321
-        return $top_level ? $flat : "[ $flat ]";
322
-    }
262
+	/**
263
+	 * converts multidimensional arrays into a single depth associative array
264
+	 * or converts arrays of any depth into a readable string representation
265
+	 *
266
+	 *  $example = [
267
+	 *      'a' => 'A',
268
+	 *      'b' => 'B',
269
+	 *      'c' => [
270
+	 *          'd' => 'D',
271
+	 *          'e' => 'E',
272
+	 *          'f' => [ 'G', 'H', 'I' ],
273
+	 *      ],
274
+	 *      [ 'J', 'K' ],
275
+	 *      'L',
276
+	 *      'M',
277
+	 *      'n' => [
278
+	 *          'o' => 'P'
279
+	 *      ],
280
+	 *  ];
281
+	 *
282
+	 *  print_r( EEH_Array::flattenArray($example) );
283
+	 *
284
+	 *  Array (
285
+	 *      [a] => A
286
+	 *      [b] => B
287
+	 *      [c] => [ d:D, e:E, f:[ G, H, I ] ]
288
+	 *      [0] => [ J, K ]
289
+	 *      [1] => L
290
+	 *      [2] => M
291
+	 *      [n] => [ o:P ]
292
+	 *  )
293
+	 *
294
+	 *  print_r( EEH_Array::flattenArray($example, true) );
295
+	 *
296
+	 *  "a:A, b:B, c:[ d:D, e:E, f:[ G, H, I ] ], [ J, K ], L, M, n:[ o:P ]"
297
+	 *
298
+	 * @param array $array      the array to be flattened
299
+	 * @param bool  $to_string  [true] will flatten the entire array down into a string
300
+	 *                          [false] will only flatten sub-arrays down into strings and return an array
301
+	 * @param bool  $top_level  used for formatting purposes only, best to leave this alone as it's set internally
302
+	 * @return array|false|string
303
+	 * @since 5.0.0.p
304
+	 */
305
+	public static function flattenArray(array $array, bool $to_string = false, bool $top_level = true)
306
+	{
307
+		$flat_array = [];
308
+		foreach ($array as $key => $value) {
309
+			$flat_array[ $key ] = is_array($value)
310
+				? EEH_Array::flattenArray($value, true, false)
311
+				: $value;
312
+		}
313
+		if (! $to_string) {
314
+			return $flat_array;
315
+		}
316
+		$flat = '';
317
+		foreach ($flat_array as $key => $value) {
318
+			$flat .= is_int($key) ? "$value, " : "$key:$value, ";
319
+		}
320
+		$flat = substr($flat, 0, -2);
321
+		return $top_level ? $flat : "[ $flat ]";
322
+	}
323 323
 
324 324
 
325
-    /**
326
-     * Filters elements of an array using a callback function recursively.
327
-     *
328
-     * This method applies a user-supplied function to each element of the input array recursively.
329
-     * It preserves keys by default. The array is traversed in a depth-first manner.
330
-     * It also provides an option to remove empty elements.
331
-     *
332
-     * @param array    $array        The input array to filter.
333
-     * @param callable $filter       The callback function to use. If the function returns true,
334
-     *                               the current value from array is returned into the result array.
335
-     * @param bool     $remove_empty Optional parameter to remove empty elements. Default is false.
336
-     * @return array The filtered array.
337
-     */
338
-    public static function arrayFilterRecursive(array $array, callable $filter, bool $remove_empty = false): array
339
-    {
340
-        $filtered = [];
341
-        foreach ($array as $key => $value) {
342
-            if (is_array($value)) {
343
-                $value = EEH_Array::arrayFilterRecursive($value, $filter);
344
-                if (! ($remove_empty && empty($value))) {
345
-                    $filtered[ $key ] = $value;
346
-                }
347
-            } else {
348
-                if (! ($remove_empty && empty($value)) && $filter($value, $key)) {
349
-                    $filtered[ $key ] = $value;
350
-                }
351
-            }
352
-        }
353
-        return $filtered;
354
-    }
325
+	/**
326
+	 * Filters elements of an array using a callback function recursively.
327
+	 *
328
+	 * This method applies a user-supplied function to each element of the input array recursively.
329
+	 * It preserves keys by default. The array is traversed in a depth-first manner.
330
+	 * It also provides an option to remove empty elements.
331
+	 *
332
+	 * @param array    $array        The input array to filter.
333
+	 * @param callable $filter       The callback function to use. If the function returns true,
334
+	 *                               the current value from array is returned into the result array.
335
+	 * @param bool     $remove_empty Optional parameter to remove empty elements. Default is false.
336
+	 * @return array The filtered array.
337
+	 */
338
+	public static function arrayFilterRecursive(array $array, callable $filter, bool $remove_empty = false): array
339
+	{
340
+		$filtered = [];
341
+		foreach ($array as $key => $value) {
342
+			if (is_array($value)) {
343
+				$value = EEH_Array::arrayFilterRecursive($value, $filter);
344
+				if (! ($remove_empty && empty($value))) {
345
+					$filtered[ $key ] = $value;
346
+				}
347
+			} else {
348
+				if (! ($remove_empty && empty($value)) && $filter($value, $key)) {
349
+					$filtered[ $key ] = $value;
350
+				}
351
+			}
352
+		}
353
+		return $filtered;
354
+	}
355 355
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Line_Item.helper.php 2 patches
Indentation   +2233 added lines, -2233 removed lines patch added patch discarded remove patch
@@ -21,2237 +21,2237 @@
 block discarded – undo
21 21
  */
22 22
 class EEH_Line_Item
23 23
 {
24
-    /**
25
-     * @var EE_Line_Item[]|null
26
-     */
27
-    private static ?array $global_taxes = null;
28
-
29
-
30
-    /**
31
-     * Adds a simple item (unrelated to any other model object) to the provided PARENT line item.
32
-     * Does NOT automatically re-calculate the line item totals or update the related transaction.
33
-     * You should call recalculate_total_including_taxes() on the grant total line item after this
34
-     * to update the subtotals, and EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
35
-     * to keep the registration final prices in-sync with the transaction's total.
36
-     *
37
-     * @param EE_Line_Item $parent_line_item
38
-     * @param string       $name
39
-     * @param float        $unit_price
40
-     * @param string       $description
41
-     * @param int          $quantity
42
-     * @param boolean      $taxable
43
-     * @param string|null  $code if set to a value, ensures there is only one line item with that code
44
-     * @param bool         $return_item
45
-     * @param bool         $recalculate_totals
46
-     * @return boolean|EE_Line_Item success
47
-     * @throws EE_Error
48
-     * @throws ReflectionException
49
-     */
50
-    public static function add_unrelated_item(
51
-        EE_Line_Item $parent_line_item,
52
-        string $name,
53
-        float $unit_price,
54
-        string $description = '',
55
-        int $quantity = 1,
56
-        bool $taxable = false,
57
-        ?string $code = null,
58
-        bool $return_item = false,
59
-        bool $recalculate_totals = true
60
-    ) {
61
-        $items_subtotal = self::get_pre_tax_subtotal($parent_line_item);
62
-        $line_item      = EE_Line_Item::new_instance(
63
-            [
64
-                'LIN_name'       => $name,
65
-                'LIN_desc'       => $description,
66
-                'LIN_unit_price' => $unit_price,
67
-                'LIN_quantity'   => $quantity,
68
-                'LIN_percent'    => null,
69
-                'LIN_is_taxable' => $taxable,
70
-                'LIN_order'      => count($items_subtotal->children()),
71
-                'LIN_total'      => $unit_price * $quantity,
72
-                'LIN_type'       => EEM_Line_Item::type_line_item,
73
-                'LIN_code'       => $code,
74
-            ]
75
-        );
76
-        $line_item      = apply_filters(
77
-            'FHEE__EEH_Line_Item__add_unrelated_item__line_item',
78
-            $line_item,
79
-            $parent_line_item
80
-        );
81
-        $added          = self::add_item($parent_line_item, $line_item, $recalculate_totals);
82
-        return $return_item ? $line_item : $added;
83
-    }
84
-
85
-
86
-    /**
87
-     * Adds a simple item ( unrelated to any other model object) to the total line item,
88
-     * in the correct spot in the line item tree. Does not automatically
89
-     * re-calculate the line item totals, nor update the related transaction, nor upgrade the transaction's
90
-     * registrations' final prices (which should probably change because of this).
91
-     * You should call recalculate_total_including_taxes() on the grand total line item, then
92
-     * update the transaction's total, and EE_Registration_Processor::update_registration_final_prices()
93
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
94
-     *
95
-     * @param EE_Line_Item $parent_line_item
96
-     * @param string       $name
97
-     * @param float        $percentage_amount
98
-     * @param string       $description
99
-     * @param boolean      $taxable
100
-     * @param string|null  $code
101
-     * @param bool         $return_item
102
-     * @return boolean|EE_Line_Item success
103
-     * @throws EE_Error
104
-     * @throws ReflectionException
105
-     */
106
-    public static function add_percentage_based_item(
107
-        EE_Line_Item $parent_line_item,
108
-        string $name,
109
-        float $percentage_amount,
110
-        string $description = '',
111
-        bool $taxable = false,
112
-        ?string $code = null,
113
-        bool $return_item = false
114
-    ) {
115
-        $total     = $percentage_amount * $parent_line_item->total() / 100;
116
-        $line_item = EE_Line_Item::new_instance(
117
-            [
118
-                'LIN_name'       => $name,
119
-                'LIN_desc'       => $description,
120
-                'LIN_unit_price' => 0,
121
-                'LIN_percent'    => $percentage_amount,
122
-                'LIN_is_taxable' => $taxable,
123
-                'LIN_total'      => $total,
124
-                'LIN_type'       => EEM_Line_Item::type_line_item,
125
-                'LIN_parent'     => $parent_line_item->ID(),
126
-                'LIN_code'       => $code,
127
-                'TXN_ID'         => $parent_line_item->TXN_ID(),
128
-            ]
129
-        );
130
-        $line_item = apply_filters(
131
-            'FHEE__EEH_Line_Item__add_percentage_based_item__line_item',
132
-            $line_item
133
-        );
134
-        $added     = $parent_line_item->add_child_line_item($line_item, false);
135
-        return $return_item ? $line_item : $added;
136
-    }
137
-
138
-
139
-    /**
140
-     * Returns the new line item created by adding a purchase of the ticket
141
-     * ensures that ticket line item is saved, and that cart total has been recalculated.
142
-     * If this ticket has already been purchased, just increments its count.
143
-     * Automatically re-calculates the line item totals and updates the related transaction. But
144
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
145
-     * should probably change because of this).
146
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
147
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
148
-     *
149
-     * @param EE_Line_Item|null $total_line_item grand total line item of type EEM_Line_Item::type_total
150
-     * @param EE_Ticket         $ticket
151
-     * @param int               $qty
152
-     * @param bool              $recalculate_totals
153
-     * @return EE_Line_Item
154
-     * @throws EE_Error
155
-     * @throws ReflectionException
156
-     */
157
-    public static function add_ticket_purchase(
158
-        ?EE_Line_Item $total_line_item,
159
-        EE_Ticket $ticket,
160
-        int $qty = 1,
161
-        bool $recalculate_totals = true
162
-    ): ?EE_Line_Item {
163
-        if (! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) {
164
-            throw new EE_Error(
165
-                sprintf(
166
-                    esc_html__(
167
-                        'A valid line item total is required in order to add tickets. A line item of type "%s" was passed.',
168
-                        'event_espresso'
169
-                    ),
170
-                    $ticket->ID(),
171
-                    $total_line_item->ID()
172
-                )
173
-            );
174
-        }
175
-        // either increment the qty for an existing ticket
176
-        $line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty);
177
-        // or add a new one
178
-        if (! $line_item instanceof EE_Line_Item) {
179
-            $line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty);
180
-        }
181
-        if ($recalculate_totals) {
182
-            $total_line_item->recalculate_total_including_taxes();
183
-        }
184
-        return $line_item;
185
-    }
186
-
187
-
188
-    /**
189
-     * Returns the new line item created by adding a purchase of the ticket
190
-     *
191
-     * @param EE_Line_Item|null $total_line_item
192
-     * @param EE_Ticket         $ticket
193
-     * @param int               $qty
194
-     * @return EE_Line_Item
195
-     * @throws EE_Error
196
-     * @throws InvalidArgumentException
197
-     * @throws InvalidDataTypeException
198
-     * @throws InvalidInterfaceException
199
-     * @throws ReflectionException
200
-     */
201
-    public static function increment_ticket_qty_if_already_in_cart(
202
-        ?EE_Line_Item $total_line_item,
203
-        EE_Ticket $ticket,
204
-        int $qty = 1
205
-    ): ?EE_Line_Item {
206
-        $line_item = null;
207
-        if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) {
208
-            $ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
209
-            foreach ($ticket_line_items as $ticket_line_item) {
210
-                if (
211
-                    $ticket_line_item instanceof EE_Line_Item
212
-                    && $ticket_line_item->OBJ_ID() === $ticket->ID()
213
-                ) {
214
-                    $line_item = $ticket_line_item;
215
-                    break;
216
-                }
217
-            }
218
-        }
219
-        if ($line_item instanceof EE_Line_Item) {
220
-            EEH_Line_Item::increment_quantity($line_item, $qty);
221
-            return $line_item;
222
-        }
223
-        return null;
224
-    }
225
-
226
-
227
-    /**
228
-     * Increments the line item and all its children's quantity by $qty (but percent line items are unaffected).
229
-     * Does NOT save or recalculate other line items totals
230
-     *
231
-     * @param EE_Line_Item $line_item
232
-     * @param int          $qty
233
-     * @return void
234
-     * @throws EE_Error
235
-     * @throws InvalidArgumentException
236
-     * @throws InvalidDataTypeException
237
-     * @throws InvalidInterfaceException
238
-     * @throws ReflectionException
239
-     */
240
-    public static function increment_quantity(EE_Line_Item $line_item, int $qty = 1)
241
-    {
242
-        if (! $line_item->is_percent()) {
243
-            $qty += $line_item->quantity();
244
-            $line_item->set_quantity($qty);
245
-            $line_item->set_total($line_item->unit_price() * $qty);
246
-            $line_item->save();
247
-        }
248
-        foreach ($line_item->children() as $child) {
249
-            if ($child->is_sub_line_item()) {
250
-                EEH_Line_Item::update_quantity($child, $qty);
251
-            }
252
-        }
253
-    }
254
-
255
-
256
-    /**
257
-     * Decrements the line item and all its children's quantity by $qty (but percent line items are unaffected).
258
-     * Does NOT save or recalculate other line items totals
259
-     *
260
-     * @param EE_Line_Item $line_item
261
-     * @param int          $qty
262
-     * @return void
263
-     * @throws EE_Error
264
-     * @throws InvalidArgumentException
265
-     * @throws InvalidDataTypeException
266
-     * @throws InvalidInterfaceException
267
-     * @throws ReflectionException
268
-     */
269
-    public static function decrement_quantity(EE_Line_Item $line_item, int $qty = 1)
270
-    {
271
-        if (! $line_item->is_percent()) {
272
-            $qty = $line_item->quantity() - $qty;
273
-            $qty = max($qty, 0);
274
-            $line_item->set_quantity($qty);
275
-            $line_item->set_total($line_item->unit_price() * $qty);
276
-            $line_item->save();
277
-        }
278
-        foreach ($line_item->children() as $child) {
279
-            if ($child->is_sub_line_item()) {
280
-                EEH_Line_Item::update_quantity($child, $qty);
281
-            }
282
-        }
283
-    }
284
-
285
-
286
-    /**
287
-     * Updates the line item and its children's quantities to the specified number.
288
-     * Does NOT save them or recalculate totals.
289
-     *
290
-     * @param EE_Line_Item $line_item
291
-     * @param int          $new_quantity
292
-     * @throws EE_Error
293
-     * @throws InvalidArgumentException
294
-     * @throws InvalidDataTypeException
295
-     * @throws InvalidInterfaceException
296
-     * @throws ReflectionException
297
-     */
298
-    public static function update_quantity(EE_Line_Item $line_item, int $new_quantity)
299
-    {
300
-        if (! $line_item->is_percent()) {
301
-            $line_item->set_quantity($new_quantity);
302
-            $line_item->set_total($line_item->unit_price() * $new_quantity);
303
-            $line_item->save();
304
-        }
305
-        foreach ($line_item->children() as $child) {
306
-            if ($child->is_sub_line_item()) {
307
-                EEH_Line_Item::update_quantity($child, $new_quantity);
308
-            }
309
-        }
310
-    }
311
-
312
-
313
-    /**
314
-     * Returns the new line item created by adding a purchase of the ticket
315
-     *
316
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
317
-     * @param EE_Ticket    $ticket
318
-     * @param int          $qty
319
-     * @return EE_Line_Item
320
-     * @throws EE_Error
321
-     * @throws InvalidArgumentException
322
-     * @throws InvalidDataTypeException
323
-     * @throws InvalidInterfaceException
324
-     * @throws ReflectionException
325
-     */
326
-    public static function create_ticket_line_item(
327
-        EE_Line_Item $total_line_item,
328
-        EE_Ticket $ticket,
329
-        int $qty = 1
330
-    ): EE_Line_Item {
331
-        $datetimes           = $ticket->datetimes();
332
-        $first_datetime      = reset($datetimes);
333
-        $first_datetime_name = esc_html__('Event', 'event_espresso');
334
-        if ($first_datetime instanceof EE_Datetime && $first_datetime->event() instanceof EE_Event) {
335
-            $first_datetime_name = $first_datetime->event()->name();
336
-        }
337
-        $event = sprintf(_x('(For %1$s)', '(For Event Name)', 'event_espresso'), $first_datetime_name);
338
-        // get event subtotal line
339
-        $events_sub_total = self::get_event_line_item_for_ticket($total_line_item, $ticket);
340
-        $taxes            = $ticket->tax_price_modifiers();
341
-        // add $ticket to cart
342
-        $line_item = EE_Line_Item::new_instance(
343
-            [
344
-                'LIN_name'       => $ticket->name(),
345
-                'LIN_desc'       => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event,
346
-                'LIN_unit_price' => $ticket->price(),
347
-                'LIN_quantity'   => $qty,
348
-                'LIN_is_taxable' => empty($taxes) && $ticket->taxable(),
349
-                'LIN_order'      => count($events_sub_total->children()),
350
-                'LIN_total'      => $ticket->price() * $qty,
351
-                'LIN_type'       => EEM_Line_Item::type_line_item,
352
-                'OBJ_ID'         => $ticket->ID(),
353
-                'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_TICKET,
354
-            ]
355
-        );
356
-        $line_item = apply_filters(
357
-            'FHEE__EEH_Line_Item__create_ticket_line_item__line_item',
358
-            $line_item
359
-        );
360
-        if (! $line_item instanceof EE_Line_Item) {
361
-            throw new DomainException(
362
-                esc_html__('Invalid EE_Line_Item received.', 'event_espresso')
363
-            );
364
-        }
365
-        $events_sub_total->add_child_line_item($line_item);
366
-        // now add the sub-line items
367
-        $running_pre_tax_total = 0;
368
-        $prices                = $ticket->prices();
369
-        if (empty($prices)) {
370
-            // WUT?!?! NO PRICES??? Well, just create a default price then.
371
-            $default_price = EEM_Price::instance()->get_new_price();
372
-            if ($default_price->amount() !== $ticket->price()) {
373
-                $default_price->set_amount($ticket->price());
374
-            }
375
-            $default_price->save();
376
-            $ticket->_add_relation_to($default_price, 'Price');
377
-            $ticket->save();
378
-            $prices = [$default_price];
379
-        }
380
-        foreach ($prices as $price) {
381
-            $sign = $price->is_discount() ? -1 : 1;
382
-            $price_amount = $price->amount();
383
-            if ($price->is_percent()) {
384
-                $price_total = $running_pre_tax_total * $price_amount / 100;
385
-                $percent    = $sign * $price_amount;
386
-                $unit_price = 0;
387
-            } else {
388
-                $price_total = $price_amount * $qty;
389
-                $percent    = 0;
390
-                $unit_price = $sign * $price_amount;
391
-            }
392
-
393
-            $price_desc = $price->desc();
394
-            $price_type = $price->type_obj();
395
-            $price_desc = $price_desc === '' && $price_type instanceof EE_Price_Type
396
-                ? $price_type->name()
397
-                : $price_desc;
398
-
399
-            $sub_line_item         = EE_Line_Item::new_instance(
400
-                [
401
-                    'LIN_name'       => $price->name(),
402
-                    'LIN_desc'       => $price_desc,
403
-                    'LIN_is_taxable' => false,
404
-                    'LIN_order'      => $price->order(),
405
-                    'LIN_total'      => $price_total,
406
-                    'LIN_pretax'     => 0,
407
-                    'LIN_unit_price' => $unit_price,
408
-                    'LIN_percent'    => $percent,
409
-                    'LIN_type'       => $price->is_tax()
410
-                        ? EEM_Line_Item::type_sub_tax
411
-                        : EEM_Line_Item::type_sub_line_item,
412
-                    'OBJ_ID'         => $price->ID(),
413
-                    'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_PRICE,
414
-                ]
415
-            );
416
-            $sub_line_item         = apply_filters(
417
-                'FHEE__EEH_Line_Item__create_ticket_line_item__sub_line_item',
418
-                $sub_line_item
419
-            );
420
-            $running_pre_tax_total += ! $price->is_tax() ? $sign * $price_total : 0;
421
-            $line_item->add_child_line_item($sub_line_item);
422
-        }
423
-        $line_item->setPretaxTotal($running_pre_tax_total);
424
-        return $line_item;
425
-    }
426
-
427
-
428
-    /**
429
-     * Adds the specified item under the pre-tax-sub-total line item. Automatically
430
-     * re-calculates the line item totals and updates the related transaction. But
431
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
432
-     * should probably change because of this).
433
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
434
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
435
-     *
436
-     * @param EE_Line_Item $total_line_item
437
-     * @param EE_Line_Item $item to be added
438
-     * @param bool         $recalculate_totals
439
-     * @return boolean
440
-     * @throws EE_Error
441
-     * @throws InvalidArgumentException
442
-     * @throws InvalidDataTypeException
443
-     * @throws InvalidInterfaceException
444
-     * @throws ReflectionException
445
-     */
446
-    public static function add_item(
447
-        EE_Line_Item $total_line_item,
448
-        EE_Line_Item $item,
449
-        bool $recalculate_totals = true
450
-    ): bool {
451
-        $pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item);
452
-        $success          = $pre_tax_subtotal->add_child_line_item($item);
453
-        if ($recalculate_totals) {
454
-            $total_line_item->recalculate_total_including_taxes();
455
-        }
456
-        return $success;
457
-    }
458
-
459
-
460
-    /**
461
-     * cancels an existing ticket line item,
462
-     * by decrementing its quantity by 1 and adding a new "type_cancellation" sub-line-item.
463
-     * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
464
-     *
465
-     * @param EE_Line_Item $ticket_line_item
466
-     * @param int          $qty
467
-     * @return bool success
468
-     * @throws EE_Error
469
-     * @throws InvalidArgumentException
470
-     * @throws InvalidDataTypeException
471
-     * @throws InvalidInterfaceException
472
-     * @throws ReflectionException
473
-     */
474
-    public static function cancel_ticket_line_item(EE_Line_Item $ticket_line_item, int $qty = 1): bool
475
-    {
476
-        // validate incoming line_item
477
-        if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) {
478
-            throw new EE_Error(
479
-                sprintf(
480
-                    esc_html__(
481
-                        'The supplied line item must have an Object Type of "Ticket", not %1$s.',
482
-                        'event_espresso'
483
-                    ),
484
-                    $ticket_line_item->type()
485
-                )
486
-            );
487
-        }
488
-        if ($ticket_line_item->quantity() < $qty) {
489
-            throw new EE_Error(
490
-                sprintf(
491
-                    esc_html__(
492
-                        'Can not cancel %1$d ticket(s) because the supplied line item has a quantity of %2$d.',
493
-                        'event_espresso'
494
-                    ),
495
-                    $qty,
496
-                    $ticket_line_item->quantity()
497
-                )
498
-            );
499
-        }
500
-        // decrement ticket quantity; don't rely on auto-fixing when recalculating totals to do this
501
-        $ticket_line_item->set_quantity($ticket_line_item->quantity() - $qty);
502
-        foreach ($ticket_line_item->children() as $child_line_item) {
503
-            if (
504
-                $child_line_item->is_sub_line_item()
505
-                && ! $child_line_item->is_percent()
506
-                && ! $child_line_item->is_cancellation()
507
-            ) {
508
-                $child_line_item->set_quantity($child_line_item->quantity() - $qty);
509
-            }
510
-        }
511
-        // get cancellation sub line item
512
-        $cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
513
-            $ticket_line_item,
514
-            EEM_Line_Item::type_cancellation
515
-        );
516
-        $cancellation_line_item = reset($cancellation_line_item);
517
-        // verify that this ticket was indeed previously cancelled
518
-        if ($cancellation_line_item instanceof EE_Line_Item) {
519
-            // increment cancelled quantity
520
-            $cancellation_line_item->set_quantity($cancellation_line_item->quantity() + $qty);
521
-        } else {
522
-            // create cancellation sub line item
523
-            $cancellation_line_item = EE_Line_Item::new_instance(
524
-                [
525
-                    'LIN_name'       => esc_html__('Cancellation', 'event_espresso'),
526
-                    'LIN_desc'       => sprintf(
527
-                        esc_html_x(
528
-                            'Cancelled %1$s : %2$s',
529
-                            'Cancelled Ticket Name : 2015-01-01 11:11',
530
-                            'event_espresso'
531
-                        ),
532
-                        $ticket_line_item->name(),
533
-                        current_time(get_option('date_format') . ' ' . get_option('time_format'))
534
-                    ),
535
-                    'LIN_total'      => 0,
536
-                    'LIN_unit_price' => 0,
537
-                    'LIN_quantity'   => $qty,
538
-                    'LIN_is_taxable' => $ticket_line_item->is_taxable(),
539
-                    'LIN_order'      => count($ticket_line_item->children()),
540
-                    'LIN_type'       => EEM_Line_Item::type_cancellation,
541
-                ]
542
-            );
543
-            $ticket_line_item->add_child_line_item($cancellation_line_item);
544
-        }
545
-        if ($ticket_line_item->save_this_and_descendants() > 0) {
546
-            // decrement parent line item quantity
547
-            $event_line_item = $ticket_line_item->parent();
548
-            if (
549
-                $event_line_item instanceof EE_Line_Item
550
-                && $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
551
-            ) {
552
-                $event_line_item->set_quantity($event_line_item->quantity() - $qty);
553
-                $event_line_item->save();
554
-            }
555
-            EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
556
-            return true;
557
-        }
558
-        return false;
559
-    }
560
-
561
-
562
-    /**
563
-     * reinstates (un-cancels?) a previously canceled ticket line item,
564
-     * by incrementing its quantity by 1, and decrementing its "type_cancellation" sub-line-item.
565
-     * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
566
-     *
567
-     * @param EE_Line_Item $ticket_line_item
568
-     * @param int          $qty
569
-     * @return bool success
570
-     * @throws EE_Error
571
-     * @throws InvalidArgumentException
572
-     * @throws InvalidDataTypeException
573
-     * @throws InvalidInterfaceException
574
-     * @throws ReflectionException
575
-     */
576
-    public static function reinstate_canceled_ticket_line_item(EE_Line_Item $ticket_line_item, int $qty = 1): bool
577
-    {
578
-        // validate incoming line_item
579
-        if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) {
580
-            throw new EE_Error(
581
-                sprintf(
582
-                    esc_html__(
583
-                        'The supplied line item must have an Object Type of "Ticket", not %1$s.',
584
-                        'event_espresso'
585
-                    ),
586
-                    $ticket_line_item->type()
587
-                )
588
-            );
589
-        }
590
-        // get cancellation sub line item
591
-        $cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
592
-            $ticket_line_item,
593
-            EEM_Line_Item::type_cancellation
594
-        );
595
-        $cancellation_line_item = reset($cancellation_line_item);
596
-        // verify that this ticket was indeed previously cancelled
597
-        if (! $cancellation_line_item instanceof EE_Line_Item) {
598
-            return false;
599
-        }
600
-        if ($cancellation_line_item->quantity() > $qty) {
601
-            // decrement cancelled quantity
602
-            $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
603
-        } elseif ($cancellation_line_item->quantity() === $qty) {
604
-            // decrement cancelled quantity in case anyone still has the object kicking around
605
-            $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
606
-            // delete because quantity will end up as 0
607
-            $cancellation_line_item->delete();
608
-            // and attempt to destroy the object,
609
-            // even though PHP won't actually destroy it until it needs the memory
610
-            unset($cancellation_line_item);
611
-        } else {
612
-            // what ?!?! negative quantity ?!?!
613
-            throw new EE_Error(
614
-                sprintf(
615
-                    esc_html__(
616
-                        'Can not reinstate %1$d cancelled ticket(s) because the cancelled ticket quantity is only %2$d.',
617
-                        'event_espresso'
618
-                    ),
619
-                    $qty,
620
-                    $cancellation_line_item->quantity()
621
-                )
622
-            );
623
-        }
624
-        // increment ticket quantity
625
-        $ticket_line_item->set_quantity($ticket_line_item->quantity() + $qty);
626
-        if ($ticket_line_item->save_this_and_descendants() > 0) {
627
-            // increment parent line item quantity
628
-            $event_line_item = $ticket_line_item->parent();
629
-            if (
630
-                $event_line_item instanceof EE_Line_Item
631
-                && $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
632
-            ) {
633
-                $event_line_item->set_quantity($event_line_item->quantity() + $qty);
634
-            }
635
-            EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
636
-            return true;
637
-        }
638
-        return false;
639
-    }
640
-
641
-
642
-    /**
643
-     * calls EEH_Line_Item::find_transaction_grand_total_for_line_item()
644
-     * then EE_Line_Item::recalculate_total_including_taxes() on the result
645
-     *
646
-     * @param EE_Line_Item $line_item
647
-     * @return float
648
-     * @throws EE_Error
649
-     * @throws InvalidArgumentException
650
-     * @throws InvalidDataTypeException
651
-     * @throws InvalidInterfaceException
652
-     * @throws ReflectionException
653
-     */
654
-    public static function get_grand_total_and_recalculate_everything(EE_Line_Item $line_item): float
655
-    {
656
-        $grand_total_line_item = EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item);
657
-        return $grand_total_line_item->recalculate_total_including_taxes();
658
-    }
659
-
660
-
661
-    /**
662
-     * Gets the line item which contains the subtotal of all the items
663
-     *
664
-     * @param EE_Line_Item        $total_line_item of type EEM_Line_Item::type_total
665
-     * @param EE_Transaction|null $transaction
666
-     * @param bool                $create_event_subtotal
667
-     * @return EE_Line_Item
668
-     * @throws EE_Error
669
-     * @throws ReflectionException
670
-     */
671
-    public static function get_pre_tax_subtotal(
672
-        EE_Line_Item $total_line_item,
673
-        ?EE_Transaction $transaction = null,
674
-        bool $create_event_subtotal = true
675
-    ): EE_Line_Item {
676
-        $pre_tax_subtotal = $total_line_item->get_child_line_item('pre-tax-subtotal');
677
-        return $pre_tax_subtotal instanceof EE_Line_Item
678
-            ? $pre_tax_subtotal
679
-            : self::create_pre_tax_subtotal($total_line_item, $transaction, $create_event_subtotal);
680
-    }
681
-
682
-
683
-    /**
684
-     * Gets the line item for the taxes subtotal
685
-     *
686
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
687
-     * @return EE_Line_Item
688
-     * @throws EE_Error
689
-     * @throws InvalidArgumentException
690
-     * @throws InvalidDataTypeException
691
-     * @throws InvalidInterfaceException
692
-     * @throws ReflectionException
693
-     */
694
-    public static function get_taxes_subtotal(EE_Line_Item $total_line_item): EE_Line_Item
695
-    {
696
-        $taxes = $total_line_item->get_child_line_item('taxes');
697
-        return $taxes ?: self::create_taxes_subtotal($total_line_item);
698
-    }
699
-
700
-
701
-    /**
702
-     * sets the TXN ID on an EE_Line_Item if passed a valid EE_Transaction object
703
-     *
704
-     * @param EE_Line_Item        $line_item
705
-     * @param EE_Transaction|null $transaction
706
-     * @return void
707
-     * @throws EE_Error
708
-     * @throws InvalidArgumentException
709
-     * @throws InvalidDataTypeException
710
-     * @throws InvalidInterfaceException
711
-     * @throws ReflectionException
712
-     */
713
-    public static function set_TXN_ID(EE_Line_Item $line_item, ?EE_Transaction $transaction = null)
714
-    {
715
-        if ($transaction) {
716
-            /** @type EEM_Transaction $EEM_Transaction */
717
-            $EEM_Transaction = EE_Registry::instance()->load_model('Transaction');
718
-            $TXN_ID          = $EEM_Transaction->ensure_is_ID($transaction);
719
-            $line_item->set_TXN_ID($TXN_ID);
720
-        }
721
-    }
722
-
723
-
724
-    /**
725
-     * Creates a new default total line item for the transaction,
726
-     * and its tickets subtotal and taxes subtotal line items (and adds the
727
-     * existing taxes as children of the taxes subtotal line item)
728
-     *
729
-     * @param EE_Transaction|null $transaction
730
-     * @return EE_Line_Item of type total
731
-     * @throws EE_Error
732
-     * @throws InvalidArgumentException
733
-     * @throws InvalidDataTypeException
734
-     * @throws InvalidInterfaceException
735
-     * @throws ReflectionException
736
-     */
737
-    public static function create_total_line_item(?EE_Transaction $transaction = null): EE_Line_Item
738
-    {
739
-        $total_line_item = EE_Line_Item::new_instance(
740
-            [
741
-                'LIN_code' => 'total',
742
-                'LIN_name' => esc_html__('Grand Total', 'event_espresso'),
743
-                'LIN_type' => EEM_Line_Item::type_total,
744
-                'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TRANSACTION,
745
-            ]
746
-        );
747
-        $total_line_item = apply_filters(
748
-            'FHEE__EEH_Line_Item__create_total_line_item__total_line_item',
749
-            $total_line_item
750
-        );
751
-        self::set_TXN_ID($total_line_item, $transaction);
752
-        self::create_pre_tax_subtotal($total_line_item, $transaction);
753
-        self::create_taxes_subtotal($total_line_item, $transaction);
754
-        return $total_line_item;
755
-    }
756
-
757
-
758
-    /**
759
-     * Creates a default items subtotal line item
760
-     *
761
-     * @param EE_Line_Item        $total_line_item
762
-     * @param EE_Transaction|null $transaction
763
-     * @param bool                $create_event_subtotal
764
-     * @return EE_Line_Item
765
-     * @throws EE_Error
766
-     * @throws ReflectionException
767
-     */
768
-    protected static function create_pre_tax_subtotal(
769
-        EE_Line_Item $total_line_item,
770
-        ?EE_Transaction $transaction = null,
771
-        bool $create_event_subtotal = true
772
-    ): EE_Line_Item {
773
-        $pre_tax_line_item = EE_Line_Item::new_instance(
774
-            [
775
-                'LIN_code' => 'pre-tax-subtotal',
776
-                'LIN_name' => esc_html__('Pre-Tax Subtotal', 'event_espresso'),
777
-                'LIN_type' => EEM_Line_Item::type_sub_total,
778
-            ]
779
-        );
780
-        $pre_tax_line_item = apply_filters(
781
-            'FHEE__EEH_Line_Item__create_pre_tax_subtotal__pre_tax_line_item',
782
-            $pre_tax_line_item
783
-        );
784
-        self::set_TXN_ID($pre_tax_line_item, $transaction);
785
-        $total_line_item->add_child_line_item($pre_tax_line_item);
786
-        if ($create_event_subtotal) {
787
-            self::create_event_subtotal($pre_tax_line_item, $transaction);
788
-        }
789
-        return $pre_tax_line_item;
790
-    }
791
-
792
-
793
-    /**
794
-     * Creates a line item for the taxes subtotal and finds all the tax prices
795
-     * and applies taxes to it
796
-     *
797
-     * @param EE_Line_Item        $total_line_item of type EEM_Line_Item::type_total
798
-     * @param EE_Transaction|null $transaction
799
-     * @return EE_Line_Item
800
-     * @throws EE_Error
801
-     * @throws InvalidArgumentException
802
-     * @throws InvalidDataTypeException
803
-     * @throws InvalidInterfaceException
804
-     * @throws ReflectionException
805
-     */
806
-    protected static function create_taxes_subtotal(
807
-        EE_Line_Item $total_line_item,
808
-        ?EE_Transaction $transaction = null
809
-    ): EE_Line_Item {
810
-        $tax_line_item = EE_Line_Item::new_instance(
811
-            [
812
-                'LIN_code'  => 'taxes',
813
-                'LIN_name'  => esc_html__('Taxes', 'event_espresso'),
814
-                'LIN_type'  => EEM_Line_Item::type_tax_sub_total,
815
-                'LIN_order' => 1000,// this should always come last
816
-            ]
817
-        );
818
-        $tax_line_item = apply_filters(
819
-            'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item',
820
-            $tax_line_item
821
-        );
822
-        self::set_TXN_ID($tax_line_item, $transaction);
823
-        $total_line_item->add_child_line_item($tax_line_item);
824
-        // and lastly, add the actual taxes
825
-        self::apply_taxes($total_line_item);
826
-        return $tax_line_item;
827
-    }
828
-
829
-
830
-    /**
831
-     * Creates a default items subtotal line item
832
-     *
833
-     * @param EE_Line_Item        $pre_tax_line_item
834
-     * @param EE_Transaction|null $transaction
835
-     * @param EE_Event|null       $event
836
-     * @return EE_Line_Item
837
-     * @throws EE_Error
838
-     * @throws InvalidArgumentException
839
-     * @throws InvalidDataTypeException
840
-     * @throws InvalidInterfaceException
841
-     * @throws ReflectionException
842
-     */
843
-    public static function create_event_subtotal(
844
-        EE_Line_Item $pre_tax_line_item,
845
-        ?EE_Transaction $transaction = null,
846
-        ?EE_Event $event = null
847
-    ): EE_Line_Item {
848
-        // first check if this line item already exists
849
-        $event_line_item = EEM_Line_Item::instance()->get_one(
850
-            [
851
-                [
852
-                    'LIN_type' => EEM_Line_Item::type_sub_total,
853
-                    'OBJ_type' => EEM_Line_Item::OBJ_TYPE_EVENT,
854
-                    'OBJ_ID'   => $event instanceof EE_Event ? $event->ID() : 0,
855
-                    'TXN_ID'   => $transaction instanceof EE_Transaction ? $transaction->ID() : 0,
856
-                ],
857
-            ]
858
-        );
859
-        if ($event_line_item instanceof EE_Line_Item) {
860
-            return $event_line_item;
861
-        }
862
-
863
-        $event_line_item = EE_Line_Item::new_instance(
864
-            [
865
-                'LIN_code' => self::get_event_code($event),
866
-                'LIN_name' => self::get_event_name($event),
867
-                'LIN_desc' => self::get_event_desc($event),
868
-                'LIN_type' => EEM_Line_Item::type_sub_total,
869
-                'OBJ_type' => EEM_Line_Item::OBJ_TYPE_EVENT,
870
-                'OBJ_ID'   => $event instanceof EE_Event ? $event->ID() : 0,
871
-            ]
872
-        );
873
-        $event_line_item = apply_filters(
874
-            'FHEE__EEH_Line_Item__create_event_subtotal__event_line_item',
875
-            $event_line_item
876
-        );
877
-        self::set_TXN_ID($event_line_item, $transaction);
878
-        $pre_tax_line_item->add_child_line_item($event_line_item);
879
-        return $event_line_item;
880
-    }
881
-
882
-
883
-    /**
884
-     * Gets what the event ticket's code SHOULD be
885
-     *
886
-     * @param EE_Event|null $event
887
-     * @return string
888
-     * @throws EE_Error
889
-     * @throws ReflectionException
890
-     */
891
-    public static function get_event_code(?EE_Event $event = null): string
892
-    {
893
-        return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0');
894
-    }
895
-
896
-
897
-    /**
898
-     * Gets the event name
899
-     *
900
-     * @param EE_Event|null $event
901
-     * @return string
902
-     * @throws EE_Error
903
-     * @throws ReflectionException
904
-     */
905
-    public static function get_event_name(?EE_Event $event = null): string
906
-    {
907
-        return $event instanceof EE_Event
908
-            ? mb_substr($event->name(), 0, 245)
909
-            : esc_html__('Event', 'event_espresso');
910
-    }
911
-
912
-
913
-    /**
914
-     * Gets the event excerpt
915
-     *
916
-     * @param EE_Event|null $event
917
-     * @return string
918
-     * @throws EE_Error
919
-     * @throws ReflectionException
920
-     */
921
-    public static function get_event_desc(?EE_Event $event = null): string
922
-    {
923
-        return $event instanceof EE_Event ? $event->short_description() : '';
924
-    }
925
-
926
-
927
-    /**
928
-     * Given the grand total line item and a ticket, finds the event sub-total
929
-     * line item the ticket's purchase should be added onto
930
-     *
931
-     * @access public
932
-     * @param EE_Line_Item $grand_total the grand total line item
933
-     * @param EE_Ticket    $ticket
934
-     * @return EE_Line_Item
935
-     * @throws EE_Error
936
-     * @throws InvalidArgumentException
937
-     * @throws InvalidDataTypeException
938
-     * @throws InvalidInterfaceException
939
-     * @throws ReflectionException
940
-     */
941
-    public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket): EE_Line_Item
942
-    {
943
-        $first_datetime = $ticket->first_datetime();
944
-        if (! $first_datetime instanceof EE_Datetime) {
945
-            throw new EE_Error(
946
-                sprintf(
947
-                    esc_html__('The supplied ticket (ID %d) has no datetimes', 'event_espresso'),
948
-                    $ticket->ID()
949
-                )
950
-            );
951
-        }
952
-        $event = $first_datetime->event();
953
-        if (! $event instanceof EE_Event) {
954
-            throw new EE_Error(
955
-                sprintf(
956
-                    esc_html__(
957
-                        'The supplied ticket (ID %d) has no event data associated with it.',
958
-                        'event_espresso'
959
-                    ),
960
-                    $ticket->ID()
961
-                )
962
-            );
963
-        }
964
-        $events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event);
965
-        if (! $events_sub_total instanceof EE_Line_Item) {
966
-            throw new EE_Error(
967
-                sprintf(
968
-                    esc_html__(
969
-                        'There is no events sub-total for ticket %s on total line item %d',
970
-                        'event_espresso'
971
-                    ),
972
-                    $ticket->ID(),
973
-                    $grand_total->ID()
974
-                )
975
-            );
976
-        }
977
-        return $events_sub_total;
978
-    }
979
-
980
-
981
-    /**
982
-     * Gets the event line item
983
-     *
984
-     * @param EE_Line_Item  $total_line_item
985
-     * @param EE_Event|null $event
986
-     * @return EE_Line_Item for the event subtotal which is a child of $grand_total
987
-     * @throws EE_Error
988
-     * @throws ReflectionException
989
-     */
990
-    public static function get_event_line_item(EE_Line_Item $total_line_item, ?EE_Event $event = null): ?EE_Line_Item
991
-    {
992
-        /** @type EE_Event $event */
993
-        $event           = EEM_Event::instance()->ensure_is_obj($event, true);
994
-        $event_line_items = EEH_Line_Item::get_event_subtotals($total_line_item);
995
-        $existing_event_line_item = null;
996
-        foreach ($event_line_items as $event_line_item) {
997
-            // default event subtotal, we should only ever find this the first time this method is called
998
-            $OBJ_ID = $event_line_item->OBJ_ID();
999
-            if ($OBJ_ID === $event->ID()) {
1000
-                // found existing line item for this event in the cart, so break out of loop and use this one
1001
-                $existing_event_line_item = $event_line_item;
1002
-                break;
1003
-            }
1004
-            if (! $OBJ_ID) {
1005
-                // OK?!?! We have an event subtotal that is not actually associated with any event???
1006
-                // let's just use this line item since it's already there, but first... set the event details
1007
-                $existing_event_line_item = $event_line_item;
1008
-                EEH_Line_Item::set_event_subtotal_details($existing_event_line_item, $event);
1009
-                break;
1010
-            }
1011
-        }
1012
-        unset($event_line_item);
1013
-        if ($existing_event_line_item instanceof EE_Line_Item) {
1014
-            return $existing_event_line_item;
1015
-        }
1016
-        // there is no event sub-total yet for this event, so create a new "event" subtotal
1017
-        $transaction = $total_line_item->transaction();
1018
-        $pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item, $transaction, false);
1019
-        $new_event_line_item = EEH_Line_Item::create_event_subtotal($pre_tax_subtotal, $transaction, $event);
1020
-        // and set the event details
1021
-        EEH_Line_Item::set_event_subtotal_details($new_event_line_item, $event, $transaction);
1022
-        return $new_event_line_item;
1023
-    }
1024
-
1025
-
1026
-    /**
1027
-     * Creates a default items subtotal line item
1028
-     *
1029
-     * @param EE_Line_Item        $event_line_item
1030
-     * @param EE_Event|null       $event
1031
-     * @param EE_Transaction|null $transaction
1032
-     * @return void
1033
-     * @throws EE_Error
1034
-     * @throws InvalidArgumentException
1035
-     * @throws InvalidDataTypeException
1036
-     * @throws InvalidInterfaceException
1037
-     * @throws ReflectionException
1038
-     */
1039
-    public static function set_event_subtotal_details(
1040
-        EE_Line_Item $event_line_item,
1041
-        EE_Event $event = null,
1042
-        ?EE_Transaction $transaction = null
1043
-    ) {
1044
-        if ($event instanceof EE_Event) {
1045
-            $event_line_item->set_code(self::get_event_code($event));
1046
-            $event_line_item->set_name(self::get_event_name($event));
1047
-            $event_line_item->set_desc(self::get_event_desc($event));
1048
-            $event_line_item->set_OBJ_ID($event->ID());
1049
-        }
1050
-        self::set_TXN_ID($event_line_item, $transaction);
1051
-    }
1052
-
1053
-
1054
-    /**
1055
-     * Finds what taxes should apply, adds them as tax line items under the taxes sub-total,
1056
-     * and recalculates the taxes sub-total and the grand total. Resets the taxes, so
1057
-     * any old taxes are removed
1058
-     *
1059
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
1060
-     * @param bool         $update_txn_status
1061
-     * @return bool
1062
-     * @throws EE_Error
1063
-     * @throws InvalidArgumentException
1064
-     * @throws InvalidDataTypeException
1065
-     * @throws InvalidInterfaceException
1066
-     * @throws ReflectionException
1067
-     * @throws RuntimeException
1068
-     */
1069
-    public static function apply_taxes(EE_Line_Item $total_line_item, bool $update_txn_status = false): bool
1070
-    {
1071
-        $total_line_item       = EEH_Line_Item::find_transaction_grand_total_for_line_item($total_line_item);
1072
-        $taxes_line_item       = self::get_taxes_subtotal($total_line_item);
1073
-        $existing_global_taxes = $taxes_line_item->tax_descendants();
1074
-        $updates               = false;
1075
-        // loop thru taxes
1076
-        $global_taxes = EEH_Line_Item::getGlobalTaxes();
1077
-        foreach ($global_taxes as $order => $taxes) {
1078
-            foreach ($taxes as $tax) {
1079
-                if ($tax instanceof EE_Price) {
1080
-                    $found = false;
1081
-                    // check if this is already an existing tax
1082
-                    foreach ($existing_global_taxes as $existing_global_tax) {
1083
-                        if ($tax->ID() === $existing_global_tax->OBJ_ID()) {
1084
-                            // maybe update the tax rate in case it has changed
1085
-                            if ($existing_global_tax->percent() !== $tax->amount()) {
1086
-                                $existing_global_tax->set_percent($tax->amount());
1087
-                                $existing_global_tax->save();
1088
-                                $updates = true;
1089
-                            }
1090
-                            $found = true;
1091
-                            break;
1092
-                        }
1093
-                    }
1094
-                    if (! $found) {
1095
-                        // add a new line item for this global tax
1096
-                        $tax_line_item = apply_filters(
1097
-                            'FHEE__EEH_Line_Item__apply_taxes__tax_line_item',
1098
-                            EE_Line_Item::new_instance(
1099
-                                [
1100
-                                    'LIN_name'       => $tax->name(),
1101
-                                    'LIN_desc'       => $tax->desc(),
1102
-                                    'LIN_percent'    => $tax->amount(),
1103
-                                    'LIN_is_taxable' => false,
1104
-                                    'LIN_order'      => $order,
1105
-                                    'LIN_total'      => 0,
1106
-                                    'LIN_type'       => EEM_Line_Item::type_tax,
1107
-                                    'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_PRICE,
1108
-                                    'OBJ_ID'         => $tax->ID(),
1109
-                                ]
1110
-                            )
1111
-                        );
1112
-                        $updates       = $taxes_line_item->add_child_line_item($tax_line_item) ? true : $updates;
1113
-                    }
1114
-                }
1115
-            }
1116
-        }
1117
-        // only recalculate totals if something changed
1118
-        if ($updates || $update_txn_status) {
1119
-            $total_line_item->recalculate_total_including_taxes($update_txn_status);
1120
-            return true;
1121
-        }
1122
-        return false;
1123
-    }
1124
-
1125
-
1126
-    /**
1127
-     * Ensures that taxes have been applied to the order, if not applies them.
1128
-     * Returns the total amount of tax
1129
-     *
1130
-     * @param EE_Line_Item|null $total_line_item of type EEM_Line_Item::type_total
1131
-     * @return float
1132
-     * @throws EE_Error
1133
-     * @throws InvalidArgumentException
1134
-     * @throws InvalidDataTypeException
1135
-     * @throws InvalidInterfaceException
1136
-     * @throws ReflectionException
1137
-     */
1138
-    public static function ensure_taxes_applied(?EE_Line_Item $total_line_item): float
1139
-    {
1140
-        $taxes_subtotal = self::get_taxes_subtotal($total_line_item);
1141
-        if (! $taxes_subtotal->children()) {
1142
-            self::apply_taxes($total_line_item);
1143
-        }
1144
-        return $taxes_subtotal->total();
1145
-    }
1146
-
1147
-
1148
-    /**
1149
-     * Deletes ALL children of the passed line item
1150
-     *
1151
-     * @param EE_Line_Item $parent_line_item
1152
-     * @return bool
1153
-     * @throws EE_Error
1154
-     * @throws InvalidArgumentException
1155
-     * @throws InvalidDataTypeException
1156
-     * @throws InvalidInterfaceException
1157
-     * @throws ReflectionException
1158
-     */
1159
-    public static function delete_all_child_items(EE_Line_Item $parent_line_item)
1160
-    {
1161
-        $deleted = 0;
1162
-        foreach ($parent_line_item->children() as $child_line_item) {
1163
-            if ($child_line_item instanceof EE_Line_Item) {
1164
-                $deleted += EEH_Line_Item::delete_all_child_items($child_line_item);
1165
-                if ($child_line_item->ID()) {
1166
-                    $child_line_item->delete();
1167
-                    unset($child_line_item);
1168
-                } else {
1169
-                    $parent_line_item->delete_child_line_item($child_line_item->code());
1170
-                }
1171
-                $deleted++;
1172
-            }
1173
-        }
1174
-        return $deleted;
1175
-    }
1176
-
1177
-
1178
-    /**
1179
-     * Deletes the line items as indicated by the line item code(s) provided,
1180
-     * regardless of where they're found in the line item tree. Automatically
1181
-     * re-calculates the line item totals and updates the related transaction. But
1182
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
1183
-     * should probably change because of this).
1184
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
1185
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
1186
-     *
1187
-     * @param EE_Line_Item      $total_line_item of type EEM_Line_Item::type_total
1188
-     * @param array|bool|string $line_item_codes
1189
-     * @return int number of items successfully removed
1190
-     * @throws EE_Error
1191
-     * @throws ReflectionException
1192
-     */
1193
-    public static function delete_items(EE_Line_Item $total_line_item, $line_item_codes = false)
1194
-    {
1195
-        if ($total_line_item->type() !== EEM_Line_Item::type_total) {
1196
-            EE_Error::doing_it_wrong(
1197
-                'EEH_Line_Item::delete_items',
1198
-                esc_html__(
1199
-                    'This static method should only be called with a TOTAL line item, otherwise we won\'t recalculate the totals correctly',
1200
-                    'event_espresso'
1201
-                ),
1202
-                '4.6.18'
1203
-            );
1204
-        }
1205
-
1206
-        // check if only a single line_item_id was passed
1207
-        if (! empty($line_item_codes) && ! is_array($line_item_codes)) {
1208
-            // place single line_item_id in an array to appear as multiple line_item_ids
1209
-            $line_item_codes = [$line_item_codes];
1210
-        }
1211
-        $removals = 0;
1212
-        // cycle thru line_item_ids
1213
-        foreach ($line_item_codes as $line_item_id) {
1214
-            $removals += $total_line_item->delete_child_line_item($line_item_id);
1215
-        }
1216
-
1217
-        if ($removals > 0) {
1218
-            $total_line_item->recalculate_taxes_and_tax_total();
1219
-            return $removals;
1220
-        }
1221
-        return false;
1222
-    }
1223
-
1224
-
1225
-    /**
1226
-     * Overwrites the previous tax by clearing out the old taxes, and creates a new
1227
-     * tax and updates the total line item accordingly
1228
-     *
1229
-     * @param EE_Line_Item $total_line_item
1230
-     * @param float        $amount
1231
-     * @param string       $name
1232
-     * @param string       $description
1233
-     * @param string       $code
1234
-     * @param boolean      $add_to_existing_line_item
1235
-     *                          if true, and a duplicate line item with the same code is found,
1236
-     *                          $amount will be added onto it; otherwise will simply set the taxes to match $amount
1237
-     * @return EE_Line_Item the new tax line item created
1238
-     * @throws EE_Error
1239
-     * @throws InvalidArgumentException
1240
-     * @throws InvalidDataTypeException
1241
-     * @throws InvalidInterfaceException
1242
-     * @throws ReflectionException
1243
-     */
1244
-    public static function set_total_tax_to(
1245
-        EE_Line_Item $total_line_item,
1246
-        float $amount,
1247
-        string $name = '',
1248
-        string $description = '',
1249
-        string $code = '',
1250
-        bool $add_to_existing_line_item = false
1251
-    ): EE_Line_Item {
1252
-        $tax_subtotal  = self::get_taxes_subtotal($total_line_item);
1253
-        $taxable_total = $total_line_item->taxable_total();
1254
-
1255
-        if ($add_to_existing_line_item) {
1256
-            $new_tax = $tax_subtotal->get_child_line_item($code);
1257
-            EEM_Line_Item::instance()->delete(
1258
-                [['LIN_code' => ['!=', $code], 'LIN_parent' => $tax_subtotal->ID()]]
1259
-            );
1260
-        } else {
1261
-            $new_tax = null;
1262
-            $tax_subtotal->delete_children_line_items();
1263
-        }
1264
-        if ($new_tax) {
1265
-            $new_tax->set_total($new_tax->total() + $amount);
1266
-            $new_tax->set_percent($taxable_total ? $new_tax->total() / $taxable_total * 100 : 0);
1267
-        } else {
1268
-            // no existing tax item. Create it
1269
-            $new_tax = EE_Line_Item::new_instance(
1270
-                [
1271
-                    'TXN_ID'      => $total_line_item->TXN_ID(),
1272
-                    'LIN_name'    => $name ?: esc_html__('Tax', 'event_espresso'),
1273
-                    'LIN_desc'    => $description ?: '',
1274
-                    'LIN_percent' => $taxable_total ? ($amount / $taxable_total * 100) : 0,
1275
-                    'LIN_total'   => $amount,
1276
-                    'LIN_parent'  => $tax_subtotal->ID(),
1277
-                    'LIN_type'    => EEM_Line_Item::type_tax,
1278
-                    'LIN_code'    => $code,
1279
-                ]
1280
-            );
1281
-        }
1282
-
1283
-        $new_tax = apply_filters(
1284
-            'FHEE__EEH_Line_Item__set_total_tax_to__new_tax_subtotal',
1285
-            $new_tax,
1286
-            $total_line_item
1287
-        );
1288
-        $new_tax->save();
1289
-        $tax_subtotal->set_total($new_tax->total());
1290
-        $tax_subtotal->save();
1291
-        $total_line_item->recalculate_total_including_taxes();
1292
-        return $new_tax;
1293
-    }
1294
-
1295
-
1296
-    /**
1297
-     * Makes all the line items which are children of $line_item taxable (or not).
1298
-     * Does NOT save the line items
1299
-     *
1300
-     * @param EE_Line_Item $line_item
1301
-     * @param boolean      $taxable
1302
-     * @param string|null  $code_substring_for_whitelist if this string is part of the line item's code
1303
-     *                                                   it will be whitelisted (ie, except from becoming taxable)
1304
-     * @throws EE_Error
1305
-     * @throws ReflectionException
1306
-     */
1307
-    public static function set_line_items_taxable(
1308
-        EE_Line_Item $line_item,
1309
-        bool $taxable = true,
1310
-        ?string $code_substring_for_whitelist = null
1311
-    ) {
1312
-        $whitelisted = false;
1313
-        if ($code_substring_for_whitelist !== null) {
1314
-            $whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false;
1315
-        }
1316
-        if (! $whitelisted && $line_item->is_line_item()) {
1317
-            $line_item->set_is_taxable($taxable);
1318
-        }
1319
-        foreach ($line_item->children() as $child_line_item) {
1320
-            EEH_Line_Item::set_line_items_taxable(
1321
-                $child_line_item,
1322
-                $taxable,
1323
-                $code_substring_for_whitelist
1324
-            );
1325
-        }
1326
-    }
1327
-
1328
-
1329
-    /**
1330
-     * Gets all descendants that are event subtotals
1331
-     *
1332
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1333
-     * @return EE_Line_Item[]
1334
-     * @throws EE_Error
1335
-     * @throws ReflectionException
1336
-     * @uses  EEH_Line_Item::get_subtotals_of_object_type()
1337
-     */
1338
-    public static function get_event_subtotals(EE_Line_Item $parent_line_item): array
1339
-    {
1340
-        return self::get_subtotals_of_object_type($parent_line_item, EEM_Line_Item::OBJ_TYPE_EVENT);
1341
-    }
1342
-
1343
-
1344
-    /**
1345
-     * Gets all descendants subtotals that match the supplied object type
1346
-     *
1347
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1348
-     * @param string       $obj_type
1349
-     * @return EE_Line_Item[]
1350
-     * @throws EE_Error
1351
-     * @throws ReflectionException
1352
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1353
-     */
1354
-    public static function get_subtotals_of_object_type(EE_Line_Item $parent_line_item, string $obj_type = ''): array
1355
-    {
1356
-        return self::_get_descendants_by_type_and_object_type(
1357
-            $parent_line_item,
1358
-            EEM_Line_Item::type_sub_total,
1359
-            $obj_type
1360
-        );
1361
-    }
1362
-
1363
-
1364
-    /**
1365
-     * Gets all descendants that are tickets
1366
-     *
1367
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1368
-     * @return EE_Line_Item[]
1369
-     * @throws EE_Error
1370
-     * @throws ReflectionException
1371
-     * @uses  EEH_Line_Item::get_line_items_of_object_type()
1372
-     */
1373
-    public static function get_ticket_line_items(EE_Line_Item $parent_line_item): array
1374
-    {
1375
-        return self::get_line_items_of_object_type(
1376
-            $parent_line_item,
1377
-            EEM_Line_Item::OBJ_TYPE_TICKET
1378
-        );
1379
-    }
1380
-
1381
-
1382
-    /**
1383
-     * Gets all descendants subtotals that match the supplied object type
1384
-     *
1385
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1386
-     * @param string       $obj_type
1387
-     * @return EE_Line_Item[]
1388
-     * @throws EE_Error
1389
-     * @throws ReflectionException
1390
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1391
-     */
1392
-    public static function get_line_items_of_object_type(EE_Line_Item $parent_line_item, string $obj_type = ''): array
1393
-    {
1394
-        return self::_get_descendants_by_type_and_object_type(
1395
-            $parent_line_item,
1396
-            EEM_Line_Item::type_line_item,
1397
-            $obj_type
1398
-        );
1399
-    }
1400
-
1401
-
1402
-    /**
1403
-     * Gets all the descendants (ie, children or children of children etc) that are of the type 'tax'
1404
-     *
1405
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1406
-     * @return EE_Line_Item[]
1407
-     * @throws EE_Error
1408
-     * @throws ReflectionException
1409
-     * @uses  EEH_Line_Item::get_descendants_of_type()
1410
-     */
1411
-    public static function get_tax_descendants(EE_Line_Item $parent_line_item): array
1412
-    {
1413
-        return EEH_Line_Item::get_descendants_of_type(
1414
-            $parent_line_item,
1415
-            EEM_Line_Item::type_tax
1416
-        );
1417
-    }
1418
-
1419
-
1420
-    /**
1421
-     * Gets all the real items purchased which are children of this item
1422
-     *
1423
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1424
-     * @return EE_Line_Item[]
1425
-     * @throws EE_Error
1426
-     * @throws ReflectionException
1427
-     * @uses  EEH_Line_Item::get_descendants_of_type()
1428
-     */
1429
-    public static function get_line_item_descendants(EE_Line_Item $parent_line_item): array
1430
-    {
1431
-        return EEH_Line_Item::get_descendants_of_type(
1432
-            $parent_line_item,
1433
-            EEM_Line_Item::type_line_item
1434
-        );
1435
-    }
1436
-
1437
-
1438
-    /**
1439
-     * Gets all descendants of supplied line item that match the supplied line item type
1440
-     *
1441
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1442
-     * @param string       $line_item_type   one of the EEM_Line_Item constants
1443
-     * @return EE_Line_Item[]
1444
-     * @throws EE_Error
1445
-     * @throws ReflectionException
1446
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1447
-     */
1448
-    public static function get_descendants_of_type(EE_Line_Item $parent_line_item, string $line_item_type): array
1449
-    {
1450
-        return self::_get_descendants_by_type_and_object_type(
1451
-            $parent_line_item,
1452
-            $line_item_type
1453
-        );
1454
-    }
1455
-
1456
-
1457
-    /**
1458
-     * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type
1459
-     * as well
1460
-     *
1461
-     * @param EE_Line_Item $parent_line_item  - the line item to find descendants of
1462
-     * @param string       $line_item_type    one of the EEM_Line_Item constants
1463
-     * @param string|null  $obj_type          object model class name (minus prefix) or NULL to ignore object type when
1464
-     *                                        searching
1465
-     * @return EE_Line_Item[]
1466
-     * @throws EE_Error
1467
-     * @throws ReflectionException
1468
-     */
1469
-    protected static function _get_descendants_by_type_and_object_type(
1470
-        EE_Line_Item $parent_line_item,
1471
-        string $line_item_type,
1472
-        ?string $obj_type = null
1473
-    ): array {
1474
-        $objects = [];
1475
-        foreach ($parent_line_item->children() as $child_line_item) {
1476
-            if ($child_line_item instanceof EE_Line_Item) {
1477
-                if (
1478
-                    $child_line_item->type() === $line_item_type
1479
-                    && (
1480
-                        $child_line_item->OBJ_type() === $obj_type || $obj_type === null
1481
-                    )
1482
-                ) {
1483
-                    $objects[] = $child_line_item;
1484
-                } else {
1485
-                    // go-through-all-its children looking for more matches
1486
-                    $objects = array_merge(
1487
-                        $objects,
1488
-                        self::_get_descendants_by_type_and_object_type(
1489
-                            $child_line_item,
1490
-                            $line_item_type,
1491
-                            $obj_type
1492
-                        )
1493
-                    );
1494
-                }
1495
-            }
1496
-        }
1497
-        return $objects;
1498
-    }
1499
-
1500
-
1501
-    /**
1502
-     * Gets all descendants subtotals that match the supplied object type
1503
-     *
1504
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1505
-     * @param string       $OBJ_type         object type (like Event)
1506
-     * @param array        $OBJ_IDs          array of OBJ_IDs
1507
-     * @return EE_Line_Item[]
1508
-     * @throws EE_Error
1509
-     * @throws ReflectionException
1510
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1511
-     */
1512
-    public static function get_line_items_by_object_type_and_IDs(
1513
-        EE_Line_Item $parent_line_item,
1514
-        string $OBJ_type = '',
1515
-        array $OBJ_IDs = []
1516
-    ): array {
1517
-        return self::_get_descendants_by_object_type_and_object_ID(
1518
-            $parent_line_item,
1519
-            $OBJ_type,
1520
-            $OBJ_IDs
1521
-        );
1522
-    }
1523
-
1524
-
1525
-    /**
1526
-     * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type
1527
-     * as well
1528
-     *
1529
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1530
-     * @param string       $OBJ_type         object type (like Event)
1531
-     * @param array        $OBJ_IDs          array of OBJ_IDs
1532
-     * @return EE_Line_Item[]
1533
-     * @throws EE_Error
1534
-     * @throws ReflectionException
1535
-     */
1536
-    protected static function _get_descendants_by_object_type_and_object_ID(
1537
-        EE_Line_Item $parent_line_item,
1538
-        string $OBJ_type,
1539
-        array $OBJ_IDs
1540
-    ): array {
1541
-        $objects = [];
1542
-        foreach ($parent_line_item->children() as $child_line_item) {
1543
-            if ($child_line_item instanceof EE_Line_Item) {
1544
-                if (
1545
-                    $child_line_item->OBJ_type() === $OBJ_type
1546
-                    && in_array($child_line_item->OBJ_ID(), $OBJ_IDs)
1547
-                ) {
1548
-                    $objects[] = $child_line_item;
1549
-                } else {
1550
-                    // go-through-all-its children looking for more matches
1551
-                    $objects = array_merge(
1552
-                        $objects,
1553
-                        self::_get_descendants_by_object_type_and_object_ID(
1554
-                            $child_line_item,
1555
-                            $OBJ_type,
1556
-                            $OBJ_IDs
1557
-                        )
1558
-                    );
1559
-                }
1560
-            }
1561
-        }
1562
-        return $objects;
1563
-    }
1564
-
1565
-
1566
-    /**
1567
-     * Uses a breadth-first-search in order to find the nearest descendant of
1568
-     * the specified type and returns it, else NULL
1569
-     *
1570
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1571
-     * @param string       $type             like one of the EEM_Line_Item::type_*
1572
-     * @return EE_Line_Item
1573
-     * @throws EE_Error
1574
-     * @throws InvalidArgumentException
1575
-     * @throws InvalidDataTypeException
1576
-     * @throws InvalidInterfaceException
1577
-     * @throws ReflectionException
1578
-     * @uses  EEH_Line_Item::_get_nearest_descendant()
1579
-     */
1580
-    public static function get_nearest_descendant_of_type(EE_Line_Item $parent_line_item, string $type): ?EE_Line_Item
1581
-    {
1582
-        return self::_get_nearest_descendant($parent_line_item, 'LIN_type', $type);
1583
-    }
1584
-
1585
-
1586
-    /**
1587
-     * Uses a breadth-first-search in order to find the nearest descendant
1588
-     * having the specified LIN_code and returns it, else NULL
1589
-     *
1590
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1591
-     * @param string       $code             any value used for LIN_code
1592
-     * @return EE_Line_Item
1593
-     * @throws EE_Error
1594
-     * @throws InvalidArgumentException
1595
-     * @throws InvalidDataTypeException
1596
-     * @throws InvalidInterfaceException
1597
-     * @throws ReflectionException
1598
-     * @uses  EEH_Line_Item::_get_nearest_descendant()
1599
-     */
1600
-    public static function get_nearest_descendant_having_code(
1601
-        EE_Line_Item $parent_line_item,
1602
-        string $code
1603
-    ): ?EE_Line_Item {
1604
-        return self::_get_nearest_descendant($parent_line_item, 'LIN_code', $code);
1605
-    }
1606
-
1607
-
1608
-    /**
1609
-     * Uses a breadth-first-search in order to find the nearest descendant
1610
-     * having the specified LIN_code and returns it, else NULL
1611
-     *
1612
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1613
-     * @param string       $search_field     name of EE_Line_Item property
1614
-     * @param mixed        $value            any value stored in $search_field
1615
-     * @return EE_Line_Item
1616
-     * @throws EE_Error
1617
-     * @throws InvalidArgumentException
1618
-     * @throws InvalidDataTypeException
1619
-     * @throws InvalidInterfaceException
1620
-     * @throws ReflectionException
1621
-     */
1622
-    protected static function _get_nearest_descendant(
1623
-        EE_Line_Item $parent_line_item,
1624
-        string $search_field,
1625
-        $value
1626
-    ): ?EE_Line_Item {
1627
-        foreach ($parent_line_item->children() as $child) {
1628
-            if ($child->get($search_field) == $value) {
1629
-                return $child;
1630
-            }
1631
-        }
1632
-        foreach ($parent_line_item->children() as $child) {
1633
-            $descendant_found = self::_get_nearest_descendant(
1634
-                $child,
1635
-                $search_field,
1636
-                $value
1637
-            );
1638
-            if ($descendant_found) {
1639
-                return $descendant_found;
1640
-            }
1641
-        }
1642
-        return null;
1643
-    }
1644
-
1645
-
1646
-    /**
1647
-     * if passed line item has a TXN ID, uses that to jump directly to the grand total line item for the transaction,
1648
-     * else recursively walks up the line item tree until a parent of type total is found,
1649
-     *
1650
-     * @param EE_Line_Item $line_item
1651
-     * @return EE_Line_Item
1652
-     * @throws EE_Error
1653
-     * @throws ReflectionException
1654
-     */
1655
-    public static function find_transaction_grand_total_for_line_item(EE_Line_Item $line_item): EE_Line_Item
1656
-    {
1657
-        if ($line_item->is_total()) {
1658
-            return $line_item;
1659
-        }
1660
-        if ($line_item->TXN_ID()) {
1661
-            $total_line_item = $line_item->transaction()->total_line_item(false);
1662
-            if ($total_line_item instanceof EE_Line_Item) {
1663
-                return $total_line_item;
1664
-            }
1665
-        } else {
1666
-            $line_item_parent = $line_item->parent();
1667
-            if ($line_item_parent instanceof EE_Line_Item) {
1668
-                if ($line_item_parent->is_total()) {
1669
-                    return $line_item_parent;
1670
-                }
1671
-                return EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item_parent);
1672
-            }
1673
-        }
1674
-        throw new EE_Error(
1675
-            sprintf(
1676
-                esc_html__(
1677
-                    'A valid grand total for line item %1$d was not found.',
1678
-                    'event_espresso'
1679
-                ),
1680
-                $line_item->ID()
1681
-            )
1682
-        );
1683
-    }
1684
-
1685
-
1686
-    /**
1687
-     * Prints out a representation of the line item tree
1688
-     *
1689
-     * @param EE_Line_Item $line_item
1690
-     * @param int          $indentation
1691
-     * @param bool         $top_level
1692
-     * @return void
1693
-     * @throws EE_Error
1694
-     * @throws ReflectionException
1695
-     */
1696
-    public static function visualize(EE_Line_Item $line_item, int $indentation = 0, bool $top_level = true)
1697
-    {
1698
-        if (! defined('WP_DEBUG') || ! WP_DEBUG) {
1699
-            return;
1700
-        }
1701
-        $no_formatting  = defined('EE_TESTS_DIR') || (defined('DOING_AJAX') && DOING_AJAX);
1702
-        $new_line = $no_formatting ? "\n" : '<br />';
1703
-        if ($top_level && ! $no_formatting) {
1704
-            echo '<div style="position: relative; z-index: 9999; margin: 2rem;">';
1705
-            echo '<pre style="padding: 2rem 3rem; color: #00CCFF; background: #363636;">';
1706
-        }
1707
-        if ($top_level || $indentation) {
1708
-            // echo $top_level ? "$new_line$new_line" : $new_line;
1709
-            echo $new_line;
1710
-        }
1711
-        echo str_repeat('. ', $indentation);
1712
-        $breakdown = '';
1713
-        if ($line_item->is_line_item() || $line_item->is_sub_line_item() || $line_item->isTax()) {
1714
-            if ($line_item->is_percent()) {
1715
-                $breakdown = "{$line_item->percent()}%";
1716
-            } else {
1717
-                $breakdown = "\${$line_item->unit_price()} x {$line_item->quantity()}";
1718
-            }
1719
-        }
1720
-        echo wp_kses($line_item->name(), AllowedTags::getAllowedTags());
1721
-        echo " [ ID:{$line_item->ID()} · qty:{$line_item->quantity()} ] {$line_item->type()}";
1722
-        echo " · \${$line_item->total()} · \${$line_item->pretaxTotal()}";
1723
-        if ($breakdown) {
1724
-            echo " ( $breakdown )";
1725
-        }
1726
-        if ($line_item->is_taxable()) {
1727
-            echo '  * taxable';
1728
-        }
1729
-        $children = $line_item->children();
1730
-        if ($children) {
1731
-            foreach ($children as $child) {
1732
-                self::visualize($child, $indentation + 1, false);
1733
-            }
1734
-        }
1735
-        if ($top_level) {
1736
-            echo $no_formatting ? $new_line : "$new_line</pre></div>$new_line";
1737
-        }
1738
-    }
1739
-
1740
-
1741
-    /**
1742
-     * Calculates the registration's final price, taking into account that they
1743
-     * need to not only help pay for their OWN ticket, but also any transaction-wide surcharges and taxes,
1744
-     * and receive a portion of any transaction-wide discounts.
1745
-     * eg1, if I buy a $1 ticket and brent buys a $9 ticket, and we receive a $5 discount
1746
-     * then I'll get 1/10 of that $5 discount, which is $0.50, and brent will get
1747
-     * 9/10ths of that $5 discount, which is $4.50. So my final price should be $0.50
1748
-     * and brent's final price should be $5.50.
1749
-     * In order to do this, we basically need to traverse the line item tree calculating
1750
-     * the running totals (just as if we were recalculating the total), but when we identify
1751
-     * regular line items, we need to keep track of their share of the grand total.
1752
-     * Also, we need to keep track of the TAXABLE total for each ticket purchase, so
1753
-     * we can know how to apply taxes to it. (Note: "taxable total" does not equal the "pretax total"
1754
-     * when there are non-taxable items; otherwise they would be the same)
1755
-     *
1756
-     * @param EE_Line_Item $line_item
1757
-     * @param array        $billable_ticket_quantities          array of EE_Ticket IDs and their corresponding quantity
1758
-     *                                                          that can be included in price calculations at this
1759
-     *                                                          moment
1760
-     * @return array        keys are line items for tickets IDs and values are their share of the running total,
1761
-     *                                                          plus the key 'total', and 'taxable' which also has keys
1762
-     *                                                          of all the ticket IDs. Eg array(
1763
-     *                                                          12 => 4.3
1764
-     *                                                          23 => 8.0
1765
-     *                                                          'total' => 16.6,
1766
-     *                                                          'taxable' => array(
1767
-     *                                                          12 => 10,
1768
-     *                                                          23 => 4
1769
-     *                                                          ).
1770
-     *                                                          So to find which registrations have which final price,
1771
-     *                                                          we need to find which line item is theirs, which can be
1772
-     *                                                          done with
1773
-     *                                                          `EEM_Line_Item::instance()->get_line_item_for_registration(
1774
-     *                                                          $registration );`
1775
-     * @throws EE_Error
1776
-     * @throws InvalidArgumentException
1777
-     * @throws InvalidDataTypeException
1778
-     * @throws InvalidInterfaceException
1779
-     * @throws ReflectionException
1780
-     */
1781
-    public static function calculate_reg_final_prices_per_line_item(
1782
-        EE_Line_Item $line_item,
1783
-        array $billable_ticket_quantities = []
1784
-    ): array {
1785
-        $running_totals = [
1786
-            'total'   => 0,
1787
-            'taxable' => ['total' => 0],
1788
-        ];
1789
-        foreach ($line_item->children() as $child_line_item) {
1790
-            switch ($child_line_item->type()) {
1791
-                case EEM_Line_Item::type_sub_total:
1792
-                    $running_totals_from_subtotal = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1793
-                        $child_line_item,
1794
-                        $billable_ticket_quantities
1795
-                    );
1796
-                    // combine arrays but preserve numeric keys
1797
-                    $running_totals                     = array_replace_recursive(
1798
-                        $running_totals_from_subtotal,
1799
-                        $running_totals
1800
-                    );
1801
-                    $running_totals['total']            += $running_totals_from_subtotal['total'];
1802
-                    $running_totals['taxable']['total'] += $running_totals_from_subtotal['taxable']['total'];
1803
-                    break;
1804
-
1805
-                case EEM_Line_Item::type_tax_sub_total:
1806
-                    // find how much the taxes percentage is
1807
-                    if ($child_line_item->percent() !== 0.0) {
1808
-                        $tax_percent_decimal = $child_line_item->percent() / 100;
1809
-                    } else {
1810
-                        $tax_percent_decimal = EE_Taxes::get_total_taxes_percentage() / 100;
1811
-                    }
1812
-                    // and apply to all the taxable totals, and add to the pretax totals
1813
-                    foreach ($running_totals as $line_item_id => $this_running_total) {
1814
-                        // "total" and "taxable" array key is an exception
1815
-                        if ($line_item_id === 'taxable') {
1816
-                            continue;
1817
-                        }
1818
-                        $taxable_total                   = $running_totals['taxable'][ $line_item_id ];
1819
-                        $running_totals[ $line_item_id ] += ($taxable_total * $tax_percent_decimal);
1820
-                    }
1821
-                    break;
1822
-
1823
-                case EEM_Line_Item::type_line_item:
1824
-                    // ticket line items or ????
1825
-                    if ($child_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) {
1826
-                        // kk it's a ticket
1827
-                        if (isset($running_totals[ $child_line_item->ID() ])) {
1828
-                            // huh? that shouldn't happen.
1829
-                            $running_totals['total'] += $child_line_item->total();
1830
-                        } else {
1831
-                            // it's not in our running totals yet. great.
1832
-                            if ($child_line_item->is_taxable()) {
1833
-                                $taxable_amount = $child_line_item->unit_price();
1834
-                            } else {
1835
-                                $taxable_amount = 0;
1836
-                            }
1837
-                            // are we only calculating totals for some tickets?
1838
-                            if (isset($billable_ticket_quantities[ $child_line_item->OBJ_ID() ])) {
1839
-                                $quantity = $billable_ticket_quantities[ $child_line_item->OBJ_ID() ];
1840
-
1841
-                                $running_totals[ $child_line_item->ID() ]            = $quantity
1842
-                                    ? $child_line_item->unit_price()
1843
-                                    : 0;
1844
-                                $running_totals['taxable'][ $child_line_item->ID() ] = $quantity
1845
-                                    ? $taxable_amount
1846
-                                    : 0;
1847
-                            } else {
1848
-                                $quantity                                            = $child_line_item->quantity();
1849
-                                $running_totals[ $child_line_item->ID() ]            = $child_line_item->unit_price();
1850
-                                $running_totals['taxable'][ $child_line_item->ID() ] = $taxable_amount;
1851
-                            }
1852
-                            $running_totals['taxable']['total'] += $taxable_amount * $quantity;
1853
-                            $running_totals['total']            += $child_line_item->unit_price() * $quantity;
1854
-                        }
1855
-                    } else {
1856
-                        // it's some other type of item added to the cart
1857
-                        // it should affect the running totals
1858
-                        // basically we want to convert it into a PERCENT modifier. Because
1859
-                        // more clearly affect all registration's final price equally
1860
-                        $line_items_percent_of_running_total = $running_totals['total'] > 0
1861
-                            ? ($child_line_item->total() / $running_totals['total']) + 1
1862
-                            : 1;
1863
-                        foreach ($running_totals as $line_item_id => $this_running_total) {
1864
-                            // the "taxable" array key is an exception
1865
-                            if ($line_item_id === 'taxable') {
1866
-                                continue;
1867
-                            }
1868
-                            // update the running totals
1869
-                            // yes this actually even works for the running grand total!
1870
-                            $running_totals[ $line_item_id ] =
1871
-                                $line_items_percent_of_running_total * $this_running_total;
1872
-
1873
-                            if ($child_line_item->is_taxable()) {
1874
-                                $running_totals['taxable'][ $line_item_id ] =
1875
-                                    $line_items_percent_of_running_total * $running_totals['taxable'][ $line_item_id ];
1876
-                            }
1877
-                        }
1878
-                    }
1879
-                    break;
1880
-            }
1881
-        }
1882
-        return $running_totals;
1883
-    }
1884
-
1885
-
1886
-    /**
1887
-     * @param EE_Line_Item $total_line_item
1888
-     * @param EE_Line_Item $ticket_line_item
1889
-     * @return float | null
1890
-     * @throws EE_Error
1891
-     * @throws InvalidArgumentException
1892
-     * @throws InvalidDataTypeException
1893
-     * @throws InvalidInterfaceException
1894
-     * @throws OutOfRangeException
1895
-     * @throws ReflectionException
1896
-     */
1897
-    public static function calculate_final_price_for_ticket_line_item(
1898
-        EE_Line_Item $total_line_item,
1899
-        EE_Line_Item $ticket_line_item
1900
-    ): ?float {
1901
-        static $final_prices_per_ticket_line_item = [];
1902
-        if (
1903
-            empty($final_prices_per_ticket_line_item)
1904
-            || empty($final_prices_per_ticket_line_item[ $total_line_item->ID() ])
1905
-        ) {
1906
-            $final_prices_per_ticket_line_item[ $total_line_item->ID() ] =
1907
-                EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1908
-                    $total_line_item
1909
-                );
1910
-        }
1911
-        // ok now find this new registration's final price
1912
-        if (isset($final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ])) {
1913
-            return $final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ];
1914
-        }
1915
-        $message = sprintf(
1916
-            esc_html__(
1917
-                'The final price for the ticket line item (ID:%1$d) on the total line item (ID:%2$d) could not be calculated.',
1918
-                'event_espresso'
1919
-            ),
1920
-            $ticket_line_item->ID(),
1921
-            $total_line_item->ID()
1922
-        );
1923
-        if (WP_DEBUG) {
1924
-            $message .= '<br>' . print_r($final_prices_per_ticket_line_item, true);
1925
-            throw new OutOfRangeException($message);
1926
-        }
1927
-        EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message);
1928
-        return null;
1929
-    }
1930
-
1931
-
1932
-    /**
1933
-     * Creates a duplicate of the line item tree, except only includes billable items
1934
-     * and the portion of line items attributed to billable things
1935
-     *
1936
-     * @param EE_Line_Item      $line_item
1937
-     * @param EE_Registration[] $registrations
1938
-     * @return EE_Line_Item
1939
-     * @throws EE_Error
1940
-     * @throws InvalidArgumentException
1941
-     * @throws InvalidDataTypeException
1942
-     * @throws InvalidInterfaceException
1943
-     * @throws ReflectionException
1944
-     */
1945
-    public static function billable_line_item_tree(EE_Line_Item $line_item, array $registrations): EE_Line_Item
1946
-    {
1947
-        $copy_li = EEH_Line_Item::billable_line_item($line_item, $registrations);
1948
-        foreach ($line_item->children() as $child_li) {
1949
-            $copy_li->add_child_line_item(
1950
-                EEH_Line_Item::billable_line_item_tree($child_li, $registrations)
1951
-            );
1952
-        }
1953
-        // if this is the grand total line item, make sure the totals all add up
1954
-        // (we could have duplicated this logic AS we copied the line items, but
1955
-        // it seems DRYer this way)
1956
-        if ($copy_li->type() === EEM_Line_Item::type_total) {
1957
-            $copy_li->recalculate_total_including_taxes();
1958
-        }
1959
-        return $copy_li;
1960
-    }
1961
-
1962
-
1963
-    /**
1964
-     * Creates a new, unsaved line item from $line_item that factors in the
1965
-     * number of billable registrations on $registrations.
1966
-     *
1967
-     * @param EE_Line_Item      $line_item
1968
-     * @param EE_Registration[] $registrations
1969
-     * @return EE_Line_Item
1970
-     * @throws EE_Error
1971
-     * @throws InvalidArgumentException
1972
-     * @throws InvalidDataTypeException
1973
-     * @throws InvalidInterfaceException
1974
-     * @throws ReflectionException
1975
-     */
1976
-    public static function billable_line_item(EE_Line_Item $line_item, array $registrations): EE_Line_Item
1977
-    {
1978
-        $new_li_fields = $line_item->model_field_array();
1979
-        if (
1980
-            $line_item->type() === EEM_Line_Item::type_line_item &&
1981
-            $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1982
-        ) {
1983
-            $count = 0;
1984
-            foreach ($registrations as $registration) {
1985
-                if (
1986
-                    $line_item->OBJ_ID() === $registration->ticket_ID() &&
1987
-                    in_array(
1988
-                        $registration->status_ID(),
1989
-                        EEM_Registration::reg_statuses_that_allow_payment(),
1990
-                        true
1991
-                    )
1992
-                ) {
1993
-                    $count++;
1994
-                }
1995
-            }
1996
-            $new_li_fields['LIN_quantity'] = $count;
1997
-        }
1998
-        // don't set the total. We'll leave that up to the code that calculates it
1999
-        unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent'], $new_li_fields['LIN_total']);
2000
-        return EE_Line_Item::new_instance($new_li_fields);
2001
-    }
2002
-
2003
-
2004
-    /**
2005
-     * Returns a modified line item tree where all the subtotals which have a total of 0
2006
-     * are removed, and line items with a quantity of 0
2007
-     *
2008
-     * @param EE_Line_Item $line_item |null
2009
-     * @return EE_Line_Item|null
2010
-     * @throws EE_Error
2011
-     * @throws InvalidArgumentException
2012
-     * @throws InvalidDataTypeException
2013
-     * @throws InvalidInterfaceException
2014
-     * @throws ReflectionException
2015
-     */
2016
-    public static function non_empty_line_items(EE_Line_Item $line_item): ?EE_Line_Item
2017
-    {
2018
-        $copied_li = EEH_Line_Item::non_empty_line_item($line_item);
2019
-        if ($copied_li === null) {
2020
-            return null;
2021
-        }
2022
-        // if this is an event subtotal, we want to only include it if it
2023
-        // has a non-zero total and at least one ticket line item child
2024
-        $ticket_children = 0;
2025
-        foreach ($line_item->children() as $child_li) {
2026
-            $child_li_copy = EEH_Line_Item::non_empty_line_items($child_li);
2027
-            if ($child_li_copy !== null) {
2028
-                $copied_li->add_child_line_item($child_li_copy);
2029
-                if (
2030
-                    $child_li_copy->type() === EEM_Line_Item::type_line_item &&
2031
-                    $child_li_copy->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
2032
-                ) {
2033
-                    $ticket_children++;
2034
-                }
2035
-            }
2036
-        }
2037
-        // if this is an event subtotal with NO ticket children
2038
-        // we basically want to ignore it
2039
-        if (
2040
-            $ticket_children === 0
2041
-            && $line_item->type() === EEM_Line_Item::type_sub_total
2042
-            && $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
2043
-            && $line_item->total() === 0.0
2044
-        ) {
2045
-            return null;
2046
-        }
2047
-        return $copied_li;
2048
-    }
2049
-
2050
-
2051
-    /**
2052
-     * Creates a new, unsaved line item, but if it's a ticket line item
2053
-     * with a total of 0, or a subtotal of 0, returns null instead
2054
-     *
2055
-     * @param EE_Line_Item $line_item
2056
-     * @return EE_Line_Item
2057
-     * @throws EE_Error
2058
-     * @throws InvalidArgumentException
2059
-     * @throws InvalidDataTypeException
2060
-     * @throws InvalidInterfaceException
2061
-     * @throws ReflectionException
2062
-     */
2063
-    public static function non_empty_line_item(EE_Line_Item $line_item): ?EE_Line_Item
2064
-    {
2065
-        if (
2066
-            $line_item->type() === EEM_Line_Item::type_line_item
2067
-            && $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
2068
-            && $line_item->quantity() === 0
2069
-        ) {
2070
-            return null;
2071
-        }
2072
-        $new_li_fields = $line_item->model_field_array();
2073
-        // don't set the total. We'll leave that up to the code that calculates it
2074
-        unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent']);
2075
-        return EE_Line_Item::new_instance($new_li_fields);
2076
-    }
2077
-
2078
-
2079
-    /**
2080
-     * Cycles through all the ticket line items for the supplied total line item
2081
-     * and ensures that the line item's "is_taxable" field matches that of its corresponding ticket
2082
-     *
2083
-     * @param EE_Line_Item $total_line_item
2084
-     * @throws EE_Error
2085
-     * @throws InvalidArgumentException
2086
-     * @throws InvalidDataTypeException
2087
-     * @throws InvalidInterfaceException
2088
-     * @throws ReflectionException
2089
-     * @since 4.9.79.p
2090
-     */
2091
-    public static function resetIsTaxableForTickets(EE_Line_Item $total_line_item)
2092
-    {
2093
-        $ticket_line_items = self::get_ticket_line_items($total_line_item);
2094
-        foreach ($ticket_line_items as $ticket_line_item) {
2095
-            if (
2096
-                $ticket_line_item instanceof EE_Line_Item
2097
-                && $ticket_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
2098
-            ) {
2099
-                $ticket = $ticket_line_item->ticket();
2100
-                if ($ticket instanceof EE_Ticket && $ticket->taxable() !== $ticket_line_item->is_taxable()) {
2101
-                    $ticket_line_item->set_is_taxable($ticket->taxable());
2102
-                    $ticket_line_item->save();
2103
-                }
2104
-            }
2105
-        }
2106
-    }
2107
-
2108
-
2109
-    /**
2110
-     * @return EE_Line_Item[]
2111
-     * @throws EE_Error
2112
-     * @throws ReflectionException
2113
-     * @since   5.0.0.p
2114
-     */
2115
-    private static function getGlobalTaxes(): array
2116
-    {
2117
-        if (EEH_Line_Item::$global_taxes === null) {
2118
-            /** @type EEM_Price $EEM_Price */
2119
-            $EEM_Price = EE_Registry::instance()->load_model('Price');
2120
-            // get array of taxes via Price Model
2121
-            EEH_Line_Item::$global_taxes = $EEM_Price->get_all_prices_that_are_taxes();
2122
-            ksort(EEH_Line_Item::$global_taxes);
2123
-        }
2124
-        return EEH_Line_Item::$global_taxes;
2125
-    }
2126
-
2127
-
2128
-
2129
-    /**************************************** @DEPRECATED METHODS *************************************** */
2130
-    /**
2131
-     * @param EE_Line_Item $total_line_item
2132
-     * @return EE_Line_Item
2133
-     * @throws EE_Error
2134
-     * @throws InvalidArgumentException
2135
-     * @throws InvalidDataTypeException
2136
-     * @throws InvalidInterfaceException
2137
-     * @throws ReflectionException
2138
-     * @deprecated
2139
-     */
2140
-    public static function get_items_subtotal(EE_Line_Item $total_line_item): EE_Line_Item
2141
-    {
2142
-        EE_Error::doing_it_wrong(
2143
-            'EEH_Line_Item::get_items_subtotal()',
2144
-            sprintf(
2145
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
2146
-                'EEH_Line_Item::get_pre_tax_subtotal()'
2147
-            ),
2148
-            '4.6.0'
2149
-        );
2150
-        return self::get_pre_tax_subtotal($total_line_item);
2151
-    }
2152
-
2153
-
2154
-    /**
2155
-     * @param EE_Transaction|null $transaction
2156
-     * @return EE_Line_Item
2157
-     * @throws EE_Error
2158
-     * @throws InvalidArgumentException
2159
-     * @throws InvalidDataTypeException
2160
-     * @throws InvalidInterfaceException
2161
-     * @throws ReflectionException
2162
-     * @deprecated
2163
-     */
2164
-    public static function create_default_total_line_item(?EE_Transaction $transaction = null): EE_Line_Item
2165
-    {
2166
-        EE_Error::doing_it_wrong(
2167
-            'EEH_Line_Item::create_default_total_line_item()',
2168
-            sprintf(
2169
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
2170
-                'EEH_Line_Item::create_total_line_item()'
2171
-            ),
2172
-            '4.6.0'
2173
-        );
2174
-        return self::create_total_line_item($transaction);
2175
-    }
2176
-
2177
-
2178
-    /**
2179
-     * @param EE_Line_Item        $total_line_item
2180
-     * @param EE_Transaction|null $transaction
2181
-     * @return EE_Line_Item
2182
-     * @throws EE_Error
2183
-     * @throws InvalidArgumentException
2184
-     * @throws InvalidDataTypeException
2185
-     * @throws InvalidInterfaceException
2186
-     * @throws ReflectionException
2187
-     * @deprecated
2188
-     */
2189
-    public static function create_default_tickets_subtotal(
2190
-        EE_Line_Item $total_line_item,
2191
-        ?EE_Transaction $transaction = null
2192
-    ): EE_Line_Item {
2193
-        EE_Error::doing_it_wrong(
2194
-            'EEH_Line_Item::create_default_tickets_subtotal()',
2195
-            sprintf(
2196
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
2197
-                'EEH_Line_Item::create_pre_tax_subtotal()'
2198
-            ),
2199
-            '4.6.0'
2200
-        );
2201
-        return self::create_pre_tax_subtotal($total_line_item, $transaction);
2202
-    }
2203
-
2204
-
2205
-    /**
2206
-     * @param EE_Line_Item        $total_line_item
2207
-     * @param EE_Transaction|null $transaction
2208
-     * @return EE_Line_Item
2209
-     * @throws EE_Error
2210
-     * @throws InvalidArgumentException
2211
-     * @throws InvalidDataTypeException
2212
-     * @throws InvalidInterfaceException
2213
-     * @throws ReflectionException
2214
-     * @deprecated
2215
-     */
2216
-    public static function create_default_taxes_subtotal(
2217
-        EE_Line_Item $total_line_item,
2218
-        ?EE_Transaction $transaction = null
2219
-    ): EE_Line_Item {
2220
-        EE_Error::doing_it_wrong(
2221
-            'EEH_Line_Item::create_default_taxes_subtotal()',
2222
-            sprintf(
2223
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
2224
-                'EEH_Line_Item::create_taxes_subtotal()'
2225
-            ),
2226
-            '4.6.0'
2227
-        );
2228
-        return self::create_taxes_subtotal($total_line_item, $transaction);
2229
-    }
2230
-
2231
-
2232
-    /**
2233
-     * @param EE_Line_Item        $total_line_item
2234
-     * @param EE_Transaction|null $transaction
2235
-     * @return EE_Line_Item
2236
-     * @throws EE_Error
2237
-     * @throws InvalidArgumentException
2238
-     * @throws InvalidDataTypeException
2239
-     * @throws InvalidInterfaceException
2240
-     * @throws ReflectionException
2241
-     * @deprecated
2242
-     */
2243
-    public static function create_default_event_subtotal(
2244
-        EE_Line_Item $total_line_item,
2245
-        ?EE_Transaction $transaction = null
2246
-    ): EE_Line_Item {
2247
-        EE_Error::doing_it_wrong(
2248
-            'EEH_Line_Item::create_default_event_subtotal()',
2249
-            sprintf(
2250
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
2251
-                'EEH_Line_Item::create_event_subtotal()'
2252
-            ),
2253
-            '4.6.0'
2254
-        );
2255
-        return self::create_event_subtotal($total_line_item, $transaction);
2256
-    }
24
+	/**
25
+	 * @var EE_Line_Item[]|null
26
+	 */
27
+	private static ?array $global_taxes = null;
28
+
29
+
30
+	/**
31
+	 * Adds a simple item (unrelated to any other model object) to the provided PARENT line item.
32
+	 * Does NOT automatically re-calculate the line item totals or update the related transaction.
33
+	 * You should call recalculate_total_including_taxes() on the grant total line item after this
34
+	 * to update the subtotals, and EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
35
+	 * to keep the registration final prices in-sync with the transaction's total.
36
+	 *
37
+	 * @param EE_Line_Item $parent_line_item
38
+	 * @param string       $name
39
+	 * @param float        $unit_price
40
+	 * @param string       $description
41
+	 * @param int          $quantity
42
+	 * @param boolean      $taxable
43
+	 * @param string|null  $code if set to a value, ensures there is only one line item with that code
44
+	 * @param bool         $return_item
45
+	 * @param bool         $recalculate_totals
46
+	 * @return boolean|EE_Line_Item success
47
+	 * @throws EE_Error
48
+	 * @throws ReflectionException
49
+	 */
50
+	public static function add_unrelated_item(
51
+		EE_Line_Item $parent_line_item,
52
+		string $name,
53
+		float $unit_price,
54
+		string $description = '',
55
+		int $quantity = 1,
56
+		bool $taxable = false,
57
+		?string $code = null,
58
+		bool $return_item = false,
59
+		bool $recalculate_totals = true
60
+	) {
61
+		$items_subtotal = self::get_pre_tax_subtotal($parent_line_item);
62
+		$line_item      = EE_Line_Item::new_instance(
63
+			[
64
+				'LIN_name'       => $name,
65
+				'LIN_desc'       => $description,
66
+				'LIN_unit_price' => $unit_price,
67
+				'LIN_quantity'   => $quantity,
68
+				'LIN_percent'    => null,
69
+				'LIN_is_taxable' => $taxable,
70
+				'LIN_order'      => count($items_subtotal->children()),
71
+				'LIN_total'      => $unit_price * $quantity,
72
+				'LIN_type'       => EEM_Line_Item::type_line_item,
73
+				'LIN_code'       => $code,
74
+			]
75
+		);
76
+		$line_item      = apply_filters(
77
+			'FHEE__EEH_Line_Item__add_unrelated_item__line_item',
78
+			$line_item,
79
+			$parent_line_item
80
+		);
81
+		$added          = self::add_item($parent_line_item, $line_item, $recalculate_totals);
82
+		return $return_item ? $line_item : $added;
83
+	}
84
+
85
+
86
+	/**
87
+	 * Adds a simple item ( unrelated to any other model object) to the total line item,
88
+	 * in the correct spot in the line item tree. Does not automatically
89
+	 * re-calculate the line item totals, nor update the related transaction, nor upgrade the transaction's
90
+	 * registrations' final prices (which should probably change because of this).
91
+	 * You should call recalculate_total_including_taxes() on the grand total line item, then
92
+	 * update the transaction's total, and EE_Registration_Processor::update_registration_final_prices()
93
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
94
+	 *
95
+	 * @param EE_Line_Item $parent_line_item
96
+	 * @param string       $name
97
+	 * @param float        $percentage_amount
98
+	 * @param string       $description
99
+	 * @param boolean      $taxable
100
+	 * @param string|null  $code
101
+	 * @param bool         $return_item
102
+	 * @return boolean|EE_Line_Item success
103
+	 * @throws EE_Error
104
+	 * @throws ReflectionException
105
+	 */
106
+	public static function add_percentage_based_item(
107
+		EE_Line_Item $parent_line_item,
108
+		string $name,
109
+		float $percentage_amount,
110
+		string $description = '',
111
+		bool $taxable = false,
112
+		?string $code = null,
113
+		bool $return_item = false
114
+	) {
115
+		$total     = $percentage_amount * $parent_line_item->total() / 100;
116
+		$line_item = EE_Line_Item::new_instance(
117
+			[
118
+				'LIN_name'       => $name,
119
+				'LIN_desc'       => $description,
120
+				'LIN_unit_price' => 0,
121
+				'LIN_percent'    => $percentage_amount,
122
+				'LIN_is_taxable' => $taxable,
123
+				'LIN_total'      => $total,
124
+				'LIN_type'       => EEM_Line_Item::type_line_item,
125
+				'LIN_parent'     => $parent_line_item->ID(),
126
+				'LIN_code'       => $code,
127
+				'TXN_ID'         => $parent_line_item->TXN_ID(),
128
+			]
129
+		);
130
+		$line_item = apply_filters(
131
+			'FHEE__EEH_Line_Item__add_percentage_based_item__line_item',
132
+			$line_item
133
+		);
134
+		$added     = $parent_line_item->add_child_line_item($line_item, false);
135
+		return $return_item ? $line_item : $added;
136
+	}
137
+
138
+
139
+	/**
140
+	 * Returns the new line item created by adding a purchase of the ticket
141
+	 * ensures that ticket line item is saved, and that cart total has been recalculated.
142
+	 * If this ticket has already been purchased, just increments its count.
143
+	 * Automatically re-calculates the line item totals and updates the related transaction. But
144
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
145
+	 * should probably change because of this).
146
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
147
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
148
+	 *
149
+	 * @param EE_Line_Item|null $total_line_item grand total line item of type EEM_Line_Item::type_total
150
+	 * @param EE_Ticket         $ticket
151
+	 * @param int               $qty
152
+	 * @param bool              $recalculate_totals
153
+	 * @return EE_Line_Item
154
+	 * @throws EE_Error
155
+	 * @throws ReflectionException
156
+	 */
157
+	public static function add_ticket_purchase(
158
+		?EE_Line_Item $total_line_item,
159
+		EE_Ticket $ticket,
160
+		int $qty = 1,
161
+		bool $recalculate_totals = true
162
+	): ?EE_Line_Item {
163
+		if (! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) {
164
+			throw new EE_Error(
165
+				sprintf(
166
+					esc_html__(
167
+						'A valid line item total is required in order to add tickets. A line item of type "%s" was passed.',
168
+						'event_espresso'
169
+					),
170
+					$ticket->ID(),
171
+					$total_line_item->ID()
172
+				)
173
+			);
174
+		}
175
+		// either increment the qty for an existing ticket
176
+		$line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty);
177
+		// or add a new one
178
+		if (! $line_item instanceof EE_Line_Item) {
179
+			$line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty);
180
+		}
181
+		if ($recalculate_totals) {
182
+			$total_line_item->recalculate_total_including_taxes();
183
+		}
184
+		return $line_item;
185
+	}
186
+
187
+
188
+	/**
189
+	 * Returns the new line item created by adding a purchase of the ticket
190
+	 *
191
+	 * @param EE_Line_Item|null $total_line_item
192
+	 * @param EE_Ticket         $ticket
193
+	 * @param int               $qty
194
+	 * @return EE_Line_Item
195
+	 * @throws EE_Error
196
+	 * @throws InvalidArgumentException
197
+	 * @throws InvalidDataTypeException
198
+	 * @throws InvalidInterfaceException
199
+	 * @throws ReflectionException
200
+	 */
201
+	public static function increment_ticket_qty_if_already_in_cart(
202
+		?EE_Line_Item $total_line_item,
203
+		EE_Ticket $ticket,
204
+		int $qty = 1
205
+	): ?EE_Line_Item {
206
+		$line_item = null;
207
+		if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) {
208
+			$ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
209
+			foreach ($ticket_line_items as $ticket_line_item) {
210
+				if (
211
+					$ticket_line_item instanceof EE_Line_Item
212
+					&& $ticket_line_item->OBJ_ID() === $ticket->ID()
213
+				) {
214
+					$line_item = $ticket_line_item;
215
+					break;
216
+				}
217
+			}
218
+		}
219
+		if ($line_item instanceof EE_Line_Item) {
220
+			EEH_Line_Item::increment_quantity($line_item, $qty);
221
+			return $line_item;
222
+		}
223
+		return null;
224
+	}
225
+
226
+
227
+	/**
228
+	 * Increments the line item and all its children's quantity by $qty (but percent line items are unaffected).
229
+	 * Does NOT save or recalculate other line items totals
230
+	 *
231
+	 * @param EE_Line_Item $line_item
232
+	 * @param int          $qty
233
+	 * @return void
234
+	 * @throws EE_Error
235
+	 * @throws InvalidArgumentException
236
+	 * @throws InvalidDataTypeException
237
+	 * @throws InvalidInterfaceException
238
+	 * @throws ReflectionException
239
+	 */
240
+	public static function increment_quantity(EE_Line_Item $line_item, int $qty = 1)
241
+	{
242
+		if (! $line_item->is_percent()) {
243
+			$qty += $line_item->quantity();
244
+			$line_item->set_quantity($qty);
245
+			$line_item->set_total($line_item->unit_price() * $qty);
246
+			$line_item->save();
247
+		}
248
+		foreach ($line_item->children() as $child) {
249
+			if ($child->is_sub_line_item()) {
250
+				EEH_Line_Item::update_quantity($child, $qty);
251
+			}
252
+		}
253
+	}
254
+
255
+
256
+	/**
257
+	 * Decrements the line item and all its children's quantity by $qty (but percent line items are unaffected).
258
+	 * Does NOT save or recalculate other line items totals
259
+	 *
260
+	 * @param EE_Line_Item $line_item
261
+	 * @param int          $qty
262
+	 * @return void
263
+	 * @throws EE_Error
264
+	 * @throws InvalidArgumentException
265
+	 * @throws InvalidDataTypeException
266
+	 * @throws InvalidInterfaceException
267
+	 * @throws ReflectionException
268
+	 */
269
+	public static function decrement_quantity(EE_Line_Item $line_item, int $qty = 1)
270
+	{
271
+		if (! $line_item->is_percent()) {
272
+			$qty = $line_item->quantity() - $qty;
273
+			$qty = max($qty, 0);
274
+			$line_item->set_quantity($qty);
275
+			$line_item->set_total($line_item->unit_price() * $qty);
276
+			$line_item->save();
277
+		}
278
+		foreach ($line_item->children() as $child) {
279
+			if ($child->is_sub_line_item()) {
280
+				EEH_Line_Item::update_quantity($child, $qty);
281
+			}
282
+		}
283
+	}
284
+
285
+
286
+	/**
287
+	 * Updates the line item and its children's quantities to the specified number.
288
+	 * Does NOT save them or recalculate totals.
289
+	 *
290
+	 * @param EE_Line_Item $line_item
291
+	 * @param int          $new_quantity
292
+	 * @throws EE_Error
293
+	 * @throws InvalidArgumentException
294
+	 * @throws InvalidDataTypeException
295
+	 * @throws InvalidInterfaceException
296
+	 * @throws ReflectionException
297
+	 */
298
+	public static function update_quantity(EE_Line_Item $line_item, int $new_quantity)
299
+	{
300
+		if (! $line_item->is_percent()) {
301
+			$line_item->set_quantity($new_quantity);
302
+			$line_item->set_total($line_item->unit_price() * $new_quantity);
303
+			$line_item->save();
304
+		}
305
+		foreach ($line_item->children() as $child) {
306
+			if ($child->is_sub_line_item()) {
307
+				EEH_Line_Item::update_quantity($child, $new_quantity);
308
+			}
309
+		}
310
+	}
311
+
312
+
313
+	/**
314
+	 * Returns the new line item created by adding a purchase of the ticket
315
+	 *
316
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
317
+	 * @param EE_Ticket    $ticket
318
+	 * @param int          $qty
319
+	 * @return EE_Line_Item
320
+	 * @throws EE_Error
321
+	 * @throws InvalidArgumentException
322
+	 * @throws InvalidDataTypeException
323
+	 * @throws InvalidInterfaceException
324
+	 * @throws ReflectionException
325
+	 */
326
+	public static function create_ticket_line_item(
327
+		EE_Line_Item $total_line_item,
328
+		EE_Ticket $ticket,
329
+		int $qty = 1
330
+	): EE_Line_Item {
331
+		$datetimes           = $ticket->datetimes();
332
+		$first_datetime      = reset($datetimes);
333
+		$first_datetime_name = esc_html__('Event', 'event_espresso');
334
+		if ($first_datetime instanceof EE_Datetime && $first_datetime->event() instanceof EE_Event) {
335
+			$first_datetime_name = $first_datetime->event()->name();
336
+		}
337
+		$event = sprintf(_x('(For %1$s)', '(For Event Name)', 'event_espresso'), $first_datetime_name);
338
+		// get event subtotal line
339
+		$events_sub_total = self::get_event_line_item_for_ticket($total_line_item, $ticket);
340
+		$taxes            = $ticket->tax_price_modifiers();
341
+		// add $ticket to cart
342
+		$line_item = EE_Line_Item::new_instance(
343
+			[
344
+				'LIN_name'       => $ticket->name(),
345
+				'LIN_desc'       => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event,
346
+				'LIN_unit_price' => $ticket->price(),
347
+				'LIN_quantity'   => $qty,
348
+				'LIN_is_taxable' => empty($taxes) && $ticket->taxable(),
349
+				'LIN_order'      => count($events_sub_total->children()),
350
+				'LIN_total'      => $ticket->price() * $qty,
351
+				'LIN_type'       => EEM_Line_Item::type_line_item,
352
+				'OBJ_ID'         => $ticket->ID(),
353
+				'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_TICKET,
354
+			]
355
+		);
356
+		$line_item = apply_filters(
357
+			'FHEE__EEH_Line_Item__create_ticket_line_item__line_item',
358
+			$line_item
359
+		);
360
+		if (! $line_item instanceof EE_Line_Item) {
361
+			throw new DomainException(
362
+				esc_html__('Invalid EE_Line_Item received.', 'event_espresso')
363
+			);
364
+		}
365
+		$events_sub_total->add_child_line_item($line_item);
366
+		// now add the sub-line items
367
+		$running_pre_tax_total = 0;
368
+		$prices                = $ticket->prices();
369
+		if (empty($prices)) {
370
+			// WUT?!?! NO PRICES??? Well, just create a default price then.
371
+			$default_price = EEM_Price::instance()->get_new_price();
372
+			if ($default_price->amount() !== $ticket->price()) {
373
+				$default_price->set_amount($ticket->price());
374
+			}
375
+			$default_price->save();
376
+			$ticket->_add_relation_to($default_price, 'Price');
377
+			$ticket->save();
378
+			$prices = [$default_price];
379
+		}
380
+		foreach ($prices as $price) {
381
+			$sign = $price->is_discount() ? -1 : 1;
382
+			$price_amount = $price->amount();
383
+			if ($price->is_percent()) {
384
+				$price_total = $running_pre_tax_total * $price_amount / 100;
385
+				$percent    = $sign * $price_amount;
386
+				$unit_price = 0;
387
+			} else {
388
+				$price_total = $price_amount * $qty;
389
+				$percent    = 0;
390
+				$unit_price = $sign * $price_amount;
391
+			}
392
+
393
+			$price_desc = $price->desc();
394
+			$price_type = $price->type_obj();
395
+			$price_desc = $price_desc === '' && $price_type instanceof EE_Price_Type
396
+				? $price_type->name()
397
+				: $price_desc;
398
+
399
+			$sub_line_item         = EE_Line_Item::new_instance(
400
+				[
401
+					'LIN_name'       => $price->name(),
402
+					'LIN_desc'       => $price_desc,
403
+					'LIN_is_taxable' => false,
404
+					'LIN_order'      => $price->order(),
405
+					'LIN_total'      => $price_total,
406
+					'LIN_pretax'     => 0,
407
+					'LIN_unit_price' => $unit_price,
408
+					'LIN_percent'    => $percent,
409
+					'LIN_type'       => $price->is_tax()
410
+						? EEM_Line_Item::type_sub_tax
411
+						: EEM_Line_Item::type_sub_line_item,
412
+					'OBJ_ID'         => $price->ID(),
413
+					'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_PRICE,
414
+				]
415
+			);
416
+			$sub_line_item         = apply_filters(
417
+				'FHEE__EEH_Line_Item__create_ticket_line_item__sub_line_item',
418
+				$sub_line_item
419
+			);
420
+			$running_pre_tax_total += ! $price->is_tax() ? $sign * $price_total : 0;
421
+			$line_item->add_child_line_item($sub_line_item);
422
+		}
423
+		$line_item->setPretaxTotal($running_pre_tax_total);
424
+		return $line_item;
425
+	}
426
+
427
+
428
+	/**
429
+	 * Adds the specified item under the pre-tax-sub-total line item. Automatically
430
+	 * re-calculates the line item totals and updates the related transaction. But
431
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
432
+	 * should probably change because of this).
433
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
434
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
435
+	 *
436
+	 * @param EE_Line_Item $total_line_item
437
+	 * @param EE_Line_Item $item to be added
438
+	 * @param bool         $recalculate_totals
439
+	 * @return boolean
440
+	 * @throws EE_Error
441
+	 * @throws InvalidArgumentException
442
+	 * @throws InvalidDataTypeException
443
+	 * @throws InvalidInterfaceException
444
+	 * @throws ReflectionException
445
+	 */
446
+	public static function add_item(
447
+		EE_Line_Item $total_line_item,
448
+		EE_Line_Item $item,
449
+		bool $recalculate_totals = true
450
+	): bool {
451
+		$pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item);
452
+		$success          = $pre_tax_subtotal->add_child_line_item($item);
453
+		if ($recalculate_totals) {
454
+			$total_line_item->recalculate_total_including_taxes();
455
+		}
456
+		return $success;
457
+	}
458
+
459
+
460
+	/**
461
+	 * cancels an existing ticket line item,
462
+	 * by decrementing its quantity by 1 and adding a new "type_cancellation" sub-line-item.
463
+	 * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
464
+	 *
465
+	 * @param EE_Line_Item $ticket_line_item
466
+	 * @param int          $qty
467
+	 * @return bool success
468
+	 * @throws EE_Error
469
+	 * @throws InvalidArgumentException
470
+	 * @throws InvalidDataTypeException
471
+	 * @throws InvalidInterfaceException
472
+	 * @throws ReflectionException
473
+	 */
474
+	public static function cancel_ticket_line_item(EE_Line_Item $ticket_line_item, int $qty = 1): bool
475
+	{
476
+		// validate incoming line_item
477
+		if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) {
478
+			throw new EE_Error(
479
+				sprintf(
480
+					esc_html__(
481
+						'The supplied line item must have an Object Type of "Ticket", not %1$s.',
482
+						'event_espresso'
483
+					),
484
+					$ticket_line_item->type()
485
+				)
486
+			);
487
+		}
488
+		if ($ticket_line_item->quantity() < $qty) {
489
+			throw new EE_Error(
490
+				sprintf(
491
+					esc_html__(
492
+						'Can not cancel %1$d ticket(s) because the supplied line item has a quantity of %2$d.',
493
+						'event_espresso'
494
+					),
495
+					$qty,
496
+					$ticket_line_item->quantity()
497
+				)
498
+			);
499
+		}
500
+		// decrement ticket quantity; don't rely on auto-fixing when recalculating totals to do this
501
+		$ticket_line_item->set_quantity($ticket_line_item->quantity() - $qty);
502
+		foreach ($ticket_line_item->children() as $child_line_item) {
503
+			if (
504
+				$child_line_item->is_sub_line_item()
505
+				&& ! $child_line_item->is_percent()
506
+				&& ! $child_line_item->is_cancellation()
507
+			) {
508
+				$child_line_item->set_quantity($child_line_item->quantity() - $qty);
509
+			}
510
+		}
511
+		// get cancellation sub line item
512
+		$cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
513
+			$ticket_line_item,
514
+			EEM_Line_Item::type_cancellation
515
+		);
516
+		$cancellation_line_item = reset($cancellation_line_item);
517
+		// verify that this ticket was indeed previously cancelled
518
+		if ($cancellation_line_item instanceof EE_Line_Item) {
519
+			// increment cancelled quantity
520
+			$cancellation_line_item->set_quantity($cancellation_line_item->quantity() + $qty);
521
+		} else {
522
+			// create cancellation sub line item
523
+			$cancellation_line_item = EE_Line_Item::new_instance(
524
+				[
525
+					'LIN_name'       => esc_html__('Cancellation', 'event_espresso'),
526
+					'LIN_desc'       => sprintf(
527
+						esc_html_x(
528
+							'Cancelled %1$s : %2$s',
529
+							'Cancelled Ticket Name : 2015-01-01 11:11',
530
+							'event_espresso'
531
+						),
532
+						$ticket_line_item->name(),
533
+						current_time(get_option('date_format') . ' ' . get_option('time_format'))
534
+					),
535
+					'LIN_total'      => 0,
536
+					'LIN_unit_price' => 0,
537
+					'LIN_quantity'   => $qty,
538
+					'LIN_is_taxable' => $ticket_line_item->is_taxable(),
539
+					'LIN_order'      => count($ticket_line_item->children()),
540
+					'LIN_type'       => EEM_Line_Item::type_cancellation,
541
+				]
542
+			);
543
+			$ticket_line_item->add_child_line_item($cancellation_line_item);
544
+		}
545
+		if ($ticket_line_item->save_this_and_descendants() > 0) {
546
+			// decrement parent line item quantity
547
+			$event_line_item = $ticket_line_item->parent();
548
+			if (
549
+				$event_line_item instanceof EE_Line_Item
550
+				&& $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
551
+			) {
552
+				$event_line_item->set_quantity($event_line_item->quantity() - $qty);
553
+				$event_line_item->save();
554
+			}
555
+			EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
556
+			return true;
557
+		}
558
+		return false;
559
+	}
560
+
561
+
562
+	/**
563
+	 * reinstates (un-cancels?) a previously canceled ticket line item,
564
+	 * by incrementing its quantity by 1, and decrementing its "type_cancellation" sub-line-item.
565
+	 * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
566
+	 *
567
+	 * @param EE_Line_Item $ticket_line_item
568
+	 * @param int          $qty
569
+	 * @return bool success
570
+	 * @throws EE_Error
571
+	 * @throws InvalidArgumentException
572
+	 * @throws InvalidDataTypeException
573
+	 * @throws InvalidInterfaceException
574
+	 * @throws ReflectionException
575
+	 */
576
+	public static function reinstate_canceled_ticket_line_item(EE_Line_Item $ticket_line_item, int $qty = 1): bool
577
+	{
578
+		// validate incoming line_item
579
+		if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) {
580
+			throw new EE_Error(
581
+				sprintf(
582
+					esc_html__(
583
+						'The supplied line item must have an Object Type of "Ticket", not %1$s.',
584
+						'event_espresso'
585
+					),
586
+					$ticket_line_item->type()
587
+				)
588
+			);
589
+		}
590
+		// get cancellation sub line item
591
+		$cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
592
+			$ticket_line_item,
593
+			EEM_Line_Item::type_cancellation
594
+		);
595
+		$cancellation_line_item = reset($cancellation_line_item);
596
+		// verify that this ticket was indeed previously cancelled
597
+		if (! $cancellation_line_item instanceof EE_Line_Item) {
598
+			return false;
599
+		}
600
+		if ($cancellation_line_item->quantity() > $qty) {
601
+			// decrement cancelled quantity
602
+			$cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
603
+		} elseif ($cancellation_line_item->quantity() === $qty) {
604
+			// decrement cancelled quantity in case anyone still has the object kicking around
605
+			$cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
606
+			// delete because quantity will end up as 0
607
+			$cancellation_line_item->delete();
608
+			// and attempt to destroy the object,
609
+			// even though PHP won't actually destroy it until it needs the memory
610
+			unset($cancellation_line_item);
611
+		} else {
612
+			// what ?!?! negative quantity ?!?!
613
+			throw new EE_Error(
614
+				sprintf(
615
+					esc_html__(
616
+						'Can not reinstate %1$d cancelled ticket(s) because the cancelled ticket quantity is only %2$d.',
617
+						'event_espresso'
618
+					),
619
+					$qty,
620
+					$cancellation_line_item->quantity()
621
+				)
622
+			);
623
+		}
624
+		// increment ticket quantity
625
+		$ticket_line_item->set_quantity($ticket_line_item->quantity() + $qty);
626
+		if ($ticket_line_item->save_this_and_descendants() > 0) {
627
+			// increment parent line item quantity
628
+			$event_line_item = $ticket_line_item->parent();
629
+			if (
630
+				$event_line_item instanceof EE_Line_Item
631
+				&& $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
632
+			) {
633
+				$event_line_item->set_quantity($event_line_item->quantity() + $qty);
634
+			}
635
+			EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
636
+			return true;
637
+		}
638
+		return false;
639
+	}
640
+
641
+
642
+	/**
643
+	 * calls EEH_Line_Item::find_transaction_grand_total_for_line_item()
644
+	 * then EE_Line_Item::recalculate_total_including_taxes() on the result
645
+	 *
646
+	 * @param EE_Line_Item $line_item
647
+	 * @return float
648
+	 * @throws EE_Error
649
+	 * @throws InvalidArgumentException
650
+	 * @throws InvalidDataTypeException
651
+	 * @throws InvalidInterfaceException
652
+	 * @throws ReflectionException
653
+	 */
654
+	public static function get_grand_total_and_recalculate_everything(EE_Line_Item $line_item): float
655
+	{
656
+		$grand_total_line_item = EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item);
657
+		return $grand_total_line_item->recalculate_total_including_taxes();
658
+	}
659
+
660
+
661
+	/**
662
+	 * Gets the line item which contains the subtotal of all the items
663
+	 *
664
+	 * @param EE_Line_Item        $total_line_item of type EEM_Line_Item::type_total
665
+	 * @param EE_Transaction|null $transaction
666
+	 * @param bool                $create_event_subtotal
667
+	 * @return EE_Line_Item
668
+	 * @throws EE_Error
669
+	 * @throws ReflectionException
670
+	 */
671
+	public static function get_pre_tax_subtotal(
672
+		EE_Line_Item $total_line_item,
673
+		?EE_Transaction $transaction = null,
674
+		bool $create_event_subtotal = true
675
+	): EE_Line_Item {
676
+		$pre_tax_subtotal = $total_line_item->get_child_line_item('pre-tax-subtotal');
677
+		return $pre_tax_subtotal instanceof EE_Line_Item
678
+			? $pre_tax_subtotal
679
+			: self::create_pre_tax_subtotal($total_line_item, $transaction, $create_event_subtotal);
680
+	}
681
+
682
+
683
+	/**
684
+	 * Gets the line item for the taxes subtotal
685
+	 *
686
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
687
+	 * @return EE_Line_Item
688
+	 * @throws EE_Error
689
+	 * @throws InvalidArgumentException
690
+	 * @throws InvalidDataTypeException
691
+	 * @throws InvalidInterfaceException
692
+	 * @throws ReflectionException
693
+	 */
694
+	public static function get_taxes_subtotal(EE_Line_Item $total_line_item): EE_Line_Item
695
+	{
696
+		$taxes = $total_line_item->get_child_line_item('taxes');
697
+		return $taxes ?: self::create_taxes_subtotal($total_line_item);
698
+	}
699
+
700
+
701
+	/**
702
+	 * sets the TXN ID on an EE_Line_Item if passed a valid EE_Transaction object
703
+	 *
704
+	 * @param EE_Line_Item        $line_item
705
+	 * @param EE_Transaction|null $transaction
706
+	 * @return void
707
+	 * @throws EE_Error
708
+	 * @throws InvalidArgumentException
709
+	 * @throws InvalidDataTypeException
710
+	 * @throws InvalidInterfaceException
711
+	 * @throws ReflectionException
712
+	 */
713
+	public static function set_TXN_ID(EE_Line_Item $line_item, ?EE_Transaction $transaction = null)
714
+	{
715
+		if ($transaction) {
716
+			/** @type EEM_Transaction $EEM_Transaction */
717
+			$EEM_Transaction = EE_Registry::instance()->load_model('Transaction');
718
+			$TXN_ID          = $EEM_Transaction->ensure_is_ID($transaction);
719
+			$line_item->set_TXN_ID($TXN_ID);
720
+		}
721
+	}
722
+
723
+
724
+	/**
725
+	 * Creates a new default total line item for the transaction,
726
+	 * and its tickets subtotal and taxes subtotal line items (and adds the
727
+	 * existing taxes as children of the taxes subtotal line item)
728
+	 *
729
+	 * @param EE_Transaction|null $transaction
730
+	 * @return EE_Line_Item of type total
731
+	 * @throws EE_Error
732
+	 * @throws InvalidArgumentException
733
+	 * @throws InvalidDataTypeException
734
+	 * @throws InvalidInterfaceException
735
+	 * @throws ReflectionException
736
+	 */
737
+	public static function create_total_line_item(?EE_Transaction $transaction = null): EE_Line_Item
738
+	{
739
+		$total_line_item = EE_Line_Item::new_instance(
740
+			[
741
+				'LIN_code' => 'total',
742
+				'LIN_name' => esc_html__('Grand Total', 'event_espresso'),
743
+				'LIN_type' => EEM_Line_Item::type_total,
744
+				'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TRANSACTION,
745
+			]
746
+		);
747
+		$total_line_item = apply_filters(
748
+			'FHEE__EEH_Line_Item__create_total_line_item__total_line_item',
749
+			$total_line_item
750
+		);
751
+		self::set_TXN_ID($total_line_item, $transaction);
752
+		self::create_pre_tax_subtotal($total_line_item, $transaction);
753
+		self::create_taxes_subtotal($total_line_item, $transaction);
754
+		return $total_line_item;
755
+	}
756
+
757
+
758
+	/**
759
+	 * Creates a default items subtotal line item
760
+	 *
761
+	 * @param EE_Line_Item        $total_line_item
762
+	 * @param EE_Transaction|null $transaction
763
+	 * @param bool                $create_event_subtotal
764
+	 * @return EE_Line_Item
765
+	 * @throws EE_Error
766
+	 * @throws ReflectionException
767
+	 */
768
+	protected static function create_pre_tax_subtotal(
769
+		EE_Line_Item $total_line_item,
770
+		?EE_Transaction $transaction = null,
771
+		bool $create_event_subtotal = true
772
+	): EE_Line_Item {
773
+		$pre_tax_line_item = EE_Line_Item::new_instance(
774
+			[
775
+				'LIN_code' => 'pre-tax-subtotal',
776
+				'LIN_name' => esc_html__('Pre-Tax Subtotal', 'event_espresso'),
777
+				'LIN_type' => EEM_Line_Item::type_sub_total,
778
+			]
779
+		);
780
+		$pre_tax_line_item = apply_filters(
781
+			'FHEE__EEH_Line_Item__create_pre_tax_subtotal__pre_tax_line_item',
782
+			$pre_tax_line_item
783
+		);
784
+		self::set_TXN_ID($pre_tax_line_item, $transaction);
785
+		$total_line_item->add_child_line_item($pre_tax_line_item);
786
+		if ($create_event_subtotal) {
787
+			self::create_event_subtotal($pre_tax_line_item, $transaction);
788
+		}
789
+		return $pre_tax_line_item;
790
+	}
791
+
792
+
793
+	/**
794
+	 * Creates a line item for the taxes subtotal and finds all the tax prices
795
+	 * and applies taxes to it
796
+	 *
797
+	 * @param EE_Line_Item        $total_line_item of type EEM_Line_Item::type_total
798
+	 * @param EE_Transaction|null $transaction
799
+	 * @return EE_Line_Item
800
+	 * @throws EE_Error
801
+	 * @throws InvalidArgumentException
802
+	 * @throws InvalidDataTypeException
803
+	 * @throws InvalidInterfaceException
804
+	 * @throws ReflectionException
805
+	 */
806
+	protected static function create_taxes_subtotal(
807
+		EE_Line_Item $total_line_item,
808
+		?EE_Transaction $transaction = null
809
+	): EE_Line_Item {
810
+		$tax_line_item = EE_Line_Item::new_instance(
811
+			[
812
+				'LIN_code'  => 'taxes',
813
+				'LIN_name'  => esc_html__('Taxes', 'event_espresso'),
814
+				'LIN_type'  => EEM_Line_Item::type_tax_sub_total,
815
+				'LIN_order' => 1000,// this should always come last
816
+			]
817
+		);
818
+		$tax_line_item = apply_filters(
819
+			'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item',
820
+			$tax_line_item
821
+		);
822
+		self::set_TXN_ID($tax_line_item, $transaction);
823
+		$total_line_item->add_child_line_item($tax_line_item);
824
+		// and lastly, add the actual taxes
825
+		self::apply_taxes($total_line_item);
826
+		return $tax_line_item;
827
+	}
828
+
829
+
830
+	/**
831
+	 * Creates a default items subtotal line item
832
+	 *
833
+	 * @param EE_Line_Item        $pre_tax_line_item
834
+	 * @param EE_Transaction|null $transaction
835
+	 * @param EE_Event|null       $event
836
+	 * @return EE_Line_Item
837
+	 * @throws EE_Error
838
+	 * @throws InvalidArgumentException
839
+	 * @throws InvalidDataTypeException
840
+	 * @throws InvalidInterfaceException
841
+	 * @throws ReflectionException
842
+	 */
843
+	public static function create_event_subtotal(
844
+		EE_Line_Item $pre_tax_line_item,
845
+		?EE_Transaction $transaction = null,
846
+		?EE_Event $event = null
847
+	): EE_Line_Item {
848
+		// first check if this line item already exists
849
+		$event_line_item = EEM_Line_Item::instance()->get_one(
850
+			[
851
+				[
852
+					'LIN_type' => EEM_Line_Item::type_sub_total,
853
+					'OBJ_type' => EEM_Line_Item::OBJ_TYPE_EVENT,
854
+					'OBJ_ID'   => $event instanceof EE_Event ? $event->ID() : 0,
855
+					'TXN_ID'   => $transaction instanceof EE_Transaction ? $transaction->ID() : 0,
856
+				],
857
+			]
858
+		);
859
+		if ($event_line_item instanceof EE_Line_Item) {
860
+			return $event_line_item;
861
+		}
862
+
863
+		$event_line_item = EE_Line_Item::new_instance(
864
+			[
865
+				'LIN_code' => self::get_event_code($event),
866
+				'LIN_name' => self::get_event_name($event),
867
+				'LIN_desc' => self::get_event_desc($event),
868
+				'LIN_type' => EEM_Line_Item::type_sub_total,
869
+				'OBJ_type' => EEM_Line_Item::OBJ_TYPE_EVENT,
870
+				'OBJ_ID'   => $event instanceof EE_Event ? $event->ID() : 0,
871
+			]
872
+		);
873
+		$event_line_item = apply_filters(
874
+			'FHEE__EEH_Line_Item__create_event_subtotal__event_line_item',
875
+			$event_line_item
876
+		);
877
+		self::set_TXN_ID($event_line_item, $transaction);
878
+		$pre_tax_line_item->add_child_line_item($event_line_item);
879
+		return $event_line_item;
880
+	}
881
+
882
+
883
+	/**
884
+	 * Gets what the event ticket's code SHOULD be
885
+	 *
886
+	 * @param EE_Event|null $event
887
+	 * @return string
888
+	 * @throws EE_Error
889
+	 * @throws ReflectionException
890
+	 */
891
+	public static function get_event_code(?EE_Event $event = null): string
892
+	{
893
+		return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0');
894
+	}
895
+
896
+
897
+	/**
898
+	 * Gets the event name
899
+	 *
900
+	 * @param EE_Event|null $event
901
+	 * @return string
902
+	 * @throws EE_Error
903
+	 * @throws ReflectionException
904
+	 */
905
+	public static function get_event_name(?EE_Event $event = null): string
906
+	{
907
+		return $event instanceof EE_Event
908
+			? mb_substr($event->name(), 0, 245)
909
+			: esc_html__('Event', 'event_espresso');
910
+	}
911
+
912
+
913
+	/**
914
+	 * Gets the event excerpt
915
+	 *
916
+	 * @param EE_Event|null $event
917
+	 * @return string
918
+	 * @throws EE_Error
919
+	 * @throws ReflectionException
920
+	 */
921
+	public static function get_event_desc(?EE_Event $event = null): string
922
+	{
923
+		return $event instanceof EE_Event ? $event->short_description() : '';
924
+	}
925
+
926
+
927
+	/**
928
+	 * Given the grand total line item and a ticket, finds the event sub-total
929
+	 * line item the ticket's purchase should be added onto
930
+	 *
931
+	 * @access public
932
+	 * @param EE_Line_Item $grand_total the grand total line item
933
+	 * @param EE_Ticket    $ticket
934
+	 * @return EE_Line_Item
935
+	 * @throws EE_Error
936
+	 * @throws InvalidArgumentException
937
+	 * @throws InvalidDataTypeException
938
+	 * @throws InvalidInterfaceException
939
+	 * @throws ReflectionException
940
+	 */
941
+	public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket): EE_Line_Item
942
+	{
943
+		$first_datetime = $ticket->first_datetime();
944
+		if (! $first_datetime instanceof EE_Datetime) {
945
+			throw new EE_Error(
946
+				sprintf(
947
+					esc_html__('The supplied ticket (ID %d) has no datetimes', 'event_espresso'),
948
+					$ticket->ID()
949
+				)
950
+			);
951
+		}
952
+		$event = $first_datetime->event();
953
+		if (! $event instanceof EE_Event) {
954
+			throw new EE_Error(
955
+				sprintf(
956
+					esc_html__(
957
+						'The supplied ticket (ID %d) has no event data associated with it.',
958
+						'event_espresso'
959
+					),
960
+					$ticket->ID()
961
+				)
962
+			);
963
+		}
964
+		$events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event);
965
+		if (! $events_sub_total instanceof EE_Line_Item) {
966
+			throw new EE_Error(
967
+				sprintf(
968
+					esc_html__(
969
+						'There is no events sub-total for ticket %s on total line item %d',
970
+						'event_espresso'
971
+					),
972
+					$ticket->ID(),
973
+					$grand_total->ID()
974
+				)
975
+			);
976
+		}
977
+		return $events_sub_total;
978
+	}
979
+
980
+
981
+	/**
982
+	 * Gets the event line item
983
+	 *
984
+	 * @param EE_Line_Item  $total_line_item
985
+	 * @param EE_Event|null $event
986
+	 * @return EE_Line_Item for the event subtotal which is a child of $grand_total
987
+	 * @throws EE_Error
988
+	 * @throws ReflectionException
989
+	 */
990
+	public static function get_event_line_item(EE_Line_Item $total_line_item, ?EE_Event $event = null): ?EE_Line_Item
991
+	{
992
+		/** @type EE_Event $event */
993
+		$event           = EEM_Event::instance()->ensure_is_obj($event, true);
994
+		$event_line_items = EEH_Line_Item::get_event_subtotals($total_line_item);
995
+		$existing_event_line_item = null;
996
+		foreach ($event_line_items as $event_line_item) {
997
+			// default event subtotal, we should only ever find this the first time this method is called
998
+			$OBJ_ID = $event_line_item->OBJ_ID();
999
+			if ($OBJ_ID === $event->ID()) {
1000
+				// found existing line item for this event in the cart, so break out of loop and use this one
1001
+				$existing_event_line_item = $event_line_item;
1002
+				break;
1003
+			}
1004
+			if (! $OBJ_ID) {
1005
+				// OK?!?! We have an event subtotal that is not actually associated with any event???
1006
+				// let's just use this line item since it's already there, but first... set the event details
1007
+				$existing_event_line_item = $event_line_item;
1008
+				EEH_Line_Item::set_event_subtotal_details($existing_event_line_item, $event);
1009
+				break;
1010
+			}
1011
+		}
1012
+		unset($event_line_item);
1013
+		if ($existing_event_line_item instanceof EE_Line_Item) {
1014
+			return $existing_event_line_item;
1015
+		}
1016
+		// there is no event sub-total yet for this event, so create a new "event" subtotal
1017
+		$transaction = $total_line_item->transaction();
1018
+		$pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item, $transaction, false);
1019
+		$new_event_line_item = EEH_Line_Item::create_event_subtotal($pre_tax_subtotal, $transaction, $event);
1020
+		// and set the event details
1021
+		EEH_Line_Item::set_event_subtotal_details($new_event_line_item, $event, $transaction);
1022
+		return $new_event_line_item;
1023
+	}
1024
+
1025
+
1026
+	/**
1027
+	 * Creates a default items subtotal line item
1028
+	 *
1029
+	 * @param EE_Line_Item        $event_line_item
1030
+	 * @param EE_Event|null       $event
1031
+	 * @param EE_Transaction|null $transaction
1032
+	 * @return void
1033
+	 * @throws EE_Error
1034
+	 * @throws InvalidArgumentException
1035
+	 * @throws InvalidDataTypeException
1036
+	 * @throws InvalidInterfaceException
1037
+	 * @throws ReflectionException
1038
+	 */
1039
+	public static function set_event_subtotal_details(
1040
+		EE_Line_Item $event_line_item,
1041
+		EE_Event $event = null,
1042
+		?EE_Transaction $transaction = null
1043
+	) {
1044
+		if ($event instanceof EE_Event) {
1045
+			$event_line_item->set_code(self::get_event_code($event));
1046
+			$event_line_item->set_name(self::get_event_name($event));
1047
+			$event_line_item->set_desc(self::get_event_desc($event));
1048
+			$event_line_item->set_OBJ_ID($event->ID());
1049
+		}
1050
+		self::set_TXN_ID($event_line_item, $transaction);
1051
+	}
1052
+
1053
+
1054
+	/**
1055
+	 * Finds what taxes should apply, adds them as tax line items under the taxes sub-total,
1056
+	 * and recalculates the taxes sub-total and the grand total. Resets the taxes, so
1057
+	 * any old taxes are removed
1058
+	 *
1059
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
1060
+	 * @param bool         $update_txn_status
1061
+	 * @return bool
1062
+	 * @throws EE_Error
1063
+	 * @throws InvalidArgumentException
1064
+	 * @throws InvalidDataTypeException
1065
+	 * @throws InvalidInterfaceException
1066
+	 * @throws ReflectionException
1067
+	 * @throws RuntimeException
1068
+	 */
1069
+	public static function apply_taxes(EE_Line_Item $total_line_item, bool $update_txn_status = false): bool
1070
+	{
1071
+		$total_line_item       = EEH_Line_Item::find_transaction_grand_total_for_line_item($total_line_item);
1072
+		$taxes_line_item       = self::get_taxes_subtotal($total_line_item);
1073
+		$existing_global_taxes = $taxes_line_item->tax_descendants();
1074
+		$updates               = false;
1075
+		// loop thru taxes
1076
+		$global_taxes = EEH_Line_Item::getGlobalTaxes();
1077
+		foreach ($global_taxes as $order => $taxes) {
1078
+			foreach ($taxes as $tax) {
1079
+				if ($tax instanceof EE_Price) {
1080
+					$found = false;
1081
+					// check if this is already an existing tax
1082
+					foreach ($existing_global_taxes as $existing_global_tax) {
1083
+						if ($tax->ID() === $existing_global_tax->OBJ_ID()) {
1084
+							// maybe update the tax rate in case it has changed
1085
+							if ($existing_global_tax->percent() !== $tax->amount()) {
1086
+								$existing_global_tax->set_percent($tax->amount());
1087
+								$existing_global_tax->save();
1088
+								$updates = true;
1089
+							}
1090
+							$found = true;
1091
+							break;
1092
+						}
1093
+					}
1094
+					if (! $found) {
1095
+						// add a new line item for this global tax
1096
+						$tax_line_item = apply_filters(
1097
+							'FHEE__EEH_Line_Item__apply_taxes__tax_line_item',
1098
+							EE_Line_Item::new_instance(
1099
+								[
1100
+									'LIN_name'       => $tax->name(),
1101
+									'LIN_desc'       => $tax->desc(),
1102
+									'LIN_percent'    => $tax->amount(),
1103
+									'LIN_is_taxable' => false,
1104
+									'LIN_order'      => $order,
1105
+									'LIN_total'      => 0,
1106
+									'LIN_type'       => EEM_Line_Item::type_tax,
1107
+									'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_PRICE,
1108
+									'OBJ_ID'         => $tax->ID(),
1109
+								]
1110
+							)
1111
+						);
1112
+						$updates       = $taxes_line_item->add_child_line_item($tax_line_item) ? true : $updates;
1113
+					}
1114
+				}
1115
+			}
1116
+		}
1117
+		// only recalculate totals if something changed
1118
+		if ($updates || $update_txn_status) {
1119
+			$total_line_item->recalculate_total_including_taxes($update_txn_status);
1120
+			return true;
1121
+		}
1122
+		return false;
1123
+	}
1124
+
1125
+
1126
+	/**
1127
+	 * Ensures that taxes have been applied to the order, if not applies them.
1128
+	 * Returns the total amount of tax
1129
+	 *
1130
+	 * @param EE_Line_Item|null $total_line_item of type EEM_Line_Item::type_total
1131
+	 * @return float
1132
+	 * @throws EE_Error
1133
+	 * @throws InvalidArgumentException
1134
+	 * @throws InvalidDataTypeException
1135
+	 * @throws InvalidInterfaceException
1136
+	 * @throws ReflectionException
1137
+	 */
1138
+	public static function ensure_taxes_applied(?EE_Line_Item $total_line_item): float
1139
+	{
1140
+		$taxes_subtotal = self::get_taxes_subtotal($total_line_item);
1141
+		if (! $taxes_subtotal->children()) {
1142
+			self::apply_taxes($total_line_item);
1143
+		}
1144
+		return $taxes_subtotal->total();
1145
+	}
1146
+
1147
+
1148
+	/**
1149
+	 * Deletes ALL children of the passed line item
1150
+	 *
1151
+	 * @param EE_Line_Item $parent_line_item
1152
+	 * @return bool
1153
+	 * @throws EE_Error
1154
+	 * @throws InvalidArgumentException
1155
+	 * @throws InvalidDataTypeException
1156
+	 * @throws InvalidInterfaceException
1157
+	 * @throws ReflectionException
1158
+	 */
1159
+	public static function delete_all_child_items(EE_Line_Item $parent_line_item)
1160
+	{
1161
+		$deleted = 0;
1162
+		foreach ($parent_line_item->children() as $child_line_item) {
1163
+			if ($child_line_item instanceof EE_Line_Item) {
1164
+				$deleted += EEH_Line_Item::delete_all_child_items($child_line_item);
1165
+				if ($child_line_item->ID()) {
1166
+					$child_line_item->delete();
1167
+					unset($child_line_item);
1168
+				} else {
1169
+					$parent_line_item->delete_child_line_item($child_line_item->code());
1170
+				}
1171
+				$deleted++;
1172
+			}
1173
+		}
1174
+		return $deleted;
1175
+	}
1176
+
1177
+
1178
+	/**
1179
+	 * Deletes the line items as indicated by the line item code(s) provided,
1180
+	 * regardless of where they're found in the line item tree. Automatically
1181
+	 * re-calculates the line item totals and updates the related transaction. But
1182
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
1183
+	 * should probably change because of this).
1184
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
1185
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
1186
+	 *
1187
+	 * @param EE_Line_Item      $total_line_item of type EEM_Line_Item::type_total
1188
+	 * @param array|bool|string $line_item_codes
1189
+	 * @return int number of items successfully removed
1190
+	 * @throws EE_Error
1191
+	 * @throws ReflectionException
1192
+	 */
1193
+	public static function delete_items(EE_Line_Item $total_line_item, $line_item_codes = false)
1194
+	{
1195
+		if ($total_line_item->type() !== EEM_Line_Item::type_total) {
1196
+			EE_Error::doing_it_wrong(
1197
+				'EEH_Line_Item::delete_items',
1198
+				esc_html__(
1199
+					'This static method should only be called with a TOTAL line item, otherwise we won\'t recalculate the totals correctly',
1200
+					'event_espresso'
1201
+				),
1202
+				'4.6.18'
1203
+			);
1204
+		}
1205
+
1206
+		// check if only a single line_item_id was passed
1207
+		if (! empty($line_item_codes) && ! is_array($line_item_codes)) {
1208
+			// place single line_item_id in an array to appear as multiple line_item_ids
1209
+			$line_item_codes = [$line_item_codes];
1210
+		}
1211
+		$removals = 0;
1212
+		// cycle thru line_item_ids
1213
+		foreach ($line_item_codes as $line_item_id) {
1214
+			$removals += $total_line_item->delete_child_line_item($line_item_id);
1215
+		}
1216
+
1217
+		if ($removals > 0) {
1218
+			$total_line_item->recalculate_taxes_and_tax_total();
1219
+			return $removals;
1220
+		}
1221
+		return false;
1222
+	}
1223
+
1224
+
1225
+	/**
1226
+	 * Overwrites the previous tax by clearing out the old taxes, and creates a new
1227
+	 * tax and updates the total line item accordingly
1228
+	 *
1229
+	 * @param EE_Line_Item $total_line_item
1230
+	 * @param float        $amount
1231
+	 * @param string       $name
1232
+	 * @param string       $description
1233
+	 * @param string       $code
1234
+	 * @param boolean      $add_to_existing_line_item
1235
+	 *                          if true, and a duplicate line item with the same code is found,
1236
+	 *                          $amount will be added onto it; otherwise will simply set the taxes to match $amount
1237
+	 * @return EE_Line_Item the new tax line item created
1238
+	 * @throws EE_Error
1239
+	 * @throws InvalidArgumentException
1240
+	 * @throws InvalidDataTypeException
1241
+	 * @throws InvalidInterfaceException
1242
+	 * @throws ReflectionException
1243
+	 */
1244
+	public static function set_total_tax_to(
1245
+		EE_Line_Item $total_line_item,
1246
+		float $amount,
1247
+		string $name = '',
1248
+		string $description = '',
1249
+		string $code = '',
1250
+		bool $add_to_existing_line_item = false
1251
+	): EE_Line_Item {
1252
+		$tax_subtotal  = self::get_taxes_subtotal($total_line_item);
1253
+		$taxable_total = $total_line_item->taxable_total();
1254
+
1255
+		if ($add_to_existing_line_item) {
1256
+			$new_tax = $tax_subtotal->get_child_line_item($code);
1257
+			EEM_Line_Item::instance()->delete(
1258
+				[['LIN_code' => ['!=', $code], 'LIN_parent' => $tax_subtotal->ID()]]
1259
+			);
1260
+		} else {
1261
+			$new_tax = null;
1262
+			$tax_subtotal->delete_children_line_items();
1263
+		}
1264
+		if ($new_tax) {
1265
+			$new_tax->set_total($new_tax->total() + $amount);
1266
+			$new_tax->set_percent($taxable_total ? $new_tax->total() / $taxable_total * 100 : 0);
1267
+		} else {
1268
+			// no existing tax item. Create it
1269
+			$new_tax = EE_Line_Item::new_instance(
1270
+				[
1271
+					'TXN_ID'      => $total_line_item->TXN_ID(),
1272
+					'LIN_name'    => $name ?: esc_html__('Tax', 'event_espresso'),
1273
+					'LIN_desc'    => $description ?: '',
1274
+					'LIN_percent' => $taxable_total ? ($amount / $taxable_total * 100) : 0,
1275
+					'LIN_total'   => $amount,
1276
+					'LIN_parent'  => $tax_subtotal->ID(),
1277
+					'LIN_type'    => EEM_Line_Item::type_tax,
1278
+					'LIN_code'    => $code,
1279
+				]
1280
+			);
1281
+		}
1282
+
1283
+		$new_tax = apply_filters(
1284
+			'FHEE__EEH_Line_Item__set_total_tax_to__new_tax_subtotal',
1285
+			$new_tax,
1286
+			$total_line_item
1287
+		);
1288
+		$new_tax->save();
1289
+		$tax_subtotal->set_total($new_tax->total());
1290
+		$tax_subtotal->save();
1291
+		$total_line_item->recalculate_total_including_taxes();
1292
+		return $new_tax;
1293
+	}
1294
+
1295
+
1296
+	/**
1297
+	 * Makes all the line items which are children of $line_item taxable (or not).
1298
+	 * Does NOT save the line items
1299
+	 *
1300
+	 * @param EE_Line_Item $line_item
1301
+	 * @param boolean      $taxable
1302
+	 * @param string|null  $code_substring_for_whitelist if this string is part of the line item's code
1303
+	 *                                                   it will be whitelisted (ie, except from becoming taxable)
1304
+	 * @throws EE_Error
1305
+	 * @throws ReflectionException
1306
+	 */
1307
+	public static function set_line_items_taxable(
1308
+		EE_Line_Item $line_item,
1309
+		bool $taxable = true,
1310
+		?string $code_substring_for_whitelist = null
1311
+	) {
1312
+		$whitelisted = false;
1313
+		if ($code_substring_for_whitelist !== null) {
1314
+			$whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false;
1315
+		}
1316
+		if (! $whitelisted && $line_item->is_line_item()) {
1317
+			$line_item->set_is_taxable($taxable);
1318
+		}
1319
+		foreach ($line_item->children() as $child_line_item) {
1320
+			EEH_Line_Item::set_line_items_taxable(
1321
+				$child_line_item,
1322
+				$taxable,
1323
+				$code_substring_for_whitelist
1324
+			);
1325
+		}
1326
+	}
1327
+
1328
+
1329
+	/**
1330
+	 * Gets all descendants that are event subtotals
1331
+	 *
1332
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1333
+	 * @return EE_Line_Item[]
1334
+	 * @throws EE_Error
1335
+	 * @throws ReflectionException
1336
+	 * @uses  EEH_Line_Item::get_subtotals_of_object_type()
1337
+	 */
1338
+	public static function get_event_subtotals(EE_Line_Item $parent_line_item): array
1339
+	{
1340
+		return self::get_subtotals_of_object_type($parent_line_item, EEM_Line_Item::OBJ_TYPE_EVENT);
1341
+	}
1342
+
1343
+
1344
+	/**
1345
+	 * Gets all descendants subtotals that match the supplied object type
1346
+	 *
1347
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1348
+	 * @param string       $obj_type
1349
+	 * @return EE_Line_Item[]
1350
+	 * @throws EE_Error
1351
+	 * @throws ReflectionException
1352
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1353
+	 */
1354
+	public static function get_subtotals_of_object_type(EE_Line_Item $parent_line_item, string $obj_type = ''): array
1355
+	{
1356
+		return self::_get_descendants_by_type_and_object_type(
1357
+			$parent_line_item,
1358
+			EEM_Line_Item::type_sub_total,
1359
+			$obj_type
1360
+		);
1361
+	}
1362
+
1363
+
1364
+	/**
1365
+	 * Gets all descendants that are tickets
1366
+	 *
1367
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1368
+	 * @return EE_Line_Item[]
1369
+	 * @throws EE_Error
1370
+	 * @throws ReflectionException
1371
+	 * @uses  EEH_Line_Item::get_line_items_of_object_type()
1372
+	 */
1373
+	public static function get_ticket_line_items(EE_Line_Item $parent_line_item): array
1374
+	{
1375
+		return self::get_line_items_of_object_type(
1376
+			$parent_line_item,
1377
+			EEM_Line_Item::OBJ_TYPE_TICKET
1378
+		);
1379
+	}
1380
+
1381
+
1382
+	/**
1383
+	 * Gets all descendants subtotals that match the supplied object type
1384
+	 *
1385
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1386
+	 * @param string       $obj_type
1387
+	 * @return EE_Line_Item[]
1388
+	 * @throws EE_Error
1389
+	 * @throws ReflectionException
1390
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1391
+	 */
1392
+	public static function get_line_items_of_object_type(EE_Line_Item $parent_line_item, string $obj_type = ''): array
1393
+	{
1394
+		return self::_get_descendants_by_type_and_object_type(
1395
+			$parent_line_item,
1396
+			EEM_Line_Item::type_line_item,
1397
+			$obj_type
1398
+		);
1399
+	}
1400
+
1401
+
1402
+	/**
1403
+	 * Gets all the descendants (ie, children or children of children etc) that are of the type 'tax'
1404
+	 *
1405
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1406
+	 * @return EE_Line_Item[]
1407
+	 * @throws EE_Error
1408
+	 * @throws ReflectionException
1409
+	 * @uses  EEH_Line_Item::get_descendants_of_type()
1410
+	 */
1411
+	public static function get_tax_descendants(EE_Line_Item $parent_line_item): array
1412
+	{
1413
+		return EEH_Line_Item::get_descendants_of_type(
1414
+			$parent_line_item,
1415
+			EEM_Line_Item::type_tax
1416
+		);
1417
+	}
1418
+
1419
+
1420
+	/**
1421
+	 * Gets all the real items purchased which are children of this item
1422
+	 *
1423
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1424
+	 * @return EE_Line_Item[]
1425
+	 * @throws EE_Error
1426
+	 * @throws ReflectionException
1427
+	 * @uses  EEH_Line_Item::get_descendants_of_type()
1428
+	 */
1429
+	public static function get_line_item_descendants(EE_Line_Item $parent_line_item): array
1430
+	{
1431
+		return EEH_Line_Item::get_descendants_of_type(
1432
+			$parent_line_item,
1433
+			EEM_Line_Item::type_line_item
1434
+		);
1435
+	}
1436
+
1437
+
1438
+	/**
1439
+	 * Gets all descendants of supplied line item that match the supplied line item type
1440
+	 *
1441
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1442
+	 * @param string       $line_item_type   one of the EEM_Line_Item constants
1443
+	 * @return EE_Line_Item[]
1444
+	 * @throws EE_Error
1445
+	 * @throws ReflectionException
1446
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1447
+	 */
1448
+	public static function get_descendants_of_type(EE_Line_Item $parent_line_item, string $line_item_type): array
1449
+	{
1450
+		return self::_get_descendants_by_type_and_object_type(
1451
+			$parent_line_item,
1452
+			$line_item_type
1453
+		);
1454
+	}
1455
+
1456
+
1457
+	/**
1458
+	 * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type
1459
+	 * as well
1460
+	 *
1461
+	 * @param EE_Line_Item $parent_line_item  - the line item to find descendants of
1462
+	 * @param string       $line_item_type    one of the EEM_Line_Item constants
1463
+	 * @param string|null  $obj_type          object model class name (minus prefix) or NULL to ignore object type when
1464
+	 *                                        searching
1465
+	 * @return EE_Line_Item[]
1466
+	 * @throws EE_Error
1467
+	 * @throws ReflectionException
1468
+	 */
1469
+	protected static function _get_descendants_by_type_and_object_type(
1470
+		EE_Line_Item $parent_line_item,
1471
+		string $line_item_type,
1472
+		?string $obj_type = null
1473
+	): array {
1474
+		$objects = [];
1475
+		foreach ($parent_line_item->children() as $child_line_item) {
1476
+			if ($child_line_item instanceof EE_Line_Item) {
1477
+				if (
1478
+					$child_line_item->type() === $line_item_type
1479
+					&& (
1480
+						$child_line_item->OBJ_type() === $obj_type || $obj_type === null
1481
+					)
1482
+				) {
1483
+					$objects[] = $child_line_item;
1484
+				} else {
1485
+					// go-through-all-its children looking for more matches
1486
+					$objects = array_merge(
1487
+						$objects,
1488
+						self::_get_descendants_by_type_and_object_type(
1489
+							$child_line_item,
1490
+							$line_item_type,
1491
+							$obj_type
1492
+						)
1493
+					);
1494
+				}
1495
+			}
1496
+		}
1497
+		return $objects;
1498
+	}
1499
+
1500
+
1501
+	/**
1502
+	 * Gets all descendants subtotals that match the supplied object type
1503
+	 *
1504
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1505
+	 * @param string       $OBJ_type         object type (like Event)
1506
+	 * @param array        $OBJ_IDs          array of OBJ_IDs
1507
+	 * @return EE_Line_Item[]
1508
+	 * @throws EE_Error
1509
+	 * @throws ReflectionException
1510
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1511
+	 */
1512
+	public static function get_line_items_by_object_type_and_IDs(
1513
+		EE_Line_Item $parent_line_item,
1514
+		string $OBJ_type = '',
1515
+		array $OBJ_IDs = []
1516
+	): array {
1517
+		return self::_get_descendants_by_object_type_and_object_ID(
1518
+			$parent_line_item,
1519
+			$OBJ_type,
1520
+			$OBJ_IDs
1521
+		);
1522
+	}
1523
+
1524
+
1525
+	/**
1526
+	 * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type
1527
+	 * as well
1528
+	 *
1529
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1530
+	 * @param string       $OBJ_type         object type (like Event)
1531
+	 * @param array        $OBJ_IDs          array of OBJ_IDs
1532
+	 * @return EE_Line_Item[]
1533
+	 * @throws EE_Error
1534
+	 * @throws ReflectionException
1535
+	 */
1536
+	protected static function _get_descendants_by_object_type_and_object_ID(
1537
+		EE_Line_Item $parent_line_item,
1538
+		string $OBJ_type,
1539
+		array $OBJ_IDs
1540
+	): array {
1541
+		$objects = [];
1542
+		foreach ($parent_line_item->children() as $child_line_item) {
1543
+			if ($child_line_item instanceof EE_Line_Item) {
1544
+				if (
1545
+					$child_line_item->OBJ_type() === $OBJ_type
1546
+					&& in_array($child_line_item->OBJ_ID(), $OBJ_IDs)
1547
+				) {
1548
+					$objects[] = $child_line_item;
1549
+				} else {
1550
+					// go-through-all-its children looking for more matches
1551
+					$objects = array_merge(
1552
+						$objects,
1553
+						self::_get_descendants_by_object_type_and_object_ID(
1554
+							$child_line_item,
1555
+							$OBJ_type,
1556
+							$OBJ_IDs
1557
+						)
1558
+					);
1559
+				}
1560
+			}
1561
+		}
1562
+		return $objects;
1563
+	}
1564
+
1565
+
1566
+	/**
1567
+	 * Uses a breadth-first-search in order to find the nearest descendant of
1568
+	 * the specified type and returns it, else NULL
1569
+	 *
1570
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1571
+	 * @param string       $type             like one of the EEM_Line_Item::type_*
1572
+	 * @return EE_Line_Item
1573
+	 * @throws EE_Error
1574
+	 * @throws InvalidArgumentException
1575
+	 * @throws InvalidDataTypeException
1576
+	 * @throws InvalidInterfaceException
1577
+	 * @throws ReflectionException
1578
+	 * @uses  EEH_Line_Item::_get_nearest_descendant()
1579
+	 */
1580
+	public static function get_nearest_descendant_of_type(EE_Line_Item $parent_line_item, string $type): ?EE_Line_Item
1581
+	{
1582
+		return self::_get_nearest_descendant($parent_line_item, 'LIN_type', $type);
1583
+	}
1584
+
1585
+
1586
+	/**
1587
+	 * Uses a breadth-first-search in order to find the nearest descendant
1588
+	 * having the specified LIN_code and returns it, else NULL
1589
+	 *
1590
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1591
+	 * @param string       $code             any value used for LIN_code
1592
+	 * @return EE_Line_Item
1593
+	 * @throws EE_Error
1594
+	 * @throws InvalidArgumentException
1595
+	 * @throws InvalidDataTypeException
1596
+	 * @throws InvalidInterfaceException
1597
+	 * @throws ReflectionException
1598
+	 * @uses  EEH_Line_Item::_get_nearest_descendant()
1599
+	 */
1600
+	public static function get_nearest_descendant_having_code(
1601
+		EE_Line_Item $parent_line_item,
1602
+		string $code
1603
+	): ?EE_Line_Item {
1604
+		return self::_get_nearest_descendant($parent_line_item, 'LIN_code', $code);
1605
+	}
1606
+
1607
+
1608
+	/**
1609
+	 * Uses a breadth-first-search in order to find the nearest descendant
1610
+	 * having the specified LIN_code and returns it, else NULL
1611
+	 *
1612
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1613
+	 * @param string       $search_field     name of EE_Line_Item property
1614
+	 * @param mixed        $value            any value stored in $search_field
1615
+	 * @return EE_Line_Item
1616
+	 * @throws EE_Error
1617
+	 * @throws InvalidArgumentException
1618
+	 * @throws InvalidDataTypeException
1619
+	 * @throws InvalidInterfaceException
1620
+	 * @throws ReflectionException
1621
+	 */
1622
+	protected static function _get_nearest_descendant(
1623
+		EE_Line_Item $parent_line_item,
1624
+		string $search_field,
1625
+		$value
1626
+	): ?EE_Line_Item {
1627
+		foreach ($parent_line_item->children() as $child) {
1628
+			if ($child->get($search_field) == $value) {
1629
+				return $child;
1630
+			}
1631
+		}
1632
+		foreach ($parent_line_item->children() as $child) {
1633
+			$descendant_found = self::_get_nearest_descendant(
1634
+				$child,
1635
+				$search_field,
1636
+				$value
1637
+			);
1638
+			if ($descendant_found) {
1639
+				return $descendant_found;
1640
+			}
1641
+		}
1642
+		return null;
1643
+	}
1644
+
1645
+
1646
+	/**
1647
+	 * if passed line item has a TXN ID, uses that to jump directly to the grand total line item for the transaction,
1648
+	 * else recursively walks up the line item tree until a parent of type total is found,
1649
+	 *
1650
+	 * @param EE_Line_Item $line_item
1651
+	 * @return EE_Line_Item
1652
+	 * @throws EE_Error
1653
+	 * @throws ReflectionException
1654
+	 */
1655
+	public static function find_transaction_grand_total_for_line_item(EE_Line_Item $line_item): EE_Line_Item
1656
+	{
1657
+		if ($line_item->is_total()) {
1658
+			return $line_item;
1659
+		}
1660
+		if ($line_item->TXN_ID()) {
1661
+			$total_line_item = $line_item->transaction()->total_line_item(false);
1662
+			if ($total_line_item instanceof EE_Line_Item) {
1663
+				return $total_line_item;
1664
+			}
1665
+		} else {
1666
+			$line_item_parent = $line_item->parent();
1667
+			if ($line_item_parent instanceof EE_Line_Item) {
1668
+				if ($line_item_parent->is_total()) {
1669
+					return $line_item_parent;
1670
+				}
1671
+				return EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item_parent);
1672
+			}
1673
+		}
1674
+		throw new EE_Error(
1675
+			sprintf(
1676
+				esc_html__(
1677
+					'A valid grand total for line item %1$d was not found.',
1678
+					'event_espresso'
1679
+				),
1680
+				$line_item->ID()
1681
+			)
1682
+		);
1683
+	}
1684
+
1685
+
1686
+	/**
1687
+	 * Prints out a representation of the line item tree
1688
+	 *
1689
+	 * @param EE_Line_Item $line_item
1690
+	 * @param int          $indentation
1691
+	 * @param bool         $top_level
1692
+	 * @return void
1693
+	 * @throws EE_Error
1694
+	 * @throws ReflectionException
1695
+	 */
1696
+	public static function visualize(EE_Line_Item $line_item, int $indentation = 0, bool $top_level = true)
1697
+	{
1698
+		if (! defined('WP_DEBUG') || ! WP_DEBUG) {
1699
+			return;
1700
+		}
1701
+		$no_formatting  = defined('EE_TESTS_DIR') || (defined('DOING_AJAX') && DOING_AJAX);
1702
+		$new_line = $no_formatting ? "\n" : '<br />';
1703
+		if ($top_level && ! $no_formatting) {
1704
+			echo '<div style="position: relative; z-index: 9999; margin: 2rem;">';
1705
+			echo '<pre style="padding: 2rem 3rem; color: #00CCFF; background: #363636;">';
1706
+		}
1707
+		if ($top_level || $indentation) {
1708
+			// echo $top_level ? "$new_line$new_line" : $new_line;
1709
+			echo $new_line;
1710
+		}
1711
+		echo str_repeat('. ', $indentation);
1712
+		$breakdown = '';
1713
+		if ($line_item->is_line_item() || $line_item->is_sub_line_item() || $line_item->isTax()) {
1714
+			if ($line_item->is_percent()) {
1715
+				$breakdown = "{$line_item->percent()}%";
1716
+			} else {
1717
+				$breakdown = "\${$line_item->unit_price()} x {$line_item->quantity()}";
1718
+			}
1719
+		}
1720
+		echo wp_kses($line_item->name(), AllowedTags::getAllowedTags());
1721
+		echo " [ ID:{$line_item->ID()} · qty:{$line_item->quantity()} ] {$line_item->type()}";
1722
+		echo " · \${$line_item->total()} · \${$line_item->pretaxTotal()}";
1723
+		if ($breakdown) {
1724
+			echo " ( $breakdown )";
1725
+		}
1726
+		if ($line_item->is_taxable()) {
1727
+			echo '  * taxable';
1728
+		}
1729
+		$children = $line_item->children();
1730
+		if ($children) {
1731
+			foreach ($children as $child) {
1732
+				self::visualize($child, $indentation + 1, false);
1733
+			}
1734
+		}
1735
+		if ($top_level) {
1736
+			echo $no_formatting ? $new_line : "$new_line</pre></div>$new_line";
1737
+		}
1738
+	}
1739
+
1740
+
1741
+	/**
1742
+	 * Calculates the registration's final price, taking into account that they
1743
+	 * need to not only help pay for their OWN ticket, but also any transaction-wide surcharges and taxes,
1744
+	 * and receive a portion of any transaction-wide discounts.
1745
+	 * eg1, if I buy a $1 ticket and brent buys a $9 ticket, and we receive a $5 discount
1746
+	 * then I'll get 1/10 of that $5 discount, which is $0.50, and brent will get
1747
+	 * 9/10ths of that $5 discount, which is $4.50. So my final price should be $0.50
1748
+	 * and brent's final price should be $5.50.
1749
+	 * In order to do this, we basically need to traverse the line item tree calculating
1750
+	 * the running totals (just as if we were recalculating the total), but when we identify
1751
+	 * regular line items, we need to keep track of their share of the grand total.
1752
+	 * Also, we need to keep track of the TAXABLE total for each ticket purchase, so
1753
+	 * we can know how to apply taxes to it. (Note: "taxable total" does not equal the "pretax total"
1754
+	 * when there are non-taxable items; otherwise they would be the same)
1755
+	 *
1756
+	 * @param EE_Line_Item $line_item
1757
+	 * @param array        $billable_ticket_quantities          array of EE_Ticket IDs and their corresponding quantity
1758
+	 *                                                          that can be included in price calculations at this
1759
+	 *                                                          moment
1760
+	 * @return array        keys are line items for tickets IDs and values are their share of the running total,
1761
+	 *                                                          plus the key 'total', and 'taxable' which also has keys
1762
+	 *                                                          of all the ticket IDs. Eg array(
1763
+	 *                                                          12 => 4.3
1764
+	 *                                                          23 => 8.0
1765
+	 *                                                          'total' => 16.6,
1766
+	 *                                                          'taxable' => array(
1767
+	 *                                                          12 => 10,
1768
+	 *                                                          23 => 4
1769
+	 *                                                          ).
1770
+	 *                                                          So to find which registrations have which final price,
1771
+	 *                                                          we need to find which line item is theirs, which can be
1772
+	 *                                                          done with
1773
+	 *                                                          `EEM_Line_Item::instance()->get_line_item_for_registration(
1774
+	 *                                                          $registration );`
1775
+	 * @throws EE_Error
1776
+	 * @throws InvalidArgumentException
1777
+	 * @throws InvalidDataTypeException
1778
+	 * @throws InvalidInterfaceException
1779
+	 * @throws ReflectionException
1780
+	 */
1781
+	public static function calculate_reg_final_prices_per_line_item(
1782
+		EE_Line_Item $line_item,
1783
+		array $billable_ticket_quantities = []
1784
+	): array {
1785
+		$running_totals = [
1786
+			'total'   => 0,
1787
+			'taxable' => ['total' => 0],
1788
+		];
1789
+		foreach ($line_item->children() as $child_line_item) {
1790
+			switch ($child_line_item->type()) {
1791
+				case EEM_Line_Item::type_sub_total:
1792
+					$running_totals_from_subtotal = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1793
+						$child_line_item,
1794
+						$billable_ticket_quantities
1795
+					);
1796
+					// combine arrays but preserve numeric keys
1797
+					$running_totals                     = array_replace_recursive(
1798
+						$running_totals_from_subtotal,
1799
+						$running_totals
1800
+					);
1801
+					$running_totals['total']            += $running_totals_from_subtotal['total'];
1802
+					$running_totals['taxable']['total'] += $running_totals_from_subtotal['taxable']['total'];
1803
+					break;
1804
+
1805
+				case EEM_Line_Item::type_tax_sub_total:
1806
+					// find how much the taxes percentage is
1807
+					if ($child_line_item->percent() !== 0.0) {
1808
+						$tax_percent_decimal = $child_line_item->percent() / 100;
1809
+					} else {
1810
+						$tax_percent_decimal = EE_Taxes::get_total_taxes_percentage() / 100;
1811
+					}
1812
+					// and apply to all the taxable totals, and add to the pretax totals
1813
+					foreach ($running_totals as $line_item_id => $this_running_total) {
1814
+						// "total" and "taxable" array key is an exception
1815
+						if ($line_item_id === 'taxable') {
1816
+							continue;
1817
+						}
1818
+						$taxable_total                   = $running_totals['taxable'][ $line_item_id ];
1819
+						$running_totals[ $line_item_id ] += ($taxable_total * $tax_percent_decimal);
1820
+					}
1821
+					break;
1822
+
1823
+				case EEM_Line_Item::type_line_item:
1824
+					// ticket line items or ????
1825
+					if ($child_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) {
1826
+						// kk it's a ticket
1827
+						if (isset($running_totals[ $child_line_item->ID() ])) {
1828
+							// huh? that shouldn't happen.
1829
+							$running_totals['total'] += $child_line_item->total();
1830
+						} else {
1831
+							// it's not in our running totals yet. great.
1832
+							if ($child_line_item->is_taxable()) {
1833
+								$taxable_amount = $child_line_item->unit_price();
1834
+							} else {
1835
+								$taxable_amount = 0;
1836
+							}
1837
+							// are we only calculating totals for some tickets?
1838
+							if (isset($billable_ticket_quantities[ $child_line_item->OBJ_ID() ])) {
1839
+								$quantity = $billable_ticket_quantities[ $child_line_item->OBJ_ID() ];
1840
+
1841
+								$running_totals[ $child_line_item->ID() ]            = $quantity
1842
+									? $child_line_item->unit_price()
1843
+									: 0;
1844
+								$running_totals['taxable'][ $child_line_item->ID() ] = $quantity
1845
+									? $taxable_amount
1846
+									: 0;
1847
+							} else {
1848
+								$quantity                                            = $child_line_item->quantity();
1849
+								$running_totals[ $child_line_item->ID() ]            = $child_line_item->unit_price();
1850
+								$running_totals['taxable'][ $child_line_item->ID() ] = $taxable_amount;
1851
+							}
1852
+							$running_totals['taxable']['total'] += $taxable_amount * $quantity;
1853
+							$running_totals['total']            += $child_line_item->unit_price() * $quantity;
1854
+						}
1855
+					} else {
1856
+						// it's some other type of item added to the cart
1857
+						// it should affect the running totals
1858
+						// basically we want to convert it into a PERCENT modifier. Because
1859
+						// more clearly affect all registration's final price equally
1860
+						$line_items_percent_of_running_total = $running_totals['total'] > 0
1861
+							? ($child_line_item->total() / $running_totals['total']) + 1
1862
+							: 1;
1863
+						foreach ($running_totals as $line_item_id => $this_running_total) {
1864
+							// the "taxable" array key is an exception
1865
+							if ($line_item_id === 'taxable') {
1866
+								continue;
1867
+							}
1868
+							// update the running totals
1869
+							// yes this actually even works for the running grand total!
1870
+							$running_totals[ $line_item_id ] =
1871
+								$line_items_percent_of_running_total * $this_running_total;
1872
+
1873
+							if ($child_line_item->is_taxable()) {
1874
+								$running_totals['taxable'][ $line_item_id ] =
1875
+									$line_items_percent_of_running_total * $running_totals['taxable'][ $line_item_id ];
1876
+							}
1877
+						}
1878
+					}
1879
+					break;
1880
+			}
1881
+		}
1882
+		return $running_totals;
1883
+	}
1884
+
1885
+
1886
+	/**
1887
+	 * @param EE_Line_Item $total_line_item
1888
+	 * @param EE_Line_Item $ticket_line_item
1889
+	 * @return float | null
1890
+	 * @throws EE_Error
1891
+	 * @throws InvalidArgumentException
1892
+	 * @throws InvalidDataTypeException
1893
+	 * @throws InvalidInterfaceException
1894
+	 * @throws OutOfRangeException
1895
+	 * @throws ReflectionException
1896
+	 */
1897
+	public static function calculate_final_price_for_ticket_line_item(
1898
+		EE_Line_Item $total_line_item,
1899
+		EE_Line_Item $ticket_line_item
1900
+	): ?float {
1901
+		static $final_prices_per_ticket_line_item = [];
1902
+		if (
1903
+			empty($final_prices_per_ticket_line_item)
1904
+			|| empty($final_prices_per_ticket_line_item[ $total_line_item->ID() ])
1905
+		) {
1906
+			$final_prices_per_ticket_line_item[ $total_line_item->ID() ] =
1907
+				EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1908
+					$total_line_item
1909
+				);
1910
+		}
1911
+		// ok now find this new registration's final price
1912
+		if (isset($final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ])) {
1913
+			return $final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ];
1914
+		}
1915
+		$message = sprintf(
1916
+			esc_html__(
1917
+				'The final price for the ticket line item (ID:%1$d) on the total line item (ID:%2$d) could not be calculated.',
1918
+				'event_espresso'
1919
+			),
1920
+			$ticket_line_item->ID(),
1921
+			$total_line_item->ID()
1922
+		);
1923
+		if (WP_DEBUG) {
1924
+			$message .= '<br>' . print_r($final_prices_per_ticket_line_item, true);
1925
+			throw new OutOfRangeException($message);
1926
+		}
1927
+		EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message);
1928
+		return null;
1929
+	}
1930
+
1931
+
1932
+	/**
1933
+	 * Creates a duplicate of the line item tree, except only includes billable items
1934
+	 * and the portion of line items attributed to billable things
1935
+	 *
1936
+	 * @param EE_Line_Item      $line_item
1937
+	 * @param EE_Registration[] $registrations
1938
+	 * @return EE_Line_Item
1939
+	 * @throws EE_Error
1940
+	 * @throws InvalidArgumentException
1941
+	 * @throws InvalidDataTypeException
1942
+	 * @throws InvalidInterfaceException
1943
+	 * @throws ReflectionException
1944
+	 */
1945
+	public static function billable_line_item_tree(EE_Line_Item $line_item, array $registrations): EE_Line_Item
1946
+	{
1947
+		$copy_li = EEH_Line_Item::billable_line_item($line_item, $registrations);
1948
+		foreach ($line_item->children() as $child_li) {
1949
+			$copy_li->add_child_line_item(
1950
+				EEH_Line_Item::billable_line_item_tree($child_li, $registrations)
1951
+			);
1952
+		}
1953
+		// if this is the grand total line item, make sure the totals all add up
1954
+		// (we could have duplicated this logic AS we copied the line items, but
1955
+		// it seems DRYer this way)
1956
+		if ($copy_li->type() === EEM_Line_Item::type_total) {
1957
+			$copy_li->recalculate_total_including_taxes();
1958
+		}
1959
+		return $copy_li;
1960
+	}
1961
+
1962
+
1963
+	/**
1964
+	 * Creates a new, unsaved line item from $line_item that factors in the
1965
+	 * number of billable registrations on $registrations.
1966
+	 *
1967
+	 * @param EE_Line_Item      $line_item
1968
+	 * @param EE_Registration[] $registrations
1969
+	 * @return EE_Line_Item
1970
+	 * @throws EE_Error
1971
+	 * @throws InvalidArgumentException
1972
+	 * @throws InvalidDataTypeException
1973
+	 * @throws InvalidInterfaceException
1974
+	 * @throws ReflectionException
1975
+	 */
1976
+	public static function billable_line_item(EE_Line_Item $line_item, array $registrations): EE_Line_Item
1977
+	{
1978
+		$new_li_fields = $line_item->model_field_array();
1979
+		if (
1980
+			$line_item->type() === EEM_Line_Item::type_line_item &&
1981
+			$line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1982
+		) {
1983
+			$count = 0;
1984
+			foreach ($registrations as $registration) {
1985
+				if (
1986
+					$line_item->OBJ_ID() === $registration->ticket_ID() &&
1987
+					in_array(
1988
+						$registration->status_ID(),
1989
+						EEM_Registration::reg_statuses_that_allow_payment(),
1990
+						true
1991
+					)
1992
+				) {
1993
+					$count++;
1994
+				}
1995
+			}
1996
+			$new_li_fields['LIN_quantity'] = $count;
1997
+		}
1998
+		// don't set the total. We'll leave that up to the code that calculates it
1999
+		unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent'], $new_li_fields['LIN_total']);
2000
+		return EE_Line_Item::new_instance($new_li_fields);
2001
+	}
2002
+
2003
+
2004
+	/**
2005
+	 * Returns a modified line item tree where all the subtotals which have a total of 0
2006
+	 * are removed, and line items with a quantity of 0
2007
+	 *
2008
+	 * @param EE_Line_Item $line_item |null
2009
+	 * @return EE_Line_Item|null
2010
+	 * @throws EE_Error
2011
+	 * @throws InvalidArgumentException
2012
+	 * @throws InvalidDataTypeException
2013
+	 * @throws InvalidInterfaceException
2014
+	 * @throws ReflectionException
2015
+	 */
2016
+	public static function non_empty_line_items(EE_Line_Item $line_item): ?EE_Line_Item
2017
+	{
2018
+		$copied_li = EEH_Line_Item::non_empty_line_item($line_item);
2019
+		if ($copied_li === null) {
2020
+			return null;
2021
+		}
2022
+		// if this is an event subtotal, we want to only include it if it
2023
+		// has a non-zero total and at least one ticket line item child
2024
+		$ticket_children = 0;
2025
+		foreach ($line_item->children() as $child_li) {
2026
+			$child_li_copy = EEH_Line_Item::non_empty_line_items($child_li);
2027
+			if ($child_li_copy !== null) {
2028
+				$copied_li->add_child_line_item($child_li_copy);
2029
+				if (
2030
+					$child_li_copy->type() === EEM_Line_Item::type_line_item &&
2031
+					$child_li_copy->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
2032
+				) {
2033
+					$ticket_children++;
2034
+				}
2035
+			}
2036
+		}
2037
+		// if this is an event subtotal with NO ticket children
2038
+		// we basically want to ignore it
2039
+		if (
2040
+			$ticket_children === 0
2041
+			&& $line_item->type() === EEM_Line_Item::type_sub_total
2042
+			&& $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
2043
+			&& $line_item->total() === 0.0
2044
+		) {
2045
+			return null;
2046
+		}
2047
+		return $copied_li;
2048
+	}
2049
+
2050
+
2051
+	/**
2052
+	 * Creates a new, unsaved line item, but if it's a ticket line item
2053
+	 * with a total of 0, or a subtotal of 0, returns null instead
2054
+	 *
2055
+	 * @param EE_Line_Item $line_item
2056
+	 * @return EE_Line_Item
2057
+	 * @throws EE_Error
2058
+	 * @throws InvalidArgumentException
2059
+	 * @throws InvalidDataTypeException
2060
+	 * @throws InvalidInterfaceException
2061
+	 * @throws ReflectionException
2062
+	 */
2063
+	public static function non_empty_line_item(EE_Line_Item $line_item): ?EE_Line_Item
2064
+	{
2065
+		if (
2066
+			$line_item->type() === EEM_Line_Item::type_line_item
2067
+			&& $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
2068
+			&& $line_item->quantity() === 0
2069
+		) {
2070
+			return null;
2071
+		}
2072
+		$new_li_fields = $line_item->model_field_array();
2073
+		// don't set the total. We'll leave that up to the code that calculates it
2074
+		unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent']);
2075
+		return EE_Line_Item::new_instance($new_li_fields);
2076
+	}
2077
+
2078
+
2079
+	/**
2080
+	 * Cycles through all the ticket line items for the supplied total line item
2081
+	 * and ensures that the line item's "is_taxable" field matches that of its corresponding ticket
2082
+	 *
2083
+	 * @param EE_Line_Item $total_line_item
2084
+	 * @throws EE_Error
2085
+	 * @throws InvalidArgumentException
2086
+	 * @throws InvalidDataTypeException
2087
+	 * @throws InvalidInterfaceException
2088
+	 * @throws ReflectionException
2089
+	 * @since 4.9.79.p
2090
+	 */
2091
+	public static function resetIsTaxableForTickets(EE_Line_Item $total_line_item)
2092
+	{
2093
+		$ticket_line_items = self::get_ticket_line_items($total_line_item);
2094
+		foreach ($ticket_line_items as $ticket_line_item) {
2095
+			if (
2096
+				$ticket_line_item instanceof EE_Line_Item
2097
+				&& $ticket_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
2098
+			) {
2099
+				$ticket = $ticket_line_item->ticket();
2100
+				if ($ticket instanceof EE_Ticket && $ticket->taxable() !== $ticket_line_item->is_taxable()) {
2101
+					$ticket_line_item->set_is_taxable($ticket->taxable());
2102
+					$ticket_line_item->save();
2103
+				}
2104
+			}
2105
+		}
2106
+	}
2107
+
2108
+
2109
+	/**
2110
+	 * @return EE_Line_Item[]
2111
+	 * @throws EE_Error
2112
+	 * @throws ReflectionException
2113
+	 * @since   5.0.0.p
2114
+	 */
2115
+	private static function getGlobalTaxes(): array
2116
+	{
2117
+		if (EEH_Line_Item::$global_taxes === null) {
2118
+			/** @type EEM_Price $EEM_Price */
2119
+			$EEM_Price = EE_Registry::instance()->load_model('Price');
2120
+			// get array of taxes via Price Model
2121
+			EEH_Line_Item::$global_taxes = $EEM_Price->get_all_prices_that_are_taxes();
2122
+			ksort(EEH_Line_Item::$global_taxes);
2123
+		}
2124
+		return EEH_Line_Item::$global_taxes;
2125
+	}
2126
+
2127
+
2128
+
2129
+	/**************************************** @DEPRECATED METHODS *************************************** */
2130
+	/**
2131
+	 * @param EE_Line_Item $total_line_item
2132
+	 * @return EE_Line_Item
2133
+	 * @throws EE_Error
2134
+	 * @throws InvalidArgumentException
2135
+	 * @throws InvalidDataTypeException
2136
+	 * @throws InvalidInterfaceException
2137
+	 * @throws ReflectionException
2138
+	 * @deprecated
2139
+	 */
2140
+	public static function get_items_subtotal(EE_Line_Item $total_line_item): EE_Line_Item
2141
+	{
2142
+		EE_Error::doing_it_wrong(
2143
+			'EEH_Line_Item::get_items_subtotal()',
2144
+			sprintf(
2145
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
2146
+				'EEH_Line_Item::get_pre_tax_subtotal()'
2147
+			),
2148
+			'4.6.0'
2149
+		);
2150
+		return self::get_pre_tax_subtotal($total_line_item);
2151
+	}
2152
+
2153
+
2154
+	/**
2155
+	 * @param EE_Transaction|null $transaction
2156
+	 * @return EE_Line_Item
2157
+	 * @throws EE_Error
2158
+	 * @throws InvalidArgumentException
2159
+	 * @throws InvalidDataTypeException
2160
+	 * @throws InvalidInterfaceException
2161
+	 * @throws ReflectionException
2162
+	 * @deprecated
2163
+	 */
2164
+	public static function create_default_total_line_item(?EE_Transaction $transaction = null): EE_Line_Item
2165
+	{
2166
+		EE_Error::doing_it_wrong(
2167
+			'EEH_Line_Item::create_default_total_line_item()',
2168
+			sprintf(
2169
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
2170
+				'EEH_Line_Item::create_total_line_item()'
2171
+			),
2172
+			'4.6.0'
2173
+		);
2174
+		return self::create_total_line_item($transaction);
2175
+	}
2176
+
2177
+
2178
+	/**
2179
+	 * @param EE_Line_Item        $total_line_item
2180
+	 * @param EE_Transaction|null $transaction
2181
+	 * @return EE_Line_Item
2182
+	 * @throws EE_Error
2183
+	 * @throws InvalidArgumentException
2184
+	 * @throws InvalidDataTypeException
2185
+	 * @throws InvalidInterfaceException
2186
+	 * @throws ReflectionException
2187
+	 * @deprecated
2188
+	 */
2189
+	public static function create_default_tickets_subtotal(
2190
+		EE_Line_Item $total_line_item,
2191
+		?EE_Transaction $transaction = null
2192
+	): EE_Line_Item {
2193
+		EE_Error::doing_it_wrong(
2194
+			'EEH_Line_Item::create_default_tickets_subtotal()',
2195
+			sprintf(
2196
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
2197
+				'EEH_Line_Item::create_pre_tax_subtotal()'
2198
+			),
2199
+			'4.6.0'
2200
+		);
2201
+		return self::create_pre_tax_subtotal($total_line_item, $transaction);
2202
+	}
2203
+
2204
+
2205
+	/**
2206
+	 * @param EE_Line_Item        $total_line_item
2207
+	 * @param EE_Transaction|null $transaction
2208
+	 * @return EE_Line_Item
2209
+	 * @throws EE_Error
2210
+	 * @throws InvalidArgumentException
2211
+	 * @throws InvalidDataTypeException
2212
+	 * @throws InvalidInterfaceException
2213
+	 * @throws ReflectionException
2214
+	 * @deprecated
2215
+	 */
2216
+	public static function create_default_taxes_subtotal(
2217
+		EE_Line_Item $total_line_item,
2218
+		?EE_Transaction $transaction = null
2219
+	): EE_Line_Item {
2220
+		EE_Error::doing_it_wrong(
2221
+			'EEH_Line_Item::create_default_taxes_subtotal()',
2222
+			sprintf(
2223
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
2224
+				'EEH_Line_Item::create_taxes_subtotal()'
2225
+			),
2226
+			'4.6.0'
2227
+		);
2228
+		return self::create_taxes_subtotal($total_line_item, $transaction);
2229
+	}
2230
+
2231
+
2232
+	/**
2233
+	 * @param EE_Line_Item        $total_line_item
2234
+	 * @param EE_Transaction|null $transaction
2235
+	 * @return EE_Line_Item
2236
+	 * @throws EE_Error
2237
+	 * @throws InvalidArgumentException
2238
+	 * @throws InvalidDataTypeException
2239
+	 * @throws InvalidInterfaceException
2240
+	 * @throws ReflectionException
2241
+	 * @deprecated
2242
+	 */
2243
+	public static function create_default_event_subtotal(
2244
+		EE_Line_Item $total_line_item,
2245
+		?EE_Transaction $transaction = null
2246
+	): EE_Line_Item {
2247
+		EE_Error::doing_it_wrong(
2248
+			'EEH_Line_Item::create_default_event_subtotal()',
2249
+			sprintf(
2250
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
2251
+				'EEH_Line_Item::create_event_subtotal()'
2252
+			),
2253
+			'4.6.0'
2254
+		);
2255
+		return self::create_event_subtotal($total_line_item, $transaction);
2256
+	}
2257 2257
 }
Please login to merge, or discard this patch.
Spacing   +47 added lines, -47 removed lines patch added patch discarded remove patch
@@ -24,7 +24,7 @@  discard block
 block discarded – undo
24 24
     /**
25 25
      * @var EE_Line_Item[]|null
26 26
      */
27
-    private static ?array $global_taxes = null;
27
+    private static ? array $global_taxes = null;
28 28
 
29 29
 
30 30
     /**
@@ -73,12 +73,12 @@  discard block
 block discarded – undo
73 73
                 'LIN_code'       => $code,
74 74
             ]
75 75
         );
76
-        $line_item      = apply_filters(
76
+        $line_item = apply_filters(
77 77
             'FHEE__EEH_Line_Item__add_unrelated_item__line_item',
78 78
             $line_item,
79 79
             $parent_line_item
80 80
         );
81
-        $added          = self::add_item($parent_line_item, $line_item, $recalculate_totals);
81
+        $added = self::add_item($parent_line_item, $line_item, $recalculate_totals);
82 82
         return $return_item ? $line_item : $added;
83 83
     }
84 84
 
@@ -131,7 +131,7 @@  discard block
 block discarded – undo
131 131
             'FHEE__EEH_Line_Item__add_percentage_based_item__line_item',
132 132
             $line_item
133 133
         );
134
-        $added     = $parent_line_item->add_child_line_item($line_item, false);
134
+        $added = $parent_line_item->add_child_line_item($line_item, false);
135 135
         return $return_item ? $line_item : $added;
136 136
     }
137 137
 
@@ -160,7 +160,7 @@  discard block
 block discarded – undo
160 160
         int $qty = 1,
161 161
         bool $recalculate_totals = true
162 162
     ): ?EE_Line_Item {
163
-        if (! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) {
163
+        if ( ! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) {
164 164
             throw new EE_Error(
165 165
                 sprintf(
166 166
                     esc_html__(
@@ -175,7 +175,7 @@  discard block
 block discarded – undo
175 175
         // either increment the qty for an existing ticket
176 176
         $line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty);
177 177
         // or add a new one
178
-        if (! $line_item instanceof EE_Line_Item) {
178
+        if ( ! $line_item instanceof EE_Line_Item) {
179 179
             $line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty);
180 180
         }
181 181
         if ($recalculate_totals) {
@@ -239,7 +239,7 @@  discard block
 block discarded – undo
239 239
      */
240 240
     public static function increment_quantity(EE_Line_Item $line_item, int $qty = 1)
241 241
     {
242
-        if (! $line_item->is_percent()) {
242
+        if ( ! $line_item->is_percent()) {
243 243
             $qty += $line_item->quantity();
244 244
             $line_item->set_quantity($qty);
245 245
             $line_item->set_total($line_item->unit_price() * $qty);
@@ -268,7 +268,7 @@  discard block
 block discarded – undo
268 268
      */
269 269
     public static function decrement_quantity(EE_Line_Item $line_item, int $qty = 1)
270 270
     {
271
-        if (! $line_item->is_percent()) {
271
+        if ( ! $line_item->is_percent()) {
272 272
             $qty = $line_item->quantity() - $qty;
273 273
             $qty = max($qty, 0);
274 274
             $line_item->set_quantity($qty);
@@ -297,7 +297,7 @@  discard block
 block discarded – undo
297 297
      */
298 298
     public static function update_quantity(EE_Line_Item $line_item, int $new_quantity)
299 299
     {
300
-        if (! $line_item->is_percent()) {
300
+        if ( ! $line_item->is_percent()) {
301 301
             $line_item->set_quantity($new_quantity);
302 302
             $line_item->set_total($line_item->unit_price() * $new_quantity);
303 303
             $line_item->save();
@@ -342,7 +342,7 @@  discard block
 block discarded – undo
342 342
         $line_item = EE_Line_Item::new_instance(
343 343
             [
344 344
                 'LIN_name'       => $ticket->name(),
345
-                'LIN_desc'       => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event,
345
+                'LIN_desc'       => $ticket->description() !== '' ? $ticket->description().' '.$event : $event,
346 346
                 'LIN_unit_price' => $ticket->price(),
347 347
                 'LIN_quantity'   => $qty,
348 348
                 'LIN_is_taxable' => empty($taxes) && $ticket->taxable(),
@@ -357,7 +357,7 @@  discard block
 block discarded – undo
357 357
             'FHEE__EEH_Line_Item__create_ticket_line_item__line_item',
358 358
             $line_item
359 359
         );
360
-        if (! $line_item instanceof EE_Line_Item) {
360
+        if ( ! $line_item instanceof EE_Line_Item) {
361 361
             throw new DomainException(
362 362
                 esc_html__('Invalid EE_Line_Item received.', 'event_espresso')
363 363
             );
@@ -396,7 +396,7 @@  discard block
 block discarded – undo
396 396
                 ? $price_type->name()
397 397
                 : $price_desc;
398 398
 
399
-            $sub_line_item         = EE_Line_Item::new_instance(
399
+            $sub_line_item = EE_Line_Item::new_instance(
400 400
                 [
401 401
                     'LIN_name'       => $price->name(),
402 402
                     'LIN_desc'       => $price_desc,
@@ -413,7 +413,7 @@  discard block
 block discarded – undo
413 413
                     'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_PRICE,
414 414
                 ]
415 415
             );
416
-            $sub_line_item         = apply_filters(
416
+            $sub_line_item = apply_filters(
417 417
                 'FHEE__EEH_Line_Item__create_ticket_line_item__sub_line_item',
418 418
                 $sub_line_item
419 419
             );
@@ -530,7 +530,7 @@  discard block
 block discarded – undo
530 530
                             'event_espresso'
531 531
                         ),
532 532
                         $ticket_line_item->name(),
533
-                        current_time(get_option('date_format') . ' ' . get_option('time_format'))
533
+                        current_time(get_option('date_format').' '.get_option('time_format'))
534 534
                     ),
535 535
                     'LIN_total'      => 0,
536 536
                     'LIN_unit_price' => 0,
@@ -594,7 +594,7 @@  discard block
 block discarded – undo
594 594
         );
595 595
         $cancellation_line_item = reset($cancellation_line_item);
596 596
         // verify that this ticket was indeed previously cancelled
597
-        if (! $cancellation_line_item instanceof EE_Line_Item) {
597
+        if ( ! $cancellation_line_item instanceof EE_Line_Item) {
598 598
             return false;
599 599
         }
600 600
         if ($cancellation_line_item->quantity() > $qty) {
@@ -812,7 +812,7 @@  discard block
 block discarded – undo
812 812
                 'LIN_code'  => 'taxes',
813 813
                 'LIN_name'  => esc_html__('Taxes', 'event_espresso'),
814 814
                 'LIN_type'  => EEM_Line_Item::type_tax_sub_total,
815
-                'LIN_order' => 1000,// this should always come last
815
+                'LIN_order' => 1000, // this should always come last
816 816
             ]
817 817
         );
818 818
         $tax_line_item = apply_filters(
@@ -890,7 +890,7 @@  discard block
 block discarded – undo
890 890
      */
891 891
     public static function get_event_code(?EE_Event $event = null): string
892 892
     {
893
-        return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0');
893
+        return 'event-'.($event instanceof EE_Event ? $event->ID() : '0');
894 894
     }
895 895
 
896 896
 
@@ -941,7 +941,7 @@  discard block
 block discarded – undo
941 941
     public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket): EE_Line_Item
942 942
     {
943 943
         $first_datetime = $ticket->first_datetime();
944
-        if (! $first_datetime instanceof EE_Datetime) {
944
+        if ( ! $first_datetime instanceof EE_Datetime) {
945 945
             throw new EE_Error(
946 946
                 sprintf(
947 947
                     esc_html__('The supplied ticket (ID %d) has no datetimes', 'event_espresso'),
@@ -950,7 +950,7 @@  discard block
 block discarded – undo
950 950
             );
951 951
         }
952 952
         $event = $first_datetime->event();
953
-        if (! $event instanceof EE_Event) {
953
+        if ( ! $event instanceof EE_Event) {
954 954
             throw new EE_Error(
955 955
                 sprintf(
956 956
                     esc_html__(
@@ -962,7 +962,7 @@  discard block
 block discarded – undo
962 962
             );
963 963
         }
964 964
         $events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event);
965
-        if (! $events_sub_total instanceof EE_Line_Item) {
965
+        if ( ! $events_sub_total instanceof EE_Line_Item) {
966 966
             throw new EE_Error(
967 967
                 sprintf(
968 968
                     esc_html__(
@@ -990,7 +990,7 @@  discard block
 block discarded – undo
990 990
     public static function get_event_line_item(EE_Line_Item $total_line_item, ?EE_Event $event = null): ?EE_Line_Item
991 991
     {
992 992
         /** @type EE_Event $event */
993
-        $event           = EEM_Event::instance()->ensure_is_obj($event, true);
993
+        $event = EEM_Event::instance()->ensure_is_obj($event, true);
994 994
         $event_line_items = EEH_Line_Item::get_event_subtotals($total_line_item);
995 995
         $existing_event_line_item = null;
996 996
         foreach ($event_line_items as $event_line_item) {
@@ -1001,7 +1001,7 @@  discard block
 block discarded – undo
1001 1001
                 $existing_event_line_item = $event_line_item;
1002 1002
                 break;
1003 1003
             }
1004
-            if (! $OBJ_ID) {
1004
+            if ( ! $OBJ_ID) {
1005 1005
                 // OK?!?! We have an event subtotal that is not actually associated with any event???
1006 1006
                 // let's just use this line item since it's already there, but first... set the event details
1007 1007
                 $existing_event_line_item = $event_line_item;
@@ -1091,7 +1091,7 @@  discard block
 block discarded – undo
1091 1091
                             break;
1092 1092
                         }
1093 1093
                     }
1094
-                    if (! $found) {
1094
+                    if ( ! $found) {
1095 1095
                         // add a new line item for this global tax
1096 1096
                         $tax_line_item = apply_filters(
1097 1097
                             'FHEE__EEH_Line_Item__apply_taxes__tax_line_item',
@@ -1109,7 +1109,7 @@  discard block
 block discarded – undo
1109 1109
                                 ]
1110 1110
                             )
1111 1111
                         );
1112
-                        $updates       = $taxes_line_item->add_child_line_item($tax_line_item) ? true : $updates;
1112
+                        $updates = $taxes_line_item->add_child_line_item($tax_line_item) ? true : $updates;
1113 1113
                     }
1114 1114
                 }
1115 1115
             }
@@ -1138,7 +1138,7 @@  discard block
 block discarded – undo
1138 1138
     public static function ensure_taxes_applied(?EE_Line_Item $total_line_item): float
1139 1139
     {
1140 1140
         $taxes_subtotal = self::get_taxes_subtotal($total_line_item);
1141
-        if (! $taxes_subtotal->children()) {
1141
+        if ( ! $taxes_subtotal->children()) {
1142 1142
             self::apply_taxes($total_line_item);
1143 1143
         }
1144 1144
         return $taxes_subtotal->total();
@@ -1204,7 +1204,7 @@  discard block
 block discarded – undo
1204 1204
         }
1205 1205
 
1206 1206
         // check if only a single line_item_id was passed
1207
-        if (! empty($line_item_codes) && ! is_array($line_item_codes)) {
1207
+        if ( ! empty($line_item_codes) && ! is_array($line_item_codes)) {
1208 1208
             // place single line_item_id in an array to appear as multiple line_item_ids
1209 1209
             $line_item_codes = [$line_item_codes];
1210 1210
         }
@@ -1313,7 +1313,7 @@  discard block
 block discarded – undo
1313 1313
         if ($code_substring_for_whitelist !== null) {
1314 1314
             $whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false;
1315 1315
         }
1316
-        if (! $whitelisted && $line_item->is_line_item()) {
1316
+        if ( ! $whitelisted && $line_item->is_line_item()) {
1317 1317
             $line_item->set_is_taxable($taxable);
1318 1318
         }
1319 1319
         foreach ($line_item->children() as $child_line_item) {
@@ -1695,10 +1695,10 @@  discard block
 block discarded – undo
1695 1695
      */
1696 1696
     public static function visualize(EE_Line_Item $line_item, int $indentation = 0, bool $top_level = true)
1697 1697
     {
1698
-        if (! defined('WP_DEBUG') || ! WP_DEBUG) {
1698
+        if ( ! defined('WP_DEBUG') || ! WP_DEBUG) {
1699 1699
             return;
1700 1700
         }
1701
-        $no_formatting  = defined('EE_TESTS_DIR') || (defined('DOING_AJAX') && DOING_AJAX);
1701
+        $no_formatting = defined('EE_TESTS_DIR') || (defined('DOING_AJAX') && DOING_AJAX);
1702 1702
         $new_line = $no_formatting ? "\n" : '<br />';
1703 1703
         if ($top_level && ! $no_formatting) {
1704 1704
             echo '<div style="position: relative; z-index: 9999; margin: 2rem;">';
@@ -1794,7 +1794,7 @@  discard block
 block discarded – undo
1794 1794
                         $billable_ticket_quantities
1795 1795
                     );
1796 1796
                     // combine arrays but preserve numeric keys
1797
-                    $running_totals                     = array_replace_recursive(
1797
+                    $running_totals = array_replace_recursive(
1798 1798
                         $running_totals_from_subtotal,
1799 1799
                         $running_totals
1800 1800
                     );
@@ -1815,8 +1815,8 @@  discard block
 block discarded – undo
1815 1815
                         if ($line_item_id === 'taxable') {
1816 1816
                             continue;
1817 1817
                         }
1818
-                        $taxable_total                   = $running_totals['taxable'][ $line_item_id ];
1819
-                        $running_totals[ $line_item_id ] += ($taxable_total * $tax_percent_decimal);
1818
+                        $taxable_total = $running_totals['taxable'][$line_item_id];
1819
+                        $running_totals[$line_item_id] += ($taxable_total * $tax_percent_decimal);
1820 1820
                     }
1821 1821
                     break;
1822 1822
 
@@ -1824,7 +1824,7 @@  discard block
 block discarded – undo
1824 1824
                     // ticket line items or ????
1825 1825
                     if ($child_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) {
1826 1826
                         // kk it's a ticket
1827
-                        if (isset($running_totals[ $child_line_item->ID() ])) {
1827
+                        if (isset($running_totals[$child_line_item->ID()])) {
1828 1828
                             // huh? that shouldn't happen.
1829 1829
                             $running_totals['total'] += $child_line_item->total();
1830 1830
                         } else {
@@ -1835,19 +1835,19 @@  discard block
 block discarded – undo
1835 1835
                                 $taxable_amount = 0;
1836 1836
                             }
1837 1837
                             // are we only calculating totals for some tickets?
1838
-                            if (isset($billable_ticket_quantities[ $child_line_item->OBJ_ID() ])) {
1839
-                                $quantity = $billable_ticket_quantities[ $child_line_item->OBJ_ID() ];
1838
+                            if (isset($billable_ticket_quantities[$child_line_item->OBJ_ID()])) {
1839
+                                $quantity = $billable_ticket_quantities[$child_line_item->OBJ_ID()];
1840 1840
 
1841
-                                $running_totals[ $child_line_item->ID() ]            = $quantity
1841
+                                $running_totals[$child_line_item->ID()]            = $quantity
1842 1842
                                     ? $child_line_item->unit_price()
1843 1843
                                     : 0;
1844
-                                $running_totals['taxable'][ $child_line_item->ID() ] = $quantity
1844
+                                $running_totals['taxable'][$child_line_item->ID()] = $quantity
1845 1845
                                     ? $taxable_amount
1846 1846
                                     : 0;
1847 1847
                             } else {
1848 1848
                                 $quantity                                            = $child_line_item->quantity();
1849
-                                $running_totals[ $child_line_item->ID() ]            = $child_line_item->unit_price();
1850
-                                $running_totals['taxable'][ $child_line_item->ID() ] = $taxable_amount;
1849
+                                $running_totals[$child_line_item->ID()]            = $child_line_item->unit_price();
1850
+                                $running_totals['taxable'][$child_line_item->ID()] = $taxable_amount;
1851 1851
                             }
1852 1852
                             $running_totals['taxable']['total'] += $taxable_amount * $quantity;
1853 1853
                             $running_totals['total']            += $child_line_item->unit_price() * $quantity;
@@ -1867,12 +1867,12 @@  discard block
 block discarded – undo
1867 1867
                             }
1868 1868
                             // update the running totals
1869 1869
                             // yes this actually even works for the running grand total!
1870
-                            $running_totals[ $line_item_id ] =
1870
+                            $running_totals[$line_item_id] =
1871 1871
                                 $line_items_percent_of_running_total * $this_running_total;
1872 1872
 
1873 1873
                             if ($child_line_item->is_taxable()) {
1874
-                                $running_totals['taxable'][ $line_item_id ] =
1875
-                                    $line_items_percent_of_running_total * $running_totals['taxable'][ $line_item_id ];
1874
+                                $running_totals['taxable'][$line_item_id] =
1875
+                                    $line_items_percent_of_running_total * $running_totals['taxable'][$line_item_id];
1876 1876
                             }
1877 1877
                         }
1878 1878
                     }
@@ -1901,16 +1901,16 @@  discard block
 block discarded – undo
1901 1901
         static $final_prices_per_ticket_line_item = [];
1902 1902
         if (
1903 1903
             empty($final_prices_per_ticket_line_item)
1904
-            || empty($final_prices_per_ticket_line_item[ $total_line_item->ID() ])
1904
+            || empty($final_prices_per_ticket_line_item[$total_line_item->ID()])
1905 1905
         ) {
1906
-            $final_prices_per_ticket_line_item[ $total_line_item->ID() ] =
1906
+            $final_prices_per_ticket_line_item[$total_line_item->ID()] =
1907 1907
                 EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1908 1908
                     $total_line_item
1909 1909
                 );
1910 1910
         }
1911 1911
         // ok now find this new registration's final price
1912
-        if (isset($final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ])) {
1913
-            return $final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ];
1912
+        if (isset($final_prices_per_ticket_line_item[$total_line_item->ID()][$ticket_line_item->ID()])) {
1913
+            return $final_prices_per_ticket_line_item[$total_line_item->ID()][$ticket_line_item->ID()];
1914 1914
         }
1915 1915
         $message = sprintf(
1916 1916
             esc_html__(
@@ -1921,7 +1921,7 @@  discard block
 block discarded – undo
1921 1921
             $total_line_item->ID()
1922 1922
         );
1923 1923
         if (WP_DEBUG) {
1924
-            $message .= '<br>' . print_r($final_prices_per_ticket_line_item, true);
1924
+            $message .= '<br>'.print_r($final_prices_per_ticket_line_item, true);
1925 1925
             throw new OutOfRangeException($message);
1926 1926
         }
1927 1927
         EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message);
Please login to merge, or discard this patch.
core/helpers/EEH_HTML.helper.php 2 patches
Indentation   +940 added lines, -940 removed lines patch added patch discarded remove patch
@@ -15,944 +15,944 @@
 block discarded – undo
15 15
  */
16 16
 class EEH_HTML
17 17
 {
18
-    private static ?EEH_HTML $_instance = null;
19
-
20
-    /**
21
-     * some initial formatting for table indentation
22
-     *
23
-     * @var int[]
24
-     */
25
-    private static array $_indent = [
26
-        'table' => 0,
27
-        'thead' => 1,
28
-        'tbody' => 1,
29
-        'tr'    => 2,
30
-        'th'    => 3,
31
-        'td'    => 3,
32
-        'div'   => 0,
33
-        'h1'    => 0,
34
-        'h2'    => 0,
35
-        'h3'    => 0,
36
-        'h4'    => 0,
37
-        'h5'    => 0,
38
-        'h6'    => 0,
39
-        'p'     => 0,
40
-        'ul'    => 0,
41
-        'li'    => 1,
42
-    ];
43
-
44
-
45
-    /**
46
-     * @singleton method used to instantiate class object
47
-     * @return EEH_HTML
48
-     */
49
-    public static function instance(): EEH_HTML
50
-    {
51
-        // check if class object is instantiated, and instantiated properly
52
-        if (! self::$_instance instanceof EEH_HTML) {
53
-            self::$_instance = new EEH_HTML();
54
-        }
55
-        return self::$_instance;
56
-    }
57
-
58
-
59
-    /**
60
-     * Generates an opening HTML <XX> tag and adds any passed attributes
61
-     * if passed content, it will also add that, as well as the closing </XX> tag
62
-     *
63
-     * @param string $tag
64
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
65
-     * @param string $id               - html id attribute
66
-     * @param string $class            - html class attribute
67
-     * @param string $style            - html style attribute for applying inline styles
68
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
69
-     * @param bool   $force_close
70
-     * @return string
71
-     */
72
-    protected static function _open_tag(
73
-        string $tag = 'div',
74
-        string $content = '',
75
-        string $id = '',
76
-        string $class = '',
77
-        string $style = '',
78
-        string $other_attributes = '',
79
-        bool $force_close = false
80
-    ): string {
81
-        $attributes = ! empty($id) ? ' id="' . EEH_HTML::sanitize_id($id) . '"' : '';
82
-        $attributes .= ! empty($class) ? ' class="' . $class . '"' : '';
83
-        $attributes .= ! empty($style) ? ' style="' . $style . '"' : '';
84
-        $attributes .= ! empty($other_attributes) ? ' ' . $other_attributes : '';
85
-        $html       = EEH_HTML::nl(0, $tag) . '<' . $tag . $attributes . '>';
86
-        $html       .= trim($content) !== '' ? EEH_HTML::nl(1, $tag) . $content : '';
87
-        $indent     = ! empty($content) || $force_close;
88
-        $html       .= ! empty($content) || $force_close
89
-            ? EEH_HTML::_close_tag($tag, $id, $class, $indent, $content)
90
-            : '';
91
-        return $html;
92
-    }
93
-
94
-
95
-    /**
96
-     * Generates HTML closing </XX> tag - if passed the id or class attribute
97
-     * used for the opening tag, will append a comment
98
-     *
99
-     * @access protected
100
-     * @param string $tag
101
-     * @param string $id    - html id attribute
102
-     * @param string $class - html class attribute
103
-     * @param bool   $indent
104
-     * @param string $content
105
-     * @return string
106
-     */
107
-    protected static function _close_tag(
108
-        string $tag = 'div',
109
-        string $id = '',
110
-        string $class = '',
111
-        bool $indent = true,
112
-        string $content = ''
113
-    ): string {
114
-        $alotta_content = strlen($content) > 500;
115
-        $comment         = '';
116
-        if ($id && $alotta_content) {
117
-            $comment = EEH_HTML::comment('close ' . $id) . EEH_HTML::nl(0, $tag);
118
-        } elseif ($class && $alotta_content) {
119
-            $comment = EEH_HTML::comment('close ' . $class) . EEH_HTML::nl(0, $tag);
120
-        }
121
-        $html = $indent ? EEH_HTML::nl(-1, $tag) : '';
122
-        $html .= '</' . $tag . '>' . $comment;
123
-        return $html;
124
-    }
125
-
126
-
127
-    /**
128
-     *  div - generates HTML opening <div> tag and adds any passed attributes
129
-     *  to add an id use:       echo EEH_HTML::div( 'this is some content', 'footer' );
130
-     *  to add a class use:     echo EEH_HTML::div( 'this is some content', '', 'float_left' );
131
-     *  to add a both an id and a class use:    echo EEH_HTML::div( 'this is some content', 'footer', 'float_left' );
132
-     *
133
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
134
-     * @param string $id               - html id attribute
135
-     * @param string $class            - html class attribute
136
-     * @param string $style            - html style attribute for applying inline styles
137
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
138
-     * @return string
139
-     */
140
-    public static function div(
141
-        string $content = '',
142
-        string $id = '',
143
-        string $class = '',
144
-        string $style = '',
145
-        string $other_attributes = ''
146
-    ): string {
147
-        return EEH_HTML::_open_tag('div', $content, $id, $class, $style, $other_attributes);
148
-    }
149
-
150
-
151
-    /**
152
-     * Generates HTML closing </div> tag - if passed the id or class attribute used for the opening div tag, will
153
-     * append a comment usage: echo EEH_HTML::divx();
154
-     *
155
-     * @param string $id    - html id attribute
156
-     * @param string $class - html class attribute
157
-     * @return string
158
-     */
159
-    public static function divx(string $id = '', string $class = ''): string
160
-    {
161
-        return EEH_HTML::_close_tag('div', $id, $class);
162
-    }
163
-
164
-
165
-    /**
166
-     * Generates HTML <h1></h1> tags, inserts content, and adds any passed attributes
167
-     * usage: echo EEH_HTML::h1( 'This is a Heading' );
168
-     *
169
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
170
-     * @param string $id               - html id attribute
171
-     * @param string $class            - html class attribute
172
-     * @param string $style            - html style attribute for applying inline styles
173
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
174
-     * @return string
175
-     */
176
-    public static function h1(
177
-        string $content = '',
178
-        string $id = '',
179
-        string $class = '',
180
-        string $style = '',
181
-        string $other_attributes = ''
182
-    ): string {
183
-        return EEH_HTML::_open_tag('h1', $content, $id, $class, $style, $other_attributes, true);
184
-    }
185
-
186
-
187
-    /**
188
-     * Generates HTML <h2></h2> tags, inserts content, and adds any passed attributes
189
-     * usage: echo EEH_HTML::h2( 'This is a Heading' );
190
-     *
191
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
192
-     * @param string $id               - html id attribute
193
-     * @param string $class            - html class attribute
194
-     * @param string $style            - html style attribute for applying inline styles
195
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
196
-     * @return string
197
-     */
198
-    public static function h2(
199
-        string $content = '',
200
-        string $id = '',
201
-        string $class = '',
202
-        string $style = '',
203
-        string $other_attributes = ''
204
-    ): string {
205
-        return EEH_HTML::_open_tag('h2', $content, $id, $class, $style, $other_attributes, true);
206
-    }
207
-
208
-
209
-    /**
210
-     * Generates HTML <h3></h3> tags, inserts content, and adds any passed attributes
211
-     * usage: echo EEH_HTML::h3( 'This is a Heading' );
212
-     *
213
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
214
-     * @param string $id               - html id attribute
215
-     * @param string $class            - html class attribute
216
-     * @param string $style            - html style attribute for applying inline styles
217
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
218
-     * @return string
219
-     */
220
-    public static function h3(
221
-        string $content = '',
222
-        string $id = '',
223
-        string $class = '',
224
-        string $style = '',
225
-        string $other_attributes = ''
226
-    ): string {
227
-        return EEH_HTML::_open_tag('h3', $content, $id, $class, $style, $other_attributes, true);
228
-    }
229
-
230
-
231
-    /**
232
-     * Generates HTML <h4></h4> tags, inserts content, and adds any passed attributes
233
-     * usage: echo EEH_HTML::h4( 'This is a Heading' );
234
-     *
235
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
236
-     * @param string $id               - html id attribute
237
-     * @param string $class            - html class attribute
238
-     * @param string $style            - html style attribute for applying inline styles
239
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
240
-     * @return string
241
-     */
242
-    public static function h4(
243
-        string $content = '',
244
-        string $id = '',
245
-        string $class = '',
246
-        string $style = '',
247
-        string $other_attributes = ''
248
-    ): string {
249
-        return EEH_HTML::_open_tag('h4', $content, $id, $class, $style, $other_attributes, true);
250
-    }
251
-
252
-
253
-    /**
254
-     * Generates HTML <h5></h5> tags, inserts content, and adds any passed attributes
255
-     * usage: echo EEH_HTML::h5( 'This is a Heading' );
256
-     *
257
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
258
-     * @param string $id               - html id attribute
259
-     * @param string $class            - html class attribute
260
-     * @param string $style            - html style attribute for applying inline styles
261
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
262
-     * @return string
263
-     */
264
-    public static function h5(
265
-        string $content = '',
266
-        string $id = '',
267
-        string $class = '',
268
-        string $style = '',
269
-        string $other_attributes = ''
270
-    ): string {
271
-        return EEH_HTML::_open_tag('h5', $content, $id, $class, $style, $other_attributes, true);
272
-    }
273
-
274
-
275
-    /**
276
-     * Generates HTML <h6></h6> tags, inserts content, and adds any passed attributes
277
-     * usage: echo EEH_HTML::h6( 'This is a Heading' );
278
-     *
279
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
280
-     * @param string $id               - html id attribute
281
-     * @param string $class            - html class attribute
282
-     * @param string $style            - html style attribute for applying inline styles
283
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
284
-     * @return string
285
-     */
286
-    public static function h6(
287
-        string $content = '',
288
-        string $id = '',
289
-        string $class = '',
290
-        string $style = '',
291
-        string $other_attributes = ''
292
-    ): string {
293
-        return EEH_HTML::_open_tag('h6', $content, $id, $class, $style, $other_attributes, true);
294
-    }
295
-
296
-
297
-    /**
298
-     * Generates HTML <p></p> tags, inserts content, and adds any passed attributes
299
-     * usage: echo EEH_HTML::p( 'this is a paragraph' );
300
-     *
301
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
302
-     * @param string $id               - html id attribute
303
-     * @param string $class            - html class attribute
304
-     * @param string $style            - html style attribute for applying inline styles
305
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
306
-     * @return string
307
-     */
308
-    public static function p(
309
-        string $content = '',
310
-        string $id = '',
311
-        string $class = '',
312
-        string $style = '',
313
-        string $other_attributes = ''
314
-    ): string {
315
-        return EEH_HTML::_open_tag('p', $content, $id, $class, $style, $other_attributes, true);
316
-    }
317
-
318
-
319
-    /**
320
-     *  ul - generates HTML opening <ul> tag and adds any passed attributes
321
-     *  usage:      echo EEH_HTML::ul( 'my-list-id', 'my-list-class' );
322
-     *
323
-     * @param string $id               - html id attribute
324
-     * @param string $class            - html class attribute
325
-     * @param string $style            - html style attribute for applying inline styles
326
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
327
-     * @return string
328
-     */
329
-    public static function ul(
330
-        string $id = '',
331
-        string $class = '',
332
-        string $style = '',
333
-        string $other_attributes = ''
334
-    ): string {
335
-        return EEH_HTML::_open_tag('ul', '', $id, $class, $style, $other_attributes);
336
-    }
337
-
338
-
339
-    /**
340
-     * Generates HTML closing </ul> tag - if passed the id or class attribute used for the opening ul tag, will append
341
-     * a comment usage: echo EEH_HTML::ulx();
342
-     *
343
-     * @param string $id    - html id attribute
344
-     * @param string $class - html class attribute
345
-     * @return string
346
-     */
347
-    public static function ulx(string $id = '', string $class = ''): string
348
-    {
349
-        return EEH_HTML::_close_tag('ul', $id, $class);
350
-    }
351
-
352
-
353
-    /**
354
-     * Generates HTML <li> tag, inserts content, and adds any passed attributes
355
-     * if passed content, it will also add that, as well as the closing </li> tag
356
-     * usage: echo EEH_HTML::li( 'this is a line item' );
357
-     *
358
-     * @param string $id               - html id attribute
359
-     * @param string $class            - html class attribute
360
-     * @param string $style            - html style attribute for applying inline styles
361
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
362
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
363
-     * @return string
364
-     */
365
-    public static function li(
366
-        string $content = '',
367
-        string $id = '',
368
-        string $class = '',
369
-        string $style = '',
370
-        string $other_attributes = ''
371
-    ): string {
372
-        return EEH_HTML::_open_tag('li', $content, $id, $class, $style, $other_attributes);
373
-    }
374
-
375
-
376
-    /**
377
-     * Generates HTML closing </li> tag - if passed the id or class attribute used for the opening ul tag, will append
378
-     * a comment usage: echo EEH_HTML::lix();
379
-     *
380
-     * @param string $id    - html id attribute
381
-     * @param string $class - html class attribute
382
-     * @return string
383
-     */
384
-    public static function lix(string $id = '', string $class = ''): string
385
-    {
386
-        return EEH_HTML::_close_tag('li', $id, $class);
387
-    }
388
-
389
-
390
-    /**
391
-     *    table - generates an HTML <table> tag and adds any passed attributes
392
-     *    usage: echo EEH_HTML::table();
393
-     *
394
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
395
-     * @param string $id               - html id attribute
396
-     * @param string $class            - html class attribute
397
-     * @param string $style            - html style attribute for applying inline styles
398
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
399
-     * @return string
400
-     */
401
-    public static function table(
402
-        string $content = '',
403
-        string $id = '',
404
-        string $class = '',
405
-        string $style = '',
406
-        string $other_attributes = ''
407
-    ): string {
408
-        return EEH_HTML::_open_tag('table', $content, $id, $class, $style, $other_attributes);
409
-    }
410
-
411
-
412
-    /**
413
-     * tablex - generates an HTML </table> tag - if passed the id or class attribute used for the opening ul tag, will
414
-     * append a comment
415
-     *
416
-     * @param string $id    - html id attribute
417
-     * @param string $class - html class attribute
418
-     * @return string
419
-     */
420
-    public static function tablex(string $id = '', string $class = ''): string
421
-    {
422
-        return EEH_HTML::_close_tag('table', $id, $class);
423
-    }
424
-
425
-
426
-    /**
427
-     *    thead - generates an HTML <thead> tag and adds any passed attributes
428
-     *    usage: echo EEH_HTML::thead();
429
-     *
430
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
431
-     * @param string $id               - html id attribute
432
-     * @param string $class            - html class attribute
433
-     * @param string $style            - html style attribute for applying inline styles
434
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
435
-     * @return string
436
-     */
437
-    public static function thead(
438
-        string $content = '',
439
-        string $id = '',
440
-        string $class = '',
441
-        string $style = '',
442
-        string $other_attributes = ''
443
-    ): string {
444
-        return EEH_HTML::_open_tag('thead', $content, $id, $class, $style, $other_attributes);
445
-    }
446
-
447
-
448
-    /**
449
-     * theadx - generates an HTML </thead> tag - if passed the id or class attribute used for the opening ul tag, will
450
-     * append a comment
451
-     *
452
-     * @param string $id    - html id attribute
453
-     * @param string $class - html class attribute
454
-     * @return string
455
-     */
456
-    public static function theadx(string $id = '', string $class = ''): string
457
-    {
458
-        return EEH_HTML::_close_tag('thead', $id, $class);
459
-    }
460
-
461
-
462
-    /**
463
-     *    tbody - generates an HTML <tbody> tag and adds any passed attributes
464
-     *    usage: echo EEH_HTML::tbody();
465
-     *
466
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
467
-     * @param string $id               - html id attribute
468
-     * @param string $class            - html class attribute
469
-     * @param string $style            - html style attribute for applying inline styles
470
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
471
-     * @return string
472
-     */
473
-    public static function tbody(
474
-        string $content = '',
475
-        string $id = '',
476
-        string $class = '',
477
-        string $style = '',
478
-        string $other_attributes = ''
479
-    ): string {
480
-        return EEH_HTML::_open_tag('tbody', $content, $id, $class, $style, $other_attributes);
481
-    }
482
-
483
-
484
-    /**
485
-     * tbodyx - generates an HTML </tbody> tag - if passed the id or class attribute used for the opening ul tag, will
486
-     * append a comment
487
-     *
488
-     * @param string $id    - html id attribute
489
-     * @param string $class - html class attribute
490
-     * @return string
491
-     */
492
-    public static function tbodyx(string $id = '', string $class = ''): string
493
-    {
494
-        return EEH_HTML::_close_tag('tbody', $id, $class);
495
-    }
496
-
497
-
498
-    /**
499
-     *    tr - generates an HTML <tr> tag and adds any passed attributes
500
-     *    usage: echo EEH_HTML::tr();
501
-     *
502
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
503
-     * @param string $id               - html id attribute
504
-     * @param string $class            - html class attribute
505
-     * @param string $style            - html style attribute for applying inline styles
506
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
507
-     * @return string
508
-     */
509
-    public static function tr(
510
-        string $content = '',
511
-        string $id = '',
512
-        string $class = '',
513
-        string $style = '',
514
-        string $other_attributes = ''
515
-    ): string {
516
-        return EEH_HTML::_open_tag('tr', $content, $id, $class, $style, $other_attributes);
517
-    }
518
-
519
-
520
-    /**
521
-     * trx - generates an HTML </tr> tag - if passed the id or class attribute used for the opening ul tag, will append
522
-     * a comment
523
-     *
524
-     * @param string $id    - html id attribute
525
-     * @param string $class - html class attribute
526
-     * @return string
527
-     */
528
-    public static function trx(string $id = '', string $class = ''): string
529
-    {
530
-        return EEH_HTML::_close_tag('tr', $id, $class);
531
-    }
532
-
533
-
534
-    /**
535
-     *    th - generates an HTML <th> tag and adds any passed attributes
536
-     *    usage: echo EEH_HTML::th();
537
-     *
538
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
539
-     * @param string $id               - html id attribute
540
-     * @param string $class            - html class attribute
541
-     * @param string $style            - html style attribute for applying inline styles
542
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
543
-     * @return string
544
-     */
545
-    public static function th(
546
-        string $content = '',
547
-        string $id = '',
548
-        string $class = '',
549
-        string $style = '',
550
-        string $other_attributes = 'scope="col"'
551
-    ): string {
552
-        return EEH_HTML::_open_tag('th', $content, $id, $class, $style, $other_attributes);
553
-    }
554
-
555
-
556
-    /**
557
-     * thx - generates an HTML </th> tag - if passed the id or class attribute used for the opening ul tag, will append
558
-     * a comment
559
-     *
560
-     * @param string $id    - html id attribute
561
-     * @param string $class - html class attribute
562
-     * @return string
563
-     */
564
-    public static function thx(string $id = '', string $class = ''): string
565
-    {
566
-        return EEH_HTML::_close_tag('th', $id, $class);
567
-    }
568
-
569
-
570
-    /**
571
-     *    td - generates an HTML <td> tag and adds any passed attributes
572
-     *    usage: echo EEH_HTML::td();
573
-     *
574
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
575
-     * @param string $id               - html id attribute
576
-     * @param string $class            - html class attribute
577
-     * @param string $style            - html style attribute for applying inline styles
578
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
579
-     * @return string
580
-     */
581
-    public static function td(
582
-        string $content = '',
583
-        string $id = '',
584
-        string $class = '',
585
-        string $style = '',
586
-        string $other_attributes = ''
587
-    ): string {
588
-        return EEH_HTML::_open_tag('td', $content, $id, $class, $style, $other_attributes);
589
-    }
590
-
591
-
592
-    /**
593
-     * tdx - generates an HTML </td> tag - if passed the id or class attribute used for the opening ul tag, will append
594
-     * a comment
595
-     *
596
-     * @param string $id    - html id attribute
597
-     * @param string $class - html class attribute
598
-     * @return string
599
-     */
600
-    public static function tdx(string $id = '', string $class = ''): string
601
-    {
602
-        return EEH_HTML::_close_tag('td', $id, $class);
603
-    }
604
-
605
-
606
-    /**
607
-     * no_row - for generating a "hidden" table row, good for embedding tables within tables
608
-     * generates a new table row with one td cell that spans however many columns you set
609
-     * removes all styles from the tr and td
610
-     *
611
-     * @param string $content
612
-     * @param int    $colspan
613
-     * @return string
614
-     */
615
-    public static function no_row(string $content = '', int $colspan = 2): string
616
-    {
617
-        return EEH_HTML::tr(
618
-            EEH_HTML::td($content, '', '', '', 'colspan="' . $colspan . '"'),
619
-            '',
620
-            'ee-no-row'
621
-        );
622
-    }
623
-
624
-
625
-    /**
626
-     * Generates HTML <a href="url">text</a> tags, inserts content, and adds any passed attributes
627
-     * usage: echo EEH_HTML::link( 'domain.com', 'this is a link' );
628
-     *
629
-     * @param string $href             URL to link to
630
-     * @param string $link_text        - the text that will become "hyperlinked"
631
-     * @param string $title            - html title attribute
632
-     * @param string $id               - html id attribute
633
-     * @param string $class            - html class attribute
634
-     * @param string $style            - html style attribute for applying inline styles
635
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
636
-     * @return string
637
-     */
638
-    public static function link(
639
-        string $href = '',
640
-        string $link_text = '',
641
-        string $title = '',
642
-        string $id = '',
643
-        string $class = '',
644
-        string $style = '',
645
-        string $other_attributes = ''
646
-    ): string {
647
-        $link_text  = ! empty($link_text) ? $link_text : $href;
648
-        $attributes = ! empty($href) ? ' href="' . $href . '"' : '';
649
-        $attributes .= ! empty($id) ? ' id="' . EEH_HTML::sanitize_id($id) . '"' : '';
650
-        $attributes .= ! empty($class) ? ' class="' . $class . '"' : '';
651
-        $attributes .= ! empty($style) ? ' style="' . $style . '"' : '';
652
-        $attributes .= ! empty($title) ? ' title="' . esc_attr($title) . '"' : '';
653
-        $attributes .= ! empty($other_attributes) ? ' ' . $other_attributes : '';
654
-        return "<a$attributes>$link_text</a>";
655
-    }
656
-
657
-
658
-    /**
659
-     * Generates HTML <button>text</button> tags, inserts content, and adds any passed attributes
660
-     * usage: echo EEH_HTML::button( 'this is a button' );
661
-     *
662
-     * @param string $btn_text         - the text that will become "hyperlinked"
663
-     * @param string $class            - html class attribute
664
-     * @param string $aria_label       - aria-label attribute
665
-     * @param string $id               - html id attribute
666
-     * @param string $style            - html style attribute for applying inline styles
667
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
668
-     * @return string
669
-     */
670
-    public static function button(
671
-        string $btn_text = '',
672
-        string $class = '',
673
-        string $aria_label = '',
674
-        string $id = '',
675
-        string $style = '',
676
-        string $other_attributes = ''
677
-    ): string {
678
-        $attributes = ! empty($aria_label) ? ' aria-label="' . $aria_label . '"' : '';
679
-        $attributes .= ! empty($id) ? ' id="' . EEH_HTML::sanitize_id($id) . '"' : '';
680
-        $attributes .= ! empty($class) ? ' class="' . $class . '"' : '';
681
-        $attributes .= ! empty($style) ? ' style="' . $style . '"' : '';
682
-        $attributes .= ! empty($other_attributes) ? ' ' . $other_attributes : '';
683
-        return "<button type='button' $attributes>$btn_text</button>";
684
-    }
685
-
686
-
687
-    /**
688
-     *    img - generates an HTML <img> tag and adds any passed attributes
689
-     *    usage: echo EEH_HTML::img();
690
-     *
691
-     * @param string $src              - html src attribute ie: the path or URL to the image
692
-     * @param string $alt              - html alt attribute
693
-     * @param string $id               - html id attribute
694
-     * @param string $class            - html class attribute
695
-     * @param string $style            - html style attribute for applying inline styles
696
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
697
-     * @return string
698
-     */
699
-    public static function img(
700
-        string $src = '',
701
-        string $alt = '',
702
-        string $id = '',
703
-        string $class = '',
704
-        string $style = '',
705
-        string $other_attributes = ''
706
-    ): string {
707
-        $attributes = ! empty($src) ? ' src="' . esc_url_raw($src) . '"' : '';
708
-        $attributes .= ! empty($alt) ? ' alt="' . esc_attr($alt) . '"' : '';
709
-        $attributes .= ! empty($id) ? ' id="' . EEH_HTML::sanitize_id($id) . '"' : '';
710
-        $attributes .= ! empty($class) ? ' class="' . $class . '"' : '';
711
-        $attributes .= ! empty($style) ? ' style="' . $style . '"' : '';
712
-        $attributes .= ! empty($other_attributes) ? ' ' . $other_attributes : '';
713
-        return '<img' . $attributes . '/>';
714
-    }
715
-
716
-
717
-    /**
718
-     * Generates HTML <tag></tag> tags, inserts content, and adds any passed attributes
719
-     * usage: echo EEH_HTML::span( 'this is some inline text' );
720
-     *
721
-     * @param string $tag
722
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
723
-     * @param string $id               - html id attribute
724
-     * @param string $class            - html class attribute
725
-     * @param string $style            - html style attribute for applying inline styles
726
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
727
-     * @return string
728
-     */
729
-    protected static function _inline_tag(
730
-        string $tag = 'span',
731
-        string $content = '',
732
-        string $id = '',
733
-        string $class = '',
734
-        string $style = '',
735
-        string $other_attributes = ''
736
-    ): string {
737
-        $attributes = ! empty($id) ? ' id="' . EEH_HTML::sanitize_id($id) . '"' : '';
738
-        $attributes .= ! empty($class) ? ' class="' . $class . '"' : '';
739
-        $attributes .= ! empty($style) ? ' style="' . $style . '"' : '';
740
-        $attributes .= ! empty($other_attributes) ? ' ' . $other_attributes : '';
741
-        return '<' . $tag . ' ' . $attributes . '>' . $content . '</' . $tag . '>';
742
-    }
743
-
744
-
745
-    /**
746
-     * Generates HTML <label></label> tags, inserts content, and adds any passed attributes
747
-     * usage: echo EEH_HTML::span( 'this is some inline text' );
748
-     *
749
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
750
-     * @param string $id               - html id attribute
751
-     * @param string $class            - html class attribute
752
-     * @param string $style            - html style attribute for applying inline styles
753
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
754
-     * @return string
755
-     */
756
-    public static function label(
757
-        string $content = '',
758
-        string $id = '',
759
-        string $class = '',
760
-        string $style = '',
761
-        string $other_attributes = ''
762
-    ): string {
763
-        return EEH_HTML::_inline_tag('label', $content, $id, $class, $style, $other_attributes);
764
-    }
765
-
766
-
767
-    /**
768
-     * Generates HTML <span></span> tags, inserts content, and adds any passed attributes
769
-     * usage: echo EEH_HTML::span( 'this is some inline text' );
770
-     *
771
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
772
-     * @param string $id               - html id attribute
773
-     * @param string $class            - html class attribute
774
-     * @param string $style            - html style attribute for applying inline styles
775
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
776
-     * @return string
777
-     */
778
-    public static function span(
779
-        string $content = '',
780
-        string $id = '',
781
-        string $class = '',
782
-        string $style = '',
783
-        string $other_attributes = ''
784
-    ): string {
785
-        return EEH_HTML::_inline_tag('span', $content, $id, $class, $style, $other_attributes);
786
-    }
787
-
788
-
789
-    /**
790
-     * Generates HTML <span></span> tags, inserts content, and adds any passed attributes
791
-     * usage: echo EEH_HTML::span( 'this is some inline text' );
792
-     *
793
-     * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
794
-     * @param string $id               - html id attribute
795
-     * @param string $class            - html class attribute
796
-     * @param string $style            - html style attribute for applying inline styles
797
-     * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
798
-     * @return string
799
-     */
800
-    public static function strong(
801
-        string $content = '',
802
-        string $id = '',
803
-        string $class = '',
804
-        string $style = '',
805
-        string $other_attributes = ''
806
-    ): string {
807
-        return EEH_HTML::_inline_tag('strong', $content, $id, $class, $style, $other_attributes);
808
-    }
809
-
810
-
811
-    /**
812
-     * Generates an html <--  comment --> tag
813
-     *  usage: echo comment( 'this is a comment' );
814
-     *
815
-     * @param string $comment
816
-     * @return string
817
-     */
818
-    public static function comment(string $comment = ''): string
819
-    {
820
-        return ! empty($comment) ? EEH_HTML::nl() . '<!-- ' . $comment . ' -->' : '';
821
-    }
822
-
823
-
824
-    /**
825
-     * br - generates a line break
826
-     *
827
-     * @param int $number - the number of line breaks to return
828
-     * @return string
829
-     */
830
-    public static function br(int $number = 1): string
831
-    {
832
-        return str_repeat('<br />', $number);
833
-    }
834
-
835
-
836
-    /**
837
-     * nbsp - generates non-breaking space entities based on number supplied
838
-     *
839
-     * @param int $number - the number of non-breaking spaces to return
840
-     * @return string
841
-     */
842
-    public static function nbsp(int $number = 1): string
843
-    {
844
-        return str_repeat('&nbsp;', $number);
845
-    }
846
-
847
-
848
-    /**
849
-     * sanitize_id
850
-     * functionally does the same as the wp_core function sanitize_key except it does NOT use
851
-     * strtolower and allows capitals.
852
-     *
853
-     * @param string $id
854
-     * @return string
855
-     */
856
-    public static function sanitize_id(string $id = ''): string
857
-    {
858
-        $key = str_replace(' ', '-', trim($id));
859
-        return preg_replace('/[^a-zA-Z0-9_\-]/', '', $key);
860
-    }
861
-
862
-
863
-    /**
864
-     * return a newline and tabs ("nl" stands for "new line")
865
-     *
866
-     * @param int    $indent the number of tabs to ADD to the current indent (can be negative or zero)
867
-     * @param string $tag
868
-     * @return string - newline character plus # of indents passed (can be + or -)
869
-     */
870
-    public static function nl(int $indent = 0, string $tag = 'none'): string
871
-    {
872
-        $html = "\n";
873
-        EEH_HTML::indent($indent, $tag);
874
-        $html .= str_repeat("\t", EEH_HTML::$_indent[ $tag ]);
875
-        return $html;
876
-    }
877
-
878
-
879
-    /**
880
-     * Changes the indents used in EEH_HTML::nl. Often it's convenient to change
881
-     * the indentation level without actually creating a new line
882
-     *
883
-     * @param int    $indent can be negative to decrease the indentation level
884
-     * @param string $tag
885
-     */
886
-    public static function indent(int $indent, string $tag = 'none')
887
-    {
888
-        static $default_indentation = false;
889
-        if (! $default_indentation) {
890
-            EEH_HTML::_set_default_indentation();
891
-            $default_indentation = true;
892
-        }
893
-        if (! isset(EEH_HTML::$_indent[ $tag ])) {
894
-            EEH_HTML::$_indent[ $tag ] = 0;
895
-        }
896
-        EEH_HTML::$_indent[ $tag ] += $indent;
897
-        EEH_HTML::$_indent[ $tag ] = max(EEH_HTML::$_indent[ $tag ], 0);
898
-    }
899
-
900
-
901
-    /**
902
-     *  class _set_default_indentation
903
-     */
904
-    private static function _set_default_indentation()
905
-    {
906
-        // set some initial formatting for table indentation
907
-        EEH_HTML::$_indent = [
908
-            'none'     => 0,
909
-            'form'     => 0,
910
-            'radio'    => 0,
911
-            'checkbox' => 0,
912
-            'select'   => 0,
913
-            'option'   => 0,
914
-            'optgroup' => 0,
915
-            'table'    => 1,
916
-            'thead'    => 2,
917
-            'tbody'    => 2,
918
-            'tr'       => 3,
919
-            'th'       => 4,
920
-            'td'       => 4,
921
-            'div'      => 0,
922
-            'h1'       => 0,
923
-            'h2'       => 0,
924
-            'h3'       => 0,
925
-            'h4'       => 0,
926
-            'h5'       => 0,
927
-            'h6'       => 0,
928
-            'p'        => 0,
929
-            'ul'       => 0,
930
-            'li'       => 1,
931
-        ];
932
-    }
933
-
934
-
935
-    /**
936
-     * Retrieves the list of tags considered "simple", that are probably safe for
937
-     * use in inputs
938
-     *
939
-     * @return array
940
-     * @global array $allowedtags
941
-     */
942
-    public static function get_simple_tags(): array
943
-    {
944
-        global $allowedtags;
945
-        $tags_we_allow = array_merge_recursive(
946
-            $allowedtags,
947
-            [
948
-                'ol' => [],
949
-                'ul' => [],
950
-                'li' => [],
951
-                'br' => [],
952
-                'p'  => [],
953
-                'a'  => ['target'],
954
-            ]
955
-        );
956
-        return apply_filters('FHEE__EEH_HTML__get_simple_tags', $tags_we_allow);
957
-    }
18
+	private static ?EEH_HTML $_instance = null;
19
+
20
+	/**
21
+	 * some initial formatting for table indentation
22
+	 *
23
+	 * @var int[]
24
+	 */
25
+	private static array $_indent = [
26
+		'table' => 0,
27
+		'thead' => 1,
28
+		'tbody' => 1,
29
+		'tr'    => 2,
30
+		'th'    => 3,
31
+		'td'    => 3,
32
+		'div'   => 0,
33
+		'h1'    => 0,
34
+		'h2'    => 0,
35
+		'h3'    => 0,
36
+		'h4'    => 0,
37
+		'h5'    => 0,
38
+		'h6'    => 0,
39
+		'p'     => 0,
40
+		'ul'    => 0,
41
+		'li'    => 1,
42
+	];
43
+
44
+
45
+	/**
46
+	 * @singleton method used to instantiate class object
47
+	 * @return EEH_HTML
48
+	 */
49
+	public static function instance(): EEH_HTML
50
+	{
51
+		// check if class object is instantiated, and instantiated properly
52
+		if (! self::$_instance instanceof EEH_HTML) {
53
+			self::$_instance = new EEH_HTML();
54
+		}
55
+		return self::$_instance;
56
+	}
57
+
58
+
59
+	/**
60
+	 * Generates an opening HTML <XX> tag and adds any passed attributes
61
+	 * if passed content, it will also add that, as well as the closing </XX> tag
62
+	 *
63
+	 * @param string $tag
64
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
65
+	 * @param string $id               - html id attribute
66
+	 * @param string $class            - html class attribute
67
+	 * @param string $style            - html style attribute for applying inline styles
68
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
69
+	 * @param bool   $force_close
70
+	 * @return string
71
+	 */
72
+	protected static function _open_tag(
73
+		string $tag = 'div',
74
+		string $content = '',
75
+		string $id = '',
76
+		string $class = '',
77
+		string $style = '',
78
+		string $other_attributes = '',
79
+		bool $force_close = false
80
+	): string {
81
+		$attributes = ! empty($id) ? ' id="' . EEH_HTML::sanitize_id($id) . '"' : '';
82
+		$attributes .= ! empty($class) ? ' class="' . $class . '"' : '';
83
+		$attributes .= ! empty($style) ? ' style="' . $style . '"' : '';
84
+		$attributes .= ! empty($other_attributes) ? ' ' . $other_attributes : '';
85
+		$html       = EEH_HTML::nl(0, $tag) . '<' . $tag . $attributes . '>';
86
+		$html       .= trim($content) !== '' ? EEH_HTML::nl(1, $tag) . $content : '';
87
+		$indent     = ! empty($content) || $force_close;
88
+		$html       .= ! empty($content) || $force_close
89
+			? EEH_HTML::_close_tag($tag, $id, $class, $indent, $content)
90
+			: '';
91
+		return $html;
92
+	}
93
+
94
+
95
+	/**
96
+	 * Generates HTML closing </XX> tag - if passed the id or class attribute
97
+	 * used for the opening tag, will append a comment
98
+	 *
99
+	 * @access protected
100
+	 * @param string $tag
101
+	 * @param string $id    - html id attribute
102
+	 * @param string $class - html class attribute
103
+	 * @param bool   $indent
104
+	 * @param string $content
105
+	 * @return string
106
+	 */
107
+	protected static function _close_tag(
108
+		string $tag = 'div',
109
+		string $id = '',
110
+		string $class = '',
111
+		bool $indent = true,
112
+		string $content = ''
113
+	): string {
114
+		$alotta_content = strlen($content) > 500;
115
+		$comment         = '';
116
+		if ($id && $alotta_content) {
117
+			$comment = EEH_HTML::comment('close ' . $id) . EEH_HTML::nl(0, $tag);
118
+		} elseif ($class && $alotta_content) {
119
+			$comment = EEH_HTML::comment('close ' . $class) . EEH_HTML::nl(0, $tag);
120
+		}
121
+		$html = $indent ? EEH_HTML::nl(-1, $tag) : '';
122
+		$html .= '</' . $tag . '>' . $comment;
123
+		return $html;
124
+	}
125
+
126
+
127
+	/**
128
+	 *  div - generates HTML opening <div> tag and adds any passed attributes
129
+	 *  to add an id use:       echo EEH_HTML::div( 'this is some content', 'footer' );
130
+	 *  to add a class use:     echo EEH_HTML::div( 'this is some content', '', 'float_left' );
131
+	 *  to add a both an id and a class use:    echo EEH_HTML::div( 'this is some content', 'footer', 'float_left' );
132
+	 *
133
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
134
+	 * @param string $id               - html id attribute
135
+	 * @param string $class            - html class attribute
136
+	 * @param string $style            - html style attribute for applying inline styles
137
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
138
+	 * @return string
139
+	 */
140
+	public static function div(
141
+		string $content = '',
142
+		string $id = '',
143
+		string $class = '',
144
+		string $style = '',
145
+		string $other_attributes = ''
146
+	): string {
147
+		return EEH_HTML::_open_tag('div', $content, $id, $class, $style, $other_attributes);
148
+	}
149
+
150
+
151
+	/**
152
+	 * Generates HTML closing </div> tag - if passed the id or class attribute used for the opening div tag, will
153
+	 * append a comment usage: echo EEH_HTML::divx();
154
+	 *
155
+	 * @param string $id    - html id attribute
156
+	 * @param string $class - html class attribute
157
+	 * @return string
158
+	 */
159
+	public static function divx(string $id = '', string $class = ''): string
160
+	{
161
+		return EEH_HTML::_close_tag('div', $id, $class);
162
+	}
163
+
164
+
165
+	/**
166
+	 * Generates HTML <h1></h1> tags, inserts content, and adds any passed attributes
167
+	 * usage: echo EEH_HTML::h1( 'This is a Heading' );
168
+	 *
169
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
170
+	 * @param string $id               - html id attribute
171
+	 * @param string $class            - html class attribute
172
+	 * @param string $style            - html style attribute for applying inline styles
173
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
174
+	 * @return string
175
+	 */
176
+	public static function h1(
177
+		string $content = '',
178
+		string $id = '',
179
+		string $class = '',
180
+		string $style = '',
181
+		string $other_attributes = ''
182
+	): string {
183
+		return EEH_HTML::_open_tag('h1', $content, $id, $class, $style, $other_attributes, true);
184
+	}
185
+
186
+
187
+	/**
188
+	 * Generates HTML <h2></h2> tags, inserts content, and adds any passed attributes
189
+	 * usage: echo EEH_HTML::h2( 'This is a Heading' );
190
+	 *
191
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
192
+	 * @param string $id               - html id attribute
193
+	 * @param string $class            - html class attribute
194
+	 * @param string $style            - html style attribute for applying inline styles
195
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
196
+	 * @return string
197
+	 */
198
+	public static function h2(
199
+		string $content = '',
200
+		string $id = '',
201
+		string $class = '',
202
+		string $style = '',
203
+		string $other_attributes = ''
204
+	): string {
205
+		return EEH_HTML::_open_tag('h2', $content, $id, $class, $style, $other_attributes, true);
206
+	}
207
+
208
+
209
+	/**
210
+	 * Generates HTML <h3></h3> tags, inserts content, and adds any passed attributes
211
+	 * usage: echo EEH_HTML::h3( 'This is a Heading' );
212
+	 *
213
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
214
+	 * @param string $id               - html id attribute
215
+	 * @param string $class            - html class attribute
216
+	 * @param string $style            - html style attribute for applying inline styles
217
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
218
+	 * @return string
219
+	 */
220
+	public static function h3(
221
+		string $content = '',
222
+		string $id = '',
223
+		string $class = '',
224
+		string $style = '',
225
+		string $other_attributes = ''
226
+	): string {
227
+		return EEH_HTML::_open_tag('h3', $content, $id, $class, $style, $other_attributes, true);
228
+	}
229
+
230
+
231
+	/**
232
+	 * Generates HTML <h4></h4> tags, inserts content, and adds any passed attributes
233
+	 * usage: echo EEH_HTML::h4( 'This is a Heading' );
234
+	 *
235
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
236
+	 * @param string $id               - html id attribute
237
+	 * @param string $class            - html class attribute
238
+	 * @param string $style            - html style attribute for applying inline styles
239
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
240
+	 * @return string
241
+	 */
242
+	public static function h4(
243
+		string $content = '',
244
+		string $id = '',
245
+		string $class = '',
246
+		string $style = '',
247
+		string $other_attributes = ''
248
+	): string {
249
+		return EEH_HTML::_open_tag('h4', $content, $id, $class, $style, $other_attributes, true);
250
+	}
251
+
252
+
253
+	/**
254
+	 * Generates HTML <h5></h5> tags, inserts content, and adds any passed attributes
255
+	 * usage: echo EEH_HTML::h5( 'This is a Heading' );
256
+	 *
257
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
258
+	 * @param string $id               - html id attribute
259
+	 * @param string $class            - html class attribute
260
+	 * @param string $style            - html style attribute for applying inline styles
261
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
262
+	 * @return string
263
+	 */
264
+	public static function h5(
265
+		string $content = '',
266
+		string $id = '',
267
+		string $class = '',
268
+		string $style = '',
269
+		string $other_attributes = ''
270
+	): string {
271
+		return EEH_HTML::_open_tag('h5', $content, $id, $class, $style, $other_attributes, true);
272
+	}
273
+
274
+
275
+	/**
276
+	 * Generates HTML <h6></h6> tags, inserts content, and adds any passed attributes
277
+	 * usage: echo EEH_HTML::h6( 'This is a Heading' );
278
+	 *
279
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
280
+	 * @param string $id               - html id attribute
281
+	 * @param string $class            - html class attribute
282
+	 * @param string $style            - html style attribute for applying inline styles
283
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
284
+	 * @return string
285
+	 */
286
+	public static function h6(
287
+		string $content = '',
288
+		string $id = '',
289
+		string $class = '',
290
+		string $style = '',
291
+		string $other_attributes = ''
292
+	): string {
293
+		return EEH_HTML::_open_tag('h6', $content, $id, $class, $style, $other_attributes, true);
294
+	}
295
+
296
+
297
+	/**
298
+	 * Generates HTML <p></p> tags, inserts content, and adds any passed attributes
299
+	 * usage: echo EEH_HTML::p( 'this is a paragraph' );
300
+	 *
301
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
302
+	 * @param string $id               - html id attribute
303
+	 * @param string $class            - html class attribute
304
+	 * @param string $style            - html style attribute for applying inline styles
305
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
306
+	 * @return string
307
+	 */
308
+	public static function p(
309
+		string $content = '',
310
+		string $id = '',
311
+		string $class = '',
312
+		string $style = '',
313
+		string $other_attributes = ''
314
+	): string {
315
+		return EEH_HTML::_open_tag('p', $content, $id, $class, $style, $other_attributes, true);
316
+	}
317
+
318
+
319
+	/**
320
+	 *  ul - generates HTML opening <ul> tag and adds any passed attributes
321
+	 *  usage:      echo EEH_HTML::ul( 'my-list-id', 'my-list-class' );
322
+	 *
323
+	 * @param string $id               - html id attribute
324
+	 * @param string $class            - html class attribute
325
+	 * @param string $style            - html style attribute for applying inline styles
326
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
327
+	 * @return string
328
+	 */
329
+	public static function ul(
330
+		string $id = '',
331
+		string $class = '',
332
+		string $style = '',
333
+		string $other_attributes = ''
334
+	): string {
335
+		return EEH_HTML::_open_tag('ul', '', $id, $class, $style, $other_attributes);
336
+	}
337
+
338
+
339
+	/**
340
+	 * Generates HTML closing </ul> tag - if passed the id or class attribute used for the opening ul tag, will append
341
+	 * a comment usage: echo EEH_HTML::ulx();
342
+	 *
343
+	 * @param string $id    - html id attribute
344
+	 * @param string $class - html class attribute
345
+	 * @return string
346
+	 */
347
+	public static function ulx(string $id = '', string $class = ''): string
348
+	{
349
+		return EEH_HTML::_close_tag('ul', $id, $class);
350
+	}
351
+
352
+
353
+	/**
354
+	 * Generates HTML <li> tag, inserts content, and adds any passed attributes
355
+	 * if passed content, it will also add that, as well as the closing </li> tag
356
+	 * usage: echo EEH_HTML::li( 'this is a line item' );
357
+	 *
358
+	 * @param string $id               - html id attribute
359
+	 * @param string $class            - html class attribute
360
+	 * @param string $style            - html style attribute for applying inline styles
361
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
362
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
363
+	 * @return string
364
+	 */
365
+	public static function li(
366
+		string $content = '',
367
+		string $id = '',
368
+		string $class = '',
369
+		string $style = '',
370
+		string $other_attributes = ''
371
+	): string {
372
+		return EEH_HTML::_open_tag('li', $content, $id, $class, $style, $other_attributes);
373
+	}
374
+
375
+
376
+	/**
377
+	 * Generates HTML closing </li> tag - if passed the id or class attribute used for the opening ul tag, will append
378
+	 * a comment usage: echo EEH_HTML::lix();
379
+	 *
380
+	 * @param string $id    - html id attribute
381
+	 * @param string $class - html class attribute
382
+	 * @return string
383
+	 */
384
+	public static function lix(string $id = '', string $class = ''): string
385
+	{
386
+		return EEH_HTML::_close_tag('li', $id, $class);
387
+	}
388
+
389
+
390
+	/**
391
+	 *    table - generates an HTML <table> tag and adds any passed attributes
392
+	 *    usage: echo EEH_HTML::table();
393
+	 *
394
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
395
+	 * @param string $id               - html id attribute
396
+	 * @param string $class            - html class attribute
397
+	 * @param string $style            - html style attribute for applying inline styles
398
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
399
+	 * @return string
400
+	 */
401
+	public static function table(
402
+		string $content = '',
403
+		string $id = '',
404
+		string $class = '',
405
+		string $style = '',
406
+		string $other_attributes = ''
407
+	): string {
408
+		return EEH_HTML::_open_tag('table', $content, $id, $class, $style, $other_attributes);
409
+	}
410
+
411
+
412
+	/**
413
+	 * tablex - generates an HTML </table> tag - if passed the id or class attribute used for the opening ul tag, will
414
+	 * append a comment
415
+	 *
416
+	 * @param string $id    - html id attribute
417
+	 * @param string $class - html class attribute
418
+	 * @return string
419
+	 */
420
+	public static function tablex(string $id = '', string $class = ''): string
421
+	{
422
+		return EEH_HTML::_close_tag('table', $id, $class);
423
+	}
424
+
425
+
426
+	/**
427
+	 *    thead - generates an HTML <thead> tag and adds any passed attributes
428
+	 *    usage: echo EEH_HTML::thead();
429
+	 *
430
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
431
+	 * @param string $id               - html id attribute
432
+	 * @param string $class            - html class attribute
433
+	 * @param string $style            - html style attribute for applying inline styles
434
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
435
+	 * @return string
436
+	 */
437
+	public static function thead(
438
+		string $content = '',
439
+		string $id = '',
440
+		string $class = '',
441
+		string $style = '',
442
+		string $other_attributes = ''
443
+	): string {
444
+		return EEH_HTML::_open_tag('thead', $content, $id, $class, $style, $other_attributes);
445
+	}
446
+
447
+
448
+	/**
449
+	 * theadx - generates an HTML </thead> tag - if passed the id or class attribute used for the opening ul tag, will
450
+	 * append a comment
451
+	 *
452
+	 * @param string $id    - html id attribute
453
+	 * @param string $class - html class attribute
454
+	 * @return string
455
+	 */
456
+	public static function theadx(string $id = '', string $class = ''): string
457
+	{
458
+		return EEH_HTML::_close_tag('thead', $id, $class);
459
+	}
460
+
461
+
462
+	/**
463
+	 *    tbody - generates an HTML <tbody> tag and adds any passed attributes
464
+	 *    usage: echo EEH_HTML::tbody();
465
+	 *
466
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
467
+	 * @param string $id               - html id attribute
468
+	 * @param string $class            - html class attribute
469
+	 * @param string $style            - html style attribute for applying inline styles
470
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
471
+	 * @return string
472
+	 */
473
+	public static function tbody(
474
+		string $content = '',
475
+		string $id = '',
476
+		string $class = '',
477
+		string $style = '',
478
+		string $other_attributes = ''
479
+	): string {
480
+		return EEH_HTML::_open_tag('tbody', $content, $id, $class, $style, $other_attributes);
481
+	}
482
+
483
+
484
+	/**
485
+	 * tbodyx - generates an HTML </tbody> tag - if passed the id or class attribute used for the opening ul tag, will
486
+	 * append a comment
487
+	 *
488
+	 * @param string $id    - html id attribute
489
+	 * @param string $class - html class attribute
490
+	 * @return string
491
+	 */
492
+	public static function tbodyx(string $id = '', string $class = ''): string
493
+	{
494
+		return EEH_HTML::_close_tag('tbody', $id, $class);
495
+	}
496
+
497
+
498
+	/**
499
+	 *    tr - generates an HTML <tr> tag and adds any passed attributes
500
+	 *    usage: echo EEH_HTML::tr();
501
+	 *
502
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
503
+	 * @param string $id               - html id attribute
504
+	 * @param string $class            - html class attribute
505
+	 * @param string $style            - html style attribute for applying inline styles
506
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
507
+	 * @return string
508
+	 */
509
+	public static function tr(
510
+		string $content = '',
511
+		string $id = '',
512
+		string $class = '',
513
+		string $style = '',
514
+		string $other_attributes = ''
515
+	): string {
516
+		return EEH_HTML::_open_tag('tr', $content, $id, $class, $style, $other_attributes);
517
+	}
518
+
519
+
520
+	/**
521
+	 * trx - generates an HTML </tr> tag - if passed the id or class attribute used for the opening ul tag, will append
522
+	 * a comment
523
+	 *
524
+	 * @param string $id    - html id attribute
525
+	 * @param string $class - html class attribute
526
+	 * @return string
527
+	 */
528
+	public static function trx(string $id = '', string $class = ''): string
529
+	{
530
+		return EEH_HTML::_close_tag('tr', $id, $class);
531
+	}
532
+
533
+
534
+	/**
535
+	 *    th - generates an HTML <th> tag and adds any passed attributes
536
+	 *    usage: echo EEH_HTML::th();
537
+	 *
538
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
539
+	 * @param string $id               - html id attribute
540
+	 * @param string $class            - html class attribute
541
+	 * @param string $style            - html style attribute for applying inline styles
542
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
543
+	 * @return string
544
+	 */
545
+	public static function th(
546
+		string $content = '',
547
+		string $id = '',
548
+		string $class = '',
549
+		string $style = '',
550
+		string $other_attributes = 'scope="col"'
551
+	): string {
552
+		return EEH_HTML::_open_tag('th', $content, $id, $class, $style, $other_attributes);
553
+	}
554
+
555
+
556
+	/**
557
+	 * thx - generates an HTML </th> tag - if passed the id or class attribute used for the opening ul tag, will append
558
+	 * a comment
559
+	 *
560
+	 * @param string $id    - html id attribute
561
+	 * @param string $class - html class attribute
562
+	 * @return string
563
+	 */
564
+	public static function thx(string $id = '', string $class = ''): string
565
+	{
566
+		return EEH_HTML::_close_tag('th', $id, $class);
567
+	}
568
+
569
+
570
+	/**
571
+	 *    td - generates an HTML <td> tag and adds any passed attributes
572
+	 *    usage: echo EEH_HTML::td();
573
+	 *
574
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
575
+	 * @param string $id               - html id attribute
576
+	 * @param string $class            - html class attribute
577
+	 * @param string $style            - html style attribute for applying inline styles
578
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
579
+	 * @return string
580
+	 */
581
+	public static function td(
582
+		string $content = '',
583
+		string $id = '',
584
+		string $class = '',
585
+		string $style = '',
586
+		string $other_attributes = ''
587
+	): string {
588
+		return EEH_HTML::_open_tag('td', $content, $id, $class, $style, $other_attributes);
589
+	}
590
+
591
+
592
+	/**
593
+	 * tdx - generates an HTML </td> tag - if passed the id or class attribute used for the opening ul tag, will append
594
+	 * a comment
595
+	 *
596
+	 * @param string $id    - html id attribute
597
+	 * @param string $class - html class attribute
598
+	 * @return string
599
+	 */
600
+	public static function tdx(string $id = '', string $class = ''): string
601
+	{
602
+		return EEH_HTML::_close_tag('td', $id, $class);
603
+	}
604
+
605
+
606
+	/**
607
+	 * no_row - for generating a "hidden" table row, good for embedding tables within tables
608
+	 * generates a new table row with one td cell that spans however many columns you set
609
+	 * removes all styles from the tr and td
610
+	 *
611
+	 * @param string $content
612
+	 * @param int    $colspan
613
+	 * @return string
614
+	 */
615
+	public static function no_row(string $content = '', int $colspan = 2): string
616
+	{
617
+		return EEH_HTML::tr(
618
+			EEH_HTML::td($content, '', '', '', 'colspan="' . $colspan . '"'),
619
+			'',
620
+			'ee-no-row'
621
+		);
622
+	}
623
+
624
+
625
+	/**
626
+	 * Generates HTML <a href="url">text</a> tags, inserts content, and adds any passed attributes
627
+	 * usage: echo EEH_HTML::link( 'domain.com', 'this is a link' );
628
+	 *
629
+	 * @param string $href             URL to link to
630
+	 * @param string $link_text        - the text that will become "hyperlinked"
631
+	 * @param string $title            - html title attribute
632
+	 * @param string $id               - html id attribute
633
+	 * @param string $class            - html class attribute
634
+	 * @param string $style            - html style attribute for applying inline styles
635
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
636
+	 * @return string
637
+	 */
638
+	public static function link(
639
+		string $href = '',
640
+		string $link_text = '',
641
+		string $title = '',
642
+		string $id = '',
643
+		string $class = '',
644
+		string $style = '',
645
+		string $other_attributes = ''
646
+	): string {
647
+		$link_text  = ! empty($link_text) ? $link_text : $href;
648
+		$attributes = ! empty($href) ? ' href="' . $href . '"' : '';
649
+		$attributes .= ! empty($id) ? ' id="' . EEH_HTML::sanitize_id($id) . '"' : '';
650
+		$attributes .= ! empty($class) ? ' class="' . $class . '"' : '';
651
+		$attributes .= ! empty($style) ? ' style="' . $style . '"' : '';
652
+		$attributes .= ! empty($title) ? ' title="' . esc_attr($title) . '"' : '';
653
+		$attributes .= ! empty($other_attributes) ? ' ' . $other_attributes : '';
654
+		return "<a$attributes>$link_text</a>";
655
+	}
656
+
657
+
658
+	/**
659
+	 * Generates HTML <button>text</button> tags, inserts content, and adds any passed attributes
660
+	 * usage: echo EEH_HTML::button( 'this is a button' );
661
+	 *
662
+	 * @param string $btn_text         - the text that will become "hyperlinked"
663
+	 * @param string $class            - html class attribute
664
+	 * @param string $aria_label       - aria-label attribute
665
+	 * @param string $id               - html id attribute
666
+	 * @param string $style            - html style attribute for applying inline styles
667
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
668
+	 * @return string
669
+	 */
670
+	public static function button(
671
+		string $btn_text = '',
672
+		string $class = '',
673
+		string $aria_label = '',
674
+		string $id = '',
675
+		string $style = '',
676
+		string $other_attributes = ''
677
+	): string {
678
+		$attributes = ! empty($aria_label) ? ' aria-label="' . $aria_label . '"' : '';
679
+		$attributes .= ! empty($id) ? ' id="' . EEH_HTML::sanitize_id($id) . '"' : '';
680
+		$attributes .= ! empty($class) ? ' class="' . $class . '"' : '';
681
+		$attributes .= ! empty($style) ? ' style="' . $style . '"' : '';
682
+		$attributes .= ! empty($other_attributes) ? ' ' . $other_attributes : '';
683
+		return "<button type='button' $attributes>$btn_text</button>";
684
+	}
685
+
686
+
687
+	/**
688
+	 *    img - generates an HTML <img> tag and adds any passed attributes
689
+	 *    usage: echo EEH_HTML::img();
690
+	 *
691
+	 * @param string $src              - html src attribute ie: the path or URL to the image
692
+	 * @param string $alt              - html alt attribute
693
+	 * @param string $id               - html id attribute
694
+	 * @param string $class            - html class attribute
695
+	 * @param string $style            - html style attribute for applying inline styles
696
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
697
+	 * @return string
698
+	 */
699
+	public static function img(
700
+		string $src = '',
701
+		string $alt = '',
702
+		string $id = '',
703
+		string $class = '',
704
+		string $style = '',
705
+		string $other_attributes = ''
706
+	): string {
707
+		$attributes = ! empty($src) ? ' src="' . esc_url_raw($src) . '"' : '';
708
+		$attributes .= ! empty($alt) ? ' alt="' . esc_attr($alt) . '"' : '';
709
+		$attributes .= ! empty($id) ? ' id="' . EEH_HTML::sanitize_id($id) . '"' : '';
710
+		$attributes .= ! empty($class) ? ' class="' . $class . '"' : '';
711
+		$attributes .= ! empty($style) ? ' style="' . $style . '"' : '';
712
+		$attributes .= ! empty($other_attributes) ? ' ' . $other_attributes : '';
713
+		return '<img' . $attributes . '/>';
714
+	}
715
+
716
+
717
+	/**
718
+	 * Generates HTML <tag></tag> tags, inserts content, and adds any passed attributes
719
+	 * usage: echo EEH_HTML::span( 'this is some inline text' );
720
+	 *
721
+	 * @param string $tag
722
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
723
+	 * @param string $id               - html id attribute
724
+	 * @param string $class            - html class attribute
725
+	 * @param string $style            - html style attribute for applying inline styles
726
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
727
+	 * @return string
728
+	 */
729
+	protected static function _inline_tag(
730
+		string $tag = 'span',
731
+		string $content = '',
732
+		string $id = '',
733
+		string $class = '',
734
+		string $style = '',
735
+		string $other_attributes = ''
736
+	): string {
737
+		$attributes = ! empty($id) ? ' id="' . EEH_HTML::sanitize_id($id) . '"' : '';
738
+		$attributes .= ! empty($class) ? ' class="' . $class . '"' : '';
739
+		$attributes .= ! empty($style) ? ' style="' . $style . '"' : '';
740
+		$attributes .= ! empty($other_attributes) ? ' ' . $other_attributes : '';
741
+		return '<' . $tag . ' ' . $attributes . '>' . $content . '</' . $tag . '>';
742
+	}
743
+
744
+
745
+	/**
746
+	 * Generates HTML <label></label> tags, inserts content, and adds any passed attributes
747
+	 * usage: echo EEH_HTML::span( 'this is some inline text' );
748
+	 *
749
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
750
+	 * @param string $id               - html id attribute
751
+	 * @param string $class            - html class attribute
752
+	 * @param string $style            - html style attribute for applying inline styles
753
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
754
+	 * @return string
755
+	 */
756
+	public static function label(
757
+		string $content = '',
758
+		string $id = '',
759
+		string $class = '',
760
+		string $style = '',
761
+		string $other_attributes = ''
762
+	): string {
763
+		return EEH_HTML::_inline_tag('label', $content, $id, $class, $style, $other_attributes);
764
+	}
765
+
766
+
767
+	/**
768
+	 * Generates HTML <span></span> tags, inserts content, and adds any passed attributes
769
+	 * usage: echo EEH_HTML::span( 'this is some inline text' );
770
+	 *
771
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
772
+	 * @param string $id               - html id attribute
773
+	 * @param string $class            - html class attribute
774
+	 * @param string $style            - html style attribute for applying inline styles
775
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
776
+	 * @return string
777
+	 */
778
+	public static function span(
779
+		string $content = '',
780
+		string $id = '',
781
+		string $class = '',
782
+		string $style = '',
783
+		string $other_attributes = ''
784
+	): string {
785
+		return EEH_HTML::_inline_tag('span', $content, $id, $class, $style, $other_attributes);
786
+	}
787
+
788
+
789
+	/**
790
+	 * Generates HTML <span></span> tags, inserts content, and adds any passed attributes
791
+	 * usage: echo EEH_HTML::span( 'this is some inline text' );
792
+	 *
793
+	 * @param string $content          - inserted after opening tag, and appends closing tag, otherwise tag is left open
794
+	 * @param string $id               - html id attribute
795
+	 * @param string $class            - html class attribute
796
+	 * @param string $style            - html style attribute for applying inline styles
797
+	 * @param string $other_attributes - additional attributes like "colspan", inline JS, "rel" tags, etc
798
+	 * @return string
799
+	 */
800
+	public static function strong(
801
+		string $content = '',
802
+		string $id = '',
803
+		string $class = '',
804
+		string $style = '',
805
+		string $other_attributes = ''
806
+	): string {
807
+		return EEH_HTML::_inline_tag('strong', $content, $id, $class, $style, $other_attributes);
808
+	}
809
+
810
+
811
+	/**
812
+	 * Generates an html <--  comment --> tag
813
+	 *  usage: echo comment( 'this is a comment' );
814
+	 *
815
+	 * @param string $comment
816
+	 * @return string
817
+	 */
818
+	public static function comment(string $comment = ''): string
819
+	{
820
+		return ! empty($comment) ? EEH_HTML::nl() . '<!-- ' . $comment . ' -->' : '';
821
+	}
822
+
823
+
824
+	/**
825
+	 * br - generates a line break
826
+	 *
827
+	 * @param int $number - the number of line breaks to return
828
+	 * @return string
829
+	 */
830
+	public static function br(int $number = 1): string
831
+	{
832
+		return str_repeat('<br />', $number);
833
+	}
834
+
835
+
836
+	/**
837
+	 * nbsp - generates non-breaking space entities based on number supplied
838
+	 *
839
+	 * @param int $number - the number of non-breaking spaces to return
840
+	 * @return string
841
+	 */
842
+	public static function nbsp(int $number = 1): string
843
+	{
844
+		return str_repeat('&nbsp;', $number);
845
+	}
846
+
847
+
848
+	/**
849
+	 * sanitize_id
850
+	 * functionally does the same as the wp_core function sanitize_key except it does NOT use
851
+	 * strtolower and allows capitals.
852
+	 *
853
+	 * @param string $id
854
+	 * @return string
855
+	 */
856
+	public static function sanitize_id(string $id = ''): string
857
+	{
858
+		$key = str_replace(' ', '-', trim($id));
859
+		return preg_replace('/[^a-zA-Z0-9_\-]/', '', $key);
860
+	}
861
+
862
+
863
+	/**
864
+	 * return a newline and tabs ("nl" stands for "new line")
865
+	 *
866
+	 * @param int    $indent the number of tabs to ADD to the current indent (can be negative or zero)
867
+	 * @param string $tag
868
+	 * @return string - newline character plus # of indents passed (can be + or -)
869
+	 */
870
+	public static function nl(int $indent = 0, string $tag = 'none'): string
871
+	{
872
+		$html = "\n";
873
+		EEH_HTML::indent($indent, $tag);
874
+		$html .= str_repeat("\t", EEH_HTML::$_indent[ $tag ]);
875
+		return $html;
876
+	}
877
+
878
+
879
+	/**
880
+	 * Changes the indents used in EEH_HTML::nl. Often it's convenient to change
881
+	 * the indentation level without actually creating a new line
882
+	 *
883
+	 * @param int    $indent can be negative to decrease the indentation level
884
+	 * @param string $tag
885
+	 */
886
+	public static function indent(int $indent, string $tag = 'none')
887
+	{
888
+		static $default_indentation = false;
889
+		if (! $default_indentation) {
890
+			EEH_HTML::_set_default_indentation();
891
+			$default_indentation = true;
892
+		}
893
+		if (! isset(EEH_HTML::$_indent[ $tag ])) {
894
+			EEH_HTML::$_indent[ $tag ] = 0;
895
+		}
896
+		EEH_HTML::$_indent[ $tag ] += $indent;
897
+		EEH_HTML::$_indent[ $tag ] = max(EEH_HTML::$_indent[ $tag ], 0);
898
+	}
899
+
900
+
901
+	/**
902
+	 *  class _set_default_indentation
903
+	 */
904
+	private static function _set_default_indentation()
905
+	{
906
+		// set some initial formatting for table indentation
907
+		EEH_HTML::$_indent = [
908
+			'none'     => 0,
909
+			'form'     => 0,
910
+			'radio'    => 0,
911
+			'checkbox' => 0,
912
+			'select'   => 0,
913
+			'option'   => 0,
914
+			'optgroup' => 0,
915
+			'table'    => 1,
916
+			'thead'    => 2,
917
+			'tbody'    => 2,
918
+			'tr'       => 3,
919
+			'th'       => 4,
920
+			'td'       => 4,
921
+			'div'      => 0,
922
+			'h1'       => 0,
923
+			'h2'       => 0,
924
+			'h3'       => 0,
925
+			'h4'       => 0,
926
+			'h5'       => 0,
927
+			'h6'       => 0,
928
+			'p'        => 0,
929
+			'ul'       => 0,
930
+			'li'       => 1,
931
+		];
932
+	}
933
+
934
+
935
+	/**
936
+	 * Retrieves the list of tags considered "simple", that are probably safe for
937
+	 * use in inputs
938
+	 *
939
+	 * @return array
940
+	 * @global array $allowedtags
941
+	 */
942
+	public static function get_simple_tags(): array
943
+	{
944
+		global $allowedtags;
945
+		$tags_we_allow = array_merge_recursive(
946
+			$allowedtags,
947
+			[
948
+				'ol' => [],
949
+				'ul' => [],
950
+				'li' => [],
951
+				'br' => [],
952
+				'p'  => [],
953
+				'a'  => ['target'],
954
+			]
955
+		);
956
+		return apply_filters('FHEE__EEH_HTML__get_simple_tags', $tags_we_allow);
957
+	}
958 958
 }
Please login to merge, or discard this patch.
Spacing   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -49,7 +49,7 @@  discard block
 block discarded – undo
49 49
     public static function instance(): EEH_HTML
50 50
     {
51 51
         // check if class object is instantiated, and instantiated properly
52
-        if (! self::$_instance instanceof EEH_HTML) {
52
+        if ( ! self::$_instance instanceof EEH_HTML) {
53 53
             self::$_instance = new EEH_HTML();
54 54
         }
55 55
         return self::$_instance;
@@ -78,12 +78,12 @@  discard block
 block discarded – undo
78 78
         string $other_attributes = '',
79 79
         bool $force_close = false
80 80
     ): string {
81
-        $attributes = ! empty($id) ? ' id="' . EEH_HTML::sanitize_id($id) . '"' : '';
82
-        $attributes .= ! empty($class) ? ' class="' . $class . '"' : '';
83
-        $attributes .= ! empty($style) ? ' style="' . $style . '"' : '';
84
-        $attributes .= ! empty($other_attributes) ? ' ' . $other_attributes : '';
85
-        $html       = EEH_HTML::nl(0, $tag) . '<' . $tag . $attributes . '>';
86
-        $html       .= trim($content) !== '' ? EEH_HTML::nl(1, $tag) . $content : '';
81
+        $attributes = ! empty($id) ? ' id="'.EEH_HTML::sanitize_id($id).'"' : '';
82
+        $attributes .= ! empty($class) ? ' class="'.$class.'"' : '';
83
+        $attributes .= ! empty($style) ? ' style="'.$style.'"' : '';
84
+        $attributes .= ! empty($other_attributes) ? ' '.$other_attributes : '';
85
+        $html       = EEH_HTML::nl(0, $tag).'<'.$tag.$attributes.'>';
86
+        $html       .= trim($content) !== '' ? EEH_HTML::nl(1, $tag).$content : '';
87 87
         $indent     = ! empty($content) || $force_close;
88 88
         $html       .= ! empty($content) || $force_close
89 89
             ? EEH_HTML::_close_tag($tag, $id, $class, $indent, $content)
@@ -112,14 +112,14 @@  discard block
 block discarded – undo
112 112
         string $content = ''
113 113
     ): string {
114 114
         $alotta_content = strlen($content) > 500;
115
-        $comment         = '';
115
+        $comment = '';
116 116
         if ($id && $alotta_content) {
117
-            $comment = EEH_HTML::comment('close ' . $id) . EEH_HTML::nl(0, $tag);
117
+            $comment = EEH_HTML::comment('close '.$id).EEH_HTML::nl(0, $tag);
118 118
         } elseif ($class && $alotta_content) {
119
-            $comment = EEH_HTML::comment('close ' . $class) . EEH_HTML::nl(0, $tag);
119
+            $comment = EEH_HTML::comment('close '.$class).EEH_HTML::nl(0, $tag);
120 120
         }
121 121
         $html = $indent ? EEH_HTML::nl(-1, $tag) : '';
122
-        $html .= '</' . $tag . '>' . $comment;
122
+        $html .= '</'.$tag.'>'.$comment;
123 123
         return $html;
124 124
     }
125 125
 
@@ -615,7 +615,7 @@  discard block
 block discarded – undo
615 615
     public static function no_row(string $content = '', int $colspan = 2): string
616 616
     {
617 617
         return EEH_HTML::tr(
618
-            EEH_HTML::td($content, '', '', '', 'colspan="' . $colspan . '"'),
618
+            EEH_HTML::td($content, '', '', '', 'colspan="'.$colspan.'"'),
619 619
             '',
620 620
             'ee-no-row'
621 621
         );
@@ -645,12 +645,12 @@  discard block
 block discarded – undo
645 645
         string $other_attributes = ''
646 646
     ): string {
647 647
         $link_text  = ! empty($link_text) ? $link_text : $href;
648
-        $attributes = ! empty($href) ? ' href="' . $href . '"' : '';
649
-        $attributes .= ! empty($id) ? ' id="' . EEH_HTML::sanitize_id($id) . '"' : '';
650
-        $attributes .= ! empty($class) ? ' class="' . $class . '"' : '';
651
-        $attributes .= ! empty($style) ? ' style="' . $style . '"' : '';
652
-        $attributes .= ! empty($title) ? ' title="' . esc_attr($title) . '"' : '';
653
-        $attributes .= ! empty($other_attributes) ? ' ' . $other_attributes : '';
648
+        $attributes = ! empty($href) ? ' href="'.$href.'"' : '';
649
+        $attributes .= ! empty($id) ? ' id="'.EEH_HTML::sanitize_id($id).'"' : '';
650
+        $attributes .= ! empty($class) ? ' class="'.$class.'"' : '';
651
+        $attributes .= ! empty($style) ? ' style="'.$style.'"' : '';
652
+        $attributes .= ! empty($title) ? ' title="'.esc_attr($title).'"' : '';
653
+        $attributes .= ! empty($other_attributes) ? ' '.$other_attributes : '';
654 654
         return "<a$attributes>$link_text</a>";
655 655
     }
656 656
 
@@ -675,11 +675,11 @@  discard block
 block discarded – undo
675 675
         string $style = '',
676 676
         string $other_attributes = ''
677 677
     ): string {
678
-        $attributes = ! empty($aria_label) ? ' aria-label="' . $aria_label . '"' : '';
679
-        $attributes .= ! empty($id) ? ' id="' . EEH_HTML::sanitize_id($id) . '"' : '';
680
-        $attributes .= ! empty($class) ? ' class="' . $class . '"' : '';
681
-        $attributes .= ! empty($style) ? ' style="' . $style . '"' : '';
682
-        $attributes .= ! empty($other_attributes) ? ' ' . $other_attributes : '';
678
+        $attributes = ! empty($aria_label) ? ' aria-label="'.$aria_label.'"' : '';
679
+        $attributes .= ! empty($id) ? ' id="'.EEH_HTML::sanitize_id($id).'"' : '';
680
+        $attributes .= ! empty($class) ? ' class="'.$class.'"' : '';
681
+        $attributes .= ! empty($style) ? ' style="'.$style.'"' : '';
682
+        $attributes .= ! empty($other_attributes) ? ' '.$other_attributes : '';
683 683
         return "<button type='button' $attributes>$btn_text</button>";
684 684
     }
685 685
 
@@ -704,13 +704,13 @@  discard block
 block discarded – undo
704 704
         string $style = '',
705 705
         string $other_attributes = ''
706 706
     ): string {
707
-        $attributes = ! empty($src) ? ' src="' . esc_url_raw($src) . '"' : '';
708
-        $attributes .= ! empty($alt) ? ' alt="' . esc_attr($alt) . '"' : '';
709
-        $attributes .= ! empty($id) ? ' id="' . EEH_HTML::sanitize_id($id) . '"' : '';
710
-        $attributes .= ! empty($class) ? ' class="' . $class . '"' : '';
711
-        $attributes .= ! empty($style) ? ' style="' . $style . '"' : '';
712
-        $attributes .= ! empty($other_attributes) ? ' ' . $other_attributes : '';
713
-        return '<img' . $attributes . '/>';
707
+        $attributes = ! empty($src) ? ' src="'.esc_url_raw($src).'"' : '';
708
+        $attributes .= ! empty($alt) ? ' alt="'.esc_attr($alt).'"' : '';
709
+        $attributes .= ! empty($id) ? ' id="'.EEH_HTML::sanitize_id($id).'"' : '';
710
+        $attributes .= ! empty($class) ? ' class="'.$class.'"' : '';
711
+        $attributes .= ! empty($style) ? ' style="'.$style.'"' : '';
712
+        $attributes .= ! empty($other_attributes) ? ' '.$other_attributes : '';
713
+        return '<img'.$attributes.'/>';
714 714
     }
715 715
 
716 716
 
@@ -734,11 +734,11 @@  discard block
 block discarded – undo
734 734
         string $style = '',
735 735
         string $other_attributes = ''
736 736
     ): string {
737
-        $attributes = ! empty($id) ? ' id="' . EEH_HTML::sanitize_id($id) . '"' : '';
738
-        $attributes .= ! empty($class) ? ' class="' . $class . '"' : '';
739
-        $attributes .= ! empty($style) ? ' style="' . $style . '"' : '';
740
-        $attributes .= ! empty($other_attributes) ? ' ' . $other_attributes : '';
741
-        return '<' . $tag . ' ' . $attributes . '>' . $content . '</' . $tag . '>';
737
+        $attributes = ! empty($id) ? ' id="'.EEH_HTML::sanitize_id($id).'"' : '';
738
+        $attributes .= ! empty($class) ? ' class="'.$class.'"' : '';
739
+        $attributes .= ! empty($style) ? ' style="'.$style.'"' : '';
740
+        $attributes .= ! empty($other_attributes) ? ' '.$other_attributes : '';
741
+        return '<'.$tag.' '.$attributes.'>'.$content.'</'.$tag.'>';
742 742
     }
743 743
 
744 744
 
@@ -817,7 +817,7 @@  discard block
 block discarded – undo
817 817
      */
818 818
     public static function comment(string $comment = ''): string
819 819
     {
820
-        return ! empty($comment) ? EEH_HTML::nl() . '<!-- ' . $comment . ' -->' : '';
820
+        return ! empty($comment) ? EEH_HTML::nl().'<!-- '.$comment.' -->' : '';
821 821
     }
822 822
 
823 823
 
@@ -871,7 +871,7 @@  discard block
 block discarded – undo
871 871
     {
872 872
         $html = "\n";
873 873
         EEH_HTML::indent($indent, $tag);
874
-        $html .= str_repeat("\t", EEH_HTML::$_indent[ $tag ]);
874
+        $html .= str_repeat("\t", EEH_HTML::$_indent[$tag]);
875 875
         return $html;
876 876
     }
877 877
 
@@ -886,15 +886,15 @@  discard block
 block discarded – undo
886 886
     public static function indent(int $indent, string $tag = 'none')
887 887
     {
888 888
         static $default_indentation = false;
889
-        if (! $default_indentation) {
889
+        if ( ! $default_indentation) {
890 890
             EEH_HTML::_set_default_indentation();
891 891
             $default_indentation = true;
892 892
         }
893
-        if (! isset(EEH_HTML::$_indent[ $tag ])) {
894
-            EEH_HTML::$_indent[ $tag ] = 0;
893
+        if ( ! isset(EEH_HTML::$_indent[$tag])) {
894
+            EEH_HTML::$_indent[$tag] = 0;
895 895
         }
896
-        EEH_HTML::$_indent[ $tag ] += $indent;
897
-        EEH_HTML::$_indent[ $tag ] = max(EEH_HTML::$_indent[ $tag ], 0);
896
+        EEH_HTML::$_indent[$tag] += $indent;
897
+        EEH_HTML::$_indent[$tag] = max(EEH_HTML::$_indent[$tag], 0);
898 898
     }
899 899
 
900 900
 
Please login to merge, or discard this patch.
core/EE_Cart.core.php 2 patches
Indentation   +411 added lines, -411 removed lines patch added patch discarded remove patch
@@ -17,415 +17,415 @@
 block discarded – undo
17 17
  */
18 18
 class EE_Cart implements ResettableInterface
19 19
 {
20
-    private static ?EE_Cart $_instance = null;
21
-
22
-    protected ?EE_Session $session = null;
23
-
24
-    /**
25
-     * The total Line item which comprises all the children line-item subtotals,
26
-     * which in turn each have their line items.
27
-     * Typically, the line item structure will look like:
28
-     * grand total
29
-     * -tickets-sub-total
30
-     * --ticket1
31
-     * --ticket2
32
-     * --...
33
-     * -taxes-sub-total
34
-     * --tax1
35
-     * --tax2
36
-     *
37
-     * If cart is serialized, this will be an ID of the line item
38
-     *
39
-     * @var EE_Line_Item|null
40
-     */
41
-    private ?EE_Line_Item $grand_total = null;
42
-
43
-    private int $grand_total_ID = 0;
44
-
45
-
46
-    /**
47
-     * singleton method used to instantiate class object
48
-     *
49
-     * @param EE_Line_Item|null $grand_total
50
-     * @param EE_Session|null   $session
51
-     * @return EE_Cart
52
-     * @throws EE_Error
53
-     * @throws ReflectionException
54
-     */
55
-    public static function instance(?EE_Line_Item $grand_total = null, ?EE_Session $session = null): ?EE_Cart
56
-    {
57
-        if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) {
58
-            self::$_instance = new self($grand_total, $session);
59
-        }
60
-        // or maybe retrieve an existing one ?
61
-        if (! self::$_instance instanceof EE_Cart) {
62
-            // try getting the cart out of the session
63
-            $saved_cart      = $session instanceof EE_Session ? $session->cart() : null;
64
-            self::$_instance = $saved_cart instanceof EE_Cart ? $saved_cart : new self($grand_total, $session);
65
-            unset($saved_cart);
66
-        }
67
-        // verify that cart is ok and grand total line item exists
68
-        if (! self::$_instance instanceof EE_Cart || ! self::$_instance->grand_total instanceof EE_Line_Item) {
69
-            self::$_instance = new self($grand_total, $session);
70
-        }
71
-        self::$_instance->get_grand_total();
72
-        // once everything is all said and done, save the cart to the EE_Session
73
-        add_action('shutdown', [self::$_instance, 'save_cart'], 90);
74
-        return self::$_instance;
75
-    }
76
-
77
-
78
-    /**
79
-     * private constructor to prevent direct creation
80
-     *
81
-     * @param EE_Line_Item|null $grand_total
82
-     * @param EE_Session|null   $session
83
-     * @throws EE_Error
84
-     * @throws ReflectionException
85
-     */
86
-    private function __construct(?EE_Line_Item $grand_total = null, ?EE_Session $session = null)
87
-    {
88
-        $this->set_session($session);
89
-        if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) {
90
-            $this->set_grand_total_line_item($grand_total);
91
-        }
92
-    }
93
-
94
-
95
-    /**
96
-     * Resets the cart completely (whereas empty_cart
97
-     *
98
-     * @param EE_Line_Item|null $grand_total
99
-     * @param EE_Session|null   $session
100
-     * @return EE_Cart
101
-     * @throws EE_Error
102
-     * @throws ReflectionException
103
-     */
104
-    public static function reset(?EE_Line_Item $grand_total = null, ?EE_Session $session = null): ?EE_Cart
105
-    {
106
-        remove_action('shutdown', [self::$_instance, 'save_cart'], 90);
107
-        if ($session instanceof EE_Session) {
108
-            $session->reset_cart();
109
-        }
110
-        self::$_instance = null;
111
-        return self::instance($grand_total, $session);
112
-    }
113
-
114
-
115
-    /**
116
-     * @return EE_Session
117
-     * @throws EE_Error
118
-     * @throws ReflectionException
119
-     */
120
-    public function session(): EE_Session
121
-    {
122
-        if (! $this->session instanceof EE_Session) {
123
-            $this->set_session();
124
-        }
125
-        return $this->session;
126
-    }
127
-
128
-
129
-    /**
130
-     * @param EE_Session|null $session
131
-     * @throws EE_Error
132
-     * @throws ReflectionException
133
-     */
134
-    public function set_session(?EE_Session $session = null)
135
-    {
136
-        $this->session = $session instanceof EE_Session ? $session : EE_Registry::instance()->load_core('Session');
137
-    }
138
-
139
-
140
-    /**
141
-     * Sets the cart to match the line item. Especially handy for loading an old cart where you
142
-     *  know the grand total line item on it
143
-     *
144
-     * @param EE_Line_Item $line_item
145
-     * @throws EE_Error
146
-     * @throws ReflectionException
147
-     */
148
-    public function set_grand_total_line_item(EE_Line_Item $line_item)
149
-    {
150
-        $this->grand_total    = $line_item;
151
-        $this->grand_total_ID = $line_item->ID();
152
-    }
153
-
154
-
155
-    /**
156
-     * get_cart_from_reg_url_link
157
-     *
158
-     * @param EE_Transaction  $transaction
159
-     * @param EE_Session|null $session
160
-     * @return EE_Cart
161
-     * @throws EE_Error
162
-     * @throws ReflectionException
163
-     */
164
-    public static function get_cart_from_txn(EE_Transaction $transaction, ?EE_Session $session = null): EE_Cart
165
-    {
166
-        $grand_total = $transaction->total_line_item();
167
-        $grand_total->get_items();
168
-        $grand_total->tax_descendants();
169
-        return EE_Cart::instance($grand_total, $session);
170
-    }
171
-
172
-
173
-    /**
174
-     * Creates the total line item, and ensures it has its 'tickets' and 'taxes' sub-items
175
-     *
176
-     * @return EE_Line_Item
177
-     * @throws EE_Error
178
-     * @throws ReflectionException
179
-     */
180
-    private function create_grand_total(): EE_Line_Item
181
-    {
182
-        $this->grand_total = EEH_Line_Item::create_total_line_item();
183
-        return $this->grand_total;
184
-    }
185
-
186
-
187
-    /**
188
-     * Gets all the line items of object type Ticket
189
-     *
190
-     * @return EE_Line_Item[]
191
-     * @throws EE_Error
192
-     * @throws ReflectionException
193
-     */
194
-    public function get_tickets(): array
195
-    {
196
-        if ($this->grand_total === null) {
197
-            return [];
198
-        }
199
-        return EEH_Line_Item::get_ticket_line_items($this->grand_total);
200
-    }
201
-
202
-
203
-    /**
204
-     * returns the total quantity of tickets in the cart
205
-     *
206
-     * @return int
207
-     * @throws EE_Error
208
-     * @throws ReflectionException
209
-     */
210
-    public function all_ticket_quantity_count(): int
211
-    {
212
-        $tickets = $this->get_tickets();
213
-        if (empty($tickets)) {
214
-            return 0;
215
-        }
216
-        $count = 0;
217
-        foreach ($tickets as $ticket) {
218
-            $count += $ticket->quantity();
219
-        }
220
-        return $count;
221
-    }
222
-
223
-
224
-    /**
225
-     * Gets all the tax line items
226
-     *
227
-     * @return EE_Line_Item[]
228
-     * @throws EE_Error
229
-     * @throws ReflectionException
230
-     */
231
-    public function get_taxes(): array
232
-    {
233
-        return EEH_Line_Item::get_taxes_subtotal($this->grand_total)->children();
234
-    }
235
-
236
-
237
-    /**
238
-     * Gets the total line item (which is a parent of all other line items) on this cart
239
-     *
240
-     * @return EE_Line_Item
241
-     * @throws EE_Error
242
-     * @throws ReflectionException
243
-     */
244
-    public function get_grand_total(): EE_Line_Item
245
-    {
246
-        if ($this->grand_total instanceof EE_Line_Item) {
247
-            return $this->grand_total;
248
-        }
249
-        // $this->grand_total_ID is set, use it to get the object from the db
250
-        if ($this->grand_total_ID !== 0) {
251
-            $this->grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->grand_total_ID);
252
-            return $this->grand_total;
253
-        }
254
-        return $this->create_grand_total();
255
-    }
256
-
257
-
258
-    /**
259
-     * process items for adding to cart
260
-     *
261
-     * @param EE_Ticket $ticket
262
-     * @param int       $qty
263
-     * @return bool TRUE on success, FALSE on fail
264
-     * @throws EE_Error
265
-     * @throws ReflectionException
266
-     */
267
-    public function add_ticket_to_cart(EE_Ticket $ticket, int $qty = 1): bool
268
-    {
269
-        EEH_Line_Item::add_ticket_purchase($this->get_grand_total(), $ticket, $qty, false);
270
-        return $this->save_cart();
271
-    }
272
-
273
-
274
-    /**
275
-     * get_cart_total_before_tax
276
-     *
277
-     * @return float
278
-     * @throws EE_Error
279
-     * @throws ReflectionException
280
-     */
281
-    public function get_cart_total_before_tax(): float
282
-    {
283
-        return $this->get_grand_total()->recalculate_pre_tax_total();
284
-    }
285
-
286
-
287
-    /**
288
-     * gets the total amount of tax paid for items in this cart
289
-     *
290
-     * @return float
291
-     * @throws EE_Error
292
-     * @throws ReflectionException
293
-     */
294
-    public function get_applied_taxes(): float
295
-    {
296
-        return EEH_Line_Item::ensure_taxes_applied($this->grand_total);
297
-    }
298
-
299
-
300
-    /**
301
-     * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
302
-     *
303
-     * @return float
304
-     * @throws EE_Error
305
-     * @throws ReflectionException
306
-     */
307
-    public function get_cart_grand_total(): float
308
-    {
309
-        EEH_Line_Item::ensure_taxes_applied($this->grand_total);
310
-        return $this->get_grand_total()->total();
311
-    }
312
-
313
-
314
-    /**
315
-     * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
316
-     *
317
-     * @return float
318
-     * @throws EE_Error
319
-     * @throws ReflectionException
320
-     */
321
-    public function recalculate_all_cart_totals(): float
322
-    {
323
-        $pre_tax_total = $this->get_cart_total_before_tax();
324
-        $taxes_total   = EEH_Line_Item::ensure_taxes_applied($this->grand_total);
325
-        $this->grand_total->set_total($pre_tax_total + $taxes_total);
326
-        $this->grand_total->save_this_and_descendants_to_txn();
327
-        return $this->get_grand_total()->total();
328
-    }
329
-
330
-
331
-    /**
332
-     * deletes an item from the cart
333
-     *
334
-     * @param array|bool|string $line_item_codes
335
-     * @return int on success, FALSE on fail
336
-     * @throws EE_Error
337
-     * @throws ReflectionException
338
-     */
339
-    public function delete_items($line_item_codes = false): int
340
-    {
341
-        return (int) EEH_Line_Item::delete_items($this->get_grand_total(), $line_item_codes);
342
-    }
343
-
344
-
345
-    /**
346
-     * @remove ALL items from cart and zero ALL totals
347
-     * @return bool
348
-     * @throws EE_Error
349
-     * @throws ReflectionException
350
-     */
351
-    public function empty_cart(): bool
352
-    {
353
-        $this->grand_total = $this->create_grand_total();
354
-        return $this->save_cart();
355
-    }
356
-
357
-
358
-    /**
359
-     * remove ALL items from cart and delete total as well
360
-     *
361
-     * @return bool
362
-     * @throws EE_Error
363
-     * @throws ReflectionException
364
-     */
365
-    public function delete_cart(): bool
366
-    {
367
-        if ($this->grand_total instanceof EE_Line_Item) {
368
-            $deleted = EEH_Line_Item::delete_all_child_items($this->grand_total);
369
-            if ($deleted) {
370
-                $this->grand_total->delete();
371
-                $this->grand_total = null;
372
-                return true;
373
-            }
374
-        }
375
-        return false;
376
-    }
377
-
378
-
379
-    /**
380
-     * save   cart to session
381
-     *
382
-     * @param bool $apply_taxes
383
-     * @return bool TRUE on success, FALSE on fail
384
-     * @throws EE_Error
385
-     * @throws ReflectionException
386
-     */
387
-    public function save_cart(bool $apply_taxes = true): bool
388
-    {
389
-        if ($apply_taxes && $this->grand_total instanceof EE_Line_Item) {
390
-            EEH_Line_Item::ensure_taxes_applied($this->grand_total);
391
-            // make sure we don't cache the transaction because it can get stale
392
-            if (
393
-                $this->grand_total->get_one_from_cache('Transaction') instanceof EE_Transaction
394
-                && $this->grand_total->get_one_from_cache('Transaction')->ID()
395
-            ) {
396
-                $this->grand_total->clear_cache('Transaction', null, true);
397
-            }
398
-        }
399
-        if ($this->session() instanceof EE_Session) {
400
-            return $this->session()->set_cart($this);
401
-        }
402
-        return false;
403
-    }
404
-
405
-
406
-    /**
407
-     * @throws EE_Error
408
-     * @throws ReflectionException
409
-     */
410
-    public function __wakeup()
411
-    {
412
-        if (! $this->grand_total instanceof EE_Line_Item && $this->grand_total_ID !== 0) {
413
-            // $this->_grand_total is actually just an ID, so use it to get the object from the db
414
-            $this->grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->grand_total_ID);
415
-        }
416
-    }
417
-
418
-
419
-    /**
420
-     * @return array
421
-     * @throws EE_Error
422
-     * @throws ReflectionException
423
-     */
424
-    public function __sleep()
425
-    {
426
-        if ($this->grand_total instanceof EE_Line_Item && $this->grand_total->ID()) {
427
-            $this->grand_total_ID = $this->grand_total->ID();
428
-        }
429
-        return ['grand_total_ID'];
430
-    }
20
+	private static ?EE_Cart $_instance = null;
21
+
22
+	protected ?EE_Session $session = null;
23
+
24
+	/**
25
+	 * The total Line item which comprises all the children line-item subtotals,
26
+	 * which in turn each have their line items.
27
+	 * Typically, the line item structure will look like:
28
+	 * grand total
29
+	 * -tickets-sub-total
30
+	 * --ticket1
31
+	 * --ticket2
32
+	 * --...
33
+	 * -taxes-sub-total
34
+	 * --tax1
35
+	 * --tax2
36
+	 *
37
+	 * If cart is serialized, this will be an ID of the line item
38
+	 *
39
+	 * @var EE_Line_Item|null
40
+	 */
41
+	private ?EE_Line_Item $grand_total = null;
42
+
43
+	private int $grand_total_ID = 0;
44
+
45
+
46
+	/**
47
+	 * singleton method used to instantiate class object
48
+	 *
49
+	 * @param EE_Line_Item|null $grand_total
50
+	 * @param EE_Session|null   $session
51
+	 * @return EE_Cart
52
+	 * @throws EE_Error
53
+	 * @throws ReflectionException
54
+	 */
55
+	public static function instance(?EE_Line_Item $grand_total = null, ?EE_Session $session = null): ?EE_Cart
56
+	{
57
+		if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) {
58
+			self::$_instance = new self($grand_total, $session);
59
+		}
60
+		// or maybe retrieve an existing one ?
61
+		if (! self::$_instance instanceof EE_Cart) {
62
+			// try getting the cart out of the session
63
+			$saved_cart      = $session instanceof EE_Session ? $session->cart() : null;
64
+			self::$_instance = $saved_cart instanceof EE_Cart ? $saved_cart : new self($grand_total, $session);
65
+			unset($saved_cart);
66
+		}
67
+		// verify that cart is ok and grand total line item exists
68
+		if (! self::$_instance instanceof EE_Cart || ! self::$_instance->grand_total instanceof EE_Line_Item) {
69
+			self::$_instance = new self($grand_total, $session);
70
+		}
71
+		self::$_instance->get_grand_total();
72
+		// once everything is all said and done, save the cart to the EE_Session
73
+		add_action('shutdown', [self::$_instance, 'save_cart'], 90);
74
+		return self::$_instance;
75
+	}
76
+
77
+
78
+	/**
79
+	 * private constructor to prevent direct creation
80
+	 *
81
+	 * @param EE_Line_Item|null $grand_total
82
+	 * @param EE_Session|null   $session
83
+	 * @throws EE_Error
84
+	 * @throws ReflectionException
85
+	 */
86
+	private function __construct(?EE_Line_Item $grand_total = null, ?EE_Session $session = null)
87
+	{
88
+		$this->set_session($session);
89
+		if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) {
90
+			$this->set_grand_total_line_item($grand_total);
91
+		}
92
+	}
93
+
94
+
95
+	/**
96
+	 * Resets the cart completely (whereas empty_cart
97
+	 *
98
+	 * @param EE_Line_Item|null $grand_total
99
+	 * @param EE_Session|null   $session
100
+	 * @return EE_Cart
101
+	 * @throws EE_Error
102
+	 * @throws ReflectionException
103
+	 */
104
+	public static function reset(?EE_Line_Item $grand_total = null, ?EE_Session $session = null): ?EE_Cart
105
+	{
106
+		remove_action('shutdown', [self::$_instance, 'save_cart'], 90);
107
+		if ($session instanceof EE_Session) {
108
+			$session->reset_cart();
109
+		}
110
+		self::$_instance = null;
111
+		return self::instance($grand_total, $session);
112
+	}
113
+
114
+
115
+	/**
116
+	 * @return EE_Session
117
+	 * @throws EE_Error
118
+	 * @throws ReflectionException
119
+	 */
120
+	public function session(): EE_Session
121
+	{
122
+		if (! $this->session instanceof EE_Session) {
123
+			$this->set_session();
124
+		}
125
+		return $this->session;
126
+	}
127
+
128
+
129
+	/**
130
+	 * @param EE_Session|null $session
131
+	 * @throws EE_Error
132
+	 * @throws ReflectionException
133
+	 */
134
+	public function set_session(?EE_Session $session = null)
135
+	{
136
+		$this->session = $session instanceof EE_Session ? $session : EE_Registry::instance()->load_core('Session');
137
+	}
138
+
139
+
140
+	/**
141
+	 * Sets the cart to match the line item. Especially handy for loading an old cart where you
142
+	 *  know the grand total line item on it
143
+	 *
144
+	 * @param EE_Line_Item $line_item
145
+	 * @throws EE_Error
146
+	 * @throws ReflectionException
147
+	 */
148
+	public function set_grand_total_line_item(EE_Line_Item $line_item)
149
+	{
150
+		$this->grand_total    = $line_item;
151
+		$this->grand_total_ID = $line_item->ID();
152
+	}
153
+
154
+
155
+	/**
156
+	 * get_cart_from_reg_url_link
157
+	 *
158
+	 * @param EE_Transaction  $transaction
159
+	 * @param EE_Session|null $session
160
+	 * @return EE_Cart
161
+	 * @throws EE_Error
162
+	 * @throws ReflectionException
163
+	 */
164
+	public static function get_cart_from_txn(EE_Transaction $transaction, ?EE_Session $session = null): EE_Cart
165
+	{
166
+		$grand_total = $transaction->total_line_item();
167
+		$grand_total->get_items();
168
+		$grand_total->tax_descendants();
169
+		return EE_Cart::instance($grand_total, $session);
170
+	}
171
+
172
+
173
+	/**
174
+	 * Creates the total line item, and ensures it has its 'tickets' and 'taxes' sub-items
175
+	 *
176
+	 * @return EE_Line_Item
177
+	 * @throws EE_Error
178
+	 * @throws ReflectionException
179
+	 */
180
+	private function create_grand_total(): EE_Line_Item
181
+	{
182
+		$this->grand_total = EEH_Line_Item::create_total_line_item();
183
+		return $this->grand_total;
184
+	}
185
+
186
+
187
+	/**
188
+	 * Gets all the line items of object type Ticket
189
+	 *
190
+	 * @return EE_Line_Item[]
191
+	 * @throws EE_Error
192
+	 * @throws ReflectionException
193
+	 */
194
+	public function get_tickets(): array
195
+	{
196
+		if ($this->grand_total === null) {
197
+			return [];
198
+		}
199
+		return EEH_Line_Item::get_ticket_line_items($this->grand_total);
200
+	}
201
+
202
+
203
+	/**
204
+	 * returns the total quantity of tickets in the cart
205
+	 *
206
+	 * @return int
207
+	 * @throws EE_Error
208
+	 * @throws ReflectionException
209
+	 */
210
+	public function all_ticket_quantity_count(): int
211
+	{
212
+		$tickets = $this->get_tickets();
213
+		if (empty($tickets)) {
214
+			return 0;
215
+		}
216
+		$count = 0;
217
+		foreach ($tickets as $ticket) {
218
+			$count += $ticket->quantity();
219
+		}
220
+		return $count;
221
+	}
222
+
223
+
224
+	/**
225
+	 * Gets all the tax line items
226
+	 *
227
+	 * @return EE_Line_Item[]
228
+	 * @throws EE_Error
229
+	 * @throws ReflectionException
230
+	 */
231
+	public function get_taxes(): array
232
+	{
233
+		return EEH_Line_Item::get_taxes_subtotal($this->grand_total)->children();
234
+	}
235
+
236
+
237
+	/**
238
+	 * Gets the total line item (which is a parent of all other line items) on this cart
239
+	 *
240
+	 * @return EE_Line_Item
241
+	 * @throws EE_Error
242
+	 * @throws ReflectionException
243
+	 */
244
+	public function get_grand_total(): EE_Line_Item
245
+	{
246
+		if ($this->grand_total instanceof EE_Line_Item) {
247
+			return $this->grand_total;
248
+		}
249
+		// $this->grand_total_ID is set, use it to get the object from the db
250
+		if ($this->grand_total_ID !== 0) {
251
+			$this->grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->grand_total_ID);
252
+			return $this->grand_total;
253
+		}
254
+		return $this->create_grand_total();
255
+	}
256
+
257
+
258
+	/**
259
+	 * process items for adding to cart
260
+	 *
261
+	 * @param EE_Ticket $ticket
262
+	 * @param int       $qty
263
+	 * @return bool TRUE on success, FALSE on fail
264
+	 * @throws EE_Error
265
+	 * @throws ReflectionException
266
+	 */
267
+	public function add_ticket_to_cart(EE_Ticket $ticket, int $qty = 1): bool
268
+	{
269
+		EEH_Line_Item::add_ticket_purchase($this->get_grand_total(), $ticket, $qty, false);
270
+		return $this->save_cart();
271
+	}
272
+
273
+
274
+	/**
275
+	 * get_cart_total_before_tax
276
+	 *
277
+	 * @return float
278
+	 * @throws EE_Error
279
+	 * @throws ReflectionException
280
+	 */
281
+	public function get_cart_total_before_tax(): float
282
+	{
283
+		return $this->get_grand_total()->recalculate_pre_tax_total();
284
+	}
285
+
286
+
287
+	/**
288
+	 * gets the total amount of tax paid for items in this cart
289
+	 *
290
+	 * @return float
291
+	 * @throws EE_Error
292
+	 * @throws ReflectionException
293
+	 */
294
+	public function get_applied_taxes(): float
295
+	{
296
+		return EEH_Line_Item::ensure_taxes_applied($this->grand_total);
297
+	}
298
+
299
+
300
+	/**
301
+	 * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
302
+	 *
303
+	 * @return float
304
+	 * @throws EE_Error
305
+	 * @throws ReflectionException
306
+	 */
307
+	public function get_cart_grand_total(): float
308
+	{
309
+		EEH_Line_Item::ensure_taxes_applied($this->grand_total);
310
+		return $this->get_grand_total()->total();
311
+	}
312
+
313
+
314
+	/**
315
+	 * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers
316
+	 *
317
+	 * @return float
318
+	 * @throws EE_Error
319
+	 * @throws ReflectionException
320
+	 */
321
+	public function recalculate_all_cart_totals(): float
322
+	{
323
+		$pre_tax_total = $this->get_cart_total_before_tax();
324
+		$taxes_total   = EEH_Line_Item::ensure_taxes_applied($this->grand_total);
325
+		$this->grand_total->set_total($pre_tax_total + $taxes_total);
326
+		$this->grand_total->save_this_and_descendants_to_txn();
327
+		return $this->get_grand_total()->total();
328
+	}
329
+
330
+
331
+	/**
332
+	 * deletes an item from the cart
333
+	 *
334
+	 * @param array|bool|string $line_item_codes
335
+	 * @return int on success, FALSE on fail
336
+	 * @throws EE_Error
337
+	 * @throws ReflectionException
338
+	 */
339
+	public function delete_items($line_item_codes = false): int
340
+	{
341
+		return (int) EEH_Line_Item::delete_items($this->get_grand_total(), $line_item_codes);
342
+	}
343
+
344
+
345
+	/**
346
+	 * @remove ALL items from cart and zero ALL totals
347
+	 * @return bool
348
+	 * @throws EE_Error
349
+	 * @throws ReflectionException
350
+	 */
351
+	public function empty_cart(): bool
352
+	{
353
+		$this->grand_total = $this->create_grand_total();
354
+		return $this->save_cart();
355
+	}
356
+
357
+
358
+	/**
359
+	 * remove ALL items from cart and delete total as well
360
+	 *
361
+	 * @return bool
362
+	 * @throws EE_Error
363
+	 * @throws ReflectionException
364
+	 */
365
+	public function delete_cart(): bool
366
+	{
367
+		if ($this->grand_total instanceof EE_Line_Item) {
368
+			$deleted = EEH_Line_Item::delete_all_child_items($this->grand_total);
369
+			if ($deleted) {
370
+				$this->grand_total->delete();
371
+				$this->grand_total = null;
372
+				return true;
373
+			}
374
+		}
375
+		return false;
376
+	}
377
+
378
+
379
+	/**
380
+	 * save   cart to session
381
+	 *
382
+	 * @param bool $apply_taxes
383
+	 * @return bool TRUE on success, FALSE on fail
384
+	 * @throws EE_Error
385
+	 * @throws ReflectionException
386
+	 */
387
+	public function save_cart(bool $apply_taxes = true): bool
388
+	{
389
+		if ($apply_taxes && $this->grand_total instanceof EE_Line_Item) {
390
+			EEH_Line_Item::ensure_taxes_applied($this->grand_total);
391
+			// make sure we don't cache the transaction because it can get stale
392
+			if (
393
+				$this->grand_total->get_one_from_cache('Transaction') instanceof EE_Transaction
394
+				&& $this->grand_total->get_one_from_cache('Transaction')->ID()
395
+			) {
396
+				$this->grand_total->clear_cache('Transaction', null, true);
397
+			}
398
+		}
399
+		if ($this->session() instanceof EE_Session) {
400
+			return $this->session()->set_cart($this);
401
+		}
402
+		return false;
403
+	}
404
+
405
+
406
+	/**
407
+	 * @throws EE_Error
408
+	 * @throws ReflectionException
409
+	 */
410
+	public function __wakeup()
411
+	{
412
+		if (! $this->grand_total instanceof EE_Line_Item && $this->grand_total_ID !== 0) {
413
+			// $this->_grand_total is actually just an ID, so use it to get the object from the db
414
+			$this->grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->grand_total_ID);
415
+		}
416
+	}
417
+
418
+
419
+	/**
420
+	 * @return array
421
+	 * @throws EE_Error
422
+	 * @throws ReflectionException
423
+	 */
424
+	public function __sleep()
425
+	{
426
+		if ($this->grand_total instanceof EE_Line_Item && $this->grand_total->ID()) {
427
+			$this->grand_total_ID = $this->grand_total->ID();
428
+		}
429
+		return ['grand_total_ID'];
430
+	}
431 431
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -58,14 +58,14 @@  discard block
 block discarded – undo
58 58
             self::$_instance = new self($grand_total, $session);
59 59
         }
60 60
         // or maybe retrieve an existing one ?
61
-        if (! self::$_instance instanceof EE_Cart) {
61
+        if ( ! self::$_instance instanceof EE_Cart) {
62 62
             // try getting the cart out of the session
63 63
             $saved_cart      = $session instanceof EE_Session ? $session->cart() : null;
64 64
             self::$_instance = $saved_cart instanceof EE_Cart ? $saved_cart : new self($grand_total, $session);
65 65
             unset($saved_cart);
66 66
         }
67 67
         // verify that cart is ok and grand total line item exists
68
-        if (! self::$_instance instanceof EE_Cart || ! self::$_instance->grand_total instanceof EE_Line_Item) {
68
+        if ( ! self::$_instance instanceof EE_Cart || ! self::$_instance->grand_total instanceof EE_Line_Item) {
69 69
             self::$_instance = new self($grand_total, $session);
70 70
         }
71 71
         self::$_instance->get_grand_total();
@@ -119,7 +119,7 @@  discard block
 block discarded – undo
119 119
      */
120 120
     public function session(): EE_Session
121 121
     {
122
-        if (! $this->session instanceof EE_Session) {
122
+        if ( ! $this->session instanceof EE_Session) {
123 123
             $this->set_session();
124 124
         }
125 125
         return $this->session;
@@ -409,7 +409,7 @@  discard block
 block discarded – undo
409 409
      */
410 410
     public function __wakeup()
411 411
     {
412
-        if (! $this->grand_total instanceof EE_Line_Item && $this->grand_total_ID !== 0) {
412
+        if ( ! $this->grand_total instanceof EE_Line_Item && $this->grand_total_ID !== 0) {
413 413
             // $this->_grand_total is actually just an ID, so use it to get the object from the db
414 414
             $this->grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->grand_total_ID);
415 415
         }
Please login to merge, or discard this patch.
core/data_migration_scripts/EE_DMS_Core_5_0_0.dms.php 1 patch
Indentation   +426 added lines, -426 removed lines patch added patch discarded remove patch
@@ -11,9 +11,9 @@  discard block
 block discarded – undo
11 11
 $stages            = glob(EE_CORE . 'data_migration_scripts/5_0_0_stages/*');
12 12
 $class_to_filepath = [];
13 13
 foreach ($stages as $filepath) {
14
-    $matches = [];
15
-    preg_match('~5_0_0_stages/(.*).dmsstage.php~', $filepath, $matches);
16
-    $class_to_filepath[ $matches[1] ] = $filepath;
14
+	$matches = [];
15
+	preg_match('~5_0_0_stages/(.*).dmsstage.php~', $filepath, $matches);
16
+	$class_to_filepath[ $matches[1] ] = $filepath;
17 17
 }
18 18
 // give addons a chance to autoload their stages too
19 19
 $class_to_filepath = apply_filters('FHEE__EE_DMS_5_0_0__autoloaded_stages', $class_to_filepath);
@@ -29,65 +29,65 @@  discard block
 block discarded – undo
29 29
  */
30 30
 class EE_DMS_Core_5_0_0 extends EE_Data_Migration_Script_Base
31 31
 {
32
-    /**
33
-     * @param EE_DMS_Core_4_10_0 $dms_4_10
34
-     * @param TableManager|null  $table_manager
35
-     * @param TableAnalysis|null $table_analysis
36
-     */
37
-    public function __construct(
38
-        EE_DMS_Core_4_10_0 $dms_4_10,
39
-        TableManager $table_manager = null,
40
-        TableAnalysis $table_analysis = null
41
-    ) {
42
-        $this->previous_dms      = $dms_4_10;
43
-        $this->_pretty_name      = esc_html__("Data Update to Event Espresso 5.0.0", "event_espresso");
44
-        $this->_priority         = 10;
45
-        $this->_migration_stages = [
46
-            new EE_DMS_5_0_0_Event_Venues(),
47
-        ];
48
-        parent::__construct($table_manager, $table_analysis);
49
-    }
50
-
51
-
52
-    /**
53
-     * Whether to migrate or not.
54
-     *
55
-     * @param array $version_array
56
-     * @return bool
57
-     */
58
-    public function can_migrate_from_version($version_array): bool
59
-    {
60
-        $version_string = $version_array['Core'];
61
-        return $version_string &&
62
-            version_compare($version_string, '5.0.0.decaf', '<') &&
63
-            version_compare($version_string, '4.10.0.decaf', '>=');
64
-    }
65
-
66
-
67
-    /**
68
-     * @return bool
69
-     * @throws EE_Error
70
-     * @throws ReflectionException
71
-     */
72
-    public function schema_changes_before_migration(): bool
73
-    {
74
-        require_once EE_HELPERS . 'EEH_Activation.helper.php';
75
-
76
-        $this->_table_has_not_changed_since_previous(
77
-            'esp_answer',
78
-            ' ANS_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
32
+	/**
33
+	 * @param EE_DMS_Core_4_10_0 $dms_4_10
34
+	 * @param TableManager|null  $table_manager
35
+	 * @param TableAnalysis|null $table_analysis
36
+	 */
37
+	public function __construct(
38
+		EE_DMS_Core_4_10_0 $dms_4_10,
39
+		TableManager $table_manager = null,
40
+		TableAnalysis $table_analysis = null
41
+	) {
42
+		$this->previous_dms      = $dms_4_10;
43
+		$this->_pretty_name      = esc_html__("Data Update to Event Espresso 5.0.0", "event_espresso");
44
+		$this->_priority         = 10;
45
+		$this->_migration_stages = [
46
+			new EE_DMS_5_0_0_Event_Venues(),
47
+		];
48
+		parent::__construct($table_manager, $table_analysis);
49
+	}
50
+
51
+
52
+	/**
53
+	 * Whether to migrate or not.
54
+	 *
55
+	 * @param array $version_array
56
+	 * @return bool
57
+	 */
58
+	public function can_migrate_from_version($version_array): bool
59
+	{
60
+		$version_string = $version_array['Core'];
61
+		return $version_string &&
62
+			version_compare($version_string, '5.0.0.decaf', '<') &&
63
+			version_compare($version_string, '4.10.0.decaf', '>=');
64
+	}
65
+
66
+
67
+	/**
68
+	 * @return bool
69
+	 * @throws EE_Error
70
+	 * @throws ReflectionException
71
+	 */
72
+	public function schema_changes_before_migration(): bool
73
+	{
74
+		require_once EE_HELPERS . 'EEH_Activation.helper.php';
75
+
76
+		$this->_table_has_not_changed_since_previous(
77
+			'esp_answer',
78
+			' ANS_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
79 79
             REG_ID int(10) unsigned NOT NULL,
80 80
             QST_ID int(10) unsigned NOT NULL,
81 81
             ANS_value text NOT NULL,
82 82
             PRIMARY KEY  (ANS_ID)'
83
-        );
84
-        $this->_get_table_manager()->addIndex('esp_answer', 'REG_ID', 'REG_ID');
85
-        $this->_get_table_manager()->addIndex('esp_answer', 'QST_ID', 'QST_ID');
83
+		);
84
+		$this->_get_table_manager()->addIndex('esp_answer', 'REG_ID', 'REG_ID');
85
+		$this->_get_table_manager()->addIndex('esp_answer', 'QST_ID', 'QST_ID');
86 86
 
87 87
 
88
-        $this->_table_has_not_changed_since_previous(
89
-            'esp_attendee_meta',
90
-            "ATTM_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
88
+		$this->_table_has_not_changed_since_previous(
89
+			'esp_attendee_meta',
90
+			"ATTM_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
91 91
 				ATT_ID bigint(20) unsigned NOT NULL,
92 92
 				ATT_fname varchar(45) NOT NULL,
93 93
 				ATT_lname varchar(45) NOT NULL,
@@ -100,43 +100,43 @@  discard block
 block discarded – undo
100 100
 				ATT_email varchar(255) NOT NULL,
101 101
 				ATT_phone varchar(45) DEFAULT NULL,
102 102
 				PRIMARY KEY  (ATTM_ID)"
103
-        );
104
-        $this->_get_table_manager()->addIndex('esp_attendee_meta', 'ATT_ID', 'ATT_ID');
105
-        $this->_get_table_manager()->addIndex(
106
-            'esp_attendee_meta',
107
-            'ATT_email',
108
-            'ATT_email',
109
-            TableAnalysis::INDEX_TYPE_INDEX,
110
-            TableAnalysis::INDEX_COLUMN_SIZE
111
-        );
112
-        $this->_get_table_manager()->addIndex('esp_attendee_meta', 'ATT_lname', 'ATT_lname');
113
-        $this->_get_table_manager()->addIndex('esp_attendee_meta', 'ATT_fname', 'ATT_fname');
114
-
115
-
116
-        $this->_table_has_not_changed_since_previous(
117
-            'esp_checkin',
118
-            "CHK_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
103
+		);
104
+		$this->_get_table_manager()->addIndex('esp_attendee_meta', 'ATT_ID', 'ATT_ID');
105
+		$this->_get_table_manager()->addIndex(
106
+			'esp_attendee_meta',
107
+			'ATT_email',
108
+			'ATT_email',
109
+			TableAnalysis::INDEX_TYPE_INDEX,
110
+			TableAnalysis::INDEX_COLUMN_SIZE
111
+		);
112
+		$this->_get_table_manager()->addIndex('esp_attendee_meta', 'ATT_lname', 'ATT_lname');
113
+		$this->_get_table_manager()->addIndex('esp_attendee_meta', 'ATT_fname', 'ATT_fname');
114
+
115
+
116
+		$this->_table_has_not_changed_since_previous(
117
+			'esp_checkin',
118
+			"CHK_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
119 119
 				REG_ID int(10) unsigned NOT NULL,
120 120
 				DTT_ID int(10) unsigned NOT NULL,
121 121
 				CHK_in tinyint(1) unsigned NOT NULL DEFAULT 1,
122 122
 				CHK_timestamp datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
123 123
 				PRIMARY KEY  (CHK_ID)"
124
-        );
125
-        $this->_get_table_manager()->addIndex('esp_checkin', 'REG_ID', 'REG_ID');
126
-        $this->_get_table_manager()->addIndex('esp_checkin', 'DTT_ID', 'DTT_ID');
127
-        $this->_get_table_manager()->addIndex(
128
-            'esp_checkin',
129
-            'CHK_timestamp',
130
-            'CHK_timestamp',
131
-            TableAnalysis::INDEX_TYPE_INDEX,
132
-            null,
133
-            true
134
-        );
135
-
136
-
137
-        $this->_table_has_not_changed_since_previous(
138
-            'esp_country',
139
-            "CNT_ISO varchar(2) NOT NULL,
124
+		);
125
+		$this->_get_table_manager()->addIndex('esp_checkin', 'REG_ID', 'REG_ID');
126
+		$this->_get_table_manager()->addIndex('esp_checkin', 'DTT_ID', 'DTT_ID');
127
+		$this->_get_table_manager()->addIndex(
128
+			'esp_checkin',
129
+			'CHK_timestamp',
130
+			'CHK_timestamp',
131
+			TableAnalysis::INDEX_TYPE_INDEX,
132
+			null,
133
+			true
134
+		);
135
+
136
+
137
+		$this->_table_has_not_changed_since_previous(
138
+			'esp_country',
139
+			"CNT_ISO varchar(2) NOT NULL,
140 140
 				CNT_ISO3 varchar(3) NOT NULL,
141 141
 				RGN_ID tinyint(3) unsigned DEFAULT NULL,
142 142
 				CNT_name varchar(45) NOT NULL,
@@ -152,38 +152,38 @@  discard block
 block discarded – undo
152 152
 				CNT_is_EU tinyint(1) DEFAULT '0',
153 153
 				CNT_active tinyint(1) DEFAULT '0',
154 154
 				PRIMARY KEY  (CNT_ISO)"
155
-        );
155
+		);
156 156
 
157 157
 
158
-        $this->_table_has_not_changed_since_previous(
159
-            'esp_currency',
160
-            "CUR_code varchar(6) NOT NULL,
158
+		$this->_table_has_not_changed_since_previous(
159
+			'esp_currency',
160
+			"CUR_code varchar(6) NOT NULL,
161 161
 				CUR_single varchar(45) DEFAULT 'dollar',
162 162
 				CUR_plural varchar(45) DEFAULT 'dollars',
163 163
 				CUR_sign varchar(45) DEFAULT '$',
164 164
 				CUR_dec_plc varchar(1) NOT NULL DEFAULT '2',
165 165
 				CUR_active tinyint(1) DEFAULT '0',
166 166
 				PRIMARY KEY  (CUR_code)"
167
-        );
167
+		);
168 168
 
169 169
 
170
-        // note: although this table is no longer in use,
171
-        // it hasn't been removed because then queries to the model will have errors.
172
-        // but you should expect this table and its corresponding model to be removed in
173
-        // the next few months
174
-        $this->_table_is_new_in_this_version(
175
-            'esp_currency_payment_method',
176
-            "CPM_ID int(11) NOT NULL AUTO_INCREMENT,
170
+		// note: although this table is no longer in use,
171
+		// it hasn't been removed because then queries to the model will have errors.
172
+		// but you should expect this table and its corresponding model to be removed in
173
+		// the next few months
174
+		$this->_table_is_new_in_this_version(
175
+			'esp_currency_payment_method',
176
+			"CPM_ID int(11) NOT NULL AUTO_INCREMENT,
177 177
 				CUR_code varchar(6) NOT NULL,
178 178
 				PMD_ID int(11) NOT NULL,
179 179
 				PRIMARY KEY  (CPM_ID)"
180
-        );
181
-        $this->_get_table_manager()->addIndex('esp_currency_payment_method', 'PMD_ID', 'PMD_ID');
180
+		);
181
+		$this->_get_table_manager()->addIndex('esp_currency_payment_method', 'PMD_ID', 'PMD_ID');
182 182
 
183 183
 
184
-        $this->_table_is_changed_in_this_version(
185
-            'esp_datetime',
186
-            "DTT_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
184
+		$this->_table_is_changed_in_this_version(
185
+			'esp_datetime',
186
+			"DTT_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
187 187
 				EVT_ID bigint(20) unsigned NOT NULL,
188 188
 			    VNU_ID bigint(20) unsigned NOT NULL DEFAULT 0,
189 189
 				DTT_name varchar(255) NOT NULL DEFAULT '',
@@ -198,39 +198,39 @@  discard block
 block discarded – undo
198 198
 				DTT_parent int(10) unsigned DEFAULT 0,
199 199
 				DTT_deleted tinyint(1) unsigned NOT NULL DEFAULT 0,
200 200
 				PRIMARY KEY  (DTT_ID)"
201
-        );
202
-        $this->_get_table_manager()->addIndex('esp_datetime', 'EVT_ID', 'EVT_ID');
203
-        // $this->_get_table_manager()->addIndex('esp_datetime', 'VNU_ID', 'VNU_ID');
204
-        $this->_get_table_manager()->addIndex('esp_datetime', 'DTT_EVT_start', 'DTT_EVT_start');
205
-        // $this->_get_table_manager()->addIndex('esp_datetime', 'DTT_EVT_end', 'DTT_EVT_end');
206
-        // $this->_get_table_manager()->dropIndex('esp_datetime', 'DTT_is_primary');
201
+		);
202
+		$this->_get_table_manager()->addIndex('esp_datetime', 'EVT_ID', 'EVT_ID');
203
+		// $this->_get_table_manager()->addIndex('esp_datetime', 'VNU_ID', 'VNU_ID');
204
+		$this->_get_table_manager()->addIndex('esp_datetime', 'DTT_EVT_start', 'DTT_EVT_start');
205
+		// $this->_get_table_manager()->addIndex('esp_datetime', 'DTT_EVT_end', 'DTT_EVT_end');
206
+		// $this->_get_table_manager()->dropIndex('esp_datetime', 'DTT_is_primary');
207 207
 
208 208
 
209
-        $this->_table_has_not_changed_since_previous(
210
-            'esp_datetime_ticket',
211
-            "DTK_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
209
+		$this->_table_has_not_changed_since_previous(
210
+			'esp_datetime_ticket',
211
+			"DTK_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
212 212
 				DTT_ID int(10) unsigned NOT NULL,
213 213
 				TKT_ID int(10) unsigned NOT NULL,
214 214
 				PRIMARY KEY  (DTK_ID)"
215
-        );
216
-        $this->_get_table_manager()->addIndex('esp_datetime_ticket', 'DTT_ID', 'DTT_ID');
217
-        $this->_get_table_manager()->addIndex('esp_datetime_ticket', 'TKT_ID', 'TKT_ID');
215
+		);
216
+		$this->_get_table_manager()->addIndex('esp_datetime_ticket', 'DTT_ID', 'DTT_ID');
217
+		$this->_get_table_manager()->addIndex('esp_datetime_ticket', 'TKT_ID', 'TKT_ID');
218 218
 
219 219
 
220
-        $this->_table_has_not_changed_since_previous(
221
-            'esp_event_message_template',
222
-            "EMT_ID bigint(20) unsigned NOT NULL AUTO_INCREMENT,
220
+		$this->_table_has_not_changed_since_previous(
221
+			'esp_event_message_template',
222
+			"EMT_ID bigint(20) unsigned NOT NULL AUTO_INCREMENT,
223 223
 				EVT_ID bigint(20) unsigned NOT NULL DEFAULT 0,
224 224
 				GRP_ID int(10) unsigned NOT NULL DEFAULT 0,
225 225
 				PRIMARY KEY  (EMT_ID)"
226
-        );
227
-        $this->_get_table_manager()->addIndex('esp_event_message_template', 'EVT_ID', 'EVT_ID');
228
-        $this->_get_table_manager()->addIndex('esp_event_message_template', 'GRP_ID', 'GRP_ID');
226
+		);
227
+		$this->_get_table_manager()->addIndex('esp_event_message_template', 'EVT_ID', 'EVT_ID');
228
+		$this->_get_table_manager()->addIndex('esp_event_message_template', 'GRP_ID', 'GRP_ID');
229 229
 
230 230
 
231
-        $this->_table_is_changed_in_this_version(
232
-            'esp_event_meta',
233
-            "EVTM_ID int(10) NOT NULL AUTO_INCREMENT,
231
+		$this->_table_is_changed_in_this_version(
232
+			'esp_event_meta',
233
+			"EVTM_ID int(10) NOT NULL AUTO_INCREMENT,
234 234
 				EVT_ID bigint(20) unsigned NOT NULL,
235 235
 			    VNU_ID bigint(20) unsigned NOT NULL DEFAULT 0,
236 236
 				EVT_display_desc tinyint(1) unsigned NOT NULL DEFAULT 1,
@@ -246,77 +246,77 @@  discard block
 block discarded – undo
246 246
 				EVT_donations tinyint(1) NULL,
247 247
 				FSC_UUID varchar(25) DEFAULT NULL,
248 248
 				PRIMARY KEY  (EVTM_ID)"
249
-        );
250
-        $this->_get_table_manager()->addIndex(
251
-            'esp_event_meta',
252
-            'EVT_ID',
253
-            'EVT_ID',
254
-            TableAnalysis::INDEX_TYPE_INDEX,
255
-            null,
256
-            true
257
-        );
258
-        // $this->_get_table_manager()->addIndex('esp_event_meta', 'VNU_ID', 'VNU_ID');
259
-
260
-
261
-        $this->_table_has_not_changed_since_previous(
262
-            'esp_event_question_group',
263
-            "EQG_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
249
+		);
250
+		$this->_get_table_manager()->addIndex(
251
+			'esp_event_meta',
252
+			'EVT_ID',
253
+			'EVT_ID',
254
+			TableAnalysis::INDEX_TYPE_INDEX,
255
+			null,
256
+			true
257
+		);
258
+		// $this->_get_table_manager()->addIndex('esp_event_meta', 'VNU_ID', 'VNU_ID');
259
+
260
+
261
+		$this->_table_has_not_changed_since_previous(
262
+			'esp_event_question_group',
263
+			"EQG_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
264 264
 				EVT_ID bigint(20) unsigned NOT NULL,
265 265
 				QSG_ID int(10) unsigned NOT NULL,
266 266
 				EQG_primary tinyint(1) unsigned NOT NULL DEFAULT 0,
267 267
 				EQG_additional tinyint(1) unsigned NOT NULL DEFAULT 0,
268 268
 				PRIMARY KEY  (EQG_ID)"
269
-        );
270
-        $this->_get_table_manager()->addIndex('esp_event_question_group', 'EVT_ID', 'EVT_ID');
271
-        $this->_get_table_manager()->addIndex('esp_event_question_group', 'QSG_ID', 'QSG_ID');
269
+		);
270
+		$this->_get_table_manager()->addIndex('esp_event_question_group', 'EVT_ID', 'EVT_ID');
271
+		$this->_get_table_manager()->addIndex('esp_event_question_group', 'QSG_ID', 'QSG_ID');
272 272
 
273 273
 
274
-        $this->_table_has_not_changed_since_previous(
275
-            'esp_event_venue',
276
-            "EVV_ID int(11) NOT NULL AUTO_INCREMENT,
274
+		$this->_table_has_not_changed_since_previous(
275
+			'esp_event_venue',
276
+			"EVV_ID int(11) NOT NULL AUTO_INCREMENT,
277 277
 				EVT_ID bigint(20) unsigned NOT NULL,
278 278
 				VNU_ID bigint(20) unsigned NOT NULL,
279 279
 				EVV_primary tinyint(1) unsigned NOT NULL DEFAULT 0,
280 280
 				PRIMARY KEY  (EVV_ID)"
281
-        );
281
+		);
282 282
 
283 283
 
284
-        $this->_table_has_not_changed_since_previous(
285
-            'esp_extra_meta',
286
-            "EXM_ID int(11) NOT NULL AUTO_INCREMENT,
284
+		$this->_table_has_not_changed_since_previous(
285
+			'esp_extra_meta',
286
+			"EXM_ID int(11) NOT NULL AUTO_INCREMENT,
287 287
 				OBJ_ID int(11) DEFAULT NULL,
288 288
 				EXM_type varchar(45) DEFAULT NULL,
289 289
 				EXM_key varchar(45) DEFAULT NULL,
290 290
 				EXM_value text,
291 291
 				PRIMARY KEY  (EXM_ID)"
292
-        );
293
-        $this->_get_table_manager()->addIndex('esp_extra_meta', 'EXM_type', 'EXM_type,OBJ_ID,EXM_key');
292
+		);
293
+		$this->_get_table_manager()->addIndex('esp_extra_meta', 'EXM_type', 'EXM_type,OBJ_ID,EXM_key');
294 294
 
295 295
 
296
-        $this->_table_has_not_changed_since_previous(
297
-            'esp_extra_join',
298
-            "EXJ_ID int(11) NOT NULL AUTO_INCREMENT,
296
+		$this->_table_has_not_changed_since_previous(
297
+			'esp_extra_join',
298
+			"EXJ_ID int(11) NOT NULL AUTO_INCREMENT,
299 299
 				EXJ_first_model_id varchar(12) NOT NULL,
300 300
 				EXJ_first_model_name varchar(20) NOT NULL,
301 301
 				EXJ_second_model_id varchar(12) NOT NULL,
302 302
 				EXJ_second_model_name varchar(20) NOT NULL,
303 303
 				PRIMARY KEY  (EXJ_ID)"
304
-        );
305
-        $this->_get_table_manager()->addIndex(
306
-            'esp_extra_join',
307
-            'first_model',
308
-            'EXJ_first_model_name,EXJ_first_model_id'
309
-        );
310
-        $this->_get_table_manager()->addIndex(
311
-            'esp_extra_join',
312
-            'second_model',
313
-            'EXJ_second_model_name,EXJ_second_model_id'
314
-        );
315
-
316
-
317
-        $this->_table_is_new_in_this_version(
318
-            'esp_form_element',
319
-            "FIN_UUID varchar(25) NOT NULL,
304
+		);
305
+		$this->_get_table_manager()->addIndex(
306
+			'esp_extra_join',
307
+			'first_model',
308
+			'EXJ_first_model_name,EXJ_first_model_id'
309
+		);
310
+		$this->_get_table_manager()->addIndex(
311
+			'esp_extra_join',
312
+			'second_model',
313
+			'EXJ_second_model_name,EXJ_second_model_id'
314
+		);
315
+
316
+
317
+		$this->_table_is_new_in_this_version(
318
+			'esp_form_element',
319
+			"FIN_UUID varchar(25) NOT NULL,
320 320
 				FSC_UUID varchar(25) NOT NULL,
321 321
 				FIN_adminOnly tinyint(1) unsigned NOT NULL DEFAULT 0,
322 322
 				FIN_attributes text DEFAULT NULL,
@@ -330,15 +330,15 @@  discard block
 block discarded – undo
330 330
 				FIN_type tinytext DEFAULT NULL,
331 331
 				FIN_wpUser bigint(20) unsigned DEFAULT NULL,
332 332
 				PRIMARY KEY  (FIN_UUID)"
333
-        );
334
-        $this->_get_table_manager()->addIndex('esp_form_element', 'FSC_UUID', 'FSC_UUID');
335
-        // $this->_get_table_manager()->dropIndex('esp_form_element', 'FIN_order');
336
-        // $this->_get_table_manager()->dropIndex('esp_form_element', 'FIN_status');
333
+		);
334
+		$this->_get_table_manager()->addIndex('esp_form_element', 'FSC_UUID', 'FSC_UUID');
335
+		// $this->_get_table_manager()->dropIndex('esp_form_element', 'FIN_order');
336
+		// $this->_get_table_manager()->dropIndex('esp_form_element', 'FIN_status');
337 337
 
338 338
 
339
-        $this->_table_is_new_in_this_version(
340
-            'esp_form_section',
341
-            "FSC_UUID varchar(25) NOT NULL,
339
+		$this->_table_is_new_in_this_version(
340
+			'esp_form_section',
341
+			"FSC_UUID varchar(25) NOT NULL,
342 342
 				FSC_appliesTo tinytext NOT NULL,
343 343
 				FSC_attributes text DEFAULT NULL,
344 344
 				FSC_belongsTo varchar(25) DEFAULT NULL,
@@ -347,36 +347,36 @@  discard block
 block discarded – undo
347 347
 				FSC_status varchar(32) NOT NULL DEFAULT 'active',
348 348
 				FSC_wpUser bigint(20) unsigned DEFAULT NULL,
349 349
 				PRIMARY KEY  (FSC_UUID)"
350
-        );
351
-        $this->_get_table_manager()->addIndex('esp_form_section', 'FSC_belongsTo', 'FSC_belongsTo');
352
-        // $this->_get_table_manager()->dropIndex('esp_form_section', 'FSC_order');
353
-        // $this->_get_table_manager()->dropIndex('esp_form_section', 'FSC_status');
350
+		);
351
+		$this->_get_table_manager()->addIndex('esp_form_section', 'FSC_belongsTo', 'FSC_belongsTo');
352
+		// $this->_get_table_manager()->dropIndex('esp_form_section', 'FSC_order');
353
+		// $this->_get_table_manager()->dropIndex('esp_form_section', 'FSC_status');
354 354
 
355 355
 
356
-        $this->_table_is_new_in_this_version(
357
-            'esp_form_submission',
358
-            "FSB_UUID varchar(25) NOT NULL,
356
+		$this->_table_is_new_in_this_version(
357
+			'esp_form_submission',
358
+			"FSB_UUID varchar(25) NOT NULL,
359 359
                 FSC_UUID varchar(25) NOT NULL,
360 360
 				TXN_ID int(10) DEFAULT NULL,
361 361
 				FSB_data mediumtext DEFAULT NULL,
362 362
 				FSB_submitted datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
363 363
 				PRIMARY KEY  (FSB_UUID)"
364
-        );
365
-        $this->_get_table_manager()->addIndex('esp_form_submission', 'FSC_UUID', 'FSC_UUID');
366
-        $this->_get_table_manager()->addIndex('esp_form_submission', 'TXN_ID', 'TXN_ID');
367
-        $this->_get_table_manager()->addIndex(
368
-            'esp_form_submission',
369
-            'FSB_submitted',
370
-            'FSB_submitted',
371
-            TableAnalysis::INDEX_TYPE_INDEX,
372
-            null,
373
-            true
374
-        );
375
-
376
-
377
-        $this->_table_is_changed_in_this_version(
378
-            'esp_line_item',
379
-            "LIN_ID int(11) NOT NULL AUTO_INCREMENT,
364
+		);
365
+		$this->_get_table_manager()->addIndex('esp_form_submission', 'FSC_UUID', 'FSC_UUID');
366
+		$this->_get_table_manager()->addIndex('esp_form_submission', 'TXN_ID', 'TXN_ID');
367
+		$this->_get_table_manager()->addIndex(
368
+			'esp_form_submission',
369
+			'FSB_submitted',
370
+			'FSB_submitted',
371
+			TableAnalysis::INDEX_TYPE_INDEX,
372
+			null,
373
+			true
374
+		);
375
+
376
+
377
+		$this->_table_is_changed_in_this_version(
378
+			'esp_line_item',
379
+			"LIN_ID int(11) NOT NULL AUTO_INCREMENT,
380 380
 				LIN_code varchar(245) NOT NULL DEFAULT '',
381 381
 				TXN_ID int(10) DEFAULT NULL,
382 382
 				LIN_name varchar(245) NOT NULL DEFAULT '',
@@ -394,24 +394,24 @@  discard block
 block discarded – undo
394 394
 				OBJ_type varchar(45) DEFAULT NULL,
395 395
 				LIN_timestamp datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
396 396
 				PRIMARY KEY  (LIN_ID)"
397
-        );
398
-        $this->_get_table_manager()->addIndex('esp_line_item', 'parent_order', 'LIN_parent,LIN_order');
399
-        $this->_get_table_manager()->addIndex('esp_line_item', 'txn_type_timestamp', 'TXN_ID,LIN_type,LIN_timestamp');
400
-        $this->_get_table_manager()->addIndex('esp_line_item', 'txn_obj_id_obj_type', 'TXN_ID,OBJ_ID,OBJ_type');
401
-        $this->_get_table_manager()->addIndex('esp_line_item', 'obj_id_obj_type', 'OBJ_ID,OBJ_type');
402
-        $this->_get_table_manager()->addIndex(
403
-            'esp_line_item',
404
-            'LIN_timestamp',
405
-            'LIN_timestamp',
406
-            TableAnalysis::INDEX_TYPE_INDEX,
407
-            null,
408
-            true
409
-        );
410
-
411
-
412
-        $this->_table_has_not_changed_since_previous(
413
-            'esp_log',
414
-            "LOG_ID int(11) NOT NULL AUTO_INCREMENT,
397
+		);
398
+		$this->_get_table_manager()->addIndex('esp_line_item', 'parent_order', 'LIN_parent,LIN_order');
399
+		$this->_get_table_manager()->addIndex('esp_line_item', 'txn_type_timestamp', 'TXN_ID,LIN_type,LIN_timestamp');
400
+		$this->_get_table_manager()->addIndex('esp_line_item', 'txn_obj_id_obj_type', 'TXN_ID,OBJ_ID,OBJ_type');
401
+		$this->_get_table_manager()->addIndex('esp_line_item', 'obj_id_obj_type', 'OBJ_ID,OBJ_type');
402
+		$this->_get_table_manager()->addIndex(
403
+			'esp_line_item',
404
+			'LIN_timestamp',
405
+			'LIN_timestamp',
406
+			TableAnalysis::INDEX_TYPE_INDEX,
407
+			null,
408
+			true
409
+		);
410
+
411
+
412
+		$this->_table_has_not_changed_since_previous(
413
+			'esp_log',
414
+			"LOG_ID int(11) NOT NULL AUTO_INCREMENT,
415 415
 				LOG_time datetime DEFAULT NULL,
416 416
 				OBJ_ID varchar(45) DEFAULT NULL,
417 417
 				OBJ_type varchar(45) DEFAULT NULL,
@@ -419,15 +419,15 @@  discard block
 block discarded – undo
419 419
 				LOG_message text,
420 420
 				LOG_wp_user int(11) DEFAULT NULL,
421 421
 				PRIMARY KEY  (LOG_ID)"
422
-        );
423
-        $this->_get_table_manager()->addIndex('esp_log', 'LOG_time', 'LOG_time');
424
-        $this->_get_table_manager()->addIndex('esp_log', 'LOG_type', 'LOG_type');
425
-        $this->_get_table_manager()->addIndex('esp_log', 'OBJ', 'OBJ_type,OBJ_ID');
422
+		);
423
+		$this->_get_table_manager()->addIndex('esp_log', 'LOG_time', 'LOG_time');
424
+		$this->_get_table_manager()->addIndex('esp_log', 'LOG_type', 'LOG_type');
425
+		$this->_get_table_manager()->addIndex('esp_log', 'OBJ', 'OBJ_type,OBJ_ID');
426 426
 
427 427
 
428
-        $this->_table_has_not_changed_since_previous(
429
-            'esp_message',
430
-            "MSG_ID bigint(20) unsigned NOT NULL AUTO_INCREMENT,
428
+		$this->_table_has_not_changed_since_previous(
429
+			'esp_message',
430
+			"MSG_ID bigint(20) unsigned NOT NULL AUTO_INCREMENT,
431 431
 				GRP_ID int(10) unsigned NULL,
432 432
 				MSG_token varchar(255) NULL,
433 433
 				TXN_ID int(10) unsigned NULL,
@@ -445,50 +445,50 @@  discard block
 block discarded – undo
445 445
 				MSG_created datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
446 446
 				MSG_modified datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
447 447
 				PRIMARY KEY  (MSG_ID)"
448
-        );
449
-        $this->_get_table_manager()->addIndex('esp_message', 'GRP_ID', 'GRP_ID');
450
-        $this->_get_table_manager()->addIndex('esp_message', 'TXN_ID', 'TXN_ID');
451
-        $this->_get_table_manager()->addIndex('esp_message', 'MSG_recipient_ID', 'MSG_recipient_ID');
452
-        $this->_get_table_manager()->addIndex(
453
-            'esp_message',
454
-            'MSG_to',
455
-            'MSG_to',
456
-            TableAnalysis::INDEX_TYPE_INDEX,
457
-            TableAnalysis::INDEX_COLUMN_SIZE
458
-        );
459
-        $this->_get_table_manager()->addIndex(
460
-            'esp_message',
461
-            'MSG_from',
462
-            'MSG_from',
463
-            TableAnalysis::INDEX_TYPE_INDEX,
464
-            TableAnalysis::INDEX_COLUMN_SIZE
465
-        );
466
-        $this->_get_table_manager()->addIndex('esp_message', 'MSG_modified', 'MSG_modified');
467
-        // $this->_get_table_manager()->dropIndex('esp_message', 'MSG_messenger');
468
-        // $this->_get_table_manager()->dropIndex('esp_message', 'MSG_message_type');
469
-        // $this->_get_table_manager()->dropIndex('esp_message', 'MSG_context');
470
-        // $this->_get_table_manager()->dropIndex('esp_message', 'MSG_recipient_type');
471
-        // $this->_get_table_manager()->dropIndex('esp_message', 'MSG_subject');
472
-        // $this->_get_table_manager()->dropIndex('esp_message', 'MSG_created');
473
-        // $this->_get_table_manager()->dropIndex('esp_message', 'MSG_priority');
474
-        // $this->_get_table_manager()->dropIndex('esp_message', 'STS_ID');
475
-
476
-
477
-        $this->_table_has_not_changed_since_previous(
478
-            'esp_message_template',
479
-            "MTP_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
448
+		);
449
+		$this->_get_table_manager()->addIndex('esp_message', 'GRP_ID', 'GRP_ID');
450
+		$this->_get_table_manager()->addIndex('esp_message', 'TXN_ID', 'TXN_ID');
451
+		$this->_get_table_manager()->addIndex('esp_message', 'MSG_recipient_ID', 'MSG_recipient_ID');
452
+		$this->_get_table_manager()->addIndex(
453
+			'esp_message',
454
+			'MSG_to',
455
+			'MSG_to',
456
+			TableAnalysis::INDEX_TYPE_INDEX,
457
+			TableAnalysis::INDEX_COLUMN_SIZE
458
+		);
459
+		$this->_get_table_manager()->addIndex(
460
+			'esp_message',
461
+			'MSG_from',
462
+			'MSG_from',
463
+			TableAnalysis::INDEX_TYPE_INDEX,
464
+			TableAnalysis::INDEX_COLUMN_SIZE
465
+		);
466
+		$this->_get_table_manager()->addIndex('esp_message', 'MSG_modified', 'MSG_modified');
467
+		// $this->_get_table_manager()->dropIndex('esp_message', 'MSG_messenger');
468
+		// $this->_get_table_manager()->dropIndex('esp_message', 'MSG_message_type');
469
+		// $this->_get_table_manager()->dropIndex('esp_message', 'MSG_context');
470
+		// $this->_get_table_manager()->dropIndex('esp_message', 'MSG_recipient_type');
471
+		// $this->_get_table_manager()->dropIndex('esp_message', 'MSG_subject');
472
+		// $this->_get_table_manager()->dropIndex('esp_message', 'MSG_created');
473
+		// $this->_get_table_manager()->dropIndex('esp_message', 'MSG_priority');
474
+		// $this->_get_table_manager()->dropIndex('esp_message', 'STS_ID');
475
+
476
+
477
+		$this->_table_has_not_changed_since_previous(
478
+			'esp_message_template',
479
+			"MTP_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
480 480
 				GRP_ID int(10) unsigned NOT NULL,
481 481
 				MTP_context varchar(50) NOT NULL,
482 482
 				MTP_template_field varchar(30) NOT NULL,
483 483
 				MTP_content text NOT NULL,
484 484
 				PRIMARY KEY  (MTP_ID)"
485
-        );
486
-        $this->_get_table_manager()->addIndex('esp_message_template', 'GRP_ID', 'GRP_ID');
485
+		);
486
+		$this->_get_table_manager()->addIndex('esp_message_template', 'GRP_ID', 'GRP_ID');
487 487
 
488 488
 
489
-        $this->_table_has_not_changed_since_previous(
490
-            'esp_message_template_group',
491
-            "GRP_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
489
+		$this->_table_has_not_changed_since_previous(
490
+			'esp_message_template_group',
491
+			"GRP_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
492 492
 				MTP_user_id int(10) NOT NULL DEFAULT '1',
493 493
 				MTP_name varchar(245) NOT NULL DEFAULT '',
494 494
 				MTP_description varchar(245) NOT NULL DEFAULT '',
@@ -499,13 +499,13 @@  discard block
 block discarded – undo
499 499
 				MTP_deleted tinyint(1) NOT NULL DEFAULT '0',
500 500
 				MTP_is_active tinyint(1) NOT NULL DEFAULT '1',
501 501
 				PRIMARY KEY  (GRP_ID)"
502
-        );
503
-        $this->_get_table_manager()->addIndex('esp_message_template_group', 'MTP_user_id', 'MTP_user_id');
502
+		);
503
+		$this->_get_table_manager()->addIndex('esp_message_template_group', 'MTP_user_id', 'MTP_user_id');
504 504
 
505 505
 
506
-        $this->_table_has_not_changed_since_previous(
507
-            'esp_payment',
508
-            "PAY_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
506
+		$this->_table_has_not_changed_since_previous(
507
+			'esp_payment',
508
+			"PAY_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
509 509
 				TXN_ID int(10) unsigned DEFAULT NULL,
510 510
 				STS_ID varchar(3) DEFAULT NULL,
511 511
 				PAY_timestamp datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
@@ -520,21 +520,21 @@  discard block
 block discarded – undo
520 520
 				PAY_redirect_url varchar(300),
521 521
 				PAY_redirect_args text,
522 522
 				PRIMARY KEY  (PAY_ID)"
523
-        );
524
-        $this->_get_table_manager()->addIndex(
525
-            'esp_payment',
526
-            'PAY_timestamp',
527
-            'PAY_timestamp',
528
-            TableAnalysis::INDEX_TYPE_INDEX,
529
-            null,
530
-            true
531
-        );
532
-        $this->_get_table_manager()->addIndex('esp_payment', 'TXN_ID', 'TXN_ID');
533
-
534
-
535
-        $this->_table_has_not_changed_since_previous(
536
-            'esp_payment_method',
537
-            "PMD_ID int(11) NOT NULL AUTO_INCREMENT,
523
+		);
524
+		$this->_get_table_manager()->addIndex(
525
+			'esp_payment',
526
+			'PAY_timestamp',
527
+			'PAY_timestamp',
528
+			TableAnalysis::INDEX_TYPE_INDEX,
529
+			null,
530
+			true
531
+		);
532
+		$this->_get_table_manager()->addIndex('esp_payment', 'TXN_ID', 'TXN_ID');
533
+
534
+
535
+		$this->_table_has_not_changed_since_previous(
536
+			'esp_payment_method',
537
+			"PMD_ID int(11) NOT NULL AUTO_INCREMENT,
538 538
 				PMD_type varchar(124) DEFAULT NULL,
539 539
 				PMD_name varchar(255) DEFAULT NULL,
540 540
 				PMD_desc text,
@@ -548,19 +548,19 @@  discard block
 block discarded – undo
548 548
 				PMD_button_url varchar(1012) DEFAULT NULL,
549 549
 				PMD_scope varchar(255) NULL DEFAULT 'frontend',
550 550
 				PRIMARY KEY  (PMD_ID)"
551
-        );
552
-        $this->_get_table_manager()->addIndex(
553
-            'esp_payment_method',
554
-            'PMD_slug_UNIQUE',
555
-            'PMD_slug',
556
-            TableAnalysis::INDEX_TYPE_UNIQUE
557
-        );
558
-        // $this->_get_table_manager()->dropIndex('esp_payment_method', 'PMD_type');
559
-
560
-
561
-        $this->_table_is_changed_in_this_version(
562
-            'esp_price',
563
-            "PRC_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
551
+		);
552
+		$this->_get_table_manager()->addIndex(
553
+			'esp_payment_method',
554
+			'PMD_slug_UNIQUE',
555
+			'PMD_slug',
556
+			TableAnalysis::INDEX_TYPE_UNIQUE
557
+		);
558
+		// $this->_get_table_manager()->dropIndex('esp_payment_method', 'PMD_type');
559
+
560
+
561
+		$this->_table_is_changed_in_this_version(
562
+			'esp_price',
563
+			"PRC_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
564 564
 				PRT_ID tinyint(3) unsigned NOT NULL,
565 565
 				PRC_amount decimal(12,6) NOT NULL DEFAULT '0.00',
566 566
 				PRC_name varchar(245) NOT NULL,
@@ -572,13 +572,13 @@  discard block
 block discarded – undo
572 572
 				PRC_wp_user bigint(20) unsigned NULL,
573 573
 				PRC_parent int(10) unsigned DEFAULT 0,
574 574
 				PRIMARY KEY  (PRC_ID)"
575
-        );
576
-        $this->_get_table_manager()->addIndex('esp_price', 'PRT_ID', 'PRT_ID');
575
+		);
576
+		$this->_get_table_manager()->addIndex('esp_price', 'PRT_ID', 'PRT_ID');
577 577
 
578 578
 
579
-        $this->_table_has_not_changed_since_previous(
580
-            'esp_price_type',
581
-            "PRT_ID tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
579
+		$this->_table_has_not_changed_since_previous(
580
+			'esp_price_type',
581
+			"PRT_ID tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
582 582
 				PRT_name varchar(45) NOT NULL,
583 583
 				PBT_ID tinyint(3) unsigned NOT NULL DEFAULT '1',
584 584
 				PRT_is_percent tinyint(1) NOT NULL DEFAULT '0',
@@ -587,33 +587,33 @@  discard block
 block discarded – undo
587 587
 				PRT_deleted tinyint(1) NOT NULL DEFAULT '0',
588 588
 				UNIQUE KEY PRT_name_UNIQUE (PRT_name),
589 589
 				PRIMARY KEY  (PRT_ID)"
590
-        );
590
+		);
591 591
 
592 592
 
593
-        $this->_table_has_not_changed_since_previous(
594
-            'esp_ticket_price',
595
-            "TKP_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
593
+		$this->_table_has_not_changed_since_previous(
594
+			'esp_ticket_price',
595
+			"TKP_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
596 596
 				TKT_ID int(10) unsigned NOT NULL,
597 597
 				PRC_ID int(10) unsigned NOT NULL,
598 598
 				PRIMARY KEY  (TKP_ID)"
599
-        );
600
-        $this->_get_table_manager()->addIndex('esp_ticket_price', 'TKT_ID', 'TKT_ID');
601
-        $this->_get_table_manager()->addIndex('esp_ticket_price', 'PRC_ID', 'PRC_ID');
599
+		);
600
+		$this->_get_table_manager()->addIndex('esp_ticket_price', 'TKT_ID', 'TKT_ID');
601
+		$this->_get_table_manager()->addIndex('esp_ticket_price', 'PRC_ID', 'PRC_ID');
602 602
 
603 603
 
604
-        $this->_table_has_not_changed_since_previous(
605
-            'esp_ticket_template',
606
-            "TTM_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
604
+		$this->_table_has_not_changed_since_previous(
605
+			'esp_ticket_template',
606
+			"TTM_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
607 607
 				TTM_name varchar(45) NOT NULL,
608 608
 				TTM_description text,
609 609
 				TTM_file varchar(45),
610 610
 				PRIMARY KEY  (TTM_ID)"
611
-        );
611
+		);
612 612
 
613 613
 
614
-        $this->_table_has_not_changed_since_previous(
615
-            'esp_question',
616
-            "QST_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
614
+		$this->_table_has_not_changed_since_previous(
615
+			'esp_question',
616
+			"QST_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
617 617
 				QST_display_text text NOT NULL,
618 618
 				QST_admin_label varchar(255) NOT NULL,
619 619
 				QST_system varchar(25) DEFAULT NULL,
@@ -626,13 +626,13 @@  discard block
 block discarded – undo
626 626
 				QST_wp_user bigint(20) unsigned NULL,
627 627
 				QST_deleted tinyint(2) unsigned NOT NULL DEFAULT 0,
628 628
 				PRIMARY KEY  (QST_ID)"
629
-        );
630
-        // $this->_get_table_manager()->dropIndex('esp_question', 'QST_order');
629
+		);
630
+		// $this->_get_table_manager()->dropIndex('esp_question', 'QST_order');
631 631
 
632 632
 
633
-        $this->_table_has_not_changed_since_previous(
634
-            'esp_question_group',
635
-            "QSG_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
633
+		$this->_table_has_not_changed_since_previous(
634
+			'esp_question_group',
635
+			"QSG_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
636 636
 				QSG_name varchar(255) NOT NULL,
637 637
 				QSG_identifier varchar(100) NOT NULL,
638 638
 				QSG_desc text NULL,
@@ -643,31 +643,31 @@  discard block
 block discarded – undo
643 643
 				QSG_deleted tinyint(1) unsigned NOT NULL DEFAULT 0,
644 644
 				QSG_wp_user bigint(20) unsigned NULL,
645 645
 				PRIMARY KEY  (QSG_ID)"
646
-        );
647
-        $this->_get_table_manager()->addIndex(
648
-            'esp_question_group',
649
-            'QSG_identifier_UNIQUE',
650
-            'QSG_identifier',
651
-            TableAnalysis::INDEX_TYPE_UNIQUE
652
-        );
653
-        // $this->_get_table_manager()->dropIndex('esp_question_group', 'QSG_order');
654
-
655
-
656
-        $this->_table_has_not_changed_since_previous(
657
-            'esp_question_group_question',
658
-            "QGQ_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
646
+		);
647
+		$this->_get_table_manager()->addIndex(
648
+			'esp_question_group',
649
+			'QSG_identifier_UNIQUE',
650
+			'QSG_identifier',
651
+			TableAnalysis::INDEX_TYPE_UNIQUE
652
+		);
653
+		// $this->_get_table_manager()->dropIndex('esp_question_group', 'QSG_order');
654
+
655
+
656
+		$this->_table_has_not_changed_since_previous(
657
+			'esp_question_group_question',
658
+			"QGQ_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
659 659
 				QSG_ID int(10) unsigned NOT NULL,
660 660
 				QST_ID int(10) unsigned NOT NULL,
661 661
 				QGQ_order int(10) unsigned NOT NULL DEFAULT 0,
662 662
 				PRIMARY KEY  (QGQ_ID)"
663
-        );
664
-        $this->_get_table_manager()->addIndex('esp_question_group_question', 'QST_ID', 'QST_ID');
665
-        // $this->_get_table_manager()->dropIndex('esp_question_group_question', 'QSG_ID_order');
663
+		);
664
+		$this->_get_table_manager()->addIndex('esp_question_group_question', 'QST_ID', 'QST_ID');
665
+		// $this->_get_table_manager()->dropIndex('esp_question_group_question', 'QSG_ID_order');
666 666
 
667 667
 
668
-        $this->_table_is_changed_in_this_version(
669
-            'esp_question_option',
670
-            "QSO_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
668
+		$this->_table_is_changed_in_this_version(
669
+			'esp_question_option',
670
+			"QSO_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
671 671
 				QSO_value varchar(255) NOT NULL,
672 672
 				QSO_desc text NOT NULL,
673 673
 				QST_ID int(10) unsigned NOT NULL,
@@ -676,14 +676,14 @@  discard block
 block discarded – undo
676 676
 				QSO_default tinyint(1) DEFAULT '0',
677 677
 				QSO_deleted tinyint(1) unsigned NOT NULL DEFAULT 0,
678 678
 				PRIMARY KEY  (QSO_ID)"
679
-        );
680
-        $this->_get_table_manager()->addIndex('esp_question_option', 'QST_ID', 'QST_ID');
681
-        $this->_get_table_manager()->dropIndex('esp_question_option', 'QSO_order');
679
+		);
680
+		$this->_get_table_manager()->addIndex('esp_question_option', 'QST_ID', 'QST_ID');
681
+		$this->_get_table_manager()->dropIndex('esp_question_option', 'QSO_order');
682 682
 
683 683
 
684
-        $this->_table_has_not_changed_since_previous(
685
-            'esp_registration',
686
-            "REG_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
684
+		$this->_table_has_not_changed_since_previous(
685
+			'esp_registration',
686
+			"REG_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
687 687
 				EVT_ID bigint(20) unsigned NOT NULL,
688 688
 				ATT_ID bigint(20) unsigned NOT NULL,
689 689
 				TXN_ID int(10) unsigned NOT NULL,
@@ -700,67 +700,67 @@  discard block
 block discarded – undo
700 700
 				REG_att_is_going tinyint(1) DEFAULT '0',
701 701
 				REG_deleted tinyint(1) DEFAULT '0',
702 702
 				PRIMARY KEY  (REG_ID)"
703
-        );
704
-        $this->_get_table_manager()->addIndex('esp_registration', 'REG_url_link', 'REG_url_link');
705
-        $this->_get_table_manager()->addIndex('esp_registration', 'REG_code', 'REG_code');
706
-        // $this->_get_table_manager()->addIndex(
707
-        //     'esp_registration',
708
-        //     'REG_date',
709
-        //     'REG_date',
710
-        //     TableAnalysis::INDEX_TYPE_INDEX,
711
-        //     null,
712
-        //     true
713
-        // );
714
-        $this->_get_table_manager()->addIndex('esp_registration', 'TXN_ID', 'TXN_ID');
715
-        $this->_get_table_manager()->addIndex('esp_registration', 'ATT_ID', 'ATT_ID');
716
-        $this->_get_table_manager()->addIndex('esp_registration', 'TKT_ID', 'TKT_ID');
717
-        $this->_get_table_manager()->addIndex('esp_registration', 'EVT_ID', 'EVT_ID');
718
-        $this->_get_table_manager()->dropIndex('esp_registration', 'REG_deleted');
719
-        // $this->_get_table_manager()->dropIndex('esp_registration', 'STS_ID');
720
-
721
-
722
-        $this->_table_has_not_changed_since_previous(
723
-            'esp_registration_payment',
724
-            "RPY_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
703
+		);
704
+		$this->_get_table_manager()->addIndex('esp_registration', 'REG_url_link', 'REG_url_link');
705
+		$this->_get_table_manager()->addIndex('esp_registration', 'REG_code', 'REG_code');
706
+		// $this->_get_table_manager()->addIndex(
707
+		//     'esp_registration',
708
+		//     'REG_date',
709
+		//     'REG_date',
710
+		//     TableAnalysis::INDEX_TYPE_INDEX,
711
+		//     null,
712
+		//     true
713
+		// );
714
+		$this->_get_table_manager()->addIndex('esp_registration', 'TXN_ID', 'TXN_ID');
715
+		$this->_get_table_manager()->addIndex('esp_registration', 'ATT_ID', 'ATT_ID');
716
+		$this->_get_table_manager()->addIndex('esp_registration', 'TKT_ID', 'TKT_ID');
717
+		$this->_get_table_manager()->addIndex('esp_registration', 'EVT_ID', 'EVT_ID');
718
+		$this->_get_table_manager()->dropIndex('esp_registration', 'REG_deleted');
719
+		// $this->_get_table_manager()->dropIndex('esp_registration', 'STS_ID');
720
+
721
+
722
+		$this->_table_has_not_changed_since_previous(
723
+			'esp_registration_payment',
724
+			"RPY_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
725 725
 					  REG_ID int(10) unsigned NOT NULL,
726 726
 					  PAY_ID int(10) unsigned NULL,
727 727
 					  RPY_amount decimal(12,3) NOT NULL DEFAULT '0.00',
728 728
 					  PRIMARY KEY  (RPY_ID)"
729
-        );
730
-        $this->_get_table_manager()->addIndex('esp_registration_payment', 'REG_ID', 'REG_ID');
731
-        $this->_get_table_manager()->addIndex('esp_registration_payment', 'PAY_ID', 'PAY_ID');
729
+		);
730
+		$this->_get_table_manager()->addIndex('esp_registration_payment', 'REG_ID', 'REG_ID');
731
+		$this->_get_table_manager()->addIndex('esp_registration_payment', 'PAY_ID', 'PAY_ID');
732 732
 
733 733
 
734
-        $this->_table_has_not_changed_since_previous(
735
-            'esp_state',
736
-            "STA_ID smallint(5) unsigned NOT NULL AUTO_INCREMENT,
734
+		$this->_table_has_not_changed_since_previous(
735
+			'esp_state',
736
+			"STA_ID smallint(5) unsigned NOT NULL AUTO_INCREMENT,
737 737
 				CNT_ISO varchar(2) NOT NULL,
738 738
 				STA_abbrev varchar(24) NOT NULL,
739 739
 				STA_name varchar(100) NOT NULL,
740 740
 				STA_active tinyint(1) DEFAULT '1',
741 741
 				PRIMARY KEY  (STA_ID)"
742
-        );
743
-        $this->_get_table_manager()->addIndex('esp_state', 'STA_abbrev', 'STA_abbrev');
744
-        $this->_get_table_manager()->addIndex('esp_state', 'CNT_ISO', 'CNT_ISO');
742
+		);
743
+		$this->_get_table_manager()->addIndex('esp_state', 'STA_abbrev', 'STA_abbrev');
744
+		$this->_get_table_manager()->addIndex('esp_state', 'CNT_ISO', 'CNT_ISO');
745 745
 
746 746
 
747
-        $this->_table_has_not_changed_since_previous(
748
-            'esp_status',
749
-            "STS_ID varchar(3) NOT NULL,
747
+		$this->_table_has_not_changed_since_previous(
748
+			'esp_status',
749
+			"STS_ID varchar(3) NOT NULL,
750 750
 				STS_code varchar(45) NOT NULL,
751 751
 				STS_type varchar(45) NOT NULL,
752 752
 				STS_can_edit tinyint(1) NOT NULL DEFAULT 0,
753 753
 				STS_desc tinytext,
754 754
 				STS_open tinyint(1) NOT NULL DEFAULT 1,
755 755
 				PRIMARY KEY  (STS_ID)"
756
-        );
757
-        $this->_get_table_manager()->addIndex('esp_status', 'STS_type', 'STS_type');
758
-        $this->_get_table_manager()->dropIndex('esp_status', 'STS_ID_UNIQUE');
756
+		);
757
+		$this->_get_table_manager()->addIndex('esp_status', 'STS_type', 'STS_type');
758
+		$this->_get_table_manager()->dropIndex('esp_status', 'STS_ID_UNIQUE');
759 759
 
760 760
 
761
-        $this->_table_is_changed_in_this_version(
762
-            'esp_ticket',
763
-            "TKT_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
761
+		$this->_table_is_changed_in_this_version(
762
+			'esp_ticket',
763
+			"TKT_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
764 764
 				TTM_ID int(10) unsigned NOT NULL,
765 765
 				TKT_name varchar(245) NOT NULL DEFAULT '',
766 766
 				TKT_description text NOT NULL,
@@ -784,14 +784,14 @@  discard block
 block discarded – undo
784 784
 				TKT_deleted tinyint(1) NOT NULL DEFAULT '0',
785 785
 				TKT_visibility smallint(6) unsigned NOT NULL DEFAULT 100,
786 786
 				PRIMARY KEY  (TKT_ID)"
787
-        );
788
-        $this->_get_table_manager()->addIndex('esp_ticket', 'TKT_start_date', 'TKT_start_date');
789
-        // $this->_get_table_manager()->addIndex('esp_ticket', 'TKT_end_date', 'TKT_end_date');
787
+		);
788
+		$this->_get_table_manager()->addIndex('esp_ticket', 'TKT_start_date', 'TKT_start_date');
789
+		// $this->_get_table_manager()->addIndex('esp_ticket', 'TKT_end_date', 'TKT_end_date');
790 790
 
791 791
 
792
-        $this->_table_has_not_changed_since_previous(
793
-            'esp_transaction',
794
-            "TXN_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
792
+		$this->_table_has_not_changed_since_previous(
793
+			'esp_transaction',
794
+			"TXN_ID int(10) unsigned NOT NULL AUTO_INCREMENT,
795 795
 				TXN_timestamp datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
796 796
 				TXN_total decimal(12,3) DEFAULT '0.00',
797 797
 				TXN_paid decimal(12,3) NOT NULL DEFAULT '0.00',
@@ -801,21 +801,21 @@  discard block
 block discarded – undo
801 801
 				PMD_ID int(11) DEFAULT NULL,
802 802
 				TXN_reg_steps text,
803 803
 				PRIMARY KEY  (TXN_ID)"
804
-        );
805
-        $this->_get_table_manager()->addIndex(
806
-            'esp_transaction',
807
-            'TXN_timestamp',
808
-            'TXN_timestamp',
809
-            TableAnalysis::INDEX_TYPE_INDEX,
810
-            null,
811
-            true
812
-        );
813
-        // $this->_get_table_manager()->dropIndex('esp_transaction', 'STS_ID');
814
-
815
-
816
-        $this->_table_has_not_changed_since_previous(
817
-            'esp_venue_meta',
818
-            'VNUM_ID int(11) NOT NULL AUTO_INCREMENT,
804
+		);
805
+		$this->_get_table_manager()->addIndex(
806
+			'esp_transaction',
807
+			'TXN_timestamp',
808
+			'TXN_timestamp',
809
+			TableAnalysis::INDEX_TYPE_INDEX,
810
+			null,
811
+			true
812
+		);
813
+		// $this->_get_table_manager()->dropIndex('esp_transaction', 'STS_ID');
814
+
815
+
816
+		$this->_table_has_not_changed_since_previous(
817
+			'esp_venue_meta',
818
+			'VNUM_ID int(11) NOT NULL AUTO_INCREMENT,
819 819
 			VNU_ID bigint(20) unsigned NOT NULL DEFAULT 0,
820 820
 			VNU_address varchar(255) DEFAULT NULL,
821 821
 			VNU_address2 varchar(255) DEFAULT NULL,
@@ -831,29 +831,29 @@  discard block
 block discarded – undo
831 831
 			VNU_enable_for_gmap tinyint(1) DEFAULT 0,
832 832
 			VNU_google_map_link varchar(255) DEFAULT NULL,
833 833
 			PRIMARY KEY  (VNUM_ID)'
834
-        );
835
-        $this->_get_table_manager()->addIndex('esp_venue_meta', 'VNU_ID', 'VNU_ID');
836
-        $this->_get_table_manager()->addIndex('esp_venue_meta', 'STA_ID', 'STA_ID');
837
-        $this->_get_table_manager()->addIndex('esp_venue_meta', 'CNT_ISO', 'CNT_ISO');
834
+		);
835
+		$this->_get_table_manager()->addIndex('esp_venue_meta', 'VNU_ID', 'VNU_ID');
836
+		$this->_get_table_manager()->addIndex('esp_venue_meta', 'STA_ID', 'STA_ID');
837
+		$this->_get_table_manager()->addIndex('esp_venue_meta', 'CNT_ISO', 'CNT_ISO');
838 838
 
839 839
 
840
-        $this->previous_dms->insert_default_data();
841
-        $LegacyTextDomainOptions = new LegacyTextDomainOptions();
842
-        $LegacyTextDomainOptions->convertToConsolidatedFormat();
843
-        return true;
844
-    }
840
+		$this->previous_dms->insert_default_data();
841
+		$LegacyTextDomainOptions = new LegacyTextDomainOptions();
842
+		$LegacyTextDomainOptions->convertToConsolidatedFormat();
843
+		return true;
844
+	}
845 845
 
846 846
 
847
-    /**
848
-     * @return bool
849
-     */
850
-    public function schema_changes_after_migration(): bool
851
-    {
852
-        return true;
853
-    }
847
+	/**
848
+	 * @return bool
849
+	 */
850
+	public function schema_changes_after_migration(): bool
851
+	{
852
+		return true;
853
+	}
854 854
 
855 855
 
856
-    public function migration_page_hooks()
857
-    {
858
-    }
856
+	public function migration_page_hooks()
857
+	{
858
+	}
859 859
 }
Please login to merge, or discard this patch.