Completed
Branch update-venue-ui (4b9c7e)
by
unknown
02:27
created
core/helpers/EEH_Qtip_Loader.helper.php 2 patches
Indentation   +278 added lines, -278 removed lines patch added patch discarded remove patch
@@ -16,282 +16,282 @@
 block discarded – undo
16 16
 class EEH_Qtip_Loader extends EEH_Base
17 17
 {
18 18
 
19
-    /**
20
-     * @var LoaderInterface $loader
21
-     */
22
-    protected $loader;
23
-
24
-    /**
25
-     * @var EEH_Qtip_Loader
26
-     */
27
-    private static $_instance;
28
-
29
-    /**
30
-     * array of qtip config objects
31
-     * @var EE_Qtip_Config[]
32
-     */
33
-    private $_qtips = array();
34
-
35
-
36
-
37
-    /**
38
-     *@singleton method used to instantiate class object
39
-     *@access public
40
-     *@return EEH_Qtip_Loader instance
41
-     */
42
-    public static function instance()
43
-    {
44
-        // check if class object is instantiated
45
-        if (! EEH_Qtip_Loader::$_instance instanceof EEH_Qtip_Loader) {
46
-            EEH_Qtip_Loader::$_instance = new EEH_Qtip_Loader();
47
-        }
48
-        return EEH_Qtip_Loader::$_instance;
49
-    }
50
-
51
-
52
-
53
-    /**
54
-     * private constructor to prevent direct creation
55
-     */
56
-    private function __construct()
57
-    {
58
-        // let's just make sure this is instantiated in the right place.
59
-        if (did_action('wp_print_styles') || did_action('admin_head')) {
60
-            EE_Error::doing_it_wrong(
61
-                'EEH_Qtip_Loader',
62
-                __(
63
-                    'This helper must be instantiated before or within a callback for the WordPress wp_enqueue_scripts hook action hook.',
64
-                    'event_espresso'
65
-                ),
66
-                '4.1'
67
-            );
68
-        }
69
-        $this->loader = LoaderFactory::getLoader();
70
-    }
71
-
72
-
73
-    /**
74
-     * Call this from wp_enqueue_scripts or admin_enqueue_scripts to setup and enqueue the qtip library
75
-     *
76
-     * @access public
77
-     * @return void
78
-     */
79
-    public function register_and_enqueue()
80
-    {
81
-        $qtips_js = !defined('SCRIPT_DEBUG')
82
-            ? EE_THIRD_PARTY_URL . 'qtip/jquery.qtip.min.js'
83
-            : EE_THIRD_PARTY_URL . 'qtip/jquery.qtip.js';
84
-        $qtip_map = EE_THIRD_PARTY_URL . 'qtip/jquery.qtip.min.map';
85
-        $qtip_css = !defined('SCRIPT_DEBUG')
86
-            ? EE_THIRD_PARTY_URL . 'qtip/jquery.qtip.min.css'
87
-            : EE_THIRD_PARTY_URL . 'qtip/jquery.qtip.css';
88
-
89
-        wp_register_script('qtip-map', $qtip_map, array(), '3', true);
90
-        wp_register_script('qtip', $qtips_js, array('jquery'), '3.0.3', true);
91
-        wp_register_script(
92
-            'ee-qtip-helper',
93
-            EE_HELPERS_ASSETS . 'ee-qtip-helper.js',
94
-            array('qtip', JqueryAssetManager::JS_HANDLE_JQUERY_COOKIE),
95
-            EVENT_ESPRESSO_VERSION,
96
-            true
97
-        );
98
-
99
-        wp_register_style('qtip-css', $qtip_css, array(), '2.2');
100
-
101
-        // k now let's see if there are any registered qtips.
102
-        // If there are, then we need to setup the localized script for ee-qtip-helper.js
103
-        // (and enqueue ee-qtip-helper.js of course!)
104
-        if (!empty($this->_qtips)) {
105
-            wp_enqueue_script('ee-qtip-helper');
106
-            wp_enqueue_style('qtip-css');
107
-            $qtips = array();
108
-            foreach ($this->_qtips as $qtip) {
109
-                $qts = $qtip->get_tips();
110
-                foreach ($qts as $qt) {
111
-                    if (! $qt instanceof EE_Qtip) {
112
-                        continue;
113
-                    }
114
-                    $qtips[] = array(
115
-                        'content_id' => $qt->content_id,
116
-                        'options' => $qt->options,
117
-                        'target' => $qt->target,
118
-                        );
119
-                }
120
-            }
121
-            if (!empty($qtips)) {
122
-                wp_localize_script('ee-qtip-helper', 'EE_QTIP_HELPER', array( 'qtips' => $qtips ));
123
-            }
124
-        } else {
125
-            // qtips has been requested without any registration (so assuming its just directly used in the admin).
126
-            wp_enqueue_script('qtip');
127
-            wp_enqueue_style('qtip-css');
128
-        }
129
-    }
130
-
131
-
132
-    /**
133
-     * This simply registers the given qtip config and:
134
-     * - adds it to the $_qtips property array.
135
-     * - sets up the content containers for all qtips in the config,
136
-     * - registers and enqueues the qtip scripts and styles.
137
-     *
138
-     * @access public
139
-     * @param array        $paths      Array of paths to check for the EE_Qtip class. If present we check these path(s)
140
-     *                                 first.  If not present (empty array), then it's assumed it's either in
141
-     *                                 core/libraries/qtips OR the file is already loaded.
142
-     * @param string|array $qtips      name of the Qtip class (full class name is expected and will be used for looking
143
-     *                                 for file, Qtip config classes must extend EE_Qtip_Config) [if this is an array,
144
-     *                                 then we loop through the array to instantiate and setup the qtips]
145
-     * @return void
146
-     * @throws DomainException
147
-     * @throws EE_Error
148
-     * @throws ReflectionException
149
-     */
150
-    public function register($qtips, $paths = array())
151
-    {
152
-        // let's just make sure this is instantiated in the right place.
153
-        if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
154
-            EE_Error::doing_it_wrong(
155
-                'EEH_Qtip_Loader->register()',
156
-                __(
157
-                    'EE_Qtip_Config objects must be registered before wp_enqueue_scripts is called.',
158
-                    'event_espresso'
159
-                ),
160
-                '4.1'
161
-            );
162
-        }
163
-
164
-        $qtips = (array) $qtips; // typecast to array
165
-        foreach ($qtips as $qtip) {
166
-            $this->_qtips[] = $this->_register($qtip, $paths);
167
-        }
168
-
169
-        // hook into appropriate footer
170
-        $footer_action = is_admin() ? 'admin_footer' : 'wp_footer';
171
-        add_action($footer_action, array($this, 'setup_qtip'), 10);
172
-
173
-        // make sure we "turn on" qtip js.
174
-        add_filter('FHEE_load_qtip', '__return_true');
175
-    }
176
-
177
-
178
-    /**
179
-     * private utility for registering and setting up qtip config objects
180
-     *
181
-     * @access private
182
-     * @param string $qtip  the short name of the class (will be used to generate the expected classname)
183
-     * @param array  $paths array of paths to check (or if empty we check core/libraries/qtips or assume its loaded)
184
-     * @return EE_Qtip_Config
185
-     * @throws DomainException
186
-     * @throws EE_Error
187
-     * @throws ReflectionException
188
-     */
189
-    private function _register($qtip, $paths)
190
-    {
191
-        // before doing anything we have to make sure that EE_Qtip_Config parent is required.
192
-        EE_Registry::instance()->load_lib('Qtip_Config', array(), true);
193
-        if (!empty($paths)) {
194
-            $paths = (array) $paths;
195
-            foreach ($paths as $path) {
196
-                $path .= $qtip . '.lib.php';
197
-                if (is_readable($path)) {
198
-                    require_once $path;
199
-                }
200
-            }
201
-        }
202
-
203
-        // does class exist at this point?  If it does then let's instantiate.  If it doesn't then let's continue with other paths.
204
-        if (! class_exists($qtip)) {
205
-            $path = EE_LIBRARIES . 'qtips/' . $qtip . '.lib.php';
206
-            if (! is_readable($path)) {
207
-                throw new DomainException(
208
-                    sprintf(
209
-                        __(
210
-                            'Unable to load the Qtip Config registered for this page (%s) because none of the file paths attempted are readable.  Please check the spelling of the paths you\'ve used in the registration',
211
-                            'event_espresso'
212
-                        ),
213
-                        $qtip
214
-                    )
215
-                );
216
-            }
217
-            require_once $path;
218
-        }
219
-
220
-        // now we attempt a class_exists one more time.
221
-        if (! class_exists($qtip)) {
222
-            throw new DomainException(
223
-                sprintf(
224
-                    __(
225
-                        'The Qtip_Config class being registered (%s) does not exist, please check the spelling.',
226
-                        'event_espresso'
227
-                    ),
228
-                    $qtip
229
-                )
230
-            );
231
-        }
232
-
233
-        // made it HERE?  FINALLY, let's get things setup.
234
-        $qtip_config = $this->loader->getShared($qtip);
235
-
236
-        // verify that $qtip is a valid object
237
-        if (! $qtip_config instanceof EE_Qtip_Config) {
238
-            throw new DomainException(
239
-                sprintf(
240
-                    esc_html__(
241
-                        'The class given for the Qtip loader (%1$s) is not a child of the %2$sEE_Qtip_Config%3$s class. Please make sure you are extending EE_Qtip_Config.',
242
-                        'event_espresso'
243
-                    ),
244
-                    $qtip,
245
-                    '<strong>',
246
-                    '</strong>'
247
-                )
248
-            );
249
-        }
250
-
251
-        return $qtip_config;
252
-    }
253
-
254
-
255
-
256
-    /**
257
-     * This takes care of generating the qtip content containers.
258
-     * Output gets put in the appropriate page footer (depending on context (either admin_footer or wp_footer) )
259
-     *
260
-     * @return void
261
-     */
262
-    public function setup_qtip()
263
-    {
264
-        if (empty($this->_qtips)) {
265
-            return; // no qtips!
266
-        }
267
-
268
-        $content = array();
269
-
270
-        foreach ($this->_qtips as $qtip) {
271
-            $content[] = $this->_generate_content_container($qtip);
272
-        }
273
-
274
-        echo implode('<br />', $content);
275
-    }
276
-
277
-
278
-    /**
279
-     * Generates a content container from a given EE_Qtip_Config object.
280
-     *
281
-     * @param  EE_Qtip_Config $qtip
282
-     * @return string  (html content container for qtip);
283
-     */
284
-    private function _generate_content_container($qtip)
285
-    {
286
-        $qts = $qtip->get_tips();
287
-        $content = array();
288
-        foreach ($qts as $qt) {
289
-            if (! $qt instanceof EE_Qtip) {
290
-                continue;
291
-            }
292
-            $content[] = '<div class="ee-qtip-helper-content hidden" id="' . $qt->content_id . '">' . $qt->content . '</div>';
293
-        }
294
-
295
-        return implode('<br />', $content);
296
-    }
19
+	/**
20
+	 * @var LoaderInterface $loader
21
+	 */
22
+	protected $loader;
23
+
24
+	/**
25
+	 * @var EEH_Qtip_Loader
26
+	 */
27
+	private static $_instance;
28
+
29
+	/**
30
+	 * array of qtip config objects
31
+	 * @var EE_Qtip_Config[]
32
+	 */
33
+	private $_qtips = array();
34
+
35
+
36
+
37
+	/**
38
+	 *@singleton method used to instantiate class object
39
+	 *@access public
40
+	 *@return EEH_Qtip_Loader instance
41
+	 */
42
+	public static function instance()
43
+	{
44
+		// check if class object is instantiated
45
+		if (! EEH_Qtip_Loader::$_instance instanceof EEH_Qtip_Loader) {
46
+			EEH_Qtip_Loader::$_instance = new EEH_Qtip_Loader();
47
+		}
48
+		return EEH_Qtip_Loader::$_instance;
49
+	}
50
+
51
+
52
+
53
+	/**
54
+	 * private constructor to prevent direct creation
55
+	 */
56
+	private function __construct()
57
+	{
58
+		// let's just make sure this is instantiated in the right place.
59
+		if (did_action('wp_print_styles') || did_action('admin_head')) {
60
+			EE_Error::doing_it_wrong(
61
+				'EEH_Qtip_Loader',
62
+				__(
63
+					'This helper must be instantiated before or within a callback for the WordPress wp_enqueue_scripts hook action hook.',
64
+					'event_espresso'
65
+				),
66
+				'4.1'
67
+			);
68
+		}
69
+		$this->loader = LoaderFactory::getLoader();
70
+	}
71
+
72
+
73
+	/**
74
+	 * Call this from wp_enqueue_scripts or admin_enqueue_scripts to setup and enqueue the qtip library
75
+	 *
76
+	 * @access public
77
+	 * @return void
78
+	 */
79
+	public function register_and_enqueue()
80
+	{
81
+		$qtips_js = !defined('SCRIPT_DEBUG')
82
+			? EE_THIRD_PARTY_URL . 'qtip/jquery.qtip.min.js'
83
+			: EE_THIRD_PARTY_URL . 'qtip/jquery.qtip.js';
84
+		$qtip_map = EE_THIRD_PARTY_URL . 'qtip/jquery.qtip.min.map';
85
+		$qtip_css = !defined('SCRIPT_DEBUG')
86
+			? EE_THIRD_PARTY_URL . 'qtip/jquery.qtip.min.css'
87
+			: EE_THIRD_PARTY_URL . 'qtip/jquery.qtip.css';
88
+
89
+		wp_register_script('qtip-map', $qtip_map, array(), '3', true);
90
+		wp_register_script('qtip', $qtips_js, array('jquery'), '3.0.3', true);
91
+		wp_register_script(
92
+			'ee-qtip-helper',
93
+			EE_HELPERS_ASSETS . 'ee-qtip-helper.js',
94
+			array('qtip', JqueryAssetManager::JS_HANDLE_JQUERY_COOKIE),
95
+			EVENT_ESPRESSO_VERSION,
96
+			true
97
+		);
98
+
99
+		wp_register_style('qtip-css', $qtip_css, array(), '2.2');
100
+
101
+		// k now let's see if there are any registered qtips.
102
+		// If there are, then we need to setup the localized script for ee-qtip-helper.js
103
+		// (and enqueue ee-qtip-helper.js of course!)
104
+		if (!empty($this->_qtips)) {
105
+			wp_enqueue_script('ee-qtip-helper');
106
+			wp_enqueue_style('qtip-css');
107
+			$qtips = array();
108
+			foreach ($this->_qtips as $qtip) {
109
+				$qts = $qtip->get_tips();
110
+				foreach ($qts as $qt) {
111
+					if (! $qt instanceof EE_Qtip) {
112
+						continue;
113
+					}
114
+					$qtips[] = array(
115
+						'content_id' => $qt->content_id,
116
+						'options' => $qt->options,
117
+						'target' => $qt->target,
118
+						);
119
+				}
120
+			}
121
+			if (!empty($qtips)) {
122
+				wp_localize_script('ee-qtip-helper', 'EE_QTIP_HELPER', array( 'qtips' => $qtips ));
123
+			}
124
+		} else {
125
+			// qtips has been requested without any registration (so assuming its just directly used in the admin).
126
+			wp_enqueue_script('qtip');
127
+			wp_enqueue_style('qtip-css');
128
+		}
129
+	}
130
+
131
+
132
+	/**
133
+	 * This simply registers the given qtip config and:
134
+	 * - adds it to the $_qtips property array.
135
+	 * - sets up the content containers for all qtips in the config,
136
+	 * - registers and enqueues the qtip scripts and styles.
137
+	 *
138
+	 * @access public
139
+	 * @param array        $paths      Array of paths to check for the EE_Qtip class. If present we check these path(s)
140
+	 *                                 first.  If not present (empty array), then it's assumed it's either in
141
+	 *                                 core/libraries/qtips OR the file is already loaded.
142
+	 * @param string|array $qtips      name of the Qtip class (full class name is expected and will be used for looking
143
+	 *                                 for file, Qtip config classes must extend EE_Qtip_Config) [if this is an array,
144
+	 *                                 then we loop through the array to instantiate and setup the qtips]
145
+	 * @return void
146
+	 * @throws DomainException
147
+	 * @throws EE_Error
148
+	 * @throws ReflectionException
149
+	 */
150
+	public function register($qtips, $paths = array())
151
+	{
152
+		// let's just make sure this is instantiated in the right place.
153
+		if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
154
+			EE_Error::doing_it_wrong(
155
+				'EEH_Qtip_Loader->register()',
156
+				__(
157
+					'EE_Qtip_Config objects must be registered before wp_enqueue_scripts is called.',
158
+					'event_espresso'
159
+				),
160
+				'4.1'
161
+			);
162
+		}
163
+
164
+		$qtips = (array) $qtips; // typecast to array
165
+		foreach ($qtips as $qtip) {
166
+			$this->_qtips[] = $this->_register($qtip, $paths);
167
+		}
168
+
169
+		// hook into appropriate footer
170
+		$footer_action = is_admin() ? 'admin_footer' : 'wp_footer';
171
+		add_action($footer_action, array($this, 'setup_qtip'), 10);
172
+
173
+		// make sure we "turn on" qtip js.
174
+		add_filter('FHEE_load_qtip', '__return_true');
175
+	}
176
+
177
+
178
+	/**
179
+	 * private utility for registering and setting up qtip config objects
180
+	 *
181
+	 * @access private
182
+	 * @param string $qtip  the short name of the class (will be used to generate the expected classname)
183
+	 * @param array  $paths array of paths to check (or if empty we check core/libraries/qtips or assume its loaded)
184
+	 * @return EE_Qtip_Config
185
+	 * @throws DomainException
186
+	 * @throws EE_Error
187
+	 * @throws ReflectionException
188
+	 */
189
+	private function _register($qtip, $paths)
190
+	{
191
+		// before doing anything we have to make sure that EE_Qtip_Config parent is required.
192
+		EE_Registry::instance()->load_lib('Qtip_Config', array(), true);
193
+		if (!empty($paths)) {
194
+			$paths = (array) $paths;
195
+			foreach ($paths as $path) {
196
+				$path .= $qtip . '.lib.php';
197
+				if (is_readable($path)) {
198
+					require_once $path;
199
+				}
200
+			}
201
+		}
202
+
203
+		// does class exist at this point?  If it does then let's instantiate.  If it doesn't then let's continue with other paths.
204
+		if (! class_exists($qtip)) {
205
+			$path = EE_LIBRARIES . 'qtips/' . $qtip . '.lib.php';
206
+			if (! is_readable($path)) {
207
+				throw new DomainException(
208
+					sprintf(
209
+						__(
210
+							'Unable to load the Qtip Config registered for this page (%s) because none of the file paths attempted are readable.  Please check the spelling of the paths you\'ve used in the registration',
211
+							'event_espresso'
212
+						),
213
+						$qtip
214
+					)
215
+				);
216
+			}
217
+			require_once $path;
218
+		}
219
+
220
+		// now we attempt a class_exists one more time.
221
+		if (! class_exists($qtip)) {
222
+			throw new DomainException(
223
+				sprintf(
224
+					__(
225
+						'The Qtip_Config class being registered (%s) does not exist, please check the spelling.',
226
+						'event_espresso'
227
+					),
228
+					$qtip
229
+				)
230
+			);
231
+		}
232
+
233
+		// made it HERE?  FINALLY, let's get things setup.
234
+		$qtip_config = $this->loader->getShared($qtip);
235
+
236
+		// verify that $qtip is a valid object
237
+		if (! $qtip_config instanceof EE_Qtip_Config) {
238
+			throw new DomainException(
239
+				sprintf(
240
+					esc_html__(
241
+						'The class given for the Qtip loader (%1$s) is not a child of the %2$sEE_Qtip_Config%3$s class. Please make sure you are extending EE_Qtip_Config.',
242
+						'event_espresso'
243
+					),
244
+					$qtip,
245
+					'<strong>',
246
+					'</strong>'
247
+				)
248
+			);
249
+		}
250
+
251
+		return $qtip_config;
252
+	}
253
+
254
+
255
+
256
+	/**
257
+	 * This takes care of generating the qtip content containers.
258
+	 * Output gets put in the appropriate page footer (depending on context (either admin_footer or wp_footer) )
259
+	 *
260
+	 * @return void
261
+	 */
262
+	public function setup_qtip()
263
+	{
264
+		if (empty($this->_qtips)) {
265
+			return; // no qtips!
266
+		}
267
+
268
+		$content = array();
269
+
270
+		foreach ($this->_qtips as $qtip) {
271
+			$content[] = $this->_generate_content_container($qtip);
272
+		}
273
+
274
+		echo implode('<br />', $content);
275
+	}
276
+
277
+
278
+	/**
279
+	 * Generates a content container from a given EE_Qtip_Config object.
280
+	 *
281
+	 * @param  EE_Qtip_Config $qtip
282
+	 * @return string  (html content container for qtip);
283
+	 */
284
+	private function _generate_content_container($qtip)
285
+	{
286
+		$qts = $qtip->get_tips();
287
+		$content = array();
288
+		foreach ($qts as $qt) {
289
+			if (! $qt instanceof EE_Qtip) {
290
+				continue;
291
+			}
292
+			$content[] = '<div class="ee-qtip-helper-content hidden" id="' . $qt->content_id . '">' . $qt->content . '</div>';
293
+		}
294
+
295
+		return implode('<br />', $content);
296
+	}
297 297
 }
Please login to merge, or discard this patch.
Spacing   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -42,7 +42,7 @@  discard block
 block discarded – undo
42 42
     public static function instance()
43 43
     {
44 44
         // check if class object is instantiated
45
-        if (! EEH_Qtip_Loader::$_instance instanceof EEH_Qtip_Loader) {
45
+        if ( ! EEH_Qtip_Loader::$_instance instanceof EEH_Qtip_Loader) {
46 46
             EEH_Qtip_Loader::$_instance = new EEH_Qtip_Loader();
47 47
         }
48 48
         return EEH_Qtip_Loader::$_instance;
@@ -78,19 +78,19 @@  discard block
 block discarded – undo
78 78
      */
79 79
     public function register_and_enqueue()
80 80
     {
81
-        $qtips_js = !defined('SCRIPT_DEBUG')
81
+        $qtips_js = ! defined('SCRIPT_DEBUG')
82 82
             ? EE_THIRD_PARTY_URL . 'qtip/jquery.qtip.min.js'
83
-            : EE_THIRD_PARTY_URL . 'qtip/jquery.qtip.js';
84
-        $qtip_map = EE_THIRD_PARTY_URL . 'qtip/jquery.qtip.min.map';
85
-        $qtip_css = !defined('SCRIPT_DEBUG')
83
+            : EE_THIRD_PARTY_URL.'qtip/jquery.qtip.js';
84
+        $qtip_map = EE_THIRD_PARTY_URL.'qtip/jquery.qtip.min.map';
85
+        $qtip_css = ! defined('SCRIPT_DEBUG')
86 86
             ? EE_THIRD_PARTY_URL . 'qtip/jquery.qtip.min.css'
87
-            : EE_THIRD_PARTY_URL . 'qtip/jquery.qtip.css';
87
+            : EE_THIRD_PARTY_URL.'qtip/jquery.qtip.css';
88 88
 
89 89
         wp_register_script('qtip-map', $qtip_map, array(), '3', true);
90 90
         wp_register_script('qtip', $qtips_js, array('jquery'), '3.0.3', true);
91 91
         wp_register_script(
92 92
             'ee-qtip-helper',
93
-            EE_HELPERS_ASSETS . 'ee-qtip-helper.js',
93
+            EE_HELPERS_ASSETS.'ee-qtip-helper.js',
94 94
             array('qtip', JqueryAssetManager::JS_HANDLE_JQUERY_COOKIE),
95 95
             EVENT_ESPRESSO_VERSION,
96 96
             true
@@ -101,14 +101,14 @@  discard block
 block discarded – undo
101 101
         // k now let's see if there are any registered qtips.
102 102
         // If there are, then we need to setup the localized script for ee-qtip-helper.js
103 103
         // (and enqueue ee-qtip-helper.js of course!)
104
-        if (!empty($this->_qtips)) {
104
+        if ( ! empty($this->_qtips)) {
105 105
             wp_enqueue_script('ee-qtip-helper');
106 106
             wp_enqueue_style('qtip-css');
107 107
             $qtips = array();
108 108
             foreach ($this->_qtips as $qtip) {
109 109
                 $qts = $qtip->get_tips();
110 110
                 foreach ($qts as $qt) {
111
-                    if (! $qt instanceof EE_Qtip) {
111
+                    if ( ! $qt instanceof EE_Qtip) {
112 112
                         continue;
113 113
                     }
114 114
                     $qtips[] = array(
@@ -118,8 +118,8 @@  discard block
 block discarded – undo
118 118
                         );
119 119
                 }
120 120
             }
121
-            if (!empty($qtips)) {
122
-                wp_localize_script('ee-qtip-helper', 'EE_QTIP_HELPER', array( 'qtips' => $qtips ));
121
+            if ( ! empty($qtips)) {
122
+                wp_localize_script('ee-qtip-helper', 'EE_QTIP_HELPER', array('qtips' => $qtips));
123 123
             }
124 124
         } else {
125 125
             // qtips has been requested without any registration (so assuming its just directly used in the admin).
@@ -190,10 +190,10 @@  discard block
 block discarded – undo
190 190
     {
191 191
         // before doing anything we have to make sure that EE_Qtip_Config parent is required.
192 192
         EE_Registry::instance()->load_lib('Qtip_Config', array(), true);
193
-        if (!empty($paths)) {
193
+        if ( ! empty($paths)) {
194 194
             $paths = (array) $paths;
195 195
             foreach ($paths as $path) {
196
-                $path .= $qtip . '.lib.php';
196
+                $path .= $qtip.'.lib.php';
197 197
                 if (is_readable($path)) {
198 198
                     require_once $path;
199 199
                 }
@@ -201,9 +201,9 @@  discard block
 block discarded – undo
201 201
         }
202 202
 
203 203
         // does class exist at this point?  If it does then let's instantiate.  If it doesn't then let's continue with other paths.
204
-        if (! class_exists($qtip)) {
205
-            $path = EE_LIBRARIES . 'qtips/' . $qtip . '.lib.php';
206
-            if (! is_readable($path)) {
204
+        if ( ! class_exists($qtip)) {
205
+            $path = EE_LIBRARIES.'qtips/'.$qtip.'.lib.php';
206
+            if ( ! is_readable($path)) {
207 207
                 throw new DomainException(
208 208
                     sprintf(
209 209
                         __(
@@ -218,7 +218,7 @@  discard block
 block discarded – undo
218 218
         }
219 219
 
220 220
         // now we attempt a class_exists one more time.
221
-        if (! class_exists($qtip)) {
221
+        if ( ! class_exists($qtip)) {
222 222
             throw new DomainException(
223 223
                 sprintf(
224 224
                     __(
@@ -234,7 +234,7 @@  discard block
 block discarded – undo
234 234
         $qtip_config = $this->loader->getShared($qtip);
235 235
 
236 236
         // verify that $qtip is a valid object
237
-        if (! $qtip_config instanceof EE_Qtip_Config) {
237
+        if ( ! $qtip_config instanceof EE_Qtip_Config) {
238 238
             throw new DomainException(
239 239
                 sprintf(
240 240
                     esc_html__(
@@ -286,10 +286,10 @@  discard block
 block discarded – undo
286 286
         $qts = $qtip->get_tips();
287 287
         $content = array();
288 288
         foreach ($qts as $qt) {
289
-            if (! $qt instanceof EE_Qtip) {
289
+            if ( ! $qt instanceof EE_Qtip) {
290 290
                 continue;
291 291
             }
292
-            $content[] = '<div class="ee-qtip-helper-content hidden" id="' . $qt->content_id . '">' . $qt->content . '</div>';
292
+            $content[] = '<div class="ee-qtip-helper-content hidden" id="'.$qt->content_id.'">'.$qt->content.'</div>';
293 293
         }
294 294
 
295 295
         return implode('<br />', $content);
Please login to merge, or discard this patch.
core/helpers/EEH_Line_Item.helper.php 2 patches
Spacing   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -138,7 +138,7 @@  discard block
 block discarded – undo
138 138
      */
139 139
     public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
140 140
     {
141
-        if (! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) {
141
+        if ( ! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) {
142 142
             throw new EE_Error(
143 143
                 sprintf(
144 144
                     esc_html__(
@@ -153,7 +153,7 @@  discard block
 block discarded – undo
153 153
         // either increment the qty for an existing ticket
154 154
         $line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty);
155 155
         // or add a new one
156
-        if (! $line_item instanceof EE_Line_Item) {
156
+        if ( ! $line_item instanceof EE_Line_Item) {
157 157
             $line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty);
158 158
         }
159 159
         $total_line_item->recalculate_total_including_taxes();
@@ -214,7 +214,7 @@  discard block
 block discarded – undo
214 214
      */
215 215
     public static function increment_quantity(EE_Line_Item $line_item, $qty = 1)
216 216
     {
217
-        if (! $line_item->is_percent()) {
217
+        if ( ! $line_item->is_percent()) {
218 218
             $qty += $line_item->quantity();
219 219
             $line_item->set_quantity($qty);
220 220
             $line_item->set_total($line_item->unit_price() * $qty);
@@ -243,7 +243,7 @@  discard block
 block discarded – undo
243 243
      */
244 244
     public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1)
245 245
     {
246
-        if (! $line_item->is_percent()) {
246
+        if ( ! $line_item->is_percent()) {
247 247
             $qty = $line_item->quantity() - $qty;
248 248
             $qty = max($qty, 0);
249 249
             $line_item->set_quantity($qty);
@@ -272,7 +272,7 @@  discard block
 block discarded – undo
272 272
      */
273 273
     public static function update_quantity(EE_Line_Item $line_item, $new_quantity)
274 274
     {
275
-        if (! $line_item->is_percent()) {
275
+        if ( ! $line_item->is_percent()) {
276 276
             $line_item->set_quantity($new_quantity);
277 277
             $line_item->set_total($line_item->unit_price() * $new_quantity);
278 278
             $line_item->save();
@@ -314,7 +314,7 @@  discard block
 block discarded – undo
314 314
         // add $ticket to cart
315 315
         $line_item = EE_Line_Item::new_instance(array(
316 316
             'LIN_name'       => $ticket->name(),
317
-            'LIN_desc'       => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event,
317
+            'LIN_desc'       => $ticket->description() !== '' ? $ticket->description().' '.$event : $event,
318 318
             'LIN_unit_price' => $ticket->price(),
319 319
             'LIN_quantity'   => $qty,
320 320
             'LIN_is_taxable' => $is_taxable,
@@ -464,7 +464,7 @@  discard block
 block discarded – undo
464 464
                         'event_espresso'
465 465
                     ),
466 466
                     $ticket_line_item->name(),
467
-                    current_time(get_option('date_format') . ' ' . get_option('time_format'))
467
+                    current_time(get_option('date_format').' '.get_option('time_format'))
468 468
                 ),
469 469
                 'LIN_unit_price' => 0, // $ticket_line_item->unit_price()
470 470
                 'LIN_quantity'   => $qty,
@@ -526,7 +526,7 @@  discard block
 block discarded – undo
526 526
         );
527 527
         $cancellation_line_item = reset($cancellation_line_item);
528 528
         // verify that this ticket was indeed previously cancelled
529
-        if (! $cancellation_line_item instanceof EE_Line_Item) {
529
+        if ( ! $cancellation_line_item instanceof EE_Line_Item) {
530 530
             return false;
531 531
         }
532 532
         if ($cancellation_line_item->quantity() > $qty) {
@@ -731,7 +731,7 @@  discard block
 block discarded – undo
731 731
             'LIN_code'  => 'taxes',
732 732
             'LIN_name'  => esc_html__('Taxes', 'event_espresso'),
733 733
             'LIN_type'  => EEM_Line_Item::type_tax_sub_total,
734
-            'LIN_order' => 1000,// this should always come last
734
+            'LIN_order' => 1000, // this should always come last
735 735
         ));
736 736
         $tax_line_item = apply_filters(
737 737
             'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item',
@@ -787,7 +787,7 @@  discard block
 block discarded – undo
787 787
      */
788 788
     public static function get_event_code($event)
789 789
     {
790
-        return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0');
790
+        return 'event-'.($event instanceof EE_Event ? $event->ID() : '0');
791 791
     }
792 792
 
793 793
 
@@ -836,7 +836,7 @@  discard block
 block discarded – undo
836 836
     public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket)
837 837
     {
838 838
         $first_datetime = $ticket->first_datetime();
839
-        if (! $first_datetime instanceof EE_Datetime) {
839
+        if ( ! $first_datetime instanceof EE_Datetime) {
840 840
             throw new EE_Error(
841 841
                 sprintf(
842 842
                     __('The supplied ticket (ID %d) has no datetimes', 'event_espresso'),
@@ -845,7 +845,7 @@  discard block
 block discarded – undo
845 845
             );
846 846
         }
847 847
         $event = $first_datetime->event();
848
-        if (! $event instanceof EE_Event) {
848
+        if ( ! $event instanceof EE_Event) {
849 849
             throw new EE_Error(
850 850
                 sprintf(
851 851
                     esc_html__(
@@ -857,7 +857,7 @@  discard block
 block discarded – undo
857 857
             );
858 858
         }
859 859
         $events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event);
860
-        if (! $events_sub_total instanceof EE_Line_Item) {
860
+        if ( ! $events_sub_total instanceof EE_Line_Item) {
861 861
             throw new EE_Error(
862 862
                 sprintf(
863 863
                     esc_html__(
@@ -893,7 +893,7 @@  discard block
 block discarded – undo
893 893
         $found = false;
894 894
         foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) {
895 895
             // default event subtotal, we should only ever find this the first time this method is called
896
-            if (! $event_line_item->OBJ_ID()) {
896
+            if ( ! $event_line_item->OBJ_ID()) {
897 897
                 // let's use this! but first... set the event details
898 898
                 EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
899 899
                 $found = true;
@@ -905,7 +905,7 @@  discard block
 block discarded – undo
905 905
                 break;
906 906
             }
907 907
         }
908
-        if (! $found) {
908
+        if ( ! $found) {
909 909
             // there is no event sub-total yet, so add it
910 910
             $pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total);
911 911
             // create a new "event" subtotal below that
@@ -1022,7 +1022,7 @@  discard block
 block discarded – undo
1022 1022
     public static function ensure_taxes_applied($total_line_item)
1023 1023
     {
1024 1024
         $taxes_subtotal = self::get_taxes_subtotal($total_line_item);
1025
-        if (! $taxes_subtotal->children()) {
1025
+        if ( ! $taxes_subtotal->children()) {
1026 1026
             self::apply_taxes($total_line_item);
1027 1027
         }
1028 1028
         return $taxes_subtotal->total();
@@ -1089,7 +1089,7 @@  discard block
 block discarded – undo
1089 1089
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1090 1090
 
1091 1091
         // check if only a single line_item_id was passed
1092
-        if (! empty($line_item_codes) && ! is_array($line_item_codes)) {
1092
+        if ( ! empty($line_item_codes) && ! is_array($line_item_codes)) {
1093 1093
             // place single line_item_id in an array to appear as multiple line_item_ids
1094 1094
             $line_item_codes = array($line_item_codes);
1095 1095
         }
@@ -1196,7 +1196,7 @@  discard block
 block discarded – undo
1196 1196
         if ($code_substring_for_whitelist !== null) {
1197 1197
             $whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false;
1198 1198
         }
1199
-        if (! $whitelisted && $line_item->is_line_item()) {
1199
+        if ( ! $whitelisted && $line_item->is_line_item()) {
1200 1200
             $line_item->set_is_taxable($taxable);
1201 1201
         }
1202 1202
         foreach ($line_item->children() as $child_line_item) {
@@ -1558,7 +1558,7 @@  discard block
 block discarded – undo
1558 1558
     public static function visualize(EE_Line_Item $line_item, $indentation = 0)
1559 1559
     {
1560 1560
         echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1561
-        if (! $indentation) {
1561
+        if ( ! $indentation) {
1562 1562
             echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1563 1563
         }
1564 1564
         for ($i = 0; $i < $indentation; $i++) {
@@ -1569,12 +1569,12 @@  discard block
 block discarded – undo
1569 1569
             if ($line_item->is_percent()) {
1570 1570
                 $breakdown = "{$line_item->percent()}%";
1571 1571
             } else {
1572
-                $breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}";
1572
+                $breakdown = '$'."{$line_item->unit_price()} x {$line_item->quantity()}";
1573 1573
             }
1574 1574
         }
1575 1575
         echo $line_item->name();
1576 1576
         echo " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : ";
1577
-        echo '$' . (string) $line_item->total();
1577
+        echo '$'.(string) $line_item->total();
1578 1578
         if ($breakdown) {
1579 1579
             echo " ( {$breakdown} )";
1580 1580
         }
@@ -1662,8 +1662,8 @@  discard block
 block discarded – undo
1662 1662
                         if ($line_item_id === 'taxable') {
1663 1663
                             continue;
1664 1664
                         }
1665
-                        $taxable_total = $running_totals['taxable'][ $line_item_id ];
1666
-                        $running_totals[ $line_item_id ] += ($taxable_total * $tax_percent_decimal);
1665
+                        $taxable_total = $running_totals['taxable'][$line_item_id];
1666
+                        $running_totals[$line_item_id] += ($taxable_total * $tax_percent_decimal);
1667 1667
                     }
1668 1668
                     break;
1669 1669
 
@@ -1671,7 +1671,7 @@  discard block
 block discarded – undo
1671 1671
                     // ticket line items or ????
1672 1672
                     if ($child_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) {
1673 1673
                         // kk it's a ticket
1674
-                        if (isset($running_totals[ $child_line_item->ID() ])) {
1674
+                        if (isset($running_totals[$child_line_item->ID()])) {
1675 1675
                             // huh? that shouldn't happen.
1676 1676
                             $running_totals['total'] += $child_line_item->total();
1677 1677
                         } else {
@@ -1682,18 +1682,18 @@  discard block
 block discarded – undo
1682 1682
                                 $taxable_amount = 0;
1683 1683
                             }
1684 1684
                             // are we only calculating totals for some tickets?
1685
-                            if (isset($billable_ticket_quantities[ $child_line_item->OBJ_ID() ])) {
1686
-                                $quantity = $billable_ticket_quantities[ $child_line_item->OBJ_ID() ];
1687
-                                $running_totals[ $child_line_item->ID() ] = $quantity
1685
+                            if (isset($billable_ticket_quantities[$child_line_item->OBJ_ID()])) {
1686
+                                $quantity = $billable_ticket_quantities[$child_line_item->OBJ_ID()];
1687
+                                $running_totals[$child_line_item->ID()] = $quantity
1688 1688
                                     ? $child_line_item->unit_price()
1689 1689
                                     : 0;
1690
-                                $running_totals['taxable'][ $child_line_item->ID() ] = $quantity
1690
+                                $running_totals['taxable'][$child_line_item->ID()] = $quantity
1691 1691
                                     ? $taxable_amount
1692 1692
                                     : 0;
1693 1693
                             } else {
1694 1694
                                 $quantity = $child_line_item->quantity();
1695
-                                $running_totals[ $child_line_item->ID() ] = $child_line_item->unit_price();
1696
-                                $running_totals['taxable'][ $child_line_item->ID() ] = $taxable_amount;
1695
+                                $running_totals[$child_line_item->ID()] = $child_line_item->unit_price();
1696
+                                $running_totals['taxable'][$child_line_item->ID()] = $taxable_amount;
1697 1697
                             }
1698 1698
                             $running_totals['taxable']['total'] += $taxable_amount * $quantity;
1699 1699
                             $running_totals['total'] += $child_line_item->unit_price() * $quantity;
@@ -1713,12 +1713,12 @@  discard block
 block discarded – undo
1713 1713
                             }
1714 1714
                             // update the running totals
1715 1715
                             // yes this actually even works for the running grand total!
1716
-                            $running_totals[ $line_item_id ] =
1716
+                            $running_totals[$line_item_id] =
1717 1717
                                 $line_items_percent_of_running_total * $this_running_total;
1718 1718
 
1719 1719
                             if ($child_line_item->is_taxable()) {
1720
-                                $running_totals['taxable'][ $line_item_id ] =
1721
-                                    $line_items_percent_of_running_total * $running_totals['taxable'][ $line_item_id ];
1720
+                                $running_totals['taxable'][$line_item_id] =
1721
+                                    $line_items_percent_of_running_total * $running_totals['taxable'][$line_item_id];
1722 1722
                             }
1723 1723
                         }
1724 1724
                     }
@@ -1745,14 +1745,14 @@  discard block
 block discarded – undo
1745 1745
         EE_Line_Item $ticket_line_item
1746 1746
     ) {
1747 1747
         static $final_prices_per_ticket_line_item = array();
1748
-        if (empty($final_prices_per_ticket_line_item) || empty($final_prices_per_ticket_line_item[ $total_line_item->ID() ])) {
1749
-            $final_prices_per_ticket_line_item[ $total_line_item->ID() ] = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1748
+        if (empty($final_prices_per_ticket_line_item) || empty($final_prices_per_ticket_line_item[$total_line_item->ID()])) {
1749
+            $final_prices_per_ticket_line_item[$total_line_item->ID()] = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1750 1750
                 $total_line_item
1751 1751
             );
1752 1752
         }
1753 1753
         // ok now find this new registration's final price
1754
-        if (isset($final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ])) {
1755
-            return $final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ];
1754
+        if (isset($final_prices_per_ticket_line_item[$total_line_item->ID()][$ticket_line_item->ID()])) {
1755
+            return $final_prices_per_ticket_line_item[$total_line_item->ID()][$ticket_line_item->ID()];
1756 1756
         }
1757 1757
         $message = sprintf(
1758 1758
             esc_html__(
@@ -1762,7 +1762,7 @@  discard block
 block discarded – undo
1762 1762
             $ticket_line_item->ID()
1763 1763
         );
1764 1764
         if (WP_DEBUG) {
1765
-            $message .= '<br>' . print_r($final_prices_per_ticket_line_item, true);
1765
+            $message .= '<br>'.print_r($final_prices_per_ticket_line_item, true);
1766 1766
             throw new OutOfRangeException($message);
1767 1767
         }
1768 1768
         EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message);
Please login to merge, or discard this patch.
Indentation   +2055 added lines, -2055 removed lines patch added patch discarded remove patch
@@ -21,2059 +21,2059 @@
 block discarded – undo
21 21
 class EEH_Line_Item
22 22
 {
23 23
 
24
-    /**
25
-     * Adds a simple item (unrelated to any other model object) to the provided PARENT line item.
26
-     * Does NOT automatically re-calculate the line item totals or update the related transaction.
27
-     * You should call recalculate_total_including_taxes() on the grant total line item after this
28
-     * to update the subtotals, and EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
29
-     * to keep the registration final prices in-sync with the transaction's total.
30
-     *
31
-     * @param EE_Line_Item $parent_line_item
32
-     * @param string       $name
33
-     * @param float        $unit_price
34
-     * @param string       $description
35
-     * @param int          $quantity
36
-     * @param boolean      $taxable
37
-     * @param boolean      $code if set to a value, ensures there is only one line item with that code
38
-     * @return boolean success
39
-     * @throws EE_Error
40
-     * @throws InvalidArgumentException
41
-     * @throws InvalidDataTypeException
42
-     * @throws InvalidInterfaceException
43
-     * @throws ReflectionException
44
-     */
45
-    public static function add_unrelated_item(
46
-        EE_Line_Item $parent_line_item,
47
-        $name,
48
-        $unit_price,
49
-        $description = '',
50
-        $quantity = 1,
51
-        $taxable = false,
52
-        $code = null
53
-    ) {
54
-        $items_subtotal = self::get_pre_tax_subtotal($parent_line_item);
55
-        $line_item = EE_Line_Item::new_instance(array(
56
-            'LIN_name'       => $name,
57
-            'LIN_desc'       => $description,
58
-            'LIN_unit_price' => $unit_price,
59
-            'LIN_quantity'   => $quantity,
60
-            'LIN_percent'    => null,
61
-            'LIN_is_taxable' => $taxable,
62
-            'LIN_order'      => $items_subtotal instanceof EE_Line_Item ? count($items_subtotal->children()) : 0,
63
-            'LIN_total'      => (float) $unit_price * (int) $quantity,
64
-            'LIN_type'       => EEM_Line_Item::type_line_item,
65
-            'LIN_code'       => $code,
66
-        ));
67
-        $line_item = apply_filters(
68
-            'FHEE__EEH_Line_Item__add_unrelated_item__line_item',
69
-            $line_item,
70
-            $parent_line_item
71
-        );
72
-        return self::add_item($parent_line_item, $line_item);
73
-    }
74
-
75
-
76
-    /**
77
-     * Adds a simple item ( unrelated to any other model object) to the total line item,
78
-     * in the correct spot in the line item tree. Does not automatically
79
-     * re-calculate the line item totals, nor update the related transaction, nor upgrade the transaction's
80
-     * registrations' final prices (which should probably change because of this).
81
-     * You should call recalculate_total_including_taxes() on the grand total line item, then
82
-     * update the transaction's total, and EE_Registration_Processor::update_registration_final_prices()
83
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
84
-     *
85
-     * @param EE_Line_Item $parent_line_item
86
-     * @param string       $name
87
-     * @param float        $percentage_amount
88
-     * @param string       $description
89
-     * @param boolean      $taxable
90
-     * @return boolean success
91
-     * @throws EE_Error
92
-     */
93
-    public static function add_percentage_based_item(
94
-        EE_Line_Item $parent_line_item,
95
-        $name,
96
-        $percentage_amount,
97
-        $description = '',
98
-        $taxable = false
99
-    ) {
100
-        $line_item = EE_Line_Item::new_instance(array(
101
-            'LIN_name'       => $name,
102
-            'LIN_desc'       => $description,
103
-            'LIN_unit_price' => 0,
104
-            'LIN_percent'    => $percentage_amount,
105
-            'LIN_quantity'   => 1,
106
-            'LIN_is_taxable' => $taxable,
107
-            'LIN_total'      => (float) ($percentage_amount * ($parent_line_item->total() / 100)),
108
-            'LIN_type'       => EEM_Line_Item::type_line_item,
109
-            'LIN_parent'     => $parent_line_item->ID(),
110
-        ));
111
-        $line_item = apply_filters(
112
-            'FHEE__EEH_Line_Item__add_percentage_based_item__line_item',
113
-            $line_item
114
-        );
115
-        return $parent_line_item->add_child_line_item($line_item, false);
116
-    }
117
-
118
-
119
-    /**
120
-     * Returns the new line item created by adding a purchase of the ticket
121
-     * ensures that ticket line item is saved, and that cart total has been recalculated.
122
-     * If this ticket has already been purchased, just increments its count.
123
-     * Automatically re-calculates the line item totals and updates the related transaction. But
124
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
125
-     * should probably change because of this).
126
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
127
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
128
-     *
129
-     * @param EE_Line_Item $total_line_item grand total line item of type EEM_Line_Item::type_total
130
-     * @param EE_Ticket    $ticket
131
-     * @param int          $qty
132
-     * @return EE_Line_Item
133
-     * @throws EE_Error
134
-     * @throws InvalidArgumentException
135
-     * @throws InvalidDataTypeException
136
-     * @throws InvalidInterfaceException
137
-     * @throws ReflectionException
138
-     */
139
-    public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
140
-    {
141
-        if (! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) {
142
-            throw new EE_Error(
143
-                sprintf(
144
-                    esc_html__(
145
-                        'A valid line item total is required in order to add tickets. A line item of type "%s" was passed.',
146
-                        'event_espresso'
147
-                    ),
148
-                    $ticket->ID(),
149
-                    $total_line_item->ID()
150
-                )
151
-            );
152
-        }
153
-        // either increment the qty for an existing ticket
154
-        $line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty);
155
-        // or add a new one
156
-        if (! $line_item instanceof EE_Line_Item) {
157
-            $line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty);
158
-        }
159
-        $total_line_item->recalculate_total_including_taxes();
160
-        return $line_item;
161
-    }
162
-
163
-
164
-    /**
165
-     * Returns the new line item created by adding a purchase of the ticket
166
-     *
167
-     * @param EE_Line_Item $total_line_item
168
-     * @param EE_Ticket    $ticket
169
-     * @param int          $qty
170
-     * @return EE_Line_Item
171
-     * @throws EE_Error
172
-     * @throws InvalidArgumentException
173
-     * @throws InvalidDataTypeException
174
-     * @throws InvalidInterfaceException
175
-     * @throws ReflectionException
176
-     */
177
-    public static function increment_ticket_qty_if_already_in_cart(
178
-        EE_Line_Item $total_line_item,
179
-        EE_Ticket $ticket,
180
-        $qty = 1
181
-    ) {
182
-        $line_item = null;
183
-        if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) {
184
-            $ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
185
-            foreach ((array) $ticket_line_items as $ticket_line_item) {
186
-                if (
187
-                    $ticket_line_item instanceof EE_Line_Item
188
-                    && (int) $ticket_line_item->OBJ_ID() === (int) $ticket->ID()
189
-                ) {
190
-                    $line_item = $ticket_line_item;
191
-                    break;
192
-                }
193
-            }
194
-        }
195
-        if ($line_item instanceof EE_Line_Item) {
196
-            EEH_Line_Item::increment_quantity($line_item, $qty);
197
-            return $line_item;
198
-        }
199
-        return null;
200
-    }
201
-
202
-
203
-    /**
204
-     * Increments the line item and all its children's quantity by $qty (but percent line items are unaffected).
205
-     * Does NOT save or recalculate other line items totals
206
-     *
207
-     * @param EE_Line_Item $line_item
208
-     * @param int          $qty
209
-     * @return void
210
-     * @throws EE_Error
211
-     * @throws InvalidArgumentException
212
-     * @throws InvalidDataTypeException
213
-     * @throws InvalidInterfaceException
214
-     * @throws ReflectionException
215
-     */
216
-    public static function increment_quantity(EE_Line_Item $line_item, $qty = 1)
217
-    {
218
-        if (! $line_item->is_percent()) {
219
-            $qty += $line_item->quantity();
220
-            $line_item->set_quantity($qty);
221
-            $line_item->set_total($line_item->unit_price() * $qty);
222
-            $line_item->save();
223
-        }
224
-        foreach ($line_item->children() as $child) {
225
-            if ($child->is_sub_line_item()) {
226
-                EEH_Line_Item::update_quantity($child, $qty);
227
-            }
228
-        }
229
-    }
230
-
231
-
232
-    /**
233
-     * Decrements the line item and all its children's quantity by $qty (but percent line items are unaffected).
234
-     * Does NOT save or recalculate other line items totals
235
-     *
236
-     * @param EE_Line_Item $line_item
237
-     * @param int          $qty
238
-     * @return void
239
-     * @throws EE_Error
240
-     * @throws InvalidArgumentException
241
-     * @throws InvalidDataTypeException
242
-     * @throws InvalidInterfaceException
243
-     * @throws ReflectionException
244
-     */
245
-    public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1)
246
-    {
247
-        if (! $line_item->is_percent()) {
248
-            $qty = $line_item->quantity() - $qty;
249
-            $qty = max($qty, 0);
250
-            $line_item->set_quantity($qty);
251
-            $line_item->set_total($line_item->unit_price() * $qty);
252
-            $line_item->save();
253
-        }
254
-        foreach ($line_item->children() as $child) {
255
-            if ($child->is_sub_line_item()) {
256
-                EEH_Line_Item::update_quantity($child, $qty);
257
-            }
258
-        }
259
-    }
260
-
261
-
262
-    /**
263
-     * Updates the line item and its children's quantities to the specified number.
264
-     * Does NOT save them or recalculate totals.
265
-     *
266
-     * @param EE_Line_Item $line_item
267
-     * @param int          $new_quantity
268
-     * @throws EE_Error
269
-     * @throws InvalidArgumentException
270
-     * @throws InvalidDataTypeException
271
-     * @throws InvalidInterfaceException
272
-     * @throws ReflectionException
273
-     */
274
-    public static function update_quantity(EE_Line_Item $line_item, $new_quantity)
275
-    {
276
-        if (! $line_item->is_percent()) {
277
-            $line_item->set_quantity($new_quantity);
278
-            $line_item->set_total($line_item->unit_price() * $new_quantity);
279
-            $line_item->save();
280
-        }
281
-        foreach ($line_item->children() as $child) {
282
-            if ($child->is_sub_line_item()) {
283
-                EEH_Line_Item::update_quantity($child, $new_quantity);
284
-            }
285
-        }
286
-    }
287
-
288
-
289
-    /**
290
-     * Returns the new line item created by adding a purchase of the ticket
291
-     *
292
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
293
-     * @param EE_Ticket    $ticket
294
-     * @param int          $qty
295
-     * @return EE_Line_Item
296
-     * @throws EE_Error
297
-     * @throws InvalidArgumentException
298
-     * @throws InvalidDataTypeException
299
-     * @throws InvalidInterfaceException
300
-     * @throws ReflectionException
301
-     */
302
-    public static function create_ticket_line_item(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
303
-    {
304
-        $datetimes = $ticket->datetimes();
305
-        $first_datetime = reset($datetimes);
306
-        $first_datetime_name = esc_html__('Event', 'event_espresso');
307
-        if ($first_datetime instanceof EE_Datetime && $first_datetime->event() instanceof EE_Event) {
308
-            $first_datetime_name = $first_datetime->event()->name();
309
-        }
310
-        $event = sprintf(_x('(For %1$s)', '(For Event Name)', 'event_espresso'), $first_datetime_name);
311
-        // get event subtotal line
312
-        $events_sub_total = self::get_event_line_item_for_ticket($total_line_item, $ticket);
313
-        $taxes = $ticket->tax_price_modifiers();
314
-        $is_taxable = empty($taxes) ? $ticket->taxable() : false;
315
-        // add $ticket to cart
316
-        $line_item = EE_Line_Item::new_instance(array(
317
-            'LIN_name'       => $ticket->name(),
318
-            'LIN_desc'       => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event,
319
-            'LIN_unit_price' => $ticket->price(),
320
-            'LIN_quantity'   => $qty,
321
-            'LIN_is_taxable' => $is_taxable,
322
-            'LIN_order'      => count($events_sub_total->children()),
323
-            'LIN_total'      => $ticket->price() * $qty,
324
-            'LIN_type'       => EEM_Line_Item::type_line_item,
325
-            'OBJ_ID'         => $ticket->ID(),
326
-            'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_TICKET,
327
-        ));
328
-        $line_item = apply_filters(
329
-            'FHEE__EEH_Line_Item__create_ticket_line_item__line_item',
330
-            $line_item
331
-        );
332
-        $events_sub_total->add_child_line_item($line_item);
333
-        // now add the sub-line items
334
-        $running_total_for_ticket = 0;
335
-        foreach ($ticket->prices(array('order_by' => array('PRC_order' => 'ASC'))) as $price) {
336
-            $sign = $price->is_discount() ? -1 : 1;
337
-            $price_total = $price->is_percent()
338
-                ? $running_total_for_ticket * $price->amount() / 100
339
-                : $price->amount() * $qty;
340
-            $sub_line_item = EE_Line_Item::new_instance(array(
341
-                'LIN_name'       => $price->name(),
342
-                'LIN_desc'       => $price->desc(),
343
-                'LIN_quantity'   => $price->is_percent() ? null : $qty,
344
-                'LIN_is_taxable' => false,
345
-                'LIN_order'      => $price->order(),
346
-                'LIN_total'      => $sign * $price_total,
347
-                'LIN_type'       => EEM_Line_Item::type_sub_line_item,
348
-                'OBJ_ID'         => $price->ID(),
349
-                'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_PRICE,
350
-            ));
351
-            $sub_line_item = apply_filters(
352
-                'FHEE__EEH_Line_Item__create_ticket_line_item__sub_line_item',
353
-                $sub_line_item
354
-            );
355
-            if ($price->is_percent()) {
356
-                $sub_line_item->set_percent($sign * $price->amount());
357
-            } else {
358
-                $sub_line_item->set_unit_price($sign * $price->amount());
359
-            }
360
-            $running_total_for_ticket += $price_total;
361
-            $line_item->add_child_line_item($sub_line_item);
362
-        }
363
-        return $line_item;
364
-    }
365
-
366
-
367
-    /**
368
-     * Adds the specified item under the pre-tax-sub-total line item. Automatically
369
-     * re-calculates the line item totals and updates the related transaction. But
370
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
371
-     * should probably change because of this).
372
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
373
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
374
-     *
375
-     * @param EE_Line_Item $total_line_item
376
-     * @param EE_Line_Item $item to be added
377
-     * @return boolean
378
-     * @throws EE_Error
379
-     * @throws InvalidArgumentException
380
-     * @throws InvalidDataTypeException
381
-     * @throws InvalidInterfaceException
382
-     * @throws ReflectionException
383
-     */
384
-    public static function add_item(EE_Line_Item $total_line_item, EE_Line_Item $item)
385
-    {
386
-        $pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item);
387
-        if ($pre_tax_subtotal instanceof EE_Line_Item) {
388
-            $success = $pre_tax_subtotal->add_child_line_item($item);
389
-        } else {
390
-            return false;
391
-        }
392
-        $total_line_item->recalculate_total_including_taxes();
393
-        return $success;
394
-    }
395
-
396
-
397
-    /**
398
-     * cancels an existing ticket line item,
399
-     * by decrementing it's quantity by 1 and adding a new "type_cancellation" sub-line-item.
400
-     * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
401
-     *
402
-     * @param EE_Line_Item $ticket_line_item
403
-     * @param int          $qty
404
-     * @return bool success
405
-     * @throws EE_Error
406
-     * @throws InvalidArgumentException
407
-     * @throws InvalidDataTypeException
408
-     * @throws InvalidInterfaceException
409
-     * @throws ReflectionException
410
-     */
411
-    public static function cancel_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
412
-    {
413
-        // validate incoming line_item
414
-        if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) {
415
-            throw new EE_Error(
416
-                sprintf(
417
-                    esc_html__(
418
-                        'The supplied line item must have an Object Type of "Ticket", not %1$s.',
419
-                        'event_espresso'
420
-                    ),
421
-                    $ticket_line_item->type()
422
-                )
423
-            );
424
-        }
425
-        if ($ticket_line_item->quantity() < $qty) {
426
-            throw new EE_Error(
427
-                sprintf(
428
-                    esc_html__(
429
-                        'Can not cancel %1$d ticket(s) because the supplied line item has a quantity of %2$d.',
430
-                        'event_espresso'
431
-                    ),
432
-                    $qty,
433
-                    $ticket_line_item->quantity()
434
-                )
435
-            );
436
-        }
437
-        // decrement ticket quantity; don't rely on auto-fixing when recalculating totals to do this
438
-        $ticket_line_item->set_quantity($ticket_line_item->quantity() - $qty);
439
-        foreach ($ticket_line_item->children() as $child_line_item) {
440
-            if (
441
-                $child_line_item->is_sub_line_item()
442
-                && ! $child_line_item->is_percent()
443
-                && ! $child_line_item->is_cancellation()
444
-            ) {
445
-                $child_line_item->set_quantity($child_line_item->quantity() - $qty);
446
-            }
447
-        }
448
-        // get cancellation sub line item
449
-        $cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
450
-            $ticket_line_item,
451
-            EEM_Line_Item::type_cancellation
452
-        );
453
-        $cancellation_line_item = reset($cancellation_line_item);
454
-        // verify that this ticket was indeed previously cancelled
455
-        if ($cancellation_line_item instanceof EE_Line_Item) {
456
-            // increment cancelled quantity
457
-            $cancellation_line_item->set_quantity($cancellation_line_item->quantity() + $qty);
458
-        } else {
459
-            // create cancellation sub line item
460
-            $cancellation_line_item = EE_Line_Item::new_instance(array(
461
-                'LIN_name'       => esc_html__('Cancellation', 'event_espresso'),
462
-                'LIN_desc'       => sprintf(
463
-                    esc_html_x(
464
-                        'Cancelled %1$s : %2$s',
465
-                        'Cancelled Ticket Name : 2015-01-01 11:11',
466
-                        'event_espresso'
467
-                    ),
468
-                    $ticket_line_item->name(),
469
-                    current_time(get_option('date_format') . ' ' . get_option('time_format'))
470
-                ),
471
-                'LIN_unit_price' => 0, // $ticket_line_item->unit_price()
472
-                'LIN_quantity'   => $qty,
473
-                'LIN_is_taxable' => $ticket_line_item->is_taxable(),
474
-                'LIN_order'      => count($ticket_line_item->children()),
475
-                'LIN_total'      => 0, // $ticket_line_item->unit_price()
476
-                'LIN_type'       => EEM_Line_Item::type_cancellation,
477
-            ));
478
-            $ticket_line_item->add_child_line_item($cancellation_line_item);
479
-        }
480
-        if ($ticket_line_item->save_this_and_descendants() > 0) {
481
-            // decrement parent line item quantity
482
-            $event_line_item = $ticket_line_item->parent();
483
-            if (
484
-                $event_line_item instanceof EE_Line_Item
485
-                && $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
486
-            ) {
487
-                $event_line_item->set_quantity($event_line_item->quantity() - $qty);
488
-                $event_line_item->save();
489
-            }
490
-            EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
491
-            return true;
492
-        }
493
-        return false;
494
-    }
495
-
496
-
497
-    /**
498
-     * reinstates (un-cancels?) a previously canceled ticket line item,
499
-     * by incrementing it's quantity by 1, and decrementing it's "type_cancellation" sub-line-item.
500
-     * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
501
-     *
502
-     * @param EE_Line_Item $ticket_line_item
503
-     * @param int          $qty
504
-     * @return bool success
505
-     * @throws EE_Error
506
-     * @throws InvalidArgumentException
507
-     * @throws InvalidDataTypeException
508
-     * @throws InvalidInterfaceException
509
-     * @throws ReflectionException
510
-     */
511
-    public static function reinstate_canceled_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
512
-    {
513
-        // validate incoming line_item
514
-        if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) {
515
-            throw new EE_Error(
516
-                sprintf(
517
-                    esc_html__(
518
-                        'The supplied line item must have an Object Type of "Ticket", not %1$s.',
519
-                        'event_espresso'
520
-                    ),
521
-                    $ticket_line_item->type()
522
-                )
523
-            );
524
-        }
525
-        // get cancellation sub line item
526
-        $cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
527
-            $ticket_line_item,
528
-            EEM_Line_Item::type_cancellation
529
-        );
530
-        $cancellation_line_item = reset($cancellation_line_item);
531
-        // verify that this ticket was indeed previously cancelled
532
-        if (! $cancellation_line_item instanceof EE_Line_Item) {
533
-            return false;
534
-        }
535
-        if ($cancellation_line_item->quantity() > $qty) {
536
-            // decrement cancelled quantity
537
-            $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
538
-        } elseif ($cancellation_line_item->quantity() === $qty) {
539
-            // decrement cancelled quantity in case anyone still has the object kicking around
540
-            $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
541
-            // delete because quantity will end up as 0
542
-            $cancellation_line_item->delete();
543
-            // and attempt to destroy the object,
544
-            // even though PHP won't actually destroy it until it needs the memory
545
-            unset($cancellation_line_item);
546
-        } else {
547
-            // what ?!?! negative quantity ?!?!
548
-            throw new EE_Error(
549
-                sprintf(
550
-                    esc_html__(
551
-                        'Can not reinstate %1$d cancelled ticket(s) because the cancelled ticket quantity is only %2$d.',
552
-                        'event_espresso'
553
-                    ),
554
-                    $qty,
555
-                    $cancellation_line_item->quantity()
556
-                )
557
-            );
558
-        }
559
-        // increment ticket quantity
560
-        $ticket_line_item->set_quantity($ticket_line_item->quantity() + $qty);
561
-        if ($ticket_line_item->save_this_and_descendants() > 0) {
562
-            // increment parent line item quantity
563
-            $event_line_item = $ticket_line_item->parent();
564
-            if (
565
-                $event_line_item instanceof EE_Line_Item
566
-                && $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
567
-            ) {
568
-                $event_line_item->set_quantity($event_line_item->quantity() + $qty);
569
-            }
570
-            EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
571
-            return true;
572
-        }
573
-        return false;
574
-    }
575
-
576
-
577
-    /**
578
-     * calls EEH_Line_Item::find_transaction_grand_total_for_line_item()
579
-     * then EE_Line_Item::recalculate_total_including_taxes() on the result
580
-     *
581
-     * @param EE_Line_Item $line_item
582
-     * @return float
583
-     * @throws EE_Error
584
-     * @throws InvalidArgumentException
585
-     * @throws InvalidDataTypeException
586
-     * @throws InvalidInterfaceException
587
-     * @throws ReflectionException
588
-     */
589
-    public static function get_grand_total_and_recalculate_everything(EE_Line_Item $line_item)
590
-    {
591
-        $grand_total_line_item = EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item);
592
-        return $grand_total_line_item->recalculate_total_including_taxes();
593
-    }
594
-
595
-
596
-    /**
597
-     * Gets the line item which contains the subtotal of all the items
598
-     *
599
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
600
-     * @return EE_Line_Item
601
-     * @throws EE_Error
602
-     * @throws InvalidArgumentException
603
-     * @throws InvalidDataTypeException
604
-     * @throws InvalidInterfaceException
605
-     * @throws ReflectionException
606
-     */
607
-    public static function get_pre_tax_subtotal(EE_Line_Item $total_line_item)
608
-    {
609
-        $pre_tax_subtotal = $total_line_item->get_child_line_item('pre-tax-subtotal');
610
-        return $pre_tax_subtotal instanceof EE_Line_Item
611
-            ? $pre_tax_subtotal
612
-            : self::create_pre_tax_subtotal($total_line_item);
613
-    }
614
-
615
-
616
-    /**
617
-     * Gets the line item for the taxes subtotal
618
-     *
619
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
620
-     * @return EE_Line_Item
621
-     * @throws EE_Error
622
-     * @throws InvalidArgumentException
623
-     * @throws InvalidDataTypeException
624
-     * @throws InvalidInterfaceException
625
-     * @throws ReflectionException
626
-     */
627
-    public static function get_taxes_subtotal(EE_Line_Item $total_line_item)
628
-    {
629
-        $taxes = $total_line_item->get_child_line_item('taxes');
630
-        return $taxes ? $taxes : self::create_taxes_subtotal($total_line_item);
631
-    }
632
-
633
-
634
-    /**
635
-     * sets the TXN ID on an EE_Line_Item if passed a valid EE_Transaction object
636
-     *
637
-     * @param EE_Line_Item   $line_item
638
-     * @param EE_Transaction $transaction
639
-     * @return void
640
-     * @throws EE_Error
641
-     * @throws InvalidArgumentException
642
-     * @throws InvalidDataTypeException
643
-     * @throws InvalidInterfaceException
644
-     * @throws ReflectionException
645
-     */
646
-    public static function set_TXN_ID(EE_Line_Item $line_item, $transaction = null)
647
-    {
648
-        if ($transaction) {
649
-            /** @type EEM_Transaction $EEM_Transaction */
650
-            $EEM_Transaction = EE_Registry::instance()->load_model('Transaction');
651
-            $TXN_ID = $EEM_Transaction->ensure_is_ID($transaction);
652
-            $line_item->set_TXN_ID($TXN_ID);
653
-        }
654
-    }
655
-
656
-
657
-    /**
658
-     * Creates a new default total line item for the transaction,
659
-     * and its tickets subtotal and taxes subtotal line items (and adds the
660
-     * existing taxes as children of the taxes subtotal line item)
661
-     *
662
-     * @param EE_Transaction $transaction
663
-     * @return EE_Line_Item of type total
664
-     * @throws EE_Error
665
-     * @throws InvalidArgumentException
666
-     * @throws InvalidDataTypeException
667
-     * @throws InvalidInterfaceException
668
-     * @throws ReflectionException
669
-     */
670
-    public static function create_total_line_item($transaction = null)
671
-    {
672
-        $total_line_item = EE_Line_Item::new_instance(array(
673
-            'LIN_code' => 'total',
674
-            'LIN_name' => esc_html__('Grand Total', 'event_espresso'),
675
-            'LIN_type' => EEM_Line_Item::type_total,
676
-            'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TRANSACTION,
677
-        ));
678
-        $total_line_item = apply_filters(
679
-            'FHEE__EEH_Line_Item__create_total_line_item__total_line_item',
680
-            $total_line_item
681
-        );
682
-        self::set_TXN_ID($total_line_item, $transaction);
683
-        self::create_pre_tax_subtotal($total_line_item, $transaction);
684
-        self::create_taxes_subtotal($total_line_item, $transaction);
685
-        return $total_line_item;
686
-    }
687
-
688
-
689
-    /**
690
-     * Creates a default items subtotal line item
691
-     *
692
-     * @param EE_Line_Item   $total_line_item
693
-     * @param EE_Transaction $transaction
694
-     * @return EE_Line_Item
695
-     * @throws EE_Error
696
-     * @throws InvalidArgumentException
697
-     * @throws InvalidDataTypeException
698
-     * @throws InvalidInterfaceException
699
-     * @throws ReflectionException
700
-     */
701
-    protected static function create_pre_tax_subtotal(EE_Line_Item $total_line_item, $transaction = null)
702
-    {
703
-        $pre_tax_line_item = EE_Line_Item::new_instance(array(
704
-            'LIN_code' => 'pre-tax-subtotal',
705
-            'LIN_name' => esc_html__('Pre-Tax Subtotal', 'event_espresso'),
706
-            'LIN_type' => EEM_Line_Item::type_sub_total,
707
-        ));
708
-        $pre_tax_line_item = apply_filters(
709
-            'FHEE__EEH_Line_Item__create_pre_tax_subtotal__pre_tax_line_item',
710
-            $pre_tax_line_item
711
-        );
712
-        self::set_TXN_ID($pre_tax_line_item, $transaction);
713
-        $total_line_item->add_child_line_item($pre_tax_line_item);
714
-        self::create_event_subtotal($pre_tax_line_item, $transaction);
715
-        return $pre_tax_line_item;
716
-    }
717
-
718
-
719
-    /**
720
-     * Creates a line item for the taxes subtotal and finds all the tax prices
721
-     * and applies taxes to it
722
-     *
723
-     * @param EE_Line_Item   $total_line_item of type EEM_Line_Item::type_total
724
-     * @param EE_Transaction $transaction
725
-     * @return EE_Line_Item
726
-     * @throws EE_Error
727
-     * @throws InvalidArgumentException
728
-     * @throws InvalidDataTypeException
729
-     * @throws InvalidInterfaceException
730
-     * @throws ReflectionException
731
-     */
732
-    protected static function create_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null)
733
-    {
734
-        $tax_line_item = EE_Line_Item::new_instance(array(
735
-            'LIN_code'  => 'taxes',
736
-            'LIN_name'  => esc_html__('Taxes', 'event_espresso'),
737
-            'LIN_type'  => EEM_Line_Item::type_tax_sub_total,
738
-            'LIN_order' => 1000,// this should always come last
739
-        ));
740
-        $tax_line_item = apply_filters(
741
-            'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item',
742
-            $tax_line_item
743
-        );
744
-        self::set_TXN_ID($tax_line_item, $transaction);
745
-        $total_line_item->add_child_line_item($tax_line_item);
746
-        // and lastly, add the actual taxes
747
-        self::apply_taxes($total_line_item);
748
-        return $tax_line_item;
749
-    }
750
-
751
-
752
-    /**
753
-     * Creates a default items subtotal line item
754
-     *
755
-     * @param EE_Line_Item   $pre_tax_line_item
756
-     * @param EE_Transaction $transaction
757
-     * @param EE_Event       $event
758
-     * @return EE_Line_Item
759
-     * @throws EE_Error
760
-     * @throws InvalidArgumentException
761
-     * @throws InvalidDataTypeException
762
-     * @throws InvalidInterfaceException
763
-     * @throws ReflectionException
764
-     */
765
-    public static function create_event_subtotal(EE_Line_Item $pre_tax_line_item, $transaction = null, $event = null)
766
-    {
767
-        $event_line_item = EE_Line_Item::new_instance(array(
768
-            'LIN_code' => self::get_event_code($event),
769
-            'LIN_name' => self::get_event_name($event),
770
-            'LIN_desc' => self::get_event_desc($event),
771
-            'LIN_type' => EEM_Line_Item::type_sub_total,
772
-            'OBJ_type' => EEM_Line_Item::OBJ_TYPE_EVENT,
773
-            'OBJ_ID'   => $event instanceof EE_Event ? $event->ID() : 0,
774
-        ));
775
-        $event_line_item = apply_filters(
776
-            'FHEE__EEH_Line_Item__create_event_subtotal__event_line_item',
777
-            $event_line_item
778
-        );
779
-        self::set_TXN_ID($event_line_item, $transaction);
780
-        $pre_tax_line_item->add_child_line_item($event_line_item);
781
-        return $event_line_item;
782
-    }
783
-
784
-
785
-    /**
786
-     * Gets what the event ticket's code SHOULD be
787
-     *
788
-     * @param EE_Event $event
789
-     * @return string
790
-     * @throws EE_Error
791
-     */
792
-    public static function get_event_code($event)
793
-    {
794
-        return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0');
795
-    }
796
-
797
-
798
-    /**
799
-     * Gets the event name
800
-     *
801
-     * @param EE_Event $event
802
-     * @return string
803
-     * @throws EE_Error
804
-     */
805
-    public static function get_event_name($event)
806
-    {
807
-        return $event instanceof EE_Event
808
-            ? mb_substr($event->name(), 0, 245)
809
-            : esc_html__('Event', 'event_espresso');
810
-    }
811
-
812
-
813
-    /**
814
-     * Gets the event excerpt
815
-     *
816
-     * @param EE_Event $event
817
-     * @return string
818
-     * @throws EE_Error
819
-     */
820
-    public static function get_event_desc($event)
821
-    {
822
-        return $event instanceof EE_Event ? $event->short_description() : '';
823
-    }
824
-
825
-
826
-    /**
827
-     * Given the grand total line item and a ticket, finds the event sub-total
828
-     * line item the ticket's purchase should be added onto
829
-     *
830
-     * @access public
831
-     * @param EE_Line_Item $grand_total the grand total line item
832
-     * @param EE_Ticket    $ticket
833
-     * @return EE_Line_Item
834
-     * @throws EE_Error
835
-     * @throws InvalidArgumentException
836
-     * @throws InvalidDataTypeException
837
-     * @throws InvalidInterfaceException
838
-     * @throws ReflectionException
839
-     */
840
-    public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket)
841
-    {
842
-        $first_datetime = $ticket->first_datetime();
843
-        if (! $first_datetime instanceof EE_Datetime) {
844
-            throw new EE_Error(
845
-                sprintf(
846
-                    __('The supplied ticket (ID %d) has no datetimes', 'event_espresso'),
847
-                    $ticket->ID()
848
-                )
849
-            );
850
-        }
851
-        $event = $first_datetime->event();
852
-        if (! $event instanceof EE_Event) {
853
-            throw new EE_Error(
854
-                sprintf(
855
-                    esc_html__(
856
-                        'The supplied ticket (ID %d) has no event data associated with it.',
857
-                        'event_espresso'
858
-                    ),
859
-                    $ticket->ID()
860
-                )
861
-            );
862
-        }
863
-        $events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event);
864
-        if (! $events_sub_total instanceof EE_Line_Item) {
865
-            throw new EE_Error(
866
-                sprintf(
867
-                    esc_html__(
868
-                        'There is no events sub-total for ticket %s on total line item %d',
869
-                        'event_espresso'
870
-                    ),
871
-                    $ticket->ID(),
872
-                    $grand_total->ID()
873
-                )
874
-            );
875
-        }
876
-        return $events_sub_total;
877
-    }
878
-
879
-
880
-    /**
881
-     * Gets the event line item
882
-     *
883
-     * @param EE_Line_Item $grand_total
884
-     * @param EE_Event     $event
885
-     * @return EE_Line_Item for the event subtotal which is a child of $grand_total
886
-     * @throws EE_Error
887
-     * @throws InvalidArgumentException
888
-     * @throws InvalidDataTypeException
889
-     * @throws InvalidInterfaceException
890
-     * @throws ReflectionException
891
-     */
892
-    public static function get_event_line_item(EE_Line_Item $grand_total, $event)
893
-    {
894
-        /** @type EE_Event $event */
895
-        $event = EEM_Event::instance()->ensure_is_obj($event, true);
896
-        $event_line_item = null;
897
-        $found = false;
898
-        foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) {
899
-            // default event subtotal, we should only ever find this the first time this method is called
900
-            if (! $event_line_item->OBJ_ID()) {
901
-                // let's use this! but first... set the event details
902
-                EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
903
-                $found = true;
904
-                break;
905
-            }
906
-            if ($event_line_item->OBJ_ID() === $event->ID()) {
907
-                // found existing line item for this event in the cart, so break out of loop and use this one
908
-                $found = true;
909
-                break;
910
-            }
911
-        }
912
-        if (! $found) {
913
-            // there is no event sub-total yet, so add it
914
-            $pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total);
915
-            // create a new "event" subtotal below that
916
-            $event_line_item = EEH_Line_Item::create_event_subtotal($pre_tax_subtotal, null, $event);
917
-            // and set the event details
918
-            EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
919
-        }
920
-        return $event_line_item;
921
-    }
922
-
923
-
924
-    /**
925
-     * Creates a default items subtotal line item
926
-     *
927
-     * @param EE_Line_Item   $event_line_item
928
-     * @param EE_Event       $event
929
-     * @param EE_Transaction $transaction
930
-     * @return void
931
-     * @throws EE_Error
932
-     * @throws InvalidArgumentException
933
-     * @throws InvalidDataTypeException
934
-     * @throws InvalidInterfaceException
935
-     * @throws ReflectionException
936
-     */
937
-    public static function set_event_subtotal_details(
938
-        EE_Line_Item $event_line_item,
939
-        EE_Event $event,
940
-        $transaction = null
941
-    ) {
942
-        if ($event instanceof EE_Event) {
943
-            $event_line_item->set_code(self::get_event_code($event));
944
-            $event_line_item->set_name(self::get_event_name($event));
945
-            $event_line_item->set_desc(self::get_event_desc($event));
946
-            $event_line_item->set_OBJ_ID($event->ID());
947
-        }
948
-        self::set_TXN_ID($event_line_item, $transaction);
949
-    }
950
-
951
-
952
-    /**
953
-     * Finds what taxes should apply, adds them as tax line items under the taxes sub-total,
954
-     * and recalculates the taxes sub-total and the grand total. Resets the taxes, so
955
-     * any old taxes are removed
956
-     *
957
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
958
-     * @param bool         $update_txn_status
959
-     * @return bool
960
-     * @throws EE_Error
961
-     * @throws InvalidArgumentException
962
-     * @throws InvalidDataTypeException
963
-     * @throws InvalidInterfaceException
964
-     * @throws ReflectionException
965
-     * @throws RuntimeException
966
-     */
967
-    public static function apply_taxes(EE_Line_Item $total_line_item, $update_txn_status = false)
968
-    {
969
-        /** @type EEM_Price $EEM_Price */
970
-        $EEM_Price = EE_Registry::instance()->load_model('Price');
971
-        // get array of taxes via Price Model
972
-        $ordered_taxes = $EEM_Price->get_all_prices_that_are_taxes();
973
-        ksort($ordered_taxes);
974
-        $taxes_line_item = self::get_taxes_subtotal($total_line_item);
975
-        // just to be safe, remove its old tax line items
976
-        $deleted = $taxes_line_item->delete_children_line_items();
977
-        $updates = false;
978
-        // loop thru taxes
979
-        foreach ($ordered_taxes as $order => $taxes) {
980
-            foreach ($taxes as $tax) {
981
-                if ($tax instanceof EE_Price) {
982
-                    $tax_line_item = EE_Line_Item::new_instance(
983
-                        array(
984
-                            'LIN_name'       => $tax->name(),
985
-                            'LIN_desc'       => $tax->desc(),
986
-                            'LIN_percent'    => $tax->amount(),
987
-                            'LIN_is_taxable' => false,
988
-                            'LIN_order'      => $order,
989
-                            'LIN_total'      => 0,
990
-                            'LIN_type'       => EEM_Line_Item::type_tax,
991
-                            'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_PRICE,
992
-                            'OBJ_ID'         => $tax->ID(),
993
-                        )
994
-                    );
995
-                    $tax_line_item = apply_filters(
996
-                        'FHEE__EEH_Line_Item__apply_taxes__tax_line_item',
997
-                        $tax_line_item
998
-                    );
999
-                    $updates = $taxes_line_item->add_child_line_item($tax_line_item) ?
1000
-                        true :
1001
-                        $updates;
1002
-                }
1003
-            }
1004
-        }
1005
-        // only recalculate totals if something changed
1006
-        if ($deleted || $updates) {
1007
-            $total_line_item->recalculate_total_including_taxes($update_txn_status);
1008
-            return true;
1009
-        }
1010
-        return false;
1011
-    }
1012
-
1013
-
1014
-    /**
1015
-     * Ensures that taxes have been applied to the order, if not applies them.
1016
-     * Returns the total amount of tax
1017
-     *
1018
-     * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
1019
-     * @return float
1020
-     * @throws EE_Error
1021
-     * @throws InvalidArgumentException
1022
-     * @throws InvalidDataTypeException
1023
-     * @throws InvalidInterfaceException
1024
-     * @throws ReflectionException
1025
-     */
1026
-    public static function ensure_taxes_applied($total_line_item)
1027
-    {
1028
-        $taxes_subtotal = self::get_taxes_subtotal($total_line_item);
1029
-        if (! $taxes_subtotal->children()) {
1030
-            self::apply_taxes($total_line_item);
1031
-        }
1032
-        return $taxes_subtotal->total();
1033
-    }
1034
-
1035
-
1036
-    /**
1037
-     * Deletes ALL children of the passed line item
1038
-     *
1039
-     * @param EE_Line_Item $parent_line_item
1040
-     * @return bool
1041
-     * @throws EE_Error
1042
-     * @throws InvalidArgumentException
1043
-     * @throws InvalidDataTypeException
1044
-     * @throws InvalidInterfaceException
1045
-     * @throws ReflectionException
1046
-     */
1047
-    public static function delete_all_child_items(EE_Line_Item $parent_line_item)
1048
-    {
1049
-        $deleted = 0;
1050
-        foreach ($parent_line_item->children() as $child_line_item) {
1051
-            if ($child_line_item instanceof EE_Line_Item) {
1052
-                $deleted += EEH_Line_Item::delete_all_child_items($child_line_item);
1053
-                if ($child_line_item->ID()) {
1054
-                    $child_line_item->delete();
1055
-                    unset($child_line_item);
1056
-                } else {
1057
-                    $parent_line_item->delete_child_line_item($child_line_item->code());
1058
-                }
1059
-                $deleted++;
1060
-            }
1061
-        }
1062
-        return $deleted;
1063
-    }
1064
-
1065
-
1066
-    /**
1067
-     * Deletes the line items as indicated by the line item code(s) provided,
1068
-     * regardless of where they're found in the line item tree. Automatically
1069
-     * re-calculates the line item totals and updates the related transaction. But
1070
-     * DOES NOT automatically upgrade the transaction's registrations' final prices (which
1071
-     * should probably change because of this).
1072
-     * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
1073
-     * after using this, to keep the registration final prices in-sync with the transaction's total.
1074
-     *
1075
-     * @param EE_Line_Item      $total_line_item of type EEM_Line_Item::type_total
1076
-     * @param array|bool|string $line_item_codes
1077
-     * @return int number of items successfully removed
1078
-     * @throws EE_Error
1079
-     */
1080
-    public static function delete_items(EE_Line_Item $total_line_item, $line_item_codes = false)
1081
-    {
1082
-
1083
-        if ($total_line_item->type() !== EEM_Line_Item::type_total) {
1084
-            EE_Error::doing_it_wrong(
1085
-                'EEH_Line_Item::delete_items',
1086
-                esc_html__(
1087
-                    'This static method should only be called with a TOTAL line item, otherwise we won\'t recalculate the totals correctly',
1088
-                    'event_espresso'
1089
-                ),
1090
-                '4.6.18'
1091
-            );
1092
-        }
1093
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1094
-
1095
-        // check if only a single line_item_id was passed
1096
-        if (! empty($line_item_codes) && ! is_array($line_item_codes)) {
1097
-            // place single line_item_id in an array to appear as multiple line_item_ids
1098
-            $line_item_codes = array($line_item_codes);
1099
-        }
1100
-        $removals = 0;
1101
-        // cycle thru line_item_ids
1102
-        foreach ($line_item_codes as $line_item_id) {
1103
-            $removals += $total_line_item->delete_child_line_item($line_item_id);
1104
-        }
1105
-
1106
-        if ($removals > 0) {
1107
-            $total_line_item->recalculate_taxes_and_tax_total();
1108
-            return $removals;
1109
-        } else {
1110
-            return false;
1111
-        }
1112
-    }
1113
-
1114
-
1115
-    /**
1116
-     * Overwrites the previous tax by clearing out the old taxes, and creates a new
1117
-     * tax and updates the total line item accordingly
1118
-     *
1119
-     * @param EE_Line_Item $total_line_item
1120
-     * @param float        $amount
1121
-     * @param string       $name
1122
-     * @param string       $description
1123
-     * @param string       $code
1124
-     * @param boolean      $add_to_existing_line_item
1125
-     *                          if true, and a duplicate line item with the same code is found,
1126
-     *                          $amount will be added onto it; otherwise will simply set the taxes to match $amount
1127
-     * @return EE_Line_Item the new tax line item created
1128
-     * @throws EE_Error
1129
-     * @throws InvalidArgumentException
1130
-     * @throws InvalidDataTypeException
1131
-     * @throws InvalidInterfaceException
1132
-     * @throws ReflectionException
1133
-     */
1134
-    public static function set_total_tax_to(
1135
-        EE_Line_Item $total_line_item,
1136
-        $amount,
1137
-        $name = null,
1138
-        $description = null,
1139
-        $code = null,
1140
-        $add_to_existing_line_item = false
1141
-    ) {
1142
-        $tax_subtotal = self::get_taxes_subtotal($total_line_item);
1143
-        $taxable_total = $total_line_item->taxable_total();
1144
-
1145
-        if ($add_to_existing_line_item) {
1146
-            $new_tax = $tax_subtotal->get_child_line_item($code);
1147
-            EEM_Line_Item::instance()->delete(
1148
-                array(array('LIN_code' => array('!=', $code), 'LIN_parent' => $tax_subtotal->ID()))
1149
-            );
1150
-        } else {
1151
-            $new_tax = null;
1152
-            $tax_subtotal->delete_children_line_items();
1153
-        }
1154
-        if ($new_tax) {
1155
-            $new_tax->set_total($new_tax->total() + $amount);
1156
-            $new_tax->set_percent($taxable_total ? $new_tax->total() / $taxable_total * 100 : 0);
1157
-        } else {
1158
-            // no existing tax item. Create it
1159
-            $new_tax = EE_Line_Item::new_instance(array(
1160
-                'TXN_ID'      => $total_line_item->TXN_ID(),
1161
-                'LIN_name'    => $name ? $name : esc_html__('Tax', 'event_espresso'),
1162
-                'LIN_desc'    => $description ? $description : '',
1163
-                'LIN_percent' => $taxable_total ? ($amount / $taxable_total * 100) : 0,
1164
-                'LIN_total'   => $amount,
1165
-                'LIN_parent'  => $tax_subtotal->ID(),
1166
-                'LIN_type'    => EEM_Line_Item::type_tax,
1167
-                'LIN_code'    => $code,
1168
-            ));
1169
-        }
1170
-
1171
-        $new_tax = apply_filters(
1172
-            'FHEE__EEH_Line_Item__set_total_tax_to__new_tax_subtotal',
1173
-            $new_tax,
1174
-            $total_line_item
1175
-        );
1176
-        $new_tax->save();
1177
-        $tax_subtotal->set_total($new_tax->total());
1178
-        $tax_subtotal->save();
1179
-        $total_line_item->recalculate_total_including_taxes();
1180
-        return $new_tax;
1181
-    }
1182
-
1183
-
1184
-    /**
1185
-     * Makes all the line items which are children of $line_item taxable (or not).
1186
-     * Does NOT save the line items
1187
-     *
1188
-     * @param EE_Line_Item $line_item
1189
-     * @param boolean      $taxable
1190
-     * @param string       $code_substring_for_whitelist if this string is part of the line item's code
1191
-     *                                                   it will be whitelisted (ie, except from becoming taxable)
1192
-     * @throws EE_Error
1193
-     */
1194
-    public static function set_line_items_taxable(
1195
-        EE_Line_Item $line_item,
1196
-        $taxable = true,
1197
-        $code_substring_for_whitelist = null
1198
-    ) {
1199
-        $whitelisted = false;
1200
-        if ($code_substring_for_whitelist !== null) {
1201
-            $whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false;
1202
-        }
1203
-        if (! $whitelisted && $line_item->is_line_item()) {
1204
-            $line_item->set_is_taxable($taxable);
1205
-        }
1206
-        foreach ($line_item->children() as $child_line_item) {
1207
-            EEH_Line_Item::set_line_items_taxable(
1208
-                $child_line_item,
1209
-                $taxable,
1210
-                $code_substring_for_whitelist
1211
-            );
1212
-        }
1213
-    }
1214
-
1215
-
1216
-    /**
1217
-     * Gets all descendants that are event subtotals
1218
-     *
1219
-     * @uses  EEH_Line_Item::get_subtotals_of_object_type()
1220
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1221
-     * @return EE_Line_Item[]
1222
-     * @throws EE_Error
1223
-     */
1224
-    public static function get_event_subtotals(EE_Line_Item $parent_line_item)
1225
-    {
1226
-        return self::get_subtotals_of_object_type($parent_line_item, EEM_Line_Item::OBJ_TYPE_EVENT);
1227
-    }
1228
-
1229
-
1230
-    /**
1231
-     * Gets all descendants subtotals that match the supplied object type
1232
-     *
1233
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1234
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1235
-     * @param string       $obj_type
1236
-     * @return EE_Line_Item[]
1237
-     * @throws EE_Error
1238
-     */
1239
-    public static function get_subtotals_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1240
-    {
1241
-        return self::_get_descendants_by_type_and_object_type(
1242
-            $parent_line_item,
1243
-            EEM_Line_Item::type_sub_total,
1244
-            $obj_type
1245
-        );
1246
-    }
1247
-
1248
-
1249
-    /**
1250
-     * Gets all descendants that are tickets
1251
-     *
1252
-     * @uses  EEH_Line_Item::get_line_items_of_object_type()
1253
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1254
-     * @return EE_Line_Item[]
1255
-     * @throws EE_Error
1256
-     */
1257
-    public static function get_ticket_line_items(EE_Line_Item $parent_line_item)
1258
-    {
1259
-        return self::get_line_items_of_object_type(
1260
-            $parent_line_item,
1261
-            EEM_Line_Item::OBJ_TYPE_TICKET
1262
-        );
1263
-    }
1264
-
1265
-
1266
-    /**
1267
-     * Gets all descendants subtotals that match the supplied object type
1268
-     *
1269
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1270
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1271
-     * @param string       $obj_type
1272
-     * @return EE_Line_Item[]
1273
-     * @throws EE_Error
1274
-     */
1275
-    public static function get_line_items_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1276
-    {
1277
-        return self::_get_descendants_by_type_and_object_type(
1278
-            $parent_line_item,
1279
-            EEM_Line_Item::type_line_item,
1280
-            $obj_type
1281
-        );
1282
-    }
1283
-
1284
-
1285
-    /**
1286
-     * Gets all the descendants (ie, children or children of children etc) that are of the type 'tax'
1287
-     *
1288
-     * @uses  EEH_Line_Item::get_descendants_of_type()
1289
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1290
-     * @return EE_Line_Item[]
1291
-     * @throws EE_Error
1292
-     */
1293
-    public static function get_tax_descendants(EE_Line_Item $parent_line_item)
1294
-    {
1295
-        return EEH_Line_Item::get_descendants_of_type(
1296
-            $parent_line_item,
1297
-            EEM_Line_Item::type_tax
1298
-        );
1299
-    }
1300
-
1301
-
1302
-    /**
1303
-     * Gets all the real items purchased which are children of this item
1304
-     *
1305
-     * @uses  EEH_Line_Item::get_descendants_of_type()
1306
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1307
-     * @return EE_Line_Item[]
1308
-     * @throws EE_Error
1309
-     */
1310
-    public static function get_line_item_descendants(EE_Line_Item $parent_line_item)
1311
-    {
1312
-        return EEH_Line_Item::get_descendants_of_type(
1313
-            $parent_line_item,
1314
-            EEM_Line_Item::type_line_item
1315
-        );
1316
-    }
1317
-
1318
-
1319
-    /**
1320
-     * Gets all descendants of supplied line item that match the supplied line item type
1321
-     *
1322
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1323
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1324
-     * @param string       $line_item_type   one of the EEM_Line_Item constants
1325
-     * @return EE_Line_Item[]
1326
-     * @throws EE_Error
1327
-     */
1328
-    public static function get_descendants_of_type(EE_Line_Item $parent_line_item, $line_item_type)
1329
-    {
1330
-        return self::_get_descendants_by_type_and_object_type(
1331
-            $parent_line_item,
1332
-            $line_item_type,
1333
-            null
1334
-        );
1335
-    }
1336
-
1337
-
1338
-    /**
1339
-     * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type
1340
-     * as well
1341
-     *
1342
-     * @param EE_Line_Item  $parent_line_item - the line item to find descendants of
1343
-     * @param string        $line_item_type   one of the EEM_Line_Item constants
1344
-     * @param string | NULL $obj_type         object model class name (minus prefix) or NULL to ignore object type when
1345
-     *                                        searching
1346
-     * @return EE_Line_Item[]
1347
-     * @throws EE_Error
1348
-     */
1349
-    protected static function _get_descendants_by_type_and_object_type(
1350
-        EE_Line_Item $parent_line_item,
1351
-        $line_item_type,
1352
-        $obj_type = null
1353
-    ) {
1354
-        $objects = array();
1355
-        foreach ($parent_line_item->children() as $child_line_item) {
1356
-            if ($child_line_item instanceof EE_Line_Item) {
1357
-                if (
1358
-                    $child_line_item->type() === $line_item_type
1359
-                    && (
1360
-                        $child_line_item->OBJ_type() === $obj_type || $obj_type === null
1361
-                    )
1362
-                ) {
1363
-                    $objects[] = $child_line_item;
1364
-                } else {
1365
-                    // go-through-all-its children looking for more matches
1366
-                    $objects = array_merge(
1367
-                        $objects,
1368
-                        self::_get_descendants_by_type_and_object_type(
1369
-                            $child_line_item,
1370
-                            $line_item_type,
1371
-                            $obj_type
1372
-                        )
1373
-                    );
1374
-                }
1375
-            }
1376
-        }
1377
-        return $objects;
1378
-    }
1379
-
1380
-
1381
-    /**
1382
-     * Gets all descendants subtotals that match the supplied object type
1383
-     *
1384
-     * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1385
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1386
-     * @param string       $OBJ_type         object type (like Event)
1387
-     * @param array        $OBJ_IDs          array of OBJ_IDs
1388
-     * @return EE_Line_Item[]
1389
-     * @throws EE_Error
1390
-     */
1391
-    public static function get_line_items_by_object_type_and_IDs(
1392
-        EE_Line_Item $parent_line_item,
1393
-        $OBJ_type = '',
1394
-        $OBJ_IDs = array()
1395
-    ) {
1396
-        return self::_get_descendants_by_object_type_and_object_ID(
1397
-            $parent_line_item,
1398
-            $OBJ_type,
1399
-            $OBJ_IDs
1400
-        );
1401
-    }
1402
-
1403
-
1404
-    /**
1405
-     * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type
1406
-     * as well
1407
-     *
1408
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1409
-     * @param string       $OBJ_type         object type (like Event)
1410
-     * @param array        $OBJ_IDs          array of OBJ_IDs
1411
-     * @return EE_Line_Item[]
1412
-     * @throws EE_Error
1413
-     */
1414
-    protected static function _get_descendants_by_object_type_and_object_ID(
1415
-        EE_Line_Item $parent_line_item,
1416
-        $OBJ_type,
1417
-        $OBJ_IDs
1418
-    ) {
1419
-        $objects = array();
1420
-        foreach ($parent_line_item->children() as $child_line_item) {
1421
-            if ($child_line_item instanceof EE_Line_Item) {
1422
-                if (
1423
-                    $child_line_item->OBJ_type() === $OBJ_type
1424
-                    && is_array($OBJ_IDs)
1425
-                    && in_array($child_line_item->OBJ_ID(), $OBJ_IDs)
1426
-                ) {
1427
-                    $objects[] = $child_line_item;
1428
-                } else {
1429
-                    // go-through-all-its children looking for more matches
1430
-                    $objects = array_merge(
1431
-                        $objects,
1432
-                        self::_get_descendants_by_object_type_and_object_ID(
1433
-                            $child_line_item,
1434
-                            $OBJ_type,
1435
-                            $OBJ_IDs
1436
-                        )
1437
-                    );
1438
-                }
1439
-            }
1440
-        }
1441
-        return $objects;
1442
-    }
1443
-
1444
-
1445
-    /**
1446
-     * Uses a breadth-first-search in order to find the nearest descendant of
1447
-     * the specified type and returns it, else NULL
1448
-     *
1449
-     * @uses  EEH_Line_Item::_get_nearest_descendant()
1450
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1451
-     * @param string       $type             like one of the EEM_Line_Item::type_*
1452
-     * @return EE_Line_Item
1453
-     * @throws EE_Error
1454
-     * @throws InvalidArgumentException
1455
-     * @throws InvalidDataTypeException
1456
-     * @throws InvalidInterfaceException
1457
-     * @throws ReflectionException
1458
-     */
1459
-    public static function get_nearest_descendant_of_type(EE_Line_Item $parent_line_item, $type)
1460
-    {
1461
-        return self::_get_nearest_descendant($parent_line_item, 'LIN_type', $type);
1462
-    }
1463
-
1464
-
1465
-    /**
1466
-     * Uses a breadth-first-search in order to find the nearest descendant
1467
-     * having the specified LIN_code and returns it, else NULL
1468
-     *
1469
-     * @uses  EEH_Line_Item::_get_nearest_descendant()
1470
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1471
-     * @param string       $code             any value used for LIN_code
1472
-     * @return EE_Line_Item
1473
-     * @throws EE_Error
1474
-     * @throws InvalidArgumentException
1475
-     * @throws InvalidDataTypeException
1476
-     * @throws InvalidInterfaceException
1477
-     * @throws ReflectionException
1478
-     */
1479
-    public static function get_nearest_descendant_having_code(EE_Line_Item $parent_line_item, $code)
1480
-    {
1481
-        return self::_get_nearest_descendant($parent_line_item, 'LIN_code', $code);
1482
-    }
1483
-
1484
-
1485
-    /**
1486
-     * Uses a breadth-first-search in order to find the nearest descendant
1487
-     * having the specified LIN_code and returns it, else NULL
1488
-     *
1489
-     * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1490
-     * @param string       $search_field     name of EE_Line_Item property
1491
-     * @param string       $value            any value stored in $search_field
1492
-     * @return EE_Line_Item
1493
-     * @throws EE_Error
1494
-     * @throws InvalidArgumentException
1495
-     * @throws InvalidDataTypeException
1496
-     * @throws InvalidInterfaceException
1497
-     * @throws ReflectionException
1498
-     */
1499
-    protected static function _get_nearest_descendant(EE_Line_Item $parent_line_item, $search_field, $value)
1500
-    {
1501
-        foreach ($parent_line_item->children() as $child) {
1502
-            if ($child->get($search_field) == $value) {
1503
-                return $child;
1504
-            }
1505
-        }
1506
-        foreach ($parent_line_item->children() as $child) {
1507
-            $descendant_found = self::_get_nearest_descendant(
1508
-                $child,
1509
-                $search_field,
1510
-                $value
1511
-            );
1512
-            if ($descendant_found) {
1513
-                return $descendant_found;
1514
-            }
1515
-        }
1516
-        return null;
1517
-    }
1518
-
1519
-
1520
-    /**
1521
-     * if passed line item has a TXN ID, uses that to jump directly to the grand total line item for the transaction,
1522
-     * else recursively walks up the line item tree until a parent of type total is found,
1523
-     *
1524
-     * @param EE_Line_Item $line_item
1525
-     * @return EE_Line_Item
1526
-     * @throws EE_Error
1527
-     */
1528
-    public static function find_transaction_grand_total_for_line_item(EE_Line_Item $line_item)
1529
-    {
1530
-        if ($line_item->TXN_ID()) {
1531
-            $total_line_item = $line_item->transaction()->total_line_item(false);
1532
-            if ($total_line_item instanceof EE_Line_Item) {
1533
-                return $total_line_item;
1534
-            }
1535
-        } else {
1536
-            $line_item_parent = $line_item->parent();
1537
-            if ($line_item_parent instanceof EE_Line_Item) {
1538
-                if ($line_item_parent->is_total()) {
1539
-                    return $line_item_parent;
1540
-                }
1541
-                return EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item_parent);
1542
-            }
1543
-        }
1544
-        throw new EE_Error(
1545
-            sprintf(
1546
-                esc_html__(
1547
-                    'A valid grand total for line item %1$d was not found.',
1548
-                    'event_espresso'
1549
-                ),
1550
-                $line_item->ID()
1551
-            )
1552
-        );
1553
-    }
1554
-
1555
-
1556
-    /**
1557
-     * Prints out a representation of the line item tree
1558
-     *
1559
-     * @param EE_Line_Item $line_item
1560
-     * @param int          $indentation
1561
-     * @return void
1562
-     * @throws EE_Error
1563
-     */
1564
-    public static function visualize(EE_Line_Item $line_item, $indentation = 0)
1565
-    {
1566
-        echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1567
-        if (! $indentation) {
1568
-            echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1569
-        }
1570
-        for ($i = 0; $i < $indentation; $i++) {
1571
-            echo '. ';
1572
-        }
1573
-        $breakdown = '';
1574
-        if ($line_item->is_line_item()) {
1575
-            if ($line_item->is_percent()) {
1576
-                $breakdown = "{$line_item->percent()}%";
1577
-            } else {
1578
-                $breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}";
1579
-            }
1580
-        }
1581
-        echo $line_item->name();
1582
-        echo " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : ";
1583
-        echo '$' . (string) $line_item->total();
1584
-        if ($breakdown) {
1585
-            echo " ( {$breakdown} )";
1586
-        }
1587
-        if ($line_item->is_taxable()) {
1588
-            echo '  * taxable';
1589
-        }
1590
-        if ($line_item->children()) {
1591
-            foreach ($line_item->children() as $child) {
1592
-                self::visualize($child, $indentation + 1);
1593
-            }
1594
-        }
1595
-    }
1596
-
1597
-
1598
-    /**
1599
-     * Calculates the registration's final price, taking into account that they
1600
-     * need to not only help pay for their OWN ticket, but also any transaction-wide surcharges and taxes,
1601
-     * and receive a portion of any transaction-wide discounts.
1602
-     * eg1, if I buy a $1 ticket and brent buys a $9 ticket, and we receive a $5 discount
1603
-     * then I'll get 1/10 of that $5 discount, which is $0.50, and brent will get
1604
-     * 9/10ths of that $5 discount, which is $4.50. So my final price should be $0.50
1605
-     * and brent's final price should be $5.50.
1606
-     * In order to do this, we basically need to traverse the line item tree calculating
1607
-     * the running totals (just as if we were recalculating the total), but when we identify
1608
-     * regular line items, we need to keep track of their share of the grand total.
1609
-     * Also, we need to keep track of the TAXABLE total for each ticket purchase, so
1610
-     * we can know how to apply taxes to it. (Note: "taxable total" does not equal the "pretax total"
1611
-     * when there are non-taxable items; otherwise they would be the same)
1612
-     *
1613
-     * @param EE_Line_Item $line_item
1614
-     * @param array        $billable_ticket_quantities  array of EE_Ticket IDs and their corresponding quantity that
1615
-     *                                                  can be included in price calculations at this moment
1616
-     * @return array        keys are line items for tickets IDs and values are their share of the running total,
1617
-     *                                                  plus the key 'total', and 'taxable' which also has keys of all
1618
-     *                                                  the ticket IDs.
1619
-     *                                                  Eg array(
1620
-     *                                                      12 => 4.3
1621
-     *                                                      23 => 8.0
1622
-     *                                                      'total' => 16.6,
1623
-     *                                                      'taxable' => array(
1624
-     *                                                          12 => 10,
1625
-     *                                                          23 => 4
1626
-     *                                                      ).
1627
-     *                                                  So to find which registrations have which final price, we need
1628
-     *                                                  to find which line item is theirs, which can be done with
1629
-     *                                                  `EEM_Line_Item::instance()->get_line_item_for_registration(
1630
-     *                                                  $registration );`
1631
-     * @throws EE_Error
1632
-     * @throws InvalidArgumentException
1633
-     * @throws InvalidDataTypeException
1634
-     * @throws InvalidInterfaceException
1635
-     * @throws ReflectionException
1636
-     */
1637
-    public static function calculate_reg_final_prices_per_line_item(
1638
-        EE_Line_Item $line_item,
1639
-        $billable_ticket_quantities = array()
1640
-    ) {
1641
-        $running_totals = [
1642
-            'total'   => 0,
1643
-            'taxable' => ['total' => 0]
1644
-        ];
1645
-        foreach ($line_item->children() as $child_line_item) {
1646
-            switch ($child_line_item->type()) {
1647
-                case EEM_Line_Item::type_sub_total:
1648
-                    $running_totals_from_subtotal = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1649
-                        $child_line_item,
1650
-                        $billable_ticket_quantities
1651
-                    );
1652
-                    // combine arrays but preserve numeric keys
1653
-                    $running_totals = array_replace_recursive($running_totals_from_subtotal, $running_totals);
1654
-                    $running_totals['total'] += $running_totals_from_subtotal['total'];
1655
-                    $running_totals['taxable']['total'] += $running_totals_from_subtotal['taxable']['total'];
1656
-                    break;
1657
-
1658
-                case EEM_Line_Item::type_tax_sub_total:
1659
-                    // find how much the taxes percentage is
1660
-                    if ($child_line_item->percent() !== 0) {
1661
-                        $tax_percent_decimal = $child_line_item->percent() / 100;
1662
-                    } else {
1663
-                        $tax_percent_decimal = EE_Taxes::get_total_taxes_percentage() / 100;
1664
-                    }
1665
-                    // and apply to all the taxable totals, and add to the pretax totals
1666
-                    foreach ($running_totals as $line_item_id => $this_running_total) {
1667
-                        // "total" and "taxable" array key is an exception
1668
-                        if ($line_item_id === 'taxable') {
1669
-                            continue;
1670
-                        }
1671
-                        $taxable_total = $running_totals['taxable'][ $line_item_id ];
1672
-                        $running_totals[ $line_item_id ] += ($taxable_total * $tax_percent_decimal);
1673
-                    }
1674
-                    break;
1675
-
1676
-                case EEM_Line_Item::type_line_item:
1677
-                    // ticket line items or ????
1678
-                    if ($child_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) {
1679
-                        // kk it's a ticket
1680
-                        if (isset($running_totals[ $child_line_item->ID() ])) {
1681
-                            // huh? that shouldn't happen.
1682
-                            $running_totals['total'] += $child_line_item->total();
1683
-                        } else {
1684
-                            // its not in our running totals yet. great.
1685
-                            if ($child_line_item->is_taxable()) {
1686
-                                $taxable_amount = $child_line_item->unit_price();
1687
-                            } else {
1688
-                                $taxable_amount = 0;
1689
-                            }
1690
-                            // are we only calculating totals for some tickets?
1691
-                            if (isset($billable_ticket_quantities[ $child_line_item->OBJ_ID() ])) {
1692
-                                $quantity = $billable_ticket_quantities[ $child_line_item->OBJ_ID() ];
1693
-                                $running_totals[ $child_line_item->ID() ] = $quantity
1694
-                                    ? $child_line_item->unit_price()
1695
-                                    : 0;
1696
-                                $running_totals['taxable'][ $child_line_item->ID() ] = $quantity
1697
-                                    ? $taxable_amount
1698
-                                    : 0;
1699
-                            } else {
1700
-                                $quantity = $child_line_item->quantity();
1701
-                                $running_totals[ $child_line_item->ID() ] = $child_line_item->unit_price();
1702
-                                $running_totals['taxable'][ $child_line_item->ID() ] = $taxable_amount;
1703
-                            }
1704
-                            $running_totals['taxable']['total'] += $taxable_amount * $quantity;
1705
-                            $running_totals['total'] += $child_line_item->unit_price() * $quantity;
1706
-                        }
1707
-                    } else {
1708
-                        // it's some other type of item added to the cart
1709
-                        // it should affect the running totals
1710
-                        // basically we want to convert it into a PERCENT modifier. Because
1711
-                        // more clearly affect all registration's final price equally
1712
-                        $line_items_percent_of_running_total = $running_totals['total'] > 0
1713
-                            ? ($child_line_item->total() / $running_totals['total']) + 1
1714
-                            : 1;
1715
-                        foreach ($running_totals as $line_item_id => $this_running_total) {
1716
-                            // the "taxable" array key is an exception
1717
-                            if ($line_item_id === 'taxable') {
1718
-                                continue;
1719
-                            }
1720
-                            // update the running totals
1721
-                            // yes this actually even works for the running grand total!
1722
-                            $running_totals[ $line_item_id ] =
1723
-                                $line_items_percent_of_running_total * $this_running_total;
1724
-
1725
-                            if ($child_line_item->is_taxable()) {
1726
-                                $running_totals['taxable'][ $line_item_id ] =
1727
-                                    $line_items_percent_of_running_total * $running_totals['taxable'][ $line_item_id ];
1728
-                            }
1729
-                        }
1730
-                    }
1731
-                    break;
1732
-            }
1733
-        }
1734
-        return $running_totals;
1735
-    }
1736
-
1737
-
1738
-    /**
1739
-     * @param EE_Line_Item $total_line_item
1740
-     * @param EE_Line_Item $ticket_line_item
1741
-     * @return float | null
1742
-     * @throws EE_Error
1743
-     * @throws InvalidArgumentException
1744
-     * @throws InvalidDataTypeException
1745
-     * @throws InvalidInterfaceException
1746
-     * @throws OutOfRangeException
1747
-     * @throws ReflectionException
1748
-     */
1749
-    public static function calculate_final_price_for_ticket_line_item(
1750
-        EE_Line_Item $total_line_item,
1751
-        EE_Line_Item $ticket_line_item
1752
-    ) {
1753
-        static $final_prices_per_ticket_line_item = array();
1754
-        if (empty($final_prices_per_ticket_line_item) || empty($final_prices_per_ticket_line_item[ $total_line_item->ID() ])) {
1755
-            $final_prices_per_ticket_line_item[ $total_line_item->ID() ] = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1756
-                $total_line_item
1757
-            );
1758
-        }
1759
-        // ok now find this new registration's final price
1760
-        if (isset($final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ])) {
1761
-            return $final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ];
1762
-        }
1763
-        $message = sprintf(
1764
-            esc_html__(
1765
-                'The final price for the ticket line item (ID:%1$d) could not be calculated.',
1766
-                'event_espresso'
1767
-            ),
1768
-            $ticket_line_item->ID()
1769
-        );
1770
-        if (WP_DEBUG) {
1771
-            $message .= '<br>' . print_r($final_prices_per_ticket_line_item, true);
1772
-            throw new OutOfRangeException($message);
1773
-        }
1774
-        EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message);
1775
-        return null;
1776
-    }
1777
-
1778
-
1779
-    /**
1780
-     * Creates a duplicate of the line item tree, except only includes billable items
1781
-     * and the portion of line items attributed to billable things
1782
-     *
1783
-     * @param EE_Line_Item      $line_item
1784
-     * @param EE_Registration[] $registrations
1785
-     * @return EE_Line_Item
1786
-     * @throws EE_Error
1787
-     * @throws InvalidArgumentException
1788
-     * @throws InvalidDataTypeException
1789
-     * @throws InvalidInterfaceException
1790
-     * @throws ReflectionException
1791
-     */
1792
-    public static function billable_line_item_tree(EE_Line_Item $line_item, $registrations)
1793
-    {
1794
-        $copy_li = EEH_Line_Item::billable_line_item($line_item, $registrations);
1795
-        foreach ($line_item->children() as $child_li) {
1796
-            $copy_li->add_child_line_item(
1797
-                EEH_Line_Item::billable_line_item_tree($child_li, $registrations)
1798
-            );
1799
-        }
1800
-        // if this is the grand total line item, make sure the totals all add up
1801
-        // (we could have duplicated this logic AS we copied the line items, but
1802
-        // it seems DRYer this way)
1803
-        if ($copy_li->type() === EEM_Line_Item::type_total) {
1804
-            $copy_li->recalculate_total_including_taxes();
1805
-        }
1806
-        return $copy_li;
1807
-    }
1808
-
1809
-
1810
-    /**
1811
-     * Creates a new, unsaved line item from $line_item that factors in the
1812
-     * number of billable registrations on $registrations.
1813
-     *
1814
-     * @param EE_Line_Item      $line_item
1815
-     * @param EE_Registration[] $registrations
1816
-     * @return EE_Line_Item
1817
-     * @throws EE_Error
1818
-     * @throws InvalidArgumentException
1819
-     * @throws InvalidDataTypeException
1820
-     * @throws InvalidInterfaceException
1821
-     * @throws ReflectionException
1822
-     */
1823
-    public static function billable_line_item(EE_Line_Item $line_item, $registrations)
1824
-    {
1825
-        $new_li_fields = $line_item->model_field_array();
1826
-        if (
1827
-            $line_item->type() === EEM_Line_Item::type_line_item &&
1828
-            $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1829
-        ) {
1830
-            $count = 0;
1831
-            foreach ($registrations as $registration) {
1832
-                if (
1833
-                    $line_item->OBJ_ID() === $registration->ticket_ID() &&
1834
-                    in_array(
1835
-                        $registration->status_ID(),
1836
-                        EEM_Registration::reg_statuses_that_allow_payment(),
1837
-                        true
1838
-                    )
1839
-                ) {
1840
-                    $count++;
1841
-                }
1842
-            }
1843
-            $new_li_fields['LIN_quantity'] = $count;
1844
-        }
1845
-        // don't set the total. We'll leave that up to the code that calculates it
1846
-        unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent'], $new_li_fields['LIN_total']);
1847
-        return EE_Line_Item::new_instance($new_li_fields);
1848
-    }
1849
-
1850
-
1851
-    /**
1852
-     * Returns a modified line item tree where all the subtotals which have a total of 0
1853
-     * are removed, and line items with a quantity of 0
1854
-     *
1855
-     * @param EE_Line_Item $line_item |null
1856
-     * @return EE_Line_Item|null
1857
-     * @throws EE_Error
1858
-     * @throws InvalidArgumentException
1859
-     * @throws InvalidDataTypeException
1860
-     * @throws InvalidInterfaceException
1861
-     * @throws ReflectionException
1862
-     */
1863
-    public static function non_empty_line_items(EE_Line_Item $line_item)
1864
-    {
1865
-        $copied_li = EEH_Line_Item::non_empty_line_item($line_item);
1866
-        if ($copied_li === null) {
1867
-            return null;
1868
-        }
1869
-        // if this is an event subtotal, we want to only include it if it
1870
-        // has a non-zero total and at least one ticket line item child
1871
-        $ticket_children = 0;
1872
-        foreach ($line_item->children() as $child_li) {
1873
-            $child_li_copy = EEH_Line_Item::non_empty_line_items($child_li);
1874
-            if ($child_li_copy !== null) {
1875
-                $copied_li->add_child_line_item($child_li_copy);
1876
-                if (
1877
-                    $child_li_copy->type() === EEM_Line_Item::type_line_item &&
1878
-                    $child_li_copy->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1879
-                ) {
1880
-                    $ticket_children++;
1881
-                }
1882
-            }
1883
-        }
1884
-        // if this is an event subtotal with NO ticket children
1885
-        // we basically want to ignore it
1886
-        if (
1887
-            $ticket_children === 0
1888
-            && $line_item->type() === EEM_Line_Item::type_sub_total
1889
-            && $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
1890
-            && $line_item->total() === 0
1891
-        ) {
1892
-            return null;
1893
-        }
1894
-        return $copied_li;
1895
-    }
1896
-
1897
-
1898
-    /**
1899
-     * Creates a new, unsaved line item, but if it's a ticket line item
1900
-     * with a total of 0, or a subtotal of 0, returns null instead
1901
-     *
1902
-     * @param EE_Line_Item $line_item
1903
-     * @return EE_Line_Item
1904
-     * @throws EE_Error
1905
-     * @throws InvalidArgumentException
1906
-     * @throws InvalidDataTypeException
1907
-     * @throws InvalidInterfaceException
1908
-     * @throws ReflectionException
1909
-     */
1910
-    public static function non_empty_line_item(EE_Line_Item $line_item)
1911
-    {
1912
-        if (
1913
-            $line_item->type() === EEM_Line_Item::type_line_item
1914
-            && $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1915
-            && $line_item->quantity() === 0
1916
-        ) {
1917
-            return null;
1918
-        }
1919
-        $new_li_fields = $line_item->model_field_array();
1920
-        // don't set the total. We'll leave that up to the code that calculates it
1921
-        unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent']);
1922
-        return EE_Line_Item::new_instance($new_li_fields);
1923
-    }
1924
-
1925
-
1926
-    /**
1927
-     * Cycles through all of the ticket line items for the supplied total line item
1928
-     * and ensures that the line item's "is_taxable" field matches that of its corresponding ticket
1929
-     *
1930
-     * @param EE_Line_Item $total_line_item
1931
-     * @since 4.9.79.p
1932
-     * @throws EE_Error
1933
-     * @throws InvalidArgumentException
1934
-     * @throws InvalidDataTypeException
1935
-     * @throws InvalidInterfaceException
1936
-     * @throws ReflectionException
1937
-     */
1938
-    public static function resetIsTaxableForTickets(EE_Line_Item $total_line_item)
1939
-    {
1940
-        $ticket_line_items = self::get_ticket_line_items($total_line_item);
1941
-        foreach ($ticket_line_items as $ticket_line_item) {
1942
-            if (
1943
-                $ticket_line_item instanceof EE_Line_Item
1944
-                && $ticket_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1945
-            ) {
1946
-                $ticket = $ticket_line_item->ticket();
1947
-                if ($ticket instanceof EE_Ticket && $ticket->taxable() !== $ticket_line_item->is_taxable()) {
1948
-                    $ticket_line_item->set_is_taxable($ticket->taxable());
1949
-                    $ticket_line_item->save();
1950
-                }
1951
-            }
1952
-        }
1953
-    }
1954
-
1955
-
1956
-
1957
-    /**************************************** @DEPRECATED METHODS *************************************** */
1958
-    /**
1959
-     * @deprecated
1960
-     * @param EE_Line_Item $total_line_item
1961
-     * @return EE_Line_Item
1962
-     * @throws EE_Error
1963
-     * @throws InvalidArgumentException
1964
-     * @throws InvalidDataTypeException
1965
-     * @throws InvalidInterfaceException
1966
-     * @throws ReflectionException
1967
-     */
1968
-    public static function get_items_subtotal(EE_Line_Item $total_line_item)
1969
-    {
1970
-        EE_Error::doing_it_wrong(
1971
-            'EEH_Line_Item::get_items_subtotal()',
1972
-            sprintf(
1973
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
1974
-                'EEH_Line_Item::get_pre_tax_subtotal()'
1975
-            ),
1976
-            '4.6.0'
1977
-        );
1978
-        return self::get_pre_tax_subtotal($total_line_item);
1979
-    }
1980
-
1981
-
1982
-    /**
1983
-     * @deprecated
1984
-     * @param EE_Transaction $transaction
1985
-     * @return EE_Line_Item
1986
-     * @throws EE_Error
1987
-     * @throws InvalidArgumentException
1988
-     * @throws InvalidDataTypeException
1989
-     * @throws InvalidInterfaceException
1990
-     * @throws ReflectionException
1991
-     */
1992
-    public static function create_default_total_line_item($transaction = null)
1993
-    {
1994
-        EE_Error::doing_it_wrong(
1995
-            'EEH_Line_Item::create_default_total_line_item()',
1996
-            sprintf(
1997
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
1998
-                'EEH_Line_Item::create_total_line_item()'
1999
-            ),
2000
-            '4.6.0'
2001
-        );
2002
-        return self::create_total_line_item($transaction);
2003
-    }
2004
-
2005
-
2006
-    /**
2007
-     * @deprecated
2008
-     * @param EE_Line_Item   $total_line_item
2009
-     * @param EE_Transaction $transaction
2010
-     * @return EE_Line_Item
2011
-     * @throws EE_Error
2012
-     * @throws InvalidArgumentException
2013
-     * @throws InvalidDataTypeException
2014
-     * @throws InvalidInterfaceException
2015
-     * @throws ReflectionException
2016
-     */
2017
-    public static function create_default_tickets_subtotal(EE_Line_Item $total_line_item, $transaction = null)
2018
-    {
2019
-        EE_Error::doing_it_wrong(
2020
-            'EEH_Line_Item::create_default_tickets_subtotal()',
2021
-            sprintf(
2022
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
2023
-                'EEH_Line_Item::create_pre_tax_subtotal()'
2024
-            ),
2025
-            '4.6.0'
2026
-        );
2027
-        return self::create_pre_tax_subtotal($total_line_item, $transaction);
2028
-    }
2029
-
2030
-
2031
-    /**
2032
-     * @deprecated
2033
-     * @param EE_Line_Item   $total_line_item
2034
-     * @param EE_Transaction $transaction
2035
-     * @return EE_Line_Item
2036
-     * @throws EE_Error
2037
-     * @throws InvalidArgumentException
2038
-     * @throws InvalidDataTypeException
2039
-     * @throws InvalidInterfaceException
2040
-     * @throws ReflectionException
2041
-     */
2042
-    public static function create_default_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null)
2043
-    {
2044
-        EE_Error::doing_it_wrong(
2045
-            'EEH_Line_Item::create_default_taxes_subtotal()',
2046
-            sprintf(
2047
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
2048
-                'EEH_Line_Item::create_taxes_subtotal()'
2049
-            ),
2050
-            '4.6.0'
2051
-        );
2052
-        return self::create_taxes_subtotal($total_line_item, $transaction);
2053
-    }
2054
-
2055
-
2056
-    /**
2057
-     * @deprecated
2058
-     * @param EE_Line_Item   $total_line_item
2059
-     * @param EE_Transaction $transaction
2060
-     * @return EE_Line_Item
2061
-     * @throws EE_Error
2062
-     * @throws InvalidArgumentException
2063
-     * @throws InvalidDataTypeException
2064
-     * @throws InvalidInterfaceException
2065
-     * @throws ReflectionException
2066
-     */
2067
-    public static function create_default_event_subtotal(EE_Line_Item $total_line_item, $transaction = null)
2068
-    {
2069
-        EE_Error::doing_it_wrong(
2070
-            'EEH_Line_Item::create_default_event_subtotal()',
2071
-            sprintf(
2072
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
2073
-                'EEH_Line_Item::create_event_subtotal()'
2074
-            ),
2075
-            '4.6.0'
2076
-        );
2077
-        return self::create_event_subtotal($total_line_item, $transaction);
2078
-    }
24
+	/**
25
+	 * Adds a simple item (unrelated to any other model object) to the provided PARENT line item.
26
+	 * Does NOT automatically re-calculate the line item totals or update the related transaction.
27
+	 * You should call recalculate_total_including_taxes() on the grant total line item after this
28
+	 * to update the subtotals, and EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
29
+	 * to keep the registration final prices in-sync with the transaction's total.
30
+	 *
31
+	 * @param EE_Line_Item $parent_line_item
32
+	 * @param string       $name
33
+	 * @param float        $unit_price
34
+	 * @param string       $description
35
+	 * @param int          $quantity
36
+	 * @param boolean      $taxable
37
+	 * @param boolean      $code if set to a value, ensures there is only one line item with that code
38
+	 * @return boolean success
39
+	 * @throws EE_Error
40
+	 * @throws InvalidArgumentException
41
+	 * @throws InvalidDataTypeException
42
+	 * @throws InvalidInterfaceException
43
+	 * @throws ReflectionException
44
+	 */
45
+	public static function add_unrelated_item(
46
+		EE_Line_Item $parent_line_item,
47
+		$name,
48
+		$unit_price,
49
+		$description = '',
50
+		$quantity = 1,
51
+		$taxable = false,
52
+		$code = null
53
+	) {
54
+		$items_subtotal = self::get_pre_tax_subtotal($parent_line_item);
55
+		$line_item = EE_Line_Item::new_instance(array(
56
+			'LIN_name'       => $name,
57
+			'LIN_desc'       => $description,
58
+			'LIN_unit_price' => $unit_price,
59
+			'LIN_quantity'   => $quantity,
60
+			'LIN_percent'    => null,
61
+			'LIN_is_taxable' => $taxable,
62
+			'LIN_order'      => $items_subtotal instanceof EE_Line_Item ? count($items_subtotal->children()) : 0,
63
+			'LIN_total'      => (float) $unit_price * (int) $quantity,
64
+			'LIN_type'       => EEM_Line_Item::type_line_item,
65
+			'LIN_code'       => $code,
66
+		));
67
+		$line_item = apply_filters(
68
+			'FHEE__EEH_Line_Item__add_unrelated_item__line_item',
69
+			$line_item,
70
+			$parent_line_item
71
+		);
72
+		return self::add_item($parent_line_item, $line_item);
73
+	}
74
+
75
+
76
+	/**
77
+	 * Adds a simple item ( unrelated to any other model object) to the total line item,
78
+	 * in the correct spot in the line item tree. Does not automatically
79
+	 * re-calculate the line item totals, nor update the related transaction, nor upgrade the transaction's
80
+	 * registrations' final prices (which should probably change because of this).
81
+	 * You should call recalculate_total_including_taxes() on the grand total line item, then
82
+	 * update the transaction's total, and EE_Registration_Processor::update_registration_final_prices()
83
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
84
+	 *
85
+	 * @param EE_Line_Item $parent_line_item
86
+	 * @param string       $name
87
+	 * @param float        $percentage_amount
88
+	 * @param string       $description
89
+	 * @param boolean      $taxable
90
+	 * @return boolean success
91
+	 * @throws EE_Error
92
+	 */
93
+	public static function add_percentage_based_item(
94
+		EE_Line_Item $parent_line_item,
95
+		$name,
96
+		$percentage_amount,
97
+		$description = '',
98
+		$taxable = false
99
+	) {
100
+		$line_item = EE_Line_Item::new_instance(array(
101
+			'LIN_name'       => $name,
102
+			'LIN_desc'       => $description,
103
+			'LIN_unit_price' => 0,
104
+			'LIN_percent'    => $percentage_amount,
105
+			'LIN_quantity'   => 1,
106
+			'LIN_is_taxable' => $taxable,
107
+			'LIN_total'      => (float) ($percentage_amount * ($parent_line_item->total() / 100)),
108
+			'LIN_type'       => EEM_Line_Item::type_line_item,
109
+			'LIN_parent'     => $parent_line_item->ID(),
110
+		));
111
+		$line_item = apply_filters(
112
+			'FHEE__EEH_Line_Item__add_percentage_based_item__line_item',
113
+			$line_item
114
+		);
115
+		return $parent_line_item->add_child_line_item($line_item, false);
116
+	}
117
+
118
+
119
+	/**
120
+	 * Returns the new line item created by adding a purchase of the ticket
121
+	 * ensures that ticket line item is saved, and that cart total has been recalculated.
122
+	 * If this ticket has already been purchased, just increments its count.
123
+	 * Automatically re-calculates the line item totals and updates the related transaction. But
124
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
125
+	 * should probably change because of this).
126
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
127
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
128
+	 *
129
+	 * @param EE_Line_Item $total_line_item grand total line item of type EEM_Line_Item::type_total
130
+	 * @param EE_Ticket    $ticket
131
+	 * @param int          $qty
132
+	 * @return EE_Line_Item
133
+	 * @throws EE_Error
134
+	 * @throws InvalidArgumentException
135
+	 * @throws InvalidDataTypeException
136
+	 * @throws InvalidInterfaceException
137
+	 * @throws ReflectionException
138
+	 */
139
+	public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
140
+	{
141
+		if (! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) {
142
+			throw new EE_Error(
143
+				sprintf(
144
+					esc_html__(
145
+						'A valid line item total is required in order to add tickets. A line item of type "%s" was passed.',
146
+						'event_espresso'
147
+					),
148
+					$ticket->ID(),
149
+					$total_line_item->ID()
150
+				)
151
+			);
152
+		}
153
+		// either increment the qty for an existing ticket
154
+		$line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty);
155
+		// or add a new one
156
+		if (! $line_item instanceof EE_Line_Item) {
157
+			$line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty);
158
+		}
159
+		$total_line_item->recalculate_total_including_taxes();
160
+		return $line_item;
161
+	}
162
+
163
+
164
+	/**
165
+	 * Returns the new line item created by adding a purchase of the ticket
166
+	 *
167
+	 * @param EE_Line_Item $total_line_item
168
+	 * @param EE_Ticket    $ticket
169
+	 * @param int          $qty
170
+	 * @return EE_Line_Item
171
+	 * @throws EE_Error
172
+	 * @throws InvalidArgumentException
173
+	 * @throws InvalidDataTypeException
174
+	 * @throws InvalidInterfaceException
175
+	 * @throws ReflectionException
176
+	 */
177
+	public static function increment_ticket_qty_if_already_in_cart(
178
+		EE_Line_Item $total_line_item,
179
+		EE_Ticket $ticket,
180
+		$qty = 1
181
+	) {
182
+		$line_item = null;
183
+		if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) {
184
+			$ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
185
+			foreach ((array) $ticket_line_items as $ticket_line_item) {
186
+				if (
187
+					$ticket_line_item instanceof EE_Line_Item
188
+					&& (int) $ticket_line_item->OBJ_ID() === (int) $ticket->ID()
189
+				) {
190
+					$line_item = $ticket_line_item;
191
+					break;
192
+				}
193
+			}
194
+		}
195
+		if ($line_item instanceof EE_Line_Item) {
196
+			EEH_Line_Item::increment_quantity($line_item, $qty);
197
+			return $line_item;
198
+		}
199
+		return null;
200
+	}
201
+
202
+
203
+	/**
204
+	 * Increments the line item and all its children's quantity by $qty (but percent line items are unaffected).
205
+	 * Does NOT save or recalculate other line items totals
206
+	 *
207
+	 * @param EE_Line_Item $line_item
208
+	 * @param int          $qty
209
+	 * @return void
210
+	 * @throws EE_Error
211
+	 * @throws InvalidArgumentException
212
+	 * @throws InvalidDataTypeException
213
+	 * @throws InvalidInterfaceException
214
+	 * @throws ReflectionException
215
+	 */
216
+	public static function increment_quantity(EE_Line_Item $line_item, $qty = 1)
217
+	{
218
+		if (! $line_item->is_percent()) {
219
+			$qty += $line_item->quantity();
220
+			$line_item->set_quantity($qty);
221
+			$line_item->set_total($line_item->unit_price() * $qty);
222
+			$line_item->save();
223
+		}
224
+		foreach ($line_item->children() as $child) {
225
+			if ($child->is_sub_line_item()) {
226
+				EEH_Line_Item::update_quantity($child, $qty);
227
+			}
228
+		}
229
+	}
230
+
231
+
232
+	/**
233
+	 * Decrements the line item and all its children's quantity by $qty (but percent line items are unaffected).
234
+	 * Does NOT save or recalculate other line items totals
235
+	 *
236
+	 * @param EE_Line_Item $line_item
237
+	 * @param int          $qty
238
+	 * @return void
239
+	 * @throws EE_Error
240
+	 * @throws InvalidArgumentException
241
+	 * @throws InvalidDataTypeException
242
+	 * @throws InvalidInterfaceException
243
+	 * @throws ReflectionException
244
+	 */
245
+	public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1)
246
+	{
247
+		if (! $line_item->is_percent()) {
248
+			$qty = $line_item->quantity() - $qty;
249
+			$qty = max($qty, 0);
250
+			$line_item->set_quantity($qty);
251
+			$line_item->set_total($line_item->unit_price() * $qty);
252
+			$line_item->save();
253
+		}
254
+		foreach ($line_item->children() as $child) {
255
+			if ($child->is_sub_line_item()) {
256
+				EEH_Line_Item::update_quantity($child, $qty);
257
+			}
258
+		}
259
+	}
260
+
261
+
262
+	/**
263
+	 * Updates the line item and its children's quantities to the specified number.
264
+	 * Does NOT save them or recalculate totals.
265
+	 *
266
+	 * @param EE_Line_Item $line_item
267
+	 * @param int          $new_quantity
268
+	 * @throws EE_Error
269
+	 * @throws InvalidArgumentException
270
+	 * @throws InvalidDataTypeException
271
+	 * @throws InvalidInterfaceException
272
+	 * @throws ReflectionException
273
+	 */
274
+	public static function update_quantity(EE_Line_Item $line_item, $new_quantity)
275
+	{
276
+		if (! $line_item->is_percent()) {
277
+			$line_item->set_quantity($new_quantity);
278
+			$line_item->set_total($line_item->unit_price() * $new_quantity);
279
+			$line_item->save();
280
+		}
281
+		foreach ($line_item->children() as $child) {
282
+			if ($child->is_sub_line_item()) {
283
+				EEH_Line_Item::update_quantity($child, $new_quantity);
284
+			}
285
+		}
286
+	}
287
+
288
+
289
+	/**
290
+	 * Returns the new line item created by adding a purchase of the ticket
291
+	 *
292
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
293
+	 * @param EE_Ticket    $ticket
294
+	 * @param int          $qty
295
+	 * @return EE_Line_Item
296
+	 * @throws EE_Error
297
+	 * @throws InvalidArgumentException
298
+	 * @throws InvalidDataTypeException
299
+	 * @throws InvalidInterfaceException
300
+	 * @throws ReflectionException
301
+	 */
302
+	public static function create_ticket_line_item(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1)
303
+	{
304
+		$datetimes = $ticket->datetimes();
305
+		$first_datetime = reset($datetimes);
306
+		$first_datetime_name = esc_html__('Event', 'event_espresso');
307
+		if ($first_datetime instanceof EE_Datetime && $first_datetime->event() instanceof EE_Event) {
308
+			$first_datetime_name = $first_datetime->event()->name();
309
+		}
310
+		$event = sprintf(_x('(For %1$s)', '(For Event Name)', 'event_espresso'), $first_datetime_name);
311
+		// get event subtotal line
312
+		$events_sub_total = self::get_event_line_item_for_ticket($total_line_item, $ticket);
313
+		$taxes = $ticket->tax_price_modifiers();
314
+		$is_taxable = empty($taxes) ? $ticket->taxable() : false;
315
+		// add $ticket to cart
316
+		$line_item = EE_Line_Item::new_instance(array(
317
+			'LIN_name'       => $ticket->name(),
318
+			'LIN_desc'       => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event,
319
+			'LIN_unit_price' => $ticket->price(),
320
+			'LIN_quantity'   => $qty,
321
+			'LIN_is_taxable' => $is_taxable,
322
+			'LIN_order'      => count($events_sub_total->children()),
323
+			'LIN_total'      => $ticket->price() * $qty,
324
+			'LIN_type'       => EEM_Line_Item::type_line_item,
325
+			'OBJ_ID'         => $ticket->ID(),
326
+			'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_TICKET,
327
+		));
328
+		$line_item = apply_filters(
329
+			'FHEE__EEH_Line_Item__create_ticket_line_item__line_item',
330
+			$line_item
331
+		);
332
+		$events_sub_total->add_child_line_item($line_item);
333
+		// now add the sub-line items
334
+		$running_total_for_ticket = 0;
335
+		foreach ($ticket->prices(array('order_by' => array('PRC_order' => 'ASC'))) as $price) {
336
+			$sign = $price->is_discount() ? -1 : 1;
337
+			$price_total = $price->is_percent()
338
+				? $running_total_for_ticket * $price->amount() / 100
339
+				: $price->amount() * $qty;
340
+			$sub_line_item = EE_Line_Item::new_instance(array(
341
+				'LIN_name'       => $price->name(),
342
+				'LIN_desc'       => $price->desc(),
343
+				'LIN_quantity'   => $price->is_percent() ? null : $qty,
344
+				'LIN_is_taxable' => false,
345
+				'LIN_order'      => $price->order(),
346
+				'LIN_total'      => $sign * $price_total,
347
+				'LIN_type'       => EEM_Line_Item::type_sub_line_item,
348
+				'OBJ_ID'         => $price->ID(),
349
+				'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_PRICE,
350
+			));
351
+			$sub_line_item = apply_filters(
352
+				'FHEE__EEH_Line_Item__create_ticket_line_item__sub_line_item',
353
+				$sub_line_item
354
+			);
355
+			if ($price->is_percent()) {
356
+				$sub_line_item->set_percent($sign * $price->amount());
357
+			} else {
358
+				$sub_line_item->set_unit_price($sign * $price->amount());
359
+			}
360
+			$running_total_for_ticket += $price_total;
361
+			$line_item->add_child_line_item($sub_line_item);
362
+		}
363
+		return $line_item;
364
+	}
365
+
366
+
367
+	/**
368
+	 * Adds the specified item under the pre-tax-sub-total line item. Automatically
369
+	 * re-calculates the line item totals and updates the related transaction. But
370
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
371
+	 * should probably change because of this).
372
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
373
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
374
+	 *
375
+	 * @param EE_Line_Item $total_line_item
376
+	 * @param EE_Line_Item $item to be added
377
+	 * @return boolean
378
+	 * @throws EE_Error
379
+	 * @throws InvalidArgumentException
380
+	 * @throws InvalidDataTypeException
381
+	 * @throws InvalidInterfaceException
382
+	 * @throws ReflectionException
383
+	 */
384
+	public static function add_item(EE_Line_Item $total_line_item, EE_Line_Item $item)
385
+	{
386
+		$pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item);
387
+		if ($pre_tax_subtotal instanceof EE_Line_Item) {
388
+			$success = $pre_tax_subtotal->add_child_line_item($item);
389
+		} else {
390
+			return false;
391
+		}
392
+		$total_line_item->recalculate_total_including_taxes();
393
+		return $success;
394
+	}
395
+
396
+
397
+	/**
398
+	 * cancels an existing ticket line item,
399
+	 * by decrementing it's quantity by 1 and adding a new "type_cancellation" sub-line-item.
400
+	 * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
401
+	 *
402
+	 * @param EE_Line_Item $ticket_line_item
403
+	 * @param int          $qty
404
+	 * @return bool success
405
+	 * @throws EE_Error
406
+	 * @throws InvalidArgumentException
407
+	 * @throws InvalidDataTypeException
408
+	 * @throws InvalidInterfaceException
409
+	 * @throws ReflectionException
410
+	 */
411
+	public static function cancel_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
412
+	{
413
+		// validate incoming line_item
414
+		if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) {
415
+			throw new EE_Error(
416
+				sprintf(
417
+					esc_html__(
418
+						'The supplied line item must have an Object Type of "Ticket", not %1$s.',
419
+						'event_espresso'
420
+					),
421
+					$ticket_line_item->type()
422
+				)
423
+			);
424
+		}
425
+		if ($ticket_line_item->quantity() < $qty) {
426
+			throw new EE_Error(
427
+				sprintf(
428
+					esc_html__(
429
+						'Can not cancel %1$d ticket(s) because the supplied line item has a quantity of %2$d.',
430
+						'event_espresso'
431
+					),
432
+					$qty,
433
+					$ticket_line_item->quantity()
434
+				)
435
+			);
436
+		}
437
+		// decrement ticket quantity; don't rely on auto-fixing when recalculating totals to do this
438
+		$ticket_line_item->set_quantity($ticket_line_item->quantity() - $qty);
439
+		foreach ($ticket_line_item->children() as $child_line_item) {
440
+			if (
441
+				$child_line_item->is_sub_line_item()
442
+				&& ! $child_line_item->is_percent()
443
+				&& ! $child_line_item->is_cancellation()
444
+			) {
445
+				$child_line_item->set_quantity($child_line_item->quantity() - $qty);
446
+			}
447
+		}
448
+		// get cancellation sub line item
449
+		$cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
450
+			$ticket_line_item,
451
+			EEM_Line_Item::type_cancellation
452
+		);
453
+		$cancellation_line_item = reset($cancellation_line_item);
454
+		// verify that this ticket was indeed previously cancelled
455
+		if ($cancellation_line_item instanceof EE_Line_Item) {
456
+			// increment cancelled quantity
457
+			$cancellation_line_item->set_quantity($cancellation_line_item->quantity() + $qty);
458
+		} else {
459
+			// create cancellation sub line item
460
+			$cancellation_line_item = EE_Line_Item::new_instance(array(
461
+				'LIN_name'       => esc_html__('Cancellation', 'event_espresso'),
462
+				'LIN_desc'       => sprintf(
463
+					esc_html_x(
464
+						'Cancelled %1$s : %2$s',
465
+						'Cancelled Ticket Name : 2015-01-01 11:11',
466
+						'event_espresso'
467
+					),
468
+					$ticket_line_item->name(),
469
+					current_time(get_option('date_format') . ' ' . get_option('time_format'))
470
+				),
471
+				'LIN_unit_price' => 0, // $ticket_line_item->unit_price()
472
+				'LIN_quantity'   => $qty,
473
+				'LIN_is_taxable' => $ticket_line_item->is_taxable(),
474
+				'LIN_order'      => count($ticket_line_item->children()),
475
+				'LIN_total'      => 0, // $ticket_line_item->unit_price()
476
+				'LIN_type'       => EEM_Line_Item::type_cancellation,
477
+			));
478
+			$ticket_line_item->add_child_line_item($cancellation_line_item);
479
+		}
480
+		if ($ticket_line_item->save_this_and_descendants() > 0) {
481
+			// decrement parent line item quantity
482
+			$event_line_item = $ticket_line_item->parent();
483
+			if (
484
+				$event_line_item instanceof EE_Line_Item
485
+				&& $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
486
+			) {
487
+				$event_line_item->set_quantity($event_line_item->quantity() - $qty);
488
+				$event_line_item->save();
489
+			}
490
+			EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
491
+			return true;
492
+		}
493
+		return false;
494
+	}
495
+
496
+
497
+	/**
498
+	 * reinstates (un-cancels?) a previously canceled ticket line item,
499
+	 * by incrementing it's quantity by 1, and decrementing it's "type_cancellation" sub-line-item.
500
+	 * ALL totals and subtotals will NEED TO BE UPDATED after performing this action
501
+	 *
502
+	 * @param EE_Line_Item $ticket_line_item
503
+	 * @param int          $qty
504
+	 * @return bool success
505
+	 * @throws EE_Error
506
+	 * @throws InvalidArgumentException
507
+	 * @throws InvalidDataTypeException
508
+	 * @throws InvalidInterfaceException
509
+	 * @throws ReflectionException
510
+	 */
511
+	public static function reinstate_canceled_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1)
512
+	{
513
+		// validate incoming line_item
514
+		if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) {
515
+			throw new EE_Error(
516
+				sprintf(
517
+					esc_html__(
518
+						'The supplied line item must have an Object Type of "Ticket", not %1$s.',
519
+						'event_espresso'
520
+					),
521
+					$ticket_line_item->type()
522
+				)
523
+			);
524
+		}
525
+		// get cancellation sub line item
526
+		$cancellation_line_item = EEH_Line_Item::get_descendants_of_type(
527
+			$ticket_line_item,
528
+			EEM_Line_Item::type_cancellation
529
+		);
530
+		$cancellation_line_item = reset($cancellation_line_item);
531
+		// verify that this ticket was indeed previously cancelled
532
+		if (! $cancellation_line_item instanceof EE_Line_Item) {
533
+			return false;
534
+		}
535
+		if ($cancellation_line_item->quantity() > $qty) {
536
+			// decrement cancelled quantity
537
+			$cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
538
+		} elseif ($cancellation_line_item->quantity() === $qty) {
539
+			// decrement cancelled quantity in case anyone still has the object kicking around
540
+			$cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty);
541
+			// delete because quantity will end up as 0
542
+			$cancellation_line_item->delete();
543
+			// and attempt to destroy the object,
544
+			// even though PHP won't actually destroy it until it needs the memory
545
+			unset($cancellation_line_item);
546
+		} else {
547
+			// what ?!?! negative quantity ?!?!
548
+			throw new EE_Error(
549
+				sprintf(
550
+					esc_html__(
551
+						'Can not reinstate %1$d cancelled ticket(s) because the cancelled ticket quantity is only %2$d.',
552
+						'event_espresso'
553
+					),
554
+					$qty,
555
+					$cancellation_line_item->quantity()
556
+				)
557
+			);
558
+		}
559
+		// increment ticket quantity
560
+		$ticket_line_item->set_quantity($ticket_line_item->quantity() + $qty);
561
+		if ($ticket_line_item->save_this_and_descendants() > 0) {
562
+			// increment parent line item quantity
563
+			$event_line_item = $ticket_line_item->parent();
564
+			if (
565
+				$event_line_item instanceof EE_Line_Item
566
+				&& $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
567
+			) {
568
+				$event_line_item->set_quantity($event_line_item->quantity() + $qty);
569
+			}
570
+			EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item);
571
+			return true;
572
+		}
573
+		return false;
574
+	}
575
+
576
+
577
+	/**
578
+	 * calls EEH_Line_Item::find_transaction_grand_total_for_line_item()
579
+	 * then EE_Line_Item::recalculate_total_including_taxes() on the result
580
+	 *
581
+	 * @param EE_Line_Item $line_item
582
+	 * @return float
583
+	 * @throws EE_Error
584
+	 * @throws InvalidArgumentException
585
+	 * @throws InvalidDataTypeException
586
+	 * @throws InvalidInterfaceException
587
+	 * @throws ReflectionException
588
+	 */
589
+	public static function get_grand_total_and_recalculate_everything(EE_Line_Item $line_item)
590
+	{
591
+		$grand_total_line_item = EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item);
592
+		return $grand_total_line_item->recalculate_total_including_taxes();
593
+	}
594
+
595
+
596
+	/**
597
+	 * Gets the line item which contains the subtotal of all the items
598
+	 *
599
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
600
+	 * @return EE_Line_Item
601
+	 * @throws EE_Error
602
+	 * @throws InvalidArgumentException
603
+	 * @throws InvalidDataTypeException
604
+	 * @throws InvalidInterfaceException
605
+	 * @throws ReflectionException
606
+	 */
607
+	public static function get_pre_tax_subtotal(EE_Line_Item $total_line_item)
608
+	{
609
+		$pre_tax_subtotal = $total_line_item->get_child_line_item('pre-tax-subtotal');
610
+		return $pre_tax_subtotal instanceof EE_Line_Item
611
+			? $pre_tax_subtotal
612
+			: self::create_pre_tax_subtotal($total_line_item);
613
+	}
614
+
615
+
616
+	/**
617
+	 * Gets the line item for the taxes subtotal
618
+	 *
619
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
620
+	 * @return EE_Line_Item
621
+	 * @throws EE_Error
622
+	 * @throws InvalidArgumentException
623
+	 * @throws InvalidDataTypeException
624
+	 * @throws InvalidInterfaceException
625
+	 * @throws ReflectionException
626
+	 */
627
+	public static function get_taxes_subtotal(EE_Line_Item $total_line_item)
628
+	{
629
+		$taxes = $total_line_item->get_child_line_item('taxes');
630
+		return $taxes ? $taxes : self::create_taxes_subtotal($total_line_item);
631
+	}
632
+
633
+
634
+	/**
635
+	 * sets the TXN ID on an EE_Line_Item if passed a valid EE_Transaction object
636
+	 *
637
+	 * @param EE_Line_Item   $line_item
638
+	 * @param EE_Transaction $transaction
639
+	 * @return void
640
+	 * @throws EE_Error
641
+	 * @throws InvalidArgumentException
642
+	 * @throws InvalidDataTypeException
643
+	 * @throws InvalidInterfaceException
644
+	 * @throws ReflectionException
645
+	 */
646
+	public static function set_TXN_ID(EE_Line_Item $line_item, $transaction = null)
647
+	{
648
+		if ($transaction) {
649
+			/** @type EEM_Transaction $EEM_Transaction */
650
+			$EEM_Transaction = EE_Registry::instance()->load_model('Transaction');
651
+			$TXN_ID = $EEM_Transaction->ensure_is_ID($transaction);
652
+			$line_item->set_TXN_ID($TXN_ID);
653
+		}
654
+	}
655
+
656
+
657
+	/**
658
+	 * Creates a new default total line item for the transaction,
659
+	 * and its tickets subtotal and taxes subtotal line items (and adds the
660
+	 * existing taxes as children of the taxes subtotal line item)
661
+	 *
662
+	 * @param EE_Transaction $transaction
663
+	 * @return EE_Line_Item of type total
664
+	 * @throws EE_Error
665
+	 * @throws InvalidArgumentException
666
+	 * @throws InvalidDataTypeException
667
+	 * @throws InvalidInterfaceException
668
+	 * @throws ReflectionException
669
+	 */
670
+	public static function create_total_line_item($transaction = null)
671
+	{
672
+		$total_line_item = EE_Line_Item::new_instance(array(
673
+			'LIN_code' => 'total',
674
+			'LIN_name' => esc_html__('Grand Total', 'event_espresso'),
675
+			'LIN_type' => EEM_Line_Item::type_total,
676
+			'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TRANSACTION,
677
+		));
678
+		$total_line_item = apply_filters(
679
+			'FHEE__EEH_Line_Item__create_total_line_item__total_line_item',
680
+			$total_line_item
681
+		);
682
+		self::set_TXN_ID($total_line_item, $transaction);
683
+		self::create_pre_tax_subtotal($total_line_item, $transaction);
684
+		self::create_taxes_subtotal($total_line_item, $transaction);
685
+		return $total_line_item;
686
+	}
687
+
688
+
689
+	/**
690
+	 * Creates a default items subtotal line item
691
+	 *
692
+	 * @param EE_Line_Item   $total_line_item
693
+	 * @param EE_Transaction $transaction
694
+	 * @return EE_Line_Item
695
+	 * @throws EE_Error
696
+	 * @throws InvalidArgumentException
697
+	 * @throws InvalidDataTypeException
698
+	 * @throws InvalidInterfaceException
699
+	 * @throws ReflectionException
700
+	 */
701
+	protected static function create_pre_tax_subtotal(EE_Line_Item $total_line_item, $transaction = null)
702
+	{
703
+		$pre_tax_line_item = EE_Line_Item::new_instance(array(
704
+			'LIN_code' => 'pre-tax-subtotal',
705
+			'LIN_name' => esc_html__('Pre-Tax Subtotal', 'event_espresso'),
706
+			'LIN_type' => EEM_Line_Item::type_sub_total,
707
+		));
708
+		$pre_tax_line_item = apply_filters(
709
+			'FHEE__EEH_Line_Item__create_pre_tax_subtotal__pre_tax_line_item',
710
+			$pre_tax_line_item
711
+		);
712
+		self::set_TXN_ID($pre_tax_line_item, $transaction);
713
+		$total_line_item->add_child_line_item($pre_tax_line_item);
714
+		self::create_event_subtotal($pre_tax_line_item, $transaction);
715
+		return $pre_tax_line_item;
716
+	}
717
+
718
+
719
+	/**
720
+	 * Creates a line item for the taxes subtotal and finds all the tax prices
721
+	 * and applies taxes to it
722
+	 *
723
+	 * @param EE_Line_Item   $total_line_item of type EEM_Line_Item::type_total
724
+	 * @param EE_Transaction $transaction
725
+	 * @return EE_Line_Item
726
+	 * @throws EE_Error
727
+	 * @throws InvalidArgumentException
728
+	 * @throws InvalidDataTypeException
729
+	 * @throws InvalidInterfaceException
730
+	 * @throws ReflectionException
731
+	 */
732
+	protected static function create_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null)
733
+	{
734
+		$tax_line_item = EE_Line_Item::new_instance(array(
735
+			'LIN_code'  => 'taxes',
736
+			'LIN_name'  => esc_html__('Taxes', 'event_espresso'),
737
+			'LIN_type'  => EEM_Line_Item::type_tax_sub_total,
738
+			'LIN_order' => 1000,// this should always come last
739
+		));
740
+		$tax_line_item = apply_filters(
741
+			'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item',
742
+			$tax_line_item
743
+		);
744
+		self::set_TXN_ID($tax_line_item, $transaction);
745
+		$total_line_item->add_child_line_item($tax_line_item);
746
+		// and lastly, add the actual taxes
747
+		self::apply_taxes($total_line_item);
748
+		return $tax_line_item;
749
+	}
750
+
751
+
752
+	/**
753
+	 * Creates a default items subtotal line item
754
+	 *
755
+	 * @param EE_Line_Item   $pre_tax_line_item
756
+	 * @param EE_Transaction $transaction
757
+	 * @param EE_Event       $event
758
+	 * @return EE_Line_Item
759
+	 * @throws EE_Error
760
+	 * @throws InvalidArgumentException
761
+	 * @throws InvalidDataTypeException
762
+	 * @throws InvalidInterfaceException
763
+	 * @throws ReflectionException
764
+	 */
765
+	public static function create_event_subtotal(EE_Line_Item $pre_tax_line_item, $transaction = null, $event = null)
766
+	{
767
+		$event_line_item = EE_Line_Item::new_instance(array(
768
+			'LIN_code' => self::get_event_code($event),
769
+			'LIN_name' => self::get_event_name($event),
770
+			'LIN_desc' => self::get_event_desc($event),
771
+			'LIN_type' => EEM_Line_Item::type_sub_total,
772
+			'OBJ_type' => EEM_Line_Item::OBJ_TYPE_EVENT,
773
+			'OBJ_ID'   => $event instanceof EE_Event ? $event->ID() : 0,
774
+		));
775
+		$event_line_item = apply_filters(
776
+			'FHEE__EEH_Line_Item__create_event_subtotal__event_line_item',
777
+			$event_line_item
778
+		);
779
+		self::set_TXN_ID($event_line_item, $transaction);
780
+		$pre_tax_line_item->add_child_line_item($event_line_item);
781
+		return $event_line_item;
782
+	}
783
+
784
+
785
+	/**
786
+	 * Gets what the event ticket's code SHOULD be
787
+	 *
788
+	 * @param EE_Event $event
789
+	 * @return string
790
+	 * @throws EE_Error
791
+	 */
792
+	public static function get_event_code($event)
793
+	{
794
+		return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0');
795
+	}
796
+
797
+
798
+	/**
799
+	 * Gets the event name
800
+	 *
801
+	 * @param EE_Event $event
802
+	 * @return string
803
+	 * @throws EE_Error
804
+	 */
805
+	public static function get_event_name($event)
806
+	{
807
+		return $event instanceof EE_Event
808
+			? mb_substr($event->name(), 0, 245)
809
+			: esc_html__('Event', 'event_espresso');
810
+	}
811
+
812
+
813
+	/**
814
+	 * Gets the event excerpt
815
+	 *
816
+	 * @param EE_Event $event
817
+	 * @return string
818
+	 * @throws EE_Error
819
+	 */
820
+	public static function get_event_desc($event)
821
+	{
822
+		return $event instanceof EE_Event ? $event->short_description() : '';
823
+	}
824
+
825
+
826
+	/**
827
+	 * Given the grand total line item and a ticket, finds the event sub-total
828
+	 * line item the ticket's purchase should be added onto
829
+	 *
830
+	 * @access public
831
+	 * @param EE_Line_Item $grand_total the grand total line item
832
+	 * @param EE_Ticket    $ticket
833
+	 * @return EE_Line_Item
834
+	 * @throws EE_Error
835
+	 * @throws InvalidArgumentException
836
+	 * @throws InvalidDataTypeException
837
+	 * @throws InvalidInterfaceException
838
+	 * @throws ReflectionException
839
+	 */
840
+	public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket)
841
+	{
842
+		$first_datetime = $ticket->first_datetime();
843
+		if (! $first_datetime instanceof EE_Datetime) {
844
+			throw new EE_Error(
845
+				sprintf(
846
+					__('The supplied ticket (ID %d) has no datetimes', 'event_espresso'),
847
+					$ticket->ID()
848
+				)
849
+			);
850
+		}
851
+		$event = $first_datetime->event();
852
+		if (! $event instanceof EE_Event) {
853
+			throw new EE_Error(
854
+				sprintf(
855
+					esc_html__(
856
+						'The supplied ticket (ID %d) has no event data associated with it.',
857
+						'event_espresso'
858
+					),
859
+					$ticket->ID()
860
+				)
861
+			);
862
+		}
863
+		$events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event);
864
+		if (! $events_sub_total instanceof EE_Line_Item) {
865
+			throw new EE_Error(
866
+				sprintf(
867
+					esc_html__(
868
+						'There is no events sub-total for ticket %s on total line item %d',
869
+						'event_espresso'
870
+					),
871
+					$ticket->ID(),
872
+					$grand_total->ID()
873
+				)
874
+			);
875
+		}
876
+		return $events_sub_total;
877
+	}
878
+
879
+
880
+	/**
881
+	 * Gets the event line item
882
+	 *
883
+	 * @param EE_Line_Item $grand_total
884
+	 * @param EE_Event     $event
885
+	 * @return EE_Line_Item for the event subtotal which is a child of $grand_total
886
+	 * @throws EE_Error
887
+	 * @throws InvalidArgumentException
888
+	 * @throws InvalidDataTypeException
889
+	 * @throws InvalidInterfaceException
890
+	 * @throws ReflectionException
891
+	 */
892
+	public static function get_event_line_item(EE_Line_Item $grand_total, $event)
893
+	{
894
+		/** @type EE_Event $event */
895
+		$event = EEM_Event::instance()->ensure_is_obj($event, true);
896
+		$event_line_item = null;
897
+		$found = false;
898
+		foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) {
899
+			// default event subtotal, we should only ever find this the first time this method is called
900
+			if (! $event_line_item->OBJ_ID()) {
901
+				// let's use this! but first... set the event details
902
+				EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
903
+				$found = true;
904
+				break;
905
+			}
906
+			if ($event_line_item->OBJ_ID() === $event->ID()) {
907
+				// found existing line item for this event in the cart, so break out of loop and use this one
908
+				$found = true;
909
+				break;
910
+			}
911
+		}
912
+		if (! $found) {
913
+			// there is no event sub-total yet, so add it
914
+			$pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total);
915
+			// create a new "event" subtotal below that
916
+			$event_line_item = EEH_Line_Item::create_event_subtotal($pre_tax_subtotal, null, $event);
917
+			// and set the event details
918
+			EEH_Line_Item::set_event_subtotal_details($event_line_item, $event);
919
+		}
920
+		return $event_line_item;
921
+	}
922
+
923
+
924
+	/**
925
+	 * Creates a default items subtotal line item
926
+	 *
927
+	 * @param EE_Line_Item   $event_line_item
928
+	 * @param EE_Event       $event
929
+	 * @param EE_Transaction $transaction
930
+	 * @return void
931
+	 * @throws EE_Error
932
+	 * @throws InvalidArgumentException
933
+	 * @throws InvalidDataTypeException
934
+	 * @throws InvalidInterfaceException
935
+	 * @throws ReflectionException
936
+	 */
937
+	public static function set_event_subtotal_details(
938
+		EE_Line_Item $event_line_item,
939
+		EE_Event $event,
940
+		$transaction = null
941
+	) {
942
+		if ($event instanceof EE_Event) {
943
+			$event_line_item->set_code(self::get_event_code($event));
944
+			$event_line_item->set_name(self::get_event_name($event));
945
+			$event_line_item->set_desc(self::get_event_desc($event));
946
+			$event_line_item->set_OBJ_ID($event->ID());
947
+		}
948
+		self::set_TXN_ID($event_line_item, $transaction);
949
+	}
950
+
951
+
952
+	/**
953
+	 * Finds what taxes should apply, adds them as tax line items under the taxes sub-total,
954
+	 * and recalculates the taxes sub-total and the grand total. Resets the taxes, so
955
+	 * any old taxes are removed
956
+	 *
957
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
958
+	 * @param bool         $update_txn_status
959
+	 * @return bool
960
+	 * @throws EE_Error
961
+	 * @throws InvalidArgumentException
962
+	 * @throws InvalidDataTypeException
963
+	 * @throws InvalidInterfaceException
964
+	 * @throws ReflectionException
965
+	 * @throws RuntimeException
966
+	 */
967
+	public static function apply_taxes(EE_Line_Item $total_line_item, $update_txn_status = false)
968
+	{
969
+		/** @type EEM_Price $EEM_Price */
970
+		$EEM_Price = EE_Registry::instance()->load_model('Price');
971
+		// get array of taxes via Price Model
972
+		$ordered_taxes = $EEM_Price->get_all_prices_that_are_taxes();
973
+		ksort($ordered_taxes);
974
+		$taxes_line_item = self::get_taxes_subtotal($total_line_item);
975
+		// just to be safe, remove its old tax line items
976
+		$deleted = $taxes_line_item->delete_children_line_items();
977
+		$updates = false;
978
+		// loop thru taxes
979
+		foreach ($ordered_taxes as $order => $taxes) {
980
+			foreach ($taxes as $tax) {
981
+				if ($tax instanceof EE_Price) {
982
+					$tax_line_item = EE_Line_Item::new_instance(
983
+						array(
984
+							'LIN_name'       => $tax->name(),
985
+							'LIN_desc'       => $tax->desc(),
986
+							'LIN_percent'    => $tax->amount(),
987
+							'LIN_is_taxable' => false,
988
+							'LIN_order'      => $order,
989
+							'LIN_total'      => 0,
990
+							'LIN_type'       => EEM_Line_Item::type_tax,
991
+							'OBJ_type'       => EEM_Line_Item::OBJ_TYPE_PRICE,
992
+							'OBJ_ID'         => $tax->ID(),
993
+						)
994
+					);
995
+					$tax_line_item = apply_filters(
996
+						'FHEE__EEH_Line_Item__apply_taxes__tax_line_item',
997
+						$tax_line_item
998
+					);
999
+					$updates = $taxes_line_item->add_child_line_item($tax_line_item) ?
1000
+						true :
1001
+						$updates;
1002
+				}
1003
+			}
1004
+		}
1005
+		// only recalculate totals if something changed
1006
+		if ($deleted || $updates) {
1007
+			$total_line_item->recalculate_total_including_taxes($update_txn_status);
1008
+			return true;
1009
+		}
1010
+		return false;
1011
+	}
1012
+
1013
+
1014
+	/**
1015
+	 * Ensures that taxes have been applied to the order, if not applies them.
1016
+	 * Returns the total amount of tax
1017
+	 *
1018
+	 * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total
1019
+	 * @return float
1020
+	 * @throws EE_Error
1021
+	 * @throws InvalidArgumentException
1022
+	 * @throws InvalidDataTypeException
1023
+	 * @throws InvalidInterfaceException
1024
+	 * @throws ReflectionException
1025
+	 */
1026
+	public static function ensure_taxes_applied($total_line_item)
1027
+	{
1028
+		$taxes_subtotal = self::get_taxes_subtotal($total_line_item);
1029
+		if (! $taxes_subtotal->children()) {
1030
+			self::apply_taxes($total_line_item);
1031
+		}
1032
+		return $taxes_subtotal->total();
1033
+	}
1034
+
1035
+
1036
+	/**
1037
+	 * Deletes ALL children of the passed line item
1038
+	 *
1039
+	 * @param EE_Line_Item $parent_line_item
1040
+	 * @return bool
1041
+	 * @throws EE_Error
1042
+	 * @throws InvalidArgumentException
1043
+	 * @throws InvalidDataTypeException
1044
+	 * @throws InvalidInterfaceException
1045
+	 * @throws ReflectionException
1046
+	 */
1047
+	public static function delete_all_child_items(EE_Line_Item $parent_line_item)
1048
+	{
1049
+		$deleted = 0;
1050
+		foreach ($parent_line_item->children() as $child_line_item) {
1051
+			if ($child_line_item instanceof EE_Line_Item) {
1052
+				$deleted += EEH_Line_Item::delete_all_child_items($child_line_item);
1053
+				if ($child_line_item->ID()) {
1054
+					$child_line_item->delete();
1055
+					unset($child_line_item);
1056
+				} else {
1057
+					$parent_line_item->delete_child_line_item($child_line_item->code());
1058
+				}
1059
+				$deleted++;
1060
+			}
1061
+		}
1062
+		return $deleted;
1063
+	}
1064
+
1065
+
1066
+	/**
1067
+	 * Deletes the line items as indicated by the line item code(s) provided,
1068
+	 * regardless of where they're found in the line item tree. Automatically
1069
+	 * re-calculates the line item totals and updates the related transaction. But
1070
+	 * DOES NOT automatically upgrade the transaction's registrations' final prices (which
1071
+	 * should probably change because of this).
1072
+	 * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item()
1073
+	 * after using this, to keep the registration final prices in-sync with the transaction's total.
1074
+	 *
1075
+	 * @param EE_Line_Item      $total_line_item of type EEM_Line_Item::type_total
1076
+	 * @param array|bool|string $line_item_codes
1077
+	 * @return int number of items successfully removed
1078
+	 * @throws EE_Error
1079
+	 */
1080
+	public static function delete_items(EE_Line_Item $total_line_item, $line_item_codes = false)
1081
+	{
1082
+
1083
+		if ($total_line_item->type() !== EEM_Line_Item::type_total) {
1084
+			EE_Error::doing_it_wrong(
1085
+				'EEH_Line_Item::delete_items',
1086
+				esc_html__(
1087
+					'This static method should only be called with a TOTAL line item, otherwise we won\'t recalculate the totals correctly',
1088
+					'event_espresso'
1089
+				),
1090
+				'4.6.18'
1091
+			);
1092
+		}
1093
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1094
+
1095
+		// check if only a single line_item_id was passed
1096
+		if (! empty($line_item_codes) && ! is_array($line_item_codes)) {
1097
+			// place single line_item_id in an array to appear as multiple line_item_ids
1098
+			$line_item_codes = array($line_item_codes);
1099
+		}
1100
+		$removals = 0;
1101
+		// cycle thru line_item_ids
1102
+		foreach ($line_item_codes as $line_item_id) {
1103
+			$removals += $total_line_item->delete_child_line_item($line_item_id);
1104
+		}
1105
+
1106
+		if ($removals > 0) {
1107
+			$total_line_item->recalculate_taxes_and_tax_total();
1108
+			return $removals;
1109
+		} else {
1110
+			return false;
1111
+		}
1112
+	}
1113
+
1114
+
1115
+	/**
1116
+	 * Overwrites the previous tax by clearing out the old taxes, and creates a new
1117
+	 * tax and updates the total line item accordingly
1118
+	 *
1119
+	 * @param EE_Line_Item $total_line_item
1120
+	 * @param float        $amount
1121
+	 * @param string       $name
1122
+	 * @param string       $description
1123
+	 * @param string       $code
1124
+	 * @param boolean      $add_to_existing_line_item
1125
+	 *                          if true, and a duplicate line item with the same code is found,
1126
+	 *                          $amount will be added onto it; otherwise will simply set the taxes to match $amount
1127
+	 * @return EE_Line_Item the new tax line item created
1128
+	 * @throws EE_Error
1129
+	 * @throws InvalidArgumentException
1130
+	 * @throws InvalidDataTypeException
1131
+	 * @throws InvalidInterfaceException
1132
+	 * @throws ReflectionException
1133
+	 */
1134
+	public static function set_total_tax_to(
1135
+		EE_Line_Item $total_line_item,
1136
+		$amount,
1137
+		$name = null,
1138
+		$description = null,
1139
+		$code = null,
1140
+		$add_to_existing_line_item = false
1141
+	) {
1142
+		$tax_subtotal = self::get_taxes_subtotal($total_line_item);
1143
+		$taxable_total = $total_line_item->taxable_total();
1144
+
1145
+		if ($add_to_existing_line_item) {
1146
+			$new_tax = $tax_subtotal->get_child_line_item($code);
1147
+			EEM_Line_Item::instance()->delete(
1148
+				array(array('LIN_code' => array('!=', $code), 'LIN_parent' => $tax_subtotal->ID()))
1149
+			);
1150
+		} else {
1151
+			$new_tax = null;
1152
+			$tax_subtotal->delete_children_line_items();
1153
+		}
1154
+		if ($new_tax) {
1155
+			$new_tax->set_total($new_tax->total() + $amount);
1156
+			$new_tax->set_percent($taxable_total ? $new_tax->total() / $taxable_total * 100 : 0);
1157
+		} else {
1158
+			// no existing tax item. Create it
1159
+			$new_tax = EE_Line_Item::new_instance(array(
1160
+				'TXN_ID'      => $total_line_item->TXN_ID(),
1161
+				'LIN_name'    => $name ? $name : esc_html__('Tax', 'event_espresso'),
1162
+				'LIN_desc'    => $description ? $description : '',
1163
+				'LIN_percent' => $taxable_total ? ($amount / $taxable_total * 100) : 0,
1164
+				'LIN_total'   => $amount,
1165
+				'LIN_parent'  => $tax_subtotal->ID(),
1166
+				'LIN_type'    => EEM_Line_Item::type_tax,
1167
+				'LIN_code'    => $code,
1168
+			));
1169
+		}
1170
+
1171
+		$new_tax = apply_filters(
1172
+			'FHEE__EEH_Line_Item__set_total_tax_to__new_tax_subtotal',
1173
+			$new_tax,
1174
+			$total_line_item
1175
+		);
1176
+		$new_tax->save();
1177
+		$tax_subtotal->set_total($new_tax->total());
1178
+		$tax_subtotal->save();
1179
+		$total_line_item->recalculate_total_including_taxes();
1180
+		return $new_tax;
1181
+	}
1182
+
1183
+
1184
+	/**
1185
+	 * Makes all the line items which are children of $line_item taxable (or not).
1186
+	 * Does NOT save the line items
1187
+	 *
1188
+	 * @param EE_Line_Item $line_item
1189
+	 * @param boolean      $taxable
1190
+	 * @param string       $code_substring_for_whitelist if this string is part of the line item's code
1191
+	 *                                                   it will be whitelisted (ie, except from becoming taxable)
1192
+	 * @throws EE_Error
1193
+	 */
1194
+	public static function set_line_items_taxable(
1195
+		EE_Line_Item $line_item,
1196
+		$taxable = true,
1197
+		$code_substring_for_whitelist = null
1198
+	) {
1199
+		$whitelisted = false;
1200
+		if ($code_substring_for_whitelist !== null) {
1201
+			$whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false;
1202
+		}
1203
+		if (! $whitelisted && $line_item->is_line_item()) {
1204
+			$line_item->set_is_taxable($taxable);
1205
+		}
1206
+		foreach ($line_item->children() as $child_line_item) {
1207
+			EEH_Line_Item::set_line_items_taxable(
1208
+				$child_line_item,
1209
+				$taxable,
1210
+				$code_substring_for_whitelist
1211
+			);
1212
+		}
1213
+	}
1214
+
1215
+
1216
+	/**
1217
+	 * Gets all descendants that are event subtotals
1218
+	 *
1219
+	 * @uses  EEH_Line_Item::get_subtotals_of_object_type()
1220
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1221
+	 * @return EE_Line_Item[]
1222
+	 * @throws EE_Error
1223
+	 */
1224
+	public static function get_event_subtotals(EE_Line_Item $parent_line_item)
1225
+	{
1226
+		return self::get_subtotals_of_object_type($parent_line_item, EEM_Line_Item::OBJ_TYPE_EVENT);
1227
+	}
1228
+
1229
+
1230
+	/**
1231
+	 * Gets all descendants subtotals that match the supplied object type
1232
+	 *
1233
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1234
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1235
+	 * @param string       $obj_type
1236
+	 * @return EE_Line_Item[]
1237
+	 * @throws EE_Error
1238
+	 */
1239
+	public static function get_subtotals_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1240
+	{
1241
+		return self::_get_descendants_by_type_and_object_type(
1242
+			$parent_line_item,
1243
+			EEM_Line_Item::type_sub_total,
1244
+			$obj_type
1245
+		);
1246
+	}
1247
+
1248
+
1249
+	/**
1250
+	 * Gets all descendants that are tickets
1251
+	 *
1252
+	 * @uses  EEH_Line_Item::get_line_items_of_object_type()
1253
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1254
+	 * @return EE_Line_Item[]
1255
+	 * @throws EE_Error
1256
+	 */
1257
+	public static function get_ticket_line_items(EE_Line_Item $parent_line_item)
1258
+	{
1259
+		return self::get_line_items_of_object_type(
1260
+			$parent_line_item,
1261
+			EEM_Line_Item::OBJ_TYPE_TICKET
1262
+		);
1263
+	}
1264
+
1265
+
1266
+	/**
1267
+	 * Gets all descendants subtotals that match the supplied object type
1268
+	 *
1269
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1270
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1271
+	 * @param string       $obj_type
1272
+	 * @return EE_Line_Item[]
1273
+	 * @throws EE_Error
1274
+	 */
1275
+	public static function get_line_items_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '')
1276
+	{
1277
+		return self::_get_descendants_by_type_and_object_type(
1278
+			$parent_line_item,
1279
+			EEM_Line_Item::type_line_item,
1280
+			$obj_type
1281
+		);
1282
+	}
1283
+
1284
+
1285
+	/**
1286
+	 * Gets all the descendants (ie, children or children of children etc) that are of the type 'tax'
1287
+	 *
1288
+	 * @uses  EEH_Line_Item::get_descendants_of_type()
1289
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1290
+	 * @return EE_Line_Item[]
1291
+	 * @throws EE_Error
1292
+	 */
1293
+	public static function get_tax_descendants(EE_Line_Item $parent_line_item)
1294
+	{
1295
+		return EEH_Line_Item::get_descendants_of_type(
1296
+			$parent_line_item,
1297
+			EEM_Line_Item::type_tax
1298
+		);
1299
+	}
1300
+
1301
+
1302
+	/**
1303
+	 * Gets all the real items purchased which are children of this item
1304
+	 *
1305
+	 * @uses  EEH_Line_Item::get_descendants_of_type()
1306
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1307
+	 * @return EE_Line_Item[]
1308
+	 * @throws EE_Error
1309
+	 */
1310
+	public static function get_line_item_descendants(EE_Line_Item $parent_line_item)
1311
+	{
1312
+		return EEH_Line_Item::get_descendants_of_type(
1313
+			$parent_line_item,
1314
+			EEM_Line_Item::type_line_item
1315
+		);
1316
+	}
1317
+
1318
+
1319
+	/**
1320
+	 * Gets all descendants of supplied line item that match the supplied line item type
1321
+	 *
1322
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1323
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1324
+	 * @param string       $line_item_type   one of the EEM_Line_Item constants
1325
+	 * @return EE_Line_Item[]
1326
+	 * @throws EE_Error
1327
+	 */
1328
+	public static function get_descendants_of_type(EE_Line_Item $parent_line_item, $line_item_type)
1329
+	{
1330
+		return self::_get_descendants_by_type_and_object_type(
1331
+			$parent_line_item,
1332
+			$line_item_type,
1333
+			null
1334
+		);
1335
+	}
1336
+
1337
+
1338
+	/**
1339
+	 * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type
1340
+	 * as well
1341
+	 *
1342
+	 * @param EE_Line_Item  $parent_line_item - the line item to find descendants of
1343
+	 * @param string        $line_item_type   one of the EEM_Line_Item constants
1344
+	 * @param string | NULL $obj_type         object model class name (minus prefix) or NULL to ignore object type when
1345
+	 *                                        searching
1346
+	 * @return EE_Line_Item[]
1347
+	 * @throws EE_Error
1348
+	 */
1349
+	protected static function _get_descendants_by_type_and_object_type(
1350
+		EE_Line_Item $parent_line_item,
1351
+		$line_item_type,
1352
+		$obj_type = null
1353
+	) {
1354
+		$objects = array();
1355
+		foreach ($parent_line_item->children() as $child_line_item) {
1356
+			if ($child_line_item instanceof EE_Line_Item) {
1357
+				if (
1358
+					$child_line_item->type() === $line_item_type
1359
+					&& (
1360
+						$child_line_item->OBJ_type() === $obj_type || $obj_type === null
1361
+					)
1362
+				) {
1363
+					$objects[] = $child_line_item;
1364
+				} else {
1365
+					// go-through-all-its children looking for more matches
1366
+					$objects = array_merge(
1367
+						$objects,
1368
+						self::_get_descendants_by_type_and_object_type(
1369
+							$child_line_item,
1370
+							$line_item_type,
1371
+							$obj_type
1372
+						)
1373
+					);
1374
+				}
1375
+			}
1376
+		}
1377
+		return $objects;
1378
+	}
1379
+
1380
+
1381
+	/**
1382
+	 * Gets all descendants subtotals that match the supplied object type
1383
+	 *
1384
+	 * @uses  EEH_Line_Item::_get_descendants_by_type_and_object_type()
1385
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1386
+	 * @param string       $OBJ_type         object type (like Event)
1387
+	 * @param array        $OBJ_IDs          array of OBJ_IDs
1388
+	 * @return EE_Line_Item[]
1389
+	 * @throws EE_Error
1390
+	 */
1391
+	public static function get_line_items_by_object_type_and_IDs(
1392
+		EE_Line_Item $parent_line_item,
1393
+		$OBJ_type = '',
1394
+		$OBJ_IDs = array()
1395
+	) {
1396
+		return self::_get_descendants_by_object_type_and_object_ID(
1397
+			$parent_line_item,
1398
+			$OBJ_type,
1399
+			$OBJ_IDs
1400
+		);
1401
+	}
1402
+
1403
+
1404
+	/**
1405
+	 * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type
1406
+	 * as well
1407
+	 *
1408
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1409
+	 * @param string       $OBJ_type         object type (like Event)
1410
+	 * @param array        $OBJ_IDs          array of OBJ_IDs
1411
+	 * @return EE_Line_Item[]
1412
+	 * @throws EE_Error
1413
+	 */
1414
+	protected static function _get_descendants_by_object_type_and_object_ID(
1415
+		EE_Line_Item $parent_line_item,
1416
+		$OBJ_type,
1417
+		$OBJ_IDs
1418
+	) {
1419
+		$objects = array();
1420
+		foreach ($parent_line_item->children() as $child_line_item) {
1421
+			if ($child_line_item instanceof EE_Line_Item) {
1422
+				if (
1423
+					$child_line_item->OBJ_type() === $OBJ_type
1424
+					&& is_array($OBJ_IDs)
1425
+					&& in_array($child_line_item->OBJ_ID(), $OBJ_IDs)
1426
+				) {
1427
+					$objects[] = $child_line_item;
1428
+				} else {
1429
+					// go-through-all-its children looking for more matches
1430
+					$objects = array_merge(
1431
+						$objects,
1432
+						self::_get_descendants_by_object_type_and_object_ID(
1433
+							$child_line_item,
1434
+							$OBJ_type,
1435
+							$OBJ_IDs
1436
+						)
1437
+					);
1438
+				}
1439
+			}
1440
+		}
1441
+		return $objects;
1442
+	}
1443
+
1444
+
1445
+	/**
1446
+	 * Uses a breadth-first-search in order to find the nearest descendant of
1447
+	 * the specified type and returns it, else NULL
1448
+	 *
1449
+	 * @uses  EEH_Line_Item::_get_nearest_descendant()
1450
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1451
+	 * @param string       $type             like one of the EEM_Line_Item::type_*
1452
+	 * @return EE_Line_Item
1453
+	 * @throws EE_Error
1454
+	 * @throws InvalidArgumentException
1455
+	 * @throws InvalidDataTypeException
1456
+	 * @throws InvalidInterfaceException
1457
+	 * @throws ReflectionException
1458
+	 */
1459
+	public static function get_nearest_descendant_of_type(EE_Line_Item $parent_line_item, $type)
1460
+	{
1461
+		return self::_get_nearest_descendant($parent_line_item, 'LIN_type', $type);
1462
+	}
1463
+
1464
+
1465
+	/**
1466
+	 * Uses a breadth-first-search in order to find the nearest descendant
1467
+	 * having the specified LIN_code and returns it, else NULL
1468
+	 *
1469
+	 * @uses  EEH_Line_Item::_get_nearest_descendant()
1470
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1471
+	 * @param string       $code             any value used for LIN_code
1472
+	 * @return EE_Line_Item
1473
+	 * @throws EE_Error
1474
+	 * @throws InvalidArgumentException
1475
+	 * @throws InvalidDataTypeException
1476
+	 * @throws InvalidInterfaceException
1477
+	 * @throws ReflectionException
1478
+	 */
1479
+	public static function get_nearest_descendant_having_code(EE_Line_Item $parent_line_item, $code)
1480
+	{
1481
+		return self::_get_nearest_descendant($parent_line_item, 'LIN_code', $code);
1482
+	}
1483
+
1484
+
1485
+	/**
1486
+	 * Uses a breadth-first-search in order to find the nearest descendant
1487
+	 * having the specified LIN_code and returns it, else NULL
1488
+	 *
1489
+	 * @param EE_Line_Item $parent_line_item - the line item to find descendants of
1490
+	 * @param string       $search_field     name of EE_Line_Item property
1491
+	 * @param string       $value            any value stored in $search_field
1492
+	 * @return EE_Line_Item
1493
+	 * @throws EE_Error
1494
+	 * @throws InvalidArgumentException
1495
+	 * @throws InvalidDataTypeException
1496
+	 * @throws InvalidInterfaceException
1497
+	 * @throws ReflectionException
1498
+	 */
1499
+	protected static function _get_nearest_descendant(EE_Line_Item $parent_line_item, $search_field, $value)
1500
+	{
1501
+		foreach ($parent_line_item->children() as $child) {
1502
+			if ($child->get($search_field) == $value) {
1503
+				return $child;
1504
+			}
1505
+		}
1506
+		foreach ($parent_line_item->children() as $child) {
1507
+			$descendant_found = self::_get_nearest_descendant(
1508
+				$child,
1509
+				$search_field,
1510
+				$value
1511
+			);
1512
+			if ($descendant_found) {
1513
+				return $descendant_found;
1514
+			}
1515
+		}
1516
+		return null;
1517
+	}
1518
+
1519
+
1520
+	/**
1521
+	 * if passed line item has a TXN ID, uses that to jump directly to the grand total line item for the transaction,
1522
+	 * else recursively walks up the line item tree until a parent of type total is found,
1523
+	 *
1524
+	 * @param EE_Line_Item $line_item
1525
+	 * @return EE_Line_Item
1526
+	 * @throws EE_Error
1527
+	 */
1528
+	public static function find_transaction_grand_total_for_line_item(EE_Line_Item $line_item)
1529
+	{
1530
+		if ($line_item->TXN_ID()) {
1531
+			$total_line_item = $line_item->transaction()->total_line_item(false);
1532
+			if ($total_line_item instanceof EE_Line_Item) {
1533
+				return $total_line_item;
1534
+			}
1535
+		} else {
1536
+			$line_item_parent = $line_item->parent();
1537
+			if ($line_item_parent instanceof EE_Line_Item) {
1538
+				if ($line_item_parent->is_total()) {
1539
+					return $line_item_parent;
1540
+				}
1541
+				return EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item_parent);
1542
+			}
1543
+		}
1544
+		throw new EE_Error(
1545
+			sprintf(
1546
+				esc_html__(
1547
+					'A valid grand total for line item %1$d was not found.',
1548
+					'event_espresso'
1549
+				),
1550
+				$line_item->ID()
1551
+			)
1552
+		);
1553
+	}
1554
+
1555
+
1556
+	/**
1557
+	 * Prints out a representation of the line item tree
1558
+	 *
1559
+	 * @param EE_Line_Item $line_item
1560
+	 * @param int          $indentation
1561
+	 * @return void
1562
+	 * @throws EE_Error
1563
+	 */
1564
+	public static function visualize(EE_Line_Item $line_item, $indentation = 0)
1565
+	{
1566
+		echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1567
+		if (! $indentation) {
1568
+			echo defined('EE_TESTS_DIR') ? "\n" : '<br />';
1569
+		}
1570
+		for ($i = 0; $i < $indentation; $i++) {
1571
+			echo '. ';
1572
+		}
1573
+		$breakdown = '';
1574
+		if ($line_item->is_line_item()) {
1575
+			if ($line_item->is_percent()) {
1576
+				$breakdown = "{$line_item->percent()}%";
1577
+			} else {
1578
+				$breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}";
1579
+			}
1580
+		}
1581
+		echo $line_item->name();
1582
+		echo " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : ";
1583
+		echo '$' . (string) $line_item->total();
1584
+		if ($breakdown) {
1585
+			echo " ( {$breakdown} )";
1586
+		}
1587
+		if ($line_item->is_taxable()) {
1588
+			echo '  * taxable';
1589
+		}
1590
+		if ($line_item->children()) {
1591
+			foreach ($line_item->children() as $child) {
1592
+				self::visualize($child, $indentation + 1);
1593
+			}
1594
+		}
1595
+	}
1596
+
1597
+
1598
+	/**
1599
+	 * Calculates the registration's final price, taking into account that they
1600
+	 * need to not only help pay for their OWN ticket, but also any transaction-wide surcharges and taxes,
1601
+	 * and receive a portion of any transaction-wide discounts.
1602
+	 * eg1, if I buy a $1 ticket and brent buys a $9 ticket, and we receive a $5 discount
1603
+	 * then I'll get 1/10 of that $5 discount, which is $0.50, and brent will get
1604
+	 * 9/10ths of that $5 discount, which is $4.50. So my final price should be $0.50
1605
+	 * and brent's final price should be $5.50.
1606
+	 * In order to do this, we basically need to traverse the line item tree calculating
1607
+	 * the running totals (just as if we were recalculating the total), but when we identify
1608
+	 * regular line items, we need to keep track of their share of the grand total.
1609
+	 * Also, we need to keep track of the TAXABLE total for each ticket purchase, so
1610
+	 * we can know how to apply taxes to it. (Note: "taxable total" does not equal the "pretax total"
1611
+	 * when there are non-taxable items; otherwise they would be the same)
1612
+	 *
1613
+	 * @param EE_Line_Item $line_item
1614
+	 * @param array        $billable_ticket_quantities  array of EE_Ticket IDs and their corresponding quantity that
1615
+	 *                                                  can be included in price calculations at this moment
1616
+	 * @return array        keys are line items for tickets IDs and values are their share of the running total,
1617
+	 *                                                  plus the key 'total', and 'taxable' which also has keys of all
1618
+	 *                                                  the ticket IDs.
1619
+	 *                                                  Eg array(
1620
+	 *                                                      12 => 4.3
1621
+	 *                                                      23 => 8.0
1622
+	 *                                                      'total' => 16.6,
1623
+	 *                                                      'taxable' => array(
1624
+	 *                                                          12 => 10,
1625
+	 *                                                          23 => 4
1626
+	 *                                                      ).
1627
+	 *                                                  So to find which registrations have which final price, we need
1628
+	 *                                                  to find which line item is theirs, which can be done with
1629
+	 *                                                  `EEM_Line_Item::instance()->get_line_item_for_registration(
1630
+	 *                                                  $registration );`
1631
+	 * @throws EE_Error
1632
+	 * @throws InvalidArgumentException
1633
+	 * @throws InvalidDataTypeException
1634
+	 * @throws InvalidInterfaceException
1635
+	 * @throws ReflectionException
1636
+	 */
1637
+	public static function calculate_reg_final_prices_per_line_item(
1638
+		EE_Line_Item $line_item,
1639
+		$billable_ticket_quantities = array()
1640
+	) {
1641
+		$running_totals = [
1642
+			'total'   => 0,
1643
+			'taxable' => ['total' => 0]
1644
+		];
1645
+		foreach ($line_item->children() as $child_line_item) {
1646
+			switch ($child_line_item->type()) {
1647
+				case EEM_Line_Item::type_sub_total:
1648
+					$running_totals_from_subtotal = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1649
+						$child_line_item,
1650
+						$billable_ticket_quantities
1651
+					);
1652
+					// combine arrays but preserve numeric keys
1653
+					$running_totals = array_replace_recursive($running_totals_from_subtotal, $running_totals);
1654
+					$running_totals['total'] += $running_totals_from_subtotal['total'];
1655
+					$running_totals['taxable']['total'] += $running_totals_from_subtotal['taxable']['total'];
1656
+					break;
1657
+
1658
+				case EEM_Line_Item::type_tax_sub_total:
1659
+					// find how much the taxes percentage is
1660
+					if ($child_line_item->percent() !== 0) {
1661
+						$tax_percent_decimal = $child_line_item->percent() / 100;
1662
+					} else {
1663
+						$tax_percent_decimal = EE_Taxes::get_total_taxes_percentage() / 100;
1664
+					}
1665
+					// and apply to all the taxable totals, and add to the pretax totals
1666
+					foreach ($running_totals as $line_item_id => $this_running_total) {
1667
+						// "total" and "taxable" array key is an exception
1668
+						if ($line_item_id === 'taxable') {
1669
+							continue;
1670
+						}
1671
+						$taxable_total = $running_totals['taxable'][ $line_item_id ];
1672
+						$running_totals[ $line_item_id ] += ($taxable_total * $tax_percent_decimal);
1673
+					}
1674
+					break;
1675
+
1676
+				case EEM_Line_Item::type_line_item:
1677
+					// ticket line items or ????
1678
+					if ($child_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) {
1679
+						// kk it's a ticket
1680
+						if (isset($running_totals[ $child_line_item->ID() ])) {
1681
+							// huh? that shouldn't happen.
1682
+							$running_totals['total'] += $child_line_item->total();
1683
+						} else {
1684
+							// its not in our running totals yet. great.
1685
+							if ($child_line_item->is_taxable()) {
1686
+								$taxable_amount = $child_line_item->unit_price();
1687
+							} else {
1688
+								$taxable_amount = 0;
1689
+							}
1690
+							// are we only calculating totals for some tickets?
1691
+							if (isset($billable_ticket_quantities[ $child_line_item->OBJ_ID() ])) {
1692
+								$quantity = $billable_ticket_quantities[ $child_line_item->OBJ_ID() ];
1693
+								$running_totals[ $child_line_item->ID() ] = $quantity
1694
+									? $child_line_item->unit_price()
1695
+									: 0;
1696
+								$running_totals['taxable'][ $child_line_item->ID() ] = $quantity
1697
+									? $taxable_amount
1698
+									: 0;
1699
+							} else {
1700
+								$quantity = $child_line_item->quantity();
1701
+								$running_totals[ $child_line_item->ID() ] = $child_line_item->unit_price();
1702
+								$running_totals['taxable'][ $child_line_item->ID() ] = $taxable_amount;
1703
+							}
1704
+							$running_totals['taxable']['total'] += $taxable_amount * $quantity;
1705
+							$running_totals['total'] += $child_line_item->unit_price() * $quantity;
1706
+						}
1707
+					} else {
1708
+						// it's some other type of item added to the cart
1709
+						// it should affect the running totals
1710
+						// basically we want to convert it into a PERCENT modifier. Because
1711
+						// more clearly affect all registration's final price equally
1712
+						$line_items_percent_of_running_total = $running_totals['total'] > 0
1713
+							? ($child_line_item->total() / $running_totals['total']) + 1
1714
+							: 1;
1715
+						foreach ($running_totals as $line_item_id => $this_running_total) {
1716
+							// the "taxable" array key is an exception
1717
+							if ($line_item_id === 'taxable') {
1718
+								continue;
1719
+							}
1720
+							// update the running totals
1721
+							// yes this actually even works for the running grand total!
1722
+							$running_totals[ $line_item_id ] =
1723
+								$line_items_percent_of_running_total * $this_running_total;
1724
+
1725
+							if ($child_line_item->is_taxable()) {
1726
+								$running_totals['taxable'][ $line_item_id ] =
1727
+									$line_items_percent_of_running_total * $running_totals['taxable'][ $line_item_id ];
1728
+							}
1729
+						}
1730
+					}
1731
+					break;
1732
+			}
1733
+		}
1734
+		return $running_totals;
1735
+	}
1736
+
1737
+
1738
+	/**
1739
+	 * @param EE_Line_Item $total_line_item
1740
+	 * @param EE_Line_Item $ticket_line_item
1741
+	 * @return float | null
1742
+	 * @throws EE_Error
1743
+	 * @throws InvalidArgumentException
1744
+	 * @throws InvalidDataTypeException
1745
+	 * @throws InvalidInterfaceException
1746
+	 * @throws OutOfRangeException
1747
+	 * @throws ReflectionException
1748
+	 */
1749
+	public static function calculate_final_price_for_ticket_line_item(
1750
+		EE_Line_Item $total_line_item,
1751
+		EE_Line_Item $ticket_line_item
1752
+	) {
1753
+		static $final_prices_per_ticket_line_item = array();
1754
+		if (empty($final_prices_per_ticket_line_item) || empty($final_prices_per_ticket_line_item[ $total_line_item->ID() ])) {
1755
+			$final_prices_per_ticket_line_item[ $total_line_item->ID() ] = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
1756
+				$total_line_item
1757
+			);
1758
+		}
1759
+		// ok now find this new registration's final price
1760
+		if (isset($final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ])) {
1761
+			return $final_prices_per_ticket_line_item[ $total_line_item->ID() ][ $ticket_line_item->ID() ];
1762
+		}
1763
+		$message = sprintf(
1764
+			esc_html__(
1765
+				'The final price for the ticket line item (ID:%1$d) could not be calculated.',
1766
+				'event_espresso'
1767
+			),
1768
+			$ticket_line_item->ID()
1769
+		);
1770
+		if (WP_DEBUG) {
1771
+			$message .= '<br>' . print_r($final_prices_per_ticket_line_item, true);
1772
+			throw new OutOfRangeException($message);
1773
+		}
1774
+		EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message);
1775
+		return null;
1776
+	}
1777
+
1778
+
1779
+	/**
1780
+	 * Creates a duplicate of the line item tree, except only includes billable items
1781
+	 * and the portion of line items attributed to billable things
1782
+	 *
1783
+	 * @param EE_Line_Item      $line_item
1784
+	 * @param EE_Registration[] $registrations
1785
+	 * @return EE_Line_Item
1786
+	 * @throws EE_Error
1787
+	 * @throws InvalidArgumentException
1788
+	 * @throws InvalidDataTypeException
1789
+	 * @throws InvalidInterfaceException
1790
+	 * @throws ReflectionException
1791
+	 */
1792
+	public static function billable_line_item_tree(EE_Line_Item $line_item, $registrations)
1793
+	{
1794
+		$copy_li = EEH_Line_Item::billable_line_item($line_item, $registrations);
1795
+		foreach ($line_item->children() as $child_li) {
1796
+			$copy_li->add_child_line_item(
1797
+				EEH_Line_Item::billable_line_item_tree($child_li, $registrations)
1798
+			);
1799
+		}
1800
+		// if this is the grand total line item, make sure the totals all add up
1801
+		// (we could have duplicated this logic AS we copied the line items, but
1802
+		// it seems DRYer this way)
1803
+		if ($copy_li->type() === EEM_Line_Item::type_total) {
1804
+			$copy_li->recalculate_total_including_taxes();
1805
+		}
1806
+		return $copy_li;
1807
+	}
1808
+
1809
+
1810
+	/**
1811
+	 * Creates a new, unsaved line item from $line_item that factors in the
1812
+	 * number of billable registrations on $registrations.
1813
+	 *
1814
+	 * @param EE_Line_Item      $line_item
1815
+	 * @param EE_Registration[] $registrations
1816
+	 * @return EE_Line_Item
1817
+	 * @throws EE_Error
1818
+	 * @throws InvalidArgumentException
1819
+	 * @throws InvalidDataTypeException
1820
+	 * @throws InvalidInterfaceException
1821
+	 * @throws ReflectionException
1822
+	 */
1823
+	public static function billable_line_item(EE_Line_Item $line_item, $registrations)
1824
+	{
1825
+		$new_li_fields = $line_item->model_field_array();
1826
+		if (
1827
+			$line_item->type() === EEM_Line_Item::type_line_item &&
1828
+			$line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1829
+		) {
1830
+			$count = 0;
1831
+			foreach ($registrations as $registration) {
1832
+				if (
1833
+					$line_item->OBJ_ID() === $registration->ticket_ID() &&
1834
+					in_array(
1835
+						$registration->status_ID(),
1836
+						EEM_Registration::reg_statuses_that_allow_payment(),
1837
+						true
1838
+					)
1839
+				) {
1840
+					$count++;
1841
+				}
1842
+			}
1843
+			$new_li_fields['LIN_quantity'] = $count;
1844
+		}
1845
+		// don't set the total. We'll leave that up to the code that calculates it
1846
+		unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent'], $new_li_fields['LIN_total']);
1847
+		return EE_Line_Item::new_instance($new_li_fields);
1848
+	}
1849
+
1850
+
1851
+	/**
1852
+	 * Returns a modified line item tree where all the subtotals which have a total of 0
1853
+	 * are removed, and line items with a quantity of 0
1854
+	 *
1855
+	 * @param EE_Line_Item $line_item |null
1856
+	 * @return EE_Line_Item|null
1857
+	 * @throws EE_Error
1858
+	 * @throws InvalidArgumentException
1859
+	 * @throws InvalidDataTypeException
1860
+	 * @throws InvalidInterfaceException
1861
+	 * @throws ReflectionException
1862
+	 */
1863
+	public static function non_empty_line_items(EE_Line_Item $line_item)
1864
+	{
1865
+		$copied_li = EEH_Line_Item::non_empty_line_item($line_item);
1866
+		if ($copied_li === null) {
1867
+			return null;
1868
+		}
1869
+		// if this is an event subtotal, we want to only include it if it
1870
+		// has a non-zero total and at least one ticket line item child
1871
+		$ticket_children = 0;
1872
+		foreach ($line_item->children() as $child_li) {
1873
+			$child_li_copy = EEH_Line_Item::non_empty_line_items($child_li);
1874
+			if ($child_li_copy !== null) {
1875
+				$copied_li->add_child_line_item($child_li_copy);
1876
+				if (
1877
+					$child_li_copy->type() === EEM_Line_Item::type_line_item &&
1878
+					$child_li_copy->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1879
+				) {
1880
+					$ticket_children++;
1881
+				}
1882
+			}
1883
+		}
1884
+		// if this is an event subtotal with NO ticket children
1885
+		// we basically want to ignore it
1886
+		if (
1887
+			$ticket_children === 0
1888
+			&& $line_item->type() === EEM_Line_Item::type_sub_total
1889
+			&& $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT
1890
+			&& $line_item->total() === 0
1891
+		) {
1892
+			return null;
1893
+		}
1894
+		return $copied_li;
1895
+	}
1896
+
1897
+
1898
+	/**
1899
+	 * Creates a new, unsaved line item, but if it's a ticket line item
1900
+	 * with a total of 0, or a subtotal of 0, returns null instead
1901
+	 *
1902
+	 * @param EE_Line_Item $line_item
1903
+	 * @return EE_Line_Item
1904
+	 * @throws EE_Error
1905
+	 * @throws InvalidArgumentException
1906
+	 * @throws InvalidDataTypeException
1907
+	 * @throws InvalidInterfaceException
1908
+	 * @throws ReflectionException
1909
+	 */
1910
+	public static function non_empty_line_item(EE_Line_Item $line_item)
1911
+	{
1912
+		if (
1913
+			$line_item->type() === EEM_Line_Item::type_line_item
1914
+			&& $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1915
+			&& $line_item->quantity() === 0
1916
+		) {
1917
+			return null;
1918
+		}
1919
+		$new_li_fields = $line_item->model_field_array();
1920
+		// don't set the total. We'll leave that up to the code that calculates it
1921
+		unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent']);
1922
+		return EE_Line_Item::new_instance($new_li_fields);
1923
+	}
1924
+
1925
+
1926
+	/**
1927
+	 * Cycles through all of the ticket line items for the supplied total line item
1928
+	 * and ensures that the line item's "is_taxable" field matches that of its corresponding ticket
1929
+	 *
1930
+	 * @param EE_Line_Item $total_line_item
1931
+	 * @since 4.9.79.p
1932
+	 * @throws EE_Error
1933
+	 * @throws InvalidArgumentException
1934
+	 * @throws InvalidDataTypeException
1935
+	 * @throws InvalidInterfaceException
1936
+	 * @throws ReflectionException
1937
+	 */
1938
+	public static function resetIsTaxableForTickets(EE_Line_Item $total_line_item)
1939
+	{
1940
+		$ticket_line_items = self::get_ticket_line_items($total_line_item);
1941
+		foreach ($ticket_line_items as $ticket_line_item) {
1942
+			if (
1943
+				$ticket_line_item instanceof EE_Line_Item
1944
+				&& $ticket_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET
1945
+			) {
1946
+				$ticket = $ticket_line_item->ticket();
1947
+				if ($ticket instanceof EE_Ticket && $ticket->taxable() !== $ticket_line_item->is_taxable()) {
1948
+					$ticket_line_item->set_is_taxable($ticket->taxable());
1949
+					$ticket_line_item->save();
1950
+				}
1951
+			}
1952
+		}
1953
+	}
1954
+
1955
+
1956
+
1957
+	/**************************************** @DEPRECATED METHODS *************************************** */
1958
+	/**
1959
+	 * @deprecated
1960
+	 * @param EE_Line_Item $total_line_item
1961
+	 * @return EE_Line_Item
1962
+	 * @throws EE_Error
1963
+	 * @throws InvalidArgumentException
1964
+	 * @throws InvalidDataTypeException
1965
+	 * @throws InvalidInterfaceException
1966
+	 * @throws ReflectionException
1967
+	 */
1968
+	public static function get_items_subtotal(EE_Line_Item $total_line_item)
1969
+	{
1970
+		EE_Error::doing_it_wrong(
1971
+			'EEH_Line_Item::get_items_subtotal()',
1972
+			sprintf(
1973
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
1974
+				'EEH_Line_Item::get_pre_tax_subtotal()'
1975
+			),
1976
+			'4.6.0'
1977
+		);
1978
+		return self::get_pre_tax_subtotal($total_line_item);
1979
+	}
1980
+
1981
+
1982
+	/**
1983
+	 * @deprecated
1984
+	 * @param EE_Transaction $transaction
1985
+	 * @return EE_Line_Item
1986
+	 * @throws EE_Error
1987
+	 * @throws InvalidArgumentException
1988
+	 * @throws InvalidDataTypeException
1989
+	 * @throws InvalidInterfaceException
1990
+	 * @throws ReflectionException
1991
+	 */
1992
+	public static function create_default_total_line_item($transaction = null)
1993
+	{
1994
+		EE_Error::doing_it_wrong(
1995
+			'EEH_Line_Item::create_default_total_line_item()',
1996
+			sprintf(
1997
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
1998
+				'EEH_Line_Item::create_total_line_item()'
1999
+			),
2000
+			'4.6.0'
2001
+		);
2002
+		return self::create_total_line_item($transaction);
2003
+	}
2004
+
2005
+
2006
+	/**
2007
+	 * @deprecated
2008
+	 * @param EE_Line_Item   $total_line_item
2009
+	 * @param EE_Transaction $transaction
2010
+	 * @return EE_Line_Item
2011
+	 * @throws EE_Error
2012
+	 * @throws InvalidArgumentException
2013
+	 * @throws InvalidDataTypeException
2014
+	 * @throws InvalidInterfaceException
2015
+	 * @throws ReflectionException
2016
+	 */
2017
+	public static function create_default_tickets_subtotal(EE_Line_Item $total_line_item, $transaction = null)
2018
+	{
2019
+		EE_Error::doing_it_wrong(
2020
+			'EEH_Line_Item::create_default_tickets_subtotal()',
2021
+			sprintf(
2022
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
2023
+				'EEH_Line_Item::create_pre_tax_subtotal()'
2024
+			),
2025
+			'4.6.0'
2026
+		);
2027
+		return self::create_pre_tax_subtotal($total_line_item, $transaction);
2028
+	}
2029
+
2030
+
2031
+	/**
2032
+	 * @deprecated
2033
+	 * @param EE_Line_Item   $total_line_item
2034
+	 * @param EE_Transaction $transaction
2035
+	 * @return EE_Line_Item
2036
+	 * @throws EE_Error
2037
+	 * @throws InvalidArgumentException
2038
+	 * @throws InvalidDataTypeException
2039
+	 * @throws InvalidInterfaceException
2040
+	 * @throws ReflectionException
2041
+	 */
2042
+	public static function create_default_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null)
2043
+	{
2044
+		EE_Error::doing_it_wrong(
2045
+			'EEH_Line_Item::create_default_taxes_subtotal()',
2046
+			sprintf(
2047
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
2048
+				'EEH_Line_Item::create_taxes_subtotal()'
2049
+			),
2050
+			'4.6.0'
2051
+		);
2052
+		return self::create_taxes_subtotal($total_line_item, $transaction);
2053
+	}
2054
+
2055
+
2056
+	/**
2057
+	 * @deprecated
2058
+	 * @param EE_Line_Item   $total_line_item
2059
+	 * @param EE_Transaction $transaction
2060
+	 * @return EE_Line_Item
2061
+	 * @throws EE_Error
2062
+	 * @throws InvalidArgumentException
2063
+	 * @throws InvalidDataTypeException
2064
+	 * @throws InvalidInterfaceException
2065
+	 * @throws ReflectionException
2066
+	 */
2067
+	public static function create_default_event_subtotal(EE_Line_Item $total_line_item, $transaction = null)
2068
+	{
2069
+		EE_Error::doing_it_wrong(
2070
+			'EEH_Line_Item::create_default_event_subtotal()',
2071
+			sprintf(
2072
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
2073
+				'EEH_Line_Item::create_event_subtotal()'
2074
+			),
2075
+			'4.6.0'
2076
+		);
2077
+		return self::create_event_subtotal($total_line_item, $transaction);
2078
+	}
2079 2079
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Ticket.class.php 2 patches
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -144,7 +144,7 @@  discard block
 block discarded – undo
144 144
     public function ticket_status($display = false, $remaining = null)
145 145
     {
146 146
         $remaining = is_bool($remaining) ? $remaining : $this->is_remaining();
147
-        if (! $remaining) {
147
+        if ( ! $remaining) {
148 148
             return $display ? EEH_Template::pretty_status(EE_Ticket::sold_out, false, 'sentence') : EE_Ticket::sold_out;
149 149
         }
150 150
         if ($this->get('TKT_deleted')) {
@@ -273,7 +273,7 @@  discard block
 block discarded – undo
273 273
             ? $this->last_datetime()->get_i18n_datetime('DTT_EVT_end', $date_format)
274 274
             : '';
275 275
 
276
-        return $first_date && $last_date ? $first_date . $conjunction . $last_date : '';
276
+        return $first_date && $last_date ? $first_date.$conjunction.$last_date : '';
277 277
     }
278 278
 
279 279
 
@@ -303,7 +303,7 @@  discard block
 block discarded – undo
303 303
      */
304 304
     public function datetimes($query_params = [])
305 305
     {
306
-        if (! isset($query_params['order_by'])) {
306
+        if ( ! isset($query_params['order_by'])) {
307 307
             $query_params['order_by']['DTT_order'] = 'ASC';
308 308
         }
309 309
         return $this->get_many_related('Datetime', $query_params);
@@ -350,7 +350,7 @@  discard block
 block discarded – undo
350 350
                 if (empty($tickets_sold['datetime'])) {
351 351
                     return $total;
352 352
                 }
353
-                if (! empty($dtt_id) && ! isset($tickets_sold['datetime'][ $dtt_id ])) {
353
+                if ( ! empty($dtt_id) && ! isset($tickets_sold['datetime'][$dtt_id])) {
354 354
                     EE_Error::add_error(
355 355
                         __(
356 356
                             'You\'ve requested the amount of tickets sold for a given ticket and datetime, however there are no records for the datetime id you included.  Are you SURE that is a datetime related to this ticket?',
@@ -362,7 +362,7 @@  discard block
 block discarded – undo
362 362
                     );
363 363
                     return $total;
364 364
                 }
365
-                return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][ $dtt_id ];
365
+                return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][$dtt_id];
366 366
                 break;
367 367
             default:
368 368
                 return $total;
@@ -381,9 +381,9 @@  discard block
 block discarded – undo
381 381
     {
382 382
         $datetimes    = $this->get_many_related('Datetime');
383 383
         $tickets_sold = [];
384
-        if (! empty($datetimes)) {
384
+        if ( ! empty($datetimes)) {
385 385
             foreach ($datetimes as $datetime) {
386
-                $tickets_sold['datetime'][ $datetime->ID() ] = $datetime->get('DTT_sold');
386
+                $tickets_sold['datetime'][$datetime->ID()] = $datetime->get('DTT_sold');
387 387
             }
388 388
         }
389 389
         // Tickets sold
@@ -1011,7 +1011,7 @@  discard block
 block discarded – undo
1011 1011
                 'TKT_qty',
1012 1012
                 $qty
1013 1013
             );
1014
-            if (! $success) {
1014
+            if ( ! $success) {
1015 1015
                 // The datetimes were successfully bumped, but not the
1016 1016
                 // ticket. So we need to manually rollback the datetimes.
1017 1017
                 $this->decreaseReservedForDatetimes($qty);
@@ -1508,7 +1508,7 @@  discard block
 block discarded – undo
1508 1508
         foreach ($this->datetimes() as $datetime) {
1509 1509
             $times[] = $datetime->start_date_and_time();
1510 1510
         }
1511
-        return $this->name() . ' @ ' . implode(', ', $times) . ' for ' . $this->pretty_price();
1511
+        return $this->name().' @ '.implode(', ', $times).' for '.$this->pretty_price();
1512 1512
     }
1513 1513
 
1514 1514
 
@@ -1616,7 +1616,7 @@  discard block
 block discarded – undo
1616 1616
     {
1617 1617
         // get one datetime to use for getting the event
1618 1618
         $datetime = $this->first_datetime();
1619
-        if (! $datetime instanceof EE_Datetime) {
1619
+        if ( ! $datetime instanceof EE_Datetime) {
1620 1620
             throw new UnexpectedEntityException(
1621 1621
                 $datetime,
1622 1622
                 'EE_Datetime',
@@ -1627,7 +1627,7 @@  discard block
 block discarded – undo
1627 1627
             );
1628 1628
         }
1629 1629
         $event = $datetime->event();
1630
-        if (! $event instanceof EE_Event) {
1630
+        if ( ! $event instanceof EE_Event) {
1631 1631
             throw new UnexpectedEntityException(
1632 1632
                 $event,
1633 1633
                 'EE_Event',
Please login to merge, or discard this patch.
Indentation   +1998 added lines, -1998 removed lines patch added patch discarded remove patch
@@ -14,2006 +14,2006 @@
 block discarded – undo
14 14
 class EE_Ticket extends EE_Soft_Delete_Base_Class implements EEI_Line_Item_Object, EEI_Event_Relation, EEI_Has_Icon
15 15
 {
16 16
 
17
-    /**
18
-     * TicKet Sold out:
19
-     * constant used by ticket_status() to indicate that a ticket is sold out
20
-     * and no longer available for purchases
21
-     */
22
-    const sold_out = 'TKS';
23
-
24
-    /**
25
-     * TicKet Expired:
26
-     * constant used by ticket_status() to indicate that a ticket is expired
27
-     * and no longer available for purchase
28
-     */
29
-    const expired = 'TKE';
30
-
31
-    /**
32
-     * TicKet Archived:
33
-     * constant used by ticket_status() to indicate that a ticket is archived
34
-     * and no longer available for purchase
35
-     */
36
-    const archived = 'TKA';
37
-
38
-    /**
39
-     * TicKet Pending:
40
-     * constant used by ticket_status() to indicate that a ticket is pending
41
-     * and is NOT YET available for purchase
42
-     */
43
-    const pending = 'TKP';
44
-
45
-    /**
46
-     * TicKet On sale:
47
-     * constant used by ticket_status() to indicate that a ticket is On Sale
48
-     * and IS available for purchase
49
-     */
50
-    const onsale = 'TKO';
51
-
52
-    /**
53
-     * extra meta key for tracking ticket reservations
54
-     *
55
-     * @type string
56
-     */
57
-    const META_KEY_TICKET_RESERVATIONS = 'ticket_reservations';
58
-
59
-    /**
60
-     * override of parent property
61
-     *
62
-     * @var EEM_Ticket
63
-     */
64
-    protected $_model;
65
-
66
-    /**
67
-     * cached result from method of the same name
68
-     *
69
-     * @var float $_ticket_total_with_taxes
70
-     */
71
-    private $_ticket_total_with_taxes;
72
-
73
-
74
-    /**
75
-     * @param array  $props_n_values          incoming values
76
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
77
-     *                                        used.)
78
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
79
-     *                                        date_format and the second value is the time format
80
-     * @return EE_Ticket
81
-     * @throws EE_Error
82
-     * @throws ReflectionException
83
-     */
84
-    public static function new_instance($props_n_values = [], $timezone = null, $date_formats = [])
85
-    {
86
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
87
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
88
-    }
89
-
90
-
91
-    /**
92
-     * @param array  $props_n_values  incoming values from the database
93
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
94
-     *                                the website will be used.
95
-     * @return EE_Ticket
96
-     * @throws EE_Error
97
-     * @throws ReflectionException
98
-     */
99
-    public static function new_instance_from_db($props_n_values = [], $timezone = null)
100
-    {
101
-        return new self($props_n_values, true, $timezone);
102
-    }
103
-
104
-
105
-    /**
106
-     * @return bool
107
-     * @throws EE_Error
108
-     * @throws ReflectionException
109
-     */
110
-    public function parent()
111
-    {
112
-        return $this->get('TKT_parent');
113
-    }
114
-
115
-
116
-    /**
117
-     * return if a ticket has quantities available for purchase
118
-     *
119
-     * @param int $DTT_ID the primary key for a particular datetime
120
-     * @return boolean
121
-     * @throws EE_Error
122
-     * @throws ReflectionException
123
-     */
124
-    public function available($DTT_ID = 0)
125
-    {
126
-        // are we checking availability for a particular datetime ?
127
-        if ($DTT_ID) {
128
-            // get that datetime object
129
-            $datetime = $this->get_first_related('Datetime', [['DTT_ID' => $DTT_ID]]);
130
-            // if  ticket sales for this datetime have exceeded the reg limit...
131
-            if ($datetime instanceof EE_Datetime && $datetime->sold_out()) {
132
-                return false;
133
-            }
134
-        }
135
-        // datetime is still open for registration, but is this ticket sold out ?
136
-        return $this->qty() < 1 || $this->qty() > $this->sold();
137
-    }
138
-
139
-
140
-    /**
141
-     * Using the start date and end date this method calculates whether the ticket is On Sale, Pending, or Expired
142
-     *
143
-     * @param bool        $display   true = we'll return a localized string, otherwise we just return the value of the
144
-     *                               relevant status const
145
-     * @param bool | null $remaining if it is already known that tickets are available, then simply pass a bool to save
146
-     *                               further processing
147
-     * @return mixed status int if the display string isn't requested
148
-     * @throws EE_Error
149
-     * @throws ReflectionException
150
-     */
151
-    public function ticket_status($display = false, $remaining = null)
152
-    {
153
-        $remaining = is_bool($remaining) ? $remaining : $this->is_remaining();
154
-        if (! $remaining) {
155
-            return $display ? EEH_Template::pretty_status(EE_Ticket::sold_out, false, 'sentence') : EE_Ticket::sold_out;
156
-        }
157
-        if ($this->get('TKT_deleted')) {
158
-            return $display ? EEH_Template::pretty_status(EE_Ticket::archived, false, 'sentence') : EE_Ticket::archived;
159
-        }
160
-        if ($this->is_expired()) {
161
-            return $display ? EEH_Template::pretty_status(EE_Ticket::expired, false, 'sentence') : EE_Ticket::expired;
162
-        }
163
-        if ($this->is_pending()) {
164
-            return $display ? EEH_Template::pretty_status(EE_Ticket::pending, false, 'sentence') : EE_Ticket::pending;
165
-        }
166
-        if ($this->is_on_sale()) {
167
-            return $display ? EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence') : EE_Ticket::onsale;
168
-        }
169
-        return '';
170
-    }
171
-
172
-
173
-    /**
174
-     * The purpose of this method is to simply return a boolean for whether there are any tickets remaining for sale
175
-     * considering ALL the factors used for figuring that out.
176
-     *
177
-     * @access public
178
-     * @param int $DTT_ID if an int above 0 is included here then we get a specific dtt.
179
-     * @return boolean         true = tickets remaining, false not.
180
-     * @throws EE_Error
181
-     * @throws ReflectionException
182
-     */
183
-    public function is_remaining($DTT_ID = 0)
184
-    {
185
-        $num_remaining = $this->remaining($DTT_ID);
186
-        if ($num_remaining === 0) {
187
-            return false;
188
-        }
189
-        if ($num_remaining > 0 && $num_remaining < $this->min()) {
190
-            return false;
191
-        }
192
-        return true;
193
-    }
194
-
195
-
196
-    /**
197
-     * return the total number of tickets available for purchase
198
-     *
199
-     * @param int $DTT_ID  the primary key for a particular datetime.
200
-     *                     set to 0 for all related datetimes
201
-     * @return int
202
-     * @throws EE_Error
203
-     * @throws ReflectionException
204
-     */
205
-    public function remaining($DTT_ID = 0)
206
-    {
207
-        return $this->real_quantity_on_ticket('saleable', $DTT_ID);
208
-    }
209
-
210
-
211
-    /**
212
-     * Gets min
213
-     *
214
-     * @return int
215
-     * @throws EE_Error
216
-     * @throws ReflectionException
217
-     */
218
-    public function min()
219
-    {
220
-        return $this->get('TKT_min');
221
-    }
222
-
223
-
224
-    /**
225
-     * return if a ticket is no longer available cause its available dates have expired.
226
-     *
227
-     * @return boolean
228
-     * @throws EE_Error
229
-     * @throws ReflectionException
230
-     */
231
-    public function is_expired()
232
-    {
233
-        return ($this->get_raw('TKT_end_date') < time());
234
-    }
235
-
236
-
237
-    /**
238
-     * Return if a ticket is yet to go on sale or not
239
-     *
240
-     * @return boolean
241
-     * @throws EE_Error
242
-     * @throws ReflectionException
243
-     */
244
-    public function is_pending()
245
-    {
246
-        return ($this->get_raw('TKT_start_date') >= time());
247
-    }
248
-
249
-
250
-    /**
251
-     * Return if a ticket is on sale or not
252
-     *
253
-     * @return boolean
254
-     * @throws EE_Error
255
-     * @throws ReflectionException
256
-     */
257
-    public function is_on_sale()
258
-    {
259
-        return ($this->get_raw('TKT_start_date') <= time() && $this->get_raw('TKT_end_date') >= time());
260
-    }
261
-
262
-
263
-    /**
264
-     * This returns the chronologically last datetime that this ticket is associated with
265
-     *
266
-     * @param string $date_format
267
-     * @param string $conjunction - conjunction junction what's your function ? this string joins the start date with
268
-     *                            the end date ie: Jan 01 "to" Dec 31
269
-     * @return string
270
-     * @throws EE_Error
271
-     * @throws ReflectionException
272
-     */
273
-    public function date_range($date_format = '', $conjunction = ' - ')
274
-    {
275
-        $date_format = ! empty($date_format) ? $date_format : $this->_dt_frmt;
276
-        $first_date  = $this->first_datetime() instanceof EE_Datetime
277
-            ? $this->first_datetime()->get_i18n_datetime('DTT_EVT_start', $date_format)
278
-            : '';
279
-        $last_date   = $this->last_datetime() instanceof EE_Datetime
280
-            ? $this->last_datetime()->get_i18n_datetime('DTT_EVT_end', $date_format)
281
-            : '';
282
-
283
-        return $first_date && $last_date ? $first_date . $conjunction . $last_date : '';
284
-    }
285
-
286
-
287
-    /**
288
-     * This returns the chronologically first datetime that this ticket is associated with
289
-     *
290
-     * @return EE_Datetime
291
-     * @throws EE_Error
292
-     * @throws ReflectionException
293
-     */
294
-    public function first_datetime()
295
-    {
296
-        $datetimes = $this->datetimes(['limit' => 1]);
297
-        return reset($datetimes);
298
-    }
299
-
300
-
301
-    /**
302
-     * Gets all the datetimes this ticket can be used for attending.
303
-     * Unless otherwise specified, orders datetimes by start date.
304
-     *
305
-     * @param array $query_params @see
306
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
307
-     * @return EE_Datetime[]|EE_Base_Class[]
308
-     * @throws EE_Error
309
-     * @throws ReflectionException
310
-     */
311
-    public function datetimes($query_params = [])
312
-    {
313
-        if (! isset($query_params['order_by'])) {
314
-            $query_params['order_by']['DTT_order'] = 'ASC';
315
-        }
316
-        return $this->get_many_related('Datetime', $query_params);
317
-    }
318
-
319
-
320
-    /**
321
-     * This returns the chronologically last datetime that this ticket is associated with
322
-     *
323
-     * @return EE_Datetime
324
-     * @throws EE_Error
325
-     * @throws ReflectionException
326
-     */
327
-    public function last_datetime()
328
-    {
329
-        $datetimes = $this->datetimes(['limit' => 1, 'order_by' => ['DTT_EVT_start' => 'DESC']]);
330
-        return end($datetimes);
331
-    }
332
-
333
-
334
-    /**
335
-     * This returns the total tickets sold depending on the given parameters.
336
-     *
337
-     * @param string $what    Can be one of two options: 'ticket', 'datetime'.
338
-     *                        'ticket' = total ticket sales for all datetimes this ticket is related to
339
-     *                        'datetime' = total ticket sales for a specified datetime (required $dtt_id)
340
-     *                        'datetime' = total ticket sales in the datetime_ticket table.
341
-     *                        If $dtt_id is not given then we return an array of sales indexed by datetime.
342
-     *                        If $dtt_id IS given then we return the tickets sold for that given datetime.
343
-     * @param int    $dtt_id  [optional] include the dtt_id with $what = 'datetime'.
344
-     * @return mixed (array|int)          how many tickets have sold
345
-     * @throws EE_Error
346
-     * @throws ReflectionException
347
-     */
348
-    public function tickets_sold($what = 'ticket', $dtt_id = null)
349
-    {
350
-        $total        = 0;
351
-        $tickets_sold = $this->_all_tickets_sold();
352
-        switch ($what) {
353
-            case 'ticket':
354
-                return $tickets_sold['ticket'];
355
-                break;
356
-            case 'datetime':
357
-                if (empty($tickets_sold['datetime'])) {
358
-                    return $total;
359
-                }
360
-                if (! empty($dtt_id) && ! isset($tickets_sold['datetime'][ $dtt_id ])) {
361
-                    EE_Error::add_error(
362
-                        __(
363
-                            'You\'ve requested the amount of tickets sold for a given ticket and datetime, however there are no records for the datetime id you included.  Are you SURE that is a datetime related to this ticket?',
364
-                            'event_espresso'
365
-                        ),
366
-                        __FILE__,
367
-                        __FUNCTION__,
368
-                        __LINE__
369
-                    );
370
-                    return $total;
371
-                }
372
-                return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][ $dtt_id ];
373
-                break;
374
-            default:
375
-                return $total;
376
-        }
377
-    }
378
-
379
-
380
-    /**
381
-     * This returns an array indexed by datetime_id for tickets sold with this ticket.
382
-     *
383
-     * @return EE_Ticket[]
384
-     * @throws EE_Error
385
-     * @throws ReflectionException
386
-     */
387
-    protected function _all_tickets_sold()
388
-    {
389
-        $datetimes    = $this->get_many_related('Datetime');
390
-        $tickets_sold = [];
391
-        if (! empty($datetimes)) {
392
-            foreach ($datetimes as $datetime) {
393
-                $tickets_sold['datetime'][ $datetime->ID() ] = $datetime->get('DTT_sold');
394
-            }
395
-        }
396
-        // Tickets sold
397
-        $tickets_sold['ticket'] = $this->sold();
398
-        return $tickets_sold;
399
-    }
400
-
401
-
402
-    /**
403
-     * This returns the base price object for the ticket.
404
-     *
405
-     * @param bool $return_array whether to return as an array indexed by price id or just the object.
406
-     * @return EE_Price|EE_Base_Class|EE_Price[]|EE_Base_Class[]
407
-     * @throws EE_Error
408
-     * @throws ReflectionException
409
-     */
410
-    public function base_price($return_array = false)
411
-    {
412
-        $_where = ['Price_Type.PBT_ID' => EEM_Price_Type::base_type_base_price];
413
-        return $return_array
414
-            ? $this->get_many_related('Price', [$_where])
415
-            : $this->get_first_related('Price', [$_where]);
416
-    }
417
-
418
-
419
-    /**
420
-     * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price)
421
-     *
422
-     * @access public
423
-     * @return EE_Price[]
424
-     * @throws EE_Error
425
-     * @throws ReflectionException
426
-     */
427
-    public function price_modifiers()
428
-    {
429
-        $query_params = [
430
-            0 => [
431
-                'Price_Type.PBT_ID' => [
432
-                    'NOT IN',
433
-                    [EEM_Price_Type::base_type_base_price, EEM_Price_Type::base_type_tax],
434
-                ],
435
-            ],
436
-        ];
437
-        return $this->prices($query_params);
438
-    }
439
-
440
-
441
-    /**
442
-     * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price)
443
-     *
444
-     * @access public
445
-     * @return EE_Price[]
446
-     * @throws EE_Error
447
-     * @throws ReflectionException
448
-     */
449
-    public function tax_price_modifiers()
450
-    {
451
-        $query_params = [
452
-            0 => [
453
-                'Price_Type.PBT_ID' => EEM_Price_Type::base_type_tax,
454
-            ],
455
-        ];
456
-        return $this->prices($query_params);
457
-    }
458
-
459
-
460
-    /**
461
-     * Gets all the prices that combine to form the final price of this ticket
462
-     *
463
-     * @param array $query_params @see
464
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
465
-     * @return EE_Price[]|EE_Base_Class[]
466
-     * @throws EE_Error
467
-     * @throws ReflectionException
468
-     */
469
-    public function prices($query_params = [])
470
-    {
471
-        return $this->get_many_related('Price', $query_params);
472
-    }
473
-
474
-
475
-    /**
476
-     * Gets all the ticket datetimes (ie, relations between datetimes and tickets)
477
-     *
478
-     * @param array $query_params @see
479
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
480
-     * @return EE_Datetime_Ticket|EE_Base_Class[]
481
-     * @throws EE_Error
482
-     * @throws ReflectionException
483
-     */
484
-    public function datetime_tickets($query_params = [])
485
-    {
486
-        return $this->get_many_related('Datetime_Ticket', $query_params);
487
-    }
488
-
489
-
490
-    /**
491
-     * Gets all the datetimes from the db ordered by DTT_order
492
-     *
493
-     * @param boolean $show_expired
494
-     * @param boolean $show_deleted
495
-     * @return EE_Datetime[]
496
-     * @throws EE_Error
497
-     * @throws ReflectionException
498
-     */
499
-    public function datetimes_ordered($show_expired = true, $show_deleted = false)
500
-    {
501
-        return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_ticket_ordered_by_DTT_order(
502
-            $this->ID(),
503
-            $show_expired,
504
-            $show_deleted
505
-        );
506
-    }
507
-
508
-
509
-    /**
510
-     * Gets ID
511
-     *
512
-     * @return int
513
-     * @throws EE_Error
514
-     * @throws ReflectionException
515
-     */
516
-    public function ID()
517
-    {
518
-        return $this->get('TKT_ID');
519
-    }
520
-
521
-
522
-    /**
523
-     * get the author of the ticket.
524
-     *
525
-     * @return int
526
-     * @throws EE_Error
527
-     * @throws ReflectionException
528
-     * @since 4.5.0
529
-     */
530
-    public function wp_user()
531
-    {
532
-        return $this->get('TKT_wp_user');
533
-    }
534
-
535
-
536
-    /**
537
-     * Gets the template for the ticket
538
-     *
539
-     * @return EE_Ticket_Template|EE_Base_Class
540
-     * @throws EE_Error
541
-     * @throws ReflectionException
542
-     */
543
-    public function template()
544
-    {
545
-        return $this->get_first_related('Ticket_Template');
546
-    }
547
-
548
-
549
-    /**
550
-     * Simply returns an array of EE_Price objects that are taxes.
551
-     *
552
-     * @return EE_Price[]
553
-     * @throws EE_Error
554
-     */
555
-    public function get_ticket_taxes_for_admin()
556
-    {
557
-        return EE_Taxes::get_taxes_for_admin();
558
-    }
559
-
560
-
561
-    /**
562
-     * @return float
563
-     * @throws EE_Error
564
-     * @throws ReflectionException
565
-     */
566
-    public function ticket_price()
567
-    {
568
-        return $this->get('TKT_price');
569
-    }
570
-
571
-
572
-    /**
573
-     * @return mixed
574
-     * @throws EE_Error
575
-     * @throws ReflectionException
576
-     */
577
-    public function pretty_price()
578
-    {
579
-        return $this->get_pretty('TKT_price');
580
-    }
581
-
582
-
583
-    /**
584
-     * @return bool
585
-     * @throws EE_Error
586
-     * @throws ReflectionException
587
-     */
588
-    public function is_free()
589
-    {
590
-        return $this->get_ticket_total_with_taxes() === (float) 0;
591
-    }
592
-
593
-
594
-    /**
595
-     * get_ticket_total_with_taxes
596
-     *
597
-     * @param bool $no_cache
598
-     * @return float
599
-     * @throws EE_Error
600
-     * @throws ReflectionException
601
-     */
602
-    public function get_ticket_total_with_taxes($no_cache = false)
603
-    {
604
-        if ($this->_ticket_total_with_taxes === null || $no_cache) {
605
-            $this->_ticket_total_with_taxes = $this->get_ticket_subtotal() + $this->get_ticket_taxes_total_for_admin();
606
-        }
607
-        return (float) $this->_ticket_total_with_taxes;
608
-    }
609
-
610
-
611
-    /**
612
-     * @throws EE_Error
613
-     * @throws ReflectionException
614
-     */
615
-    public function ensure_TKT_Price_correct()
616
-    {
617
-        $this->set('TKT_price', EE_Taxes::get_subtotal_for_admin($this));
618
-        $this->save();
619
-    }
620
-
621
-
622
-    /**
623
-     * @return float
624
-     * @throws EE_Error
625
-     * @throws ReflectionException
626
-     */
627
-    public function get_ticket_subtotal()
628
-    {
629
-        return EE_Taxes::get_subtotal_for_admin($this);
630
-    }
631
-
632
-
633
-    /**
634
-     * Returns the total taxes applied to this ticket
635
-     *
636
-     * @return float
637
-     * @throws EE_Error
638
-     * @throws ReflectionException
639
-     */
640
-    public function get_ticket_taxes_total_for_admin()
641
-    {
642
-        return EE_Taxes::get_total_taxes_for_admin($this);
643
-    }
644
-
645
-
646
-    /**
647
-     * Sets name
648
-     *
649
-     * @param string $name
650
-     * @throws EE_Error
651
-     * @throws ReflectionException
652
-     */
653
-    public function set_name($name)
654
-    {
655
-        $this->set('TKT_name', $name);
656
-    }
657
-
658
-
659
-    /**
660
-     * Gets description
661
-     *
662
-     * @return string
663
-     * @throws EE_Error
664
-     * @throws ReflectionException
665
-     */
666
-    public function description()
667
-    {
668
-        return $this->get('TKT_description');
669
-    }
670
-
671
-
672
-    /**
673
-     * Sets description
674
-     *
675
-     * @param string $description
676
-     * @throws EE_Error
677
-     * @throws ReflectionException
678
-     */
679
-    public function set_description($description)
680
-    {
681
-        $this->set('TKT_description', $description);
682
-    }
683
-
684
-
685
-    /**
686
-     * Gets start_date
687
-     *
688
-     * @param string $date_format
689
-     * @param string $time_format
690
-     * @return string
691
-     * @throws EE_Error
692
-     * @throws ReflectionException
693
-     */
694
-    public function start_date($date_format = '', $time_format = '')
695
-    {
696
-        return $this->_get_datetime('TKT_start_date', $date_format, $time_format);
697
-    }
698
-
699
-
700
-    /**
701
-     * Sets start_date
702
-     *
703
-     * @param string $start_date
704
-     * @return void
705
-     * @throws EE_Error
706
-     * @throws ReflectionException
707
-     */
708
-    public function set_start_date($start_date)
709
-    {
710
-        $this->_set_date_time('B', $start_date, 'TKT_start_date');
711
-    }
712
-
713
-
714
-    /**
715
-     * Gets end_date
716
-     *
717
-     * @param string $date_format
718
-     * @param string $time_format
719
-     * @return string
720
-     * @throws EE_Error
721
-     * @throws ReflectionException
722
-     */
723
-    public function end_date($date_format = '', $time_format = '')
724
-    {
725
-        return $this->_get_datetime('TKT_end_date', $date_format, $time_format);
726
-    }
727
-
728
-
729
-    /**
730
-     * Sets end_date
731
-     *
732
-     * @param string $end_date
733
-     * @return void
734
-     * @throws EE_Error
735
-     * @throws ReflectionException
736
-     */
737
-    public function set_end_date($end_date)
738
-    {
739
-        $this->_set_date_time('B', $end_date, 'TKT_end_date');
740
-    }
741
-
742
-
743
-    /**
744
-     * Sets sell until time
745
-     *
746
-     * @param string $time a string representation of the sell until time (ex 9am or 7:30pm)
747
-     * @throws EE_Error
748
-     * @throws ReflectionException
749
-     * @since 4.5.0
750
-     */
751
-    public function set_end_time($time)
752
-    {
753
-        $this->_set_time_for($time, 'TKT_end_date');
754
-    }
755
-
756
-
757
-    /**
758
-     * Sets min
759
-     *
760
-     * @param int $min
761
-     * @return void
762
-     * @throws EE_Error
763
-     * @throws ReflectionException
764
-     */
765
-    public function set_min($min)
766
-    {
767
-        $this->set('TKT_min', $min);
768
-    }
769
-
770
-
771
-    /**
772
-     * Gets max
773
-     *
774
-     * @return int
775
-     * @throws EE_Error
776
-     * @throws ReflectionException
777
-     */
778
-    public function max()
779
-    {
780
-        return $this->get('TKT_max');
781
-    }
782
-
783
-
784
-    /**
785
-     * Sets max
786
-     *
787
-     * @param int $max
788
-     * @return void
789
-     * @throws EE_Error
790
-     * @throws ReflectionException
791
-     */
792
-    public function set_max($max)
793
-    {
794
-        $this->set('TKT_max', $max);
795
-    }
796
-
797
-
798
-    /**
799
-     * Sets price
800
-     *
801
-     * @param float $price
802
-     * @return void
803
-     * @throws EE_Error
804
-     * @throws ReflectionException
805
-     */
806
-    public function set_price($price)
807
-    {
808
-        $this->set('TKT_price', $price);
809
-    }
810
-
811
-
812
-    /**
813
-     * Gets sold
814
-     *
815
-     * @return int
816
-     * @throws EE_Error
817
-     * @throws ReflectionException
818
-     */
819
-    public function sold()
820
-    {
821
-        return $this->get_raw('TKT_sold');
822
-    }
823
-
824
-
825
-    /**
826
-     * Sets sold
827
-     *
828
-     * @param int $sold
829
-     * @return void
830
-     * @throws EE_Error
831
-     * @throws ReflectionException
832
-     */
833
-    public function set_sold($sold)
834
-    {
835
-        // sold can not go below zero
836
-        $sold = max(0, $sold);
837
-        $this->set('TKT_sold', $sold);
838
-    }
839
-
840
-
841
-    /**
842
-     * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
843
-     * associated datetimes.
844
-     *
845
-     * @param int $qty
846
-     * @return boolean
847
-     * @throws EE_Error
848
-     * @throws InvalidArgumentException
849
-     * @throws InvalidDataTypeException
850
-     * @throws InvalidInterfaceException
851
-     * @throws ReflectionException
852
-     * @since 4.9.80.p
853
-     */
854
-    public function increaseSold($qty = 1)
855
-    {
856
-        $qty = absint($qty);
857
-        // increment sold and decrement reserved datetime quantities simultaneously
858
-        // don't worry about failures, because they must have already had a spot reserved
859
-        $this->increaseSoldForDatetimes($qty);
860
-        // Increment and decrement ticket quantities simultaneously
861
-        $success = $this->adjustNumericFieldsInDb(
862
-            [
863
-                'TKT_reserved' => $qty * -1,
864
-                'TKT_sold'     => $qty,
865
-            ]
866
-        );
867
-        do_action(
868
-            'AHEE__EE_Ticket__increase_sold',
869
-            $this,
870
-            $qty,
871
-            $this->sold(),
872
-            $success
873
-        );
874
-        return $success;
875
-    }
876
-
877
-
878
-    /**
879
-     * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
880
-     *
881
-     * @param int           $qty positive or negative. Positive means to increase sold counts (and decrease reserved
882
-     *                           counts), Negative means to decreases old counts (and increase reserved counts).
883
-     * @param EE_Datetime[] $datetimes
884
-     * @throws EE_Error
885
-     * @throws InvalidArgumentException
886
-     * @throws InvalidDataTypeException
887
-     * @throws InvalidInterfaceException
888
-     * @throws ReflectionException
889
-     * @since 4.9.80.p
890
-     */
891
-    protected function increaseSoldForDatetimes($qty, array $datetimes = [])
892
-    {
893
-        $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
894
-        foreach ($datetimes as $datetime) {
895
-            $datetime->increaseSold($qty);
896
-        }
897
-    }
898
-
899
-
900
-    /**
901
-     * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
902
-     * DB and then updates the model objects.
903
-     * Does not affect the reserved counts.
904
-     *
905
-     * @param int $qty
906
-     * @return boolean
907
-     * @throws EE_Error
908
-     * @throws InvalidArgumentException
909
-     * @throws InvalidDataTypeException
910
-     * @throws InvalidInterfaceException
911
-     * @throws ReflectionException
912
-     * @since 4.9.80.p
913
-     */
914
-    public function decreaseSold($qty = 1)
915
-    {
916
-        $qty = absint($qty);
917
-        $this->decreaseSoldForDatetimes($qty);
918
-        $success = $this->adjustNumericFieldsInDb(
919
-            [
920
-                'TKT_sold' => $qty * -1,
921
-            ]
922
-        );
923
-        do_action(
924
-            'AHEE__EE_Ticket__decrease_sold',
925
-            $this,
926
-            $qty,
927
-            $this->sold(),
928
-            $success
929
-        );
930
-        return $success;
931
-    }
932
-
933
-
934
-    /**
935
-     * Decreases sold on related datetimes
936
-     *
937
-     * @param int           $qty
938
-     * @param EE_Datetime[] $datetimes
939
-     * @return void
940
-     * @throws EE_Error
941
-     * @throws InvalidArgumentException
942
-     * @throws InvalidDataTypeException
943
-     * @throws InvalidInterfaceException
944
-     * @throws ReflectionException
945
-     * @since 4.9.80.p
946
-     */
947
-    protected function decreaseSoldForDatetimes($qty = 1, array $datetimes = [])
948
-    {
949
-        $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
950
-        if (is_array($datetimes)) {
951
-            foreach ($datetimes as $datetime) {
952
-                if ($datetime instanceof EE_Datetime) {
953
-                    $datetime->decreaseSold($qty);
954
-                }
955
-            }
956
-        }
957
-    }
958
-
959
-
960
-    /**
961
-     * Gets qty of reserved tickets
962
-     *
963
-     * @return int
964
-     * @throws EE_Error
965
-     * @throws ReflectionException
966
-     */
967
-    public function reserved()
968
-    {
969
-        return $this->get_raw('TKT_reserved');
970
-    }
971
-
972
-
973
-    /**
974
-     * Sets reserved
975
-     *
976
-     * @param int $reserved
977
-     * @return void
978
-     * @throws EE_Error
979
-     * @throws ReflectionException
980
-     */
981
-    public function set_reserved($reserved)
982
-    {
983
-        // reserved can not go below zero
984
-        $reserved = max(0, (int) $reserved);
985
-        $this->set('TKT_reserved', $reserved);
986
-    }
987
-
988
-
989
-    /**
990
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
991
-     *
992
-     * @param int    $qty
993
-     * @param string $source
994
-     * @return bool whether we successfully reserved the ticket or not.
995
-     * @throws EE_Error
996
-     * @throws InvalidArgumentException
997
-     * @throws ReflectionException
998
-     * @throws InvalidDataTypeException
999
-     * @throws InvalidInterfaceException
1000
-     * @since 4.9.80.p
1001
-     */
1002
-    public function increaseReserved($qty = 1, $source = 'unknown')
1003
-    {
1004
-        $qty = absint($qty);
1005
-        do_action(
1006
-            'AHEE__EE_Ticket__increase_reserved__begin',
1007
-            $this,
1008
-            $qty,
1009
-            $source
1010
-        );
1011
-        $this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "{$qty} from {$source}");
1012
-        $success                         = false;
1013
-        $datetimes_adjusted_successfully = $this->increaseReservedForDatetimes($qty);
1014
-        if ($datetimes_adjusted_successfully) {
1015
-            $success = $this->incrementFieldConditionallyInDb(
1016
-                'TKT_reserved',
1017
-                'TKT_sold',
1018
-                'TKT_qty',
1019
-                $qty
1020
-            );
1021
-            if (! $success) {
1022
-                // The datetimes were successfully bumped, but not the
1023
-                // ticket. So we need to manually rollback the datetimes.
1024
-                $this->decreaseReservedForDatetimes($qty);
1025
-            }
1026
-        }
1027
-        do_action(
1028
-            'AHEE__EE_Ticket__increase_reserved',
1029
-            $this,
1030
-            $qty,
1031
-            $this->reserved(),
1032
-            $success
1033
-        );
1034
-        return $success;
1035
-    }
1036
-
1037
-
1038
-    /**
1039
-     * Increases reserved counts on related datetimes
1040
-     *
1041
-     * @param int           $qty
1042
-     * @param EE_Datetime[] $datetimes
1043
-     * @return boolean indicating success
1044
-     * @throws EE_Error
1045
-     * @throws InvalidArgumentException
1046
-     * @throws InvalidDataTypeException
1047
-     * @throws InvalidInterfaceException
1048
-     * @throws ReflectionException
1049
-     * @since 4.9.80.p
1050
-     */
1051
-    protected function increaseReservedForDatetimes($qty = 1, array $datetimes = [])
1052
-    {
1053
-        $datetimes         = ! empty($datetimes) ? $datetimes : $this->datetimes();
1054
-        $datetimes_updated = [];
1055
-        $limit_exceeded    = false;
1056
-        if (is_array($datetimes)) {
1057
-            foreach ($datetimes as $datetime) {
1058
-                if ($datetime instanceof EE_Datetime) {
1059
-                    if ($datetime->increaseReserved($qty)) {
1060
-                        $datetimes_updated[] = $datetime;
1061
-                    } else {
1062
-                        $limit_exceeded = true;
1063
-                        break;
1064
-                    }
1065
-                }
1066
-            }
1067
-            // If somewhere along the way we detected a datetime whose
1068
-            // limit was exceeded, do a manual rollback.
1069
-            if ($limit_exceeded) {
1070
-                $this->decreaseReservedForDatetimes($qty, $datetimes_updated);
1071
-                return false;
1072
-            }
1073
-        }
1074
-        return true;
1075
-    }
1076
-
1077
-
1078
-    /**
1079
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1080
-     *
1081
-     * @param int    $qty
1082
-     * @param bool   $adjust_datetimes
1083
-     * @param string $source
1084
-     * @return boolean
1085
-     * @throws EE_Error
1086
-     * @throws InvalidArgumentException
1087
-     * @throws ReflectionException
1088
-     * @throws InvalidDataTypeException
1089
-     * @throws InvalidInterfaceException
1090
-     * @since 4.9.80.p
1091
-     */
1092
-    public function decreaseReserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
1093
-    {
1094
-        $qty = absint($qty);
1095
-        $this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "-{$qty} from {$source}");
1096
-        if ($adjust_datetimes) {
1097
-            $this->decreaseReservedForDatetimes($qty);
1098
-        }
1099
-        $success = $this->adjustNumericFieldsInDb(
1100
-            [
1101
-                'TKT_reserved' => $qty * -1,
1102
-            ]
1103
-        );
1104
-        do_action(
1105
-            'AHEE__EE_Ticket__decrease_reserved',
1106
-            $this,
1107
-            $qty,
1108
-            $this->reserved(),
1109
-            $success
1110
-        );
1111
-        return $success;
1112
-    }
1113
-
1114
-
1115
-    /**
1116
-     * Decreases the reserved count on the specified datetimes.
1117
-     *
1118
-     * @param int           $qty
1119
-     * @param EE_Datetime[] $datetimes
1120
-     * @throws EE_Error
1121
-     * @throws InvalidArgumentException
1122
-     * @throws ReflectionException
1123
-     * @throws InvalidDataTypeException
1124
-     * @throws InvalidInterfaceException
1125
-     * @since 4.9.80.p
1126
-     */
1127
-    protected function decreaseReservedForDatetimes($qty = 1, array $datetimes = [])
1128
-    {
1129
-        $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
1130
-        foreach ($datetimes as $datetime) {
1131
-            if ($datetime instanceof EE_Datetime) {
1132
-                $datetime->decreaseReserved($qty);
1133
-            }
1134
-        }
1135
-    }
1136
-
1137
-
1138
-    /**
1139
-     * Gets ticket quantity
1140
-     *
1141
-     * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1142
-     *                            therefore $context can be one of three values: '', 'reg_limit', or 'saleable'
1143
-     *                            '' (default) quantity is the actual db value for TKT_qty, unaffected by other objects
1144
-     *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1145
-     *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1146
-     *                            is therefore the truest measure of tickets that can be purchased at the moment
1147
-     * @return int
1148
-     * @throws EE_Error
1149
-     * @throws ReflectionException
1150
-     */
1151
-    public function qty($context = '')
1152
-    {
1153
-        switch ($context) {
1154
-            case 'reg_limit':
1155
-                return $this->real_quantity_on_ticket();
1156
-            case 'saleable':
1157
-                return $this->real_quantity_on_ticket('saleable');
1158
-            default:
1159
-                return $this->get_raw('TKT_qty');
1160
-        }
1161
-    }
1162
-
1163
-
1164
-    /**
1165
-     * Gets ticket quantity
1166
-     *
1167
-     * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1168
-     *                            therefore $context can be one of two values: 'reg_limit', or 'saleable'
1169
-     *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1170
-     *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1171
-     *                            is therefore the truest measure of tickets that can be purchased at the moment
1172
-     * @param int    $DTT_ID      the primary key for a particular datetime.
1173
-     *                            set to 0 for all related datetimes
1174
-     * @return int
1175
-     * @throws EE_Error
1176
-     * @throws ReflectionException
1177
-     */
1178
-    public function real_quantity_on_ticket($context = 'reg_limit', $DTT_ID = 0)
1179
-    {
1180
-        $raw = $this->get_raw('TKT_qty');
1181
-        // return immediately if it's zero
1182
-        if ($raw === 0) {
1183
-            return $raw;
1184
-        }
1185
-        // echo "\n\n<br />Ticket: " . $this->name() . '<br />';
1186
-        // ensure qty doesn't exceed raw value for THIS ticket
1187
-        $qty = min(EE_INF, $raw);
1188
-        // echo "\n . qty: " . $qty . '<br />';
1189
-        // calculate this ticket's total sales and reservations
1190
-        $sold_and_reserved_for_this_ticket = $this->sold() + $this->reserved();
1191
-        // echo "\n . sold: " . $this->sold() . '<br />';
1192
-        // echo "\n . reserved: " . $this->reserved() . '<br />';
1193
-        // echo "\n . sold_and_reserved_for_this_ticket: " . $sold_and_reserved_for_this_ticket . '<br />';
1194
-        // first we need to calculate the maximum number of tickets available for the datetime
1195
-        // do we want data for one datetime or all of them ?
1196
-        $query_params = $DTT_ID ? [['DTT_ID' => $DTT_ID]] : [];
1197
-        $datetimes    = $this->datetimes($query_params);
1198
-        if (is_array($datetimes) && ! empty($datetimes)) {
1199
-            foreach ($datetimes as $datetime) {
1200
-                if ($datetime instanceof EE_Datetime) {
1201
-                    $datetime->refresh_from_db();
1202
-                    // echo "\n . . datetime name: " . $datetime->name() . '<br />';
1203
-                    // echo "\n . . datetime ID: " . $datetime->ID() . '<br />';
1204
-                    // initialize with no restrictions for each datetime
1205
-                    // but adjust datetime qty based on datetime reg limit
1206
-                    $datetime_qty = min(EE_INF, $datetime->reg_limit());
1207
-                    // echo "\n . . . datetime reg_limit: " . $datetime->reg_limit() . '<br />';
1208
-                    // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1209
-                    // if we want the actual saleable amount, then we need to consider OTHER ticket sales
1210
-                    // and reservations for this datetime, that do NOT include sales and reservations
1211
-                    // for this ticket (so we add $this->sold() and $this->reserved() back in)
1212
-                    if ($context === 'saleable') {
1213
-                        $datetime_qty = max(
1214
-                            $datetime_qty - $datetime->sold_and_reserved() + $sold_and_reserved_for_this_ticket,
1215
-                            0
1216
-                        );
1217
-                        // echo "\n . . . datetime sold: " . $datetime->sold() . '<br />';
1218
-                        // echo "\n . . . datetime reserved: " . $datetime->reserved() . '<br />';
1219
-                        // echo "\n . . . datetime sold_and_reserved: " . $datetime->sold_and_reserved() . '<br />';
1220
-                        // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1221
-                        $datetime_qty = ! $datetime->sold_out() ? $datetime_qty : 0;
1222
-                        // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1223
-                    }
1224
-                    $qty = min($datetime_qty, $qty);
1225
-                    // echo "\n . . qty: " . $qty . '<br />';
1226
-                }
1227
-            }
1228
-        }
1229
-        // NOW that we know the  maximum number of tickets available for the datetime
1230
-        // we can finally factor in the details for this specific ticket
1231
-        if ($qty > 0 && $context === 'saleable') {
1232
-            // and subtract the sales for THIS ticket
1233
-            $qty = max($qty - $sold_and_reserved_for_this_ticket, 0);
1234
-            // echo "\n . qty: " . $qty . '<br />';
1235
-        }
1236
-        // echo "\nFINAL QTY: " . $qty . "<br /><br />";
1237
-        return $qty;
1238
-    }
1239
-
1240
-
1241
-    /**
1242
-     * Sets qty - IMPORTANT!!! Does NOT allow QTY to be set higher than the lowest reg limit of any related datetimes
1243
-     *
1244
-     * @param int $qty
1245
-     * @return void
1246
-     * @throws EE_Error
1247
-     * @throws ReflectionException
1248
-     */
1249
-    public function set_qty($qty)
1250
-    {
1251
-        $datetimes = $this->datetimes();
1252
-        foreach ($datetimes as $datetime) {
1253
-            if ($datetime instanceof EE_Datetime) {
1254
-                $qty = min($qty, $datetime->reg_limit());
1255
-            }
1256
-        }
1257
-        $this->set('TKT_qty', $qty);
1258
-    }
1259
-
1260
-
1261
-    /**
1262
-     * Gets uses
1263
-     *
1264
-     * @return int
1265
-     * @throws EE_Error
1266
-     * @throws ReflectionException
1267
-     */
1268
-    public function uses()
1269
-    {
1270
-        return $this->get('TKT_uses');
1271
-    }
1272
-
1273
-
1274
-    /**
1275
-     * Sets uses
1276
-     *
1277
-     * @param int $uses
1278
-     * @return void
1279
-     * @throws EE_Error
1280
-     * @throws ReflectionException
1281
-     */
1282
-    public function set_uses($uses)
1283
-    {
1284
-        $this->set('TKT_uses', $uses);
1285
-    }
1286
-
1287
-
1288
-    /**
1289
-     * returns whether ticket is required or not.
1290
-     *
1291
-     * @return boolean
1292
-     * @throws EE_Error
1293
-     * @throws ReflectionException
1294
-     */
1295
-    public function required()
1296
-    {
1297
-        return $this->get('TKT_required');
1298
-    }
1299
-
1300
-
1301
-    /**
1302
-     * sets the TKT_required property
1303
-     *
1304
-     * @param boolean $required
1305
-     * @return void
1306
-     * @throws EE_Error
1307
-     * @throws ReflectionException
1308
-     */
1309
-    public function set_required($required)
1310
-    {
1311
-        $this->set('TKT_required', $required);
1312
-    }
1313
-
1314
-
1315
-    /**
1316
-     * Gets taxable
1317
-     *
1318
-     * @return boolean
1319
-     * @throws EE_Error
1320
-     * @throws ReflectionException
1321
-     */
1322
-    public function taxable()
1323
-    {
1324
-        return $this->get('TKT_taxable');
1325
-    }
1326
-
1327
-
1328
-    /**
1329
-     * Sets taxable
1330
-     *
1331
-     * @param boolean $taxable
1332
-     * @return void
1333
-     * @throws EE_Error
1334
-     * @throws ReflectionException
1335
-     */
1336
-    public function set_taxable($taxable)
1337
-    {
1338
-        $this->set('TKT_taxable', $taxable);
1339
-    }
1340
-
1341
-
1342
-    /**
1343
-     * Gets is_default
1344
-     *
1345
-     * @return boolean
1346
-     * @throws EE_Error
1347
-     * @throws ReflectionException
1348
-     */
1349
-    public function is_default()
1350
-    {
1351
-        return $this->get('TKT_is_default');
1352
-    }
1353
-
1354
-
1355
-    /**
1356
-     * Sets is_default
1357
-     *
1358
-     * @param boolean $is_default
1359
-     * @return void
1360
-     * @throws EE_Error
1361
-     * @throws ReflectionException
1362
-     */
1363
-    public function set_is_default($is_default)
1364
-    {
1365
-        $this->set('TKT_is_default', $is_default);
1366
-    }
1367
-
1368
-
1369
-    /**
1370
-     * Gets order
1371
-     *
1372
-     * @return int
1373
-     * @throws EE_Error
1374
-     * @throws ReflectionException
1375
-     */
1376
-    public function order()
1377
-    {
1378
-        return $this->get('TKT_order');
1379
-    }
1380
-
1381
-
1382
-    /**
1383
-     * Sets order
1384
-     *
1385
-     * @param int $order
1386
-     * @return void
1387
-     * @throws EE_Error
1388
-     * @throws ReflectionException
1389
-     */
1390
-    public function set_order($order)
1391
-    {
1392
-        $this->set('TKT_order', $order);
1393
-    }
1394
-
1395
-
1396
-    /**
1397
-     * Gets row
1398
-     *
1399
-     * @return int
1400
-     * @throws EE_Error
1401
-     * @throws ReflectionException
1402
-     */
1403
-    public function row()
1404
-    {
1405
-        return $this->get('TKT_row');
1406
-    }
1407
-
1408
-
1409
-    /**
1410
-     * Sets row
1411
-     *
1412
-     * @param int $row
1413
-     * @return void
1414
-     * @throws EE_Error
1415
-     * @throws ReflectionException
1416
-     */
1417
-    public function set_row($row)
1418
-    {
1419
-        $this->set('TKT_row', $row);
1420
-    }
1421
-
1422
-
1423
-    /**
1424
-     * Gets deleted
1425
-     *
1426
-     * @return boolean
1427
-     * @throws EE_Error
1428
-     * @throws ReflectionException
1429
-     */
1430
-    public function deleted()
1431
-    {
1432
-        return $this->get('TKT_deleted');
1433
-    }
1434
-
1435
-
1436
-    /**
1437
-     * Sets deleted
1438
-     *
1439
-     * @param boolean $deleted
1440
-     * @return void
1441
-     * @throws EE_Error
1442
-     * @throws ReflectionException
1443
-     */
1444
-    public function set_deleted($deleted)
1445
-    {
1446
-        $this->set('TKT_deleted', $deleted);
1447
-    }
1448
-
1449
-
1450
-    /**
1451
-     * Gets parent
1452
-     *
1453
-     * @return int
1454
-     * @throws EE_Error
1455
-     * @throws ReflectionException
1456
-     */
1457
-    public function parent_ID()
1458
-    {
1459
-        return $this->get('TKT_parent');
1460
-    }
1461
-
1462
-
1463
-    /**
1464
-     * Sets parent
1465
-     *
1466
-     * @param int $parent
1467
-     * @return void
1468
-     * @throws EE_Error
1469
-     * @throws ReflectionException
1470
-     */
1471
-    public function set_parent_ID($parent)
1472
-    {
1473
-        $this->set('TKT_parent', $parent);
1474
-    }
1475
-
1476
-
1477
-    /**
1478
-     * @return boolean
1479
-     * @throws EE_Error
1480
-     * @throws InvalidArgumentException
1481
-     * @throws InvalidDataTypeException
1482
-     * @throws InvalidInterfaceException
1483
-     * @throws ReflectionException
1484
-     */
1485
-    public function reverse_calculate()
1486
-    {
1487
-        return $this->get('TKT_reverse_calculate');
1488
-    }
1489
-
1490
-
1491
-    /**
1492
-     * @param boolean $reverse_calculate
1493
-     * @throws EE_Error
1494
-     * @throws InvalidArgumentException
1495
-     * @throws InvalidDataTypeException
1496
-     * @throws InvalidInterfaceException
1497
-     * @throws ReflectionException
1498
-     */
1499
-    public function set_reverse_calculate($reverse_calculate)
1500
-    {
1501
-        $this->set('TKT_reverse_calculate', $reverse_calculate);
1502
-    }
1503
-
1504
-
1505
-    /**
1506
-     * Gets a string which is handy for showing in gateways etc that describes the ticket.
1507
-     *
1508
-     * @return string
1509
-     * @throws EE_Error
1510
-     * @throws ReflectionException
1511
-     */
1512
-    public function name_and_info()
1513
-    {
1514
-        $times = [];
1515
-        foreach ($this->datetimes() as $datetime) {
1516
-            $times[] = $datetime->start_date_and_time();
1517
-        }
1518
-        return $this->name() . ' @ ' . implode(', ', $times) . ' for ' . $this->pretty_price();
1519
-    }
1520
-
1521
-
1522
-    /**
1523
-     * Gets name
1524
-     *
1525
-     * @return string
1526
-     * @throws EE_Error
1527
-     * @throws ReflectionException
1528
-     */
1529
-    public function name()
1530
-    {
1531
-        return $this->get('TKT_name');
1532
-    }
1533
-
1534
-
1535
-    /**
1536
-     * Gets price
1537
-     *
1538
-     * @return float
1539
-     * @throws EE_Error
1540
-     * @throws ReflectionException
1541
-     */
1542
-    public function price()
1543
-    {
1544
-        return $this->get('TKT_price');
1545
-    }
1546
-
1547
-
1548
-    /**
1549
-     * Gets all the registrations for this ticket
1550
-     *
1551
-     * @param array $query_params @see
1552
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1553
-     * @return EE_Registration[]|EE_Base_Class[]
1554
-     * @throws EE_Error
1555
-     * @throws ReflectionException
1556
-     */
1557
-    public function registrations($query_params = [])
1558
-    {
1559
-        return $this->get_many_related('Registration', $query_params);
1560
-    }
1561
-
1562
-
1563
-    /**
1564
-     * Updates the TKT_sold attribute (and saves) based on the number of APPROVED registrations for this ticket.
1565
-     *
1566
-     * @return int
1567
-     * @throws EE_Error
1568
-     * @throws ReflectionException
1569
-     */
1570
-    public function update_tickets_sold()
1571
-    {
1572
-        $count_regs_for_this_ticket = $this->count_registrations(
1573
-            [
1574
-                [
1575
-                    'STS_ID'      => EEM_Registration::status_id_approved,
1576
-                    'REG_deleted' => 0,
1577
-                ],
1578
-            ]
1579
-        );
1580
-        $this->set_sold($count_regs_for_this_ticket);
1581
-        $this->save();
1582
-        return $count_regs_for_this_ticket;
1583
-    }
1584
-
1585
-
1586
-    /**
1587
-     * Counts the registrations for this ticket
1588
-     *
1589
-     * @param array $query_params @see
1590
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1591
-     * @return int
1592
-     * @throws EE_Error
1593
-     * @throws ReflectionException
1594
-     */
1595
-    public function count_registrations($query_params = [])
1596
-    {
1597
-        return $this->count_related('Registration', $query_params);
1598
-    }
1599
-
1600
-
1601
-    /**
1602
-     * Implementation for EEI_Has_Icon interface method.
1603
-     *
1604
-     * @return string
1605
-     * @see EEI_Visual_Representation for comments
1606
-     */
1607
-    public function get_icon()
1608
-    {
1609
-        return '<span class="dashicons dashicons-tickets-alt"/>';
1610
-    }
1611
-
1612
-
1613
-    /**
1614
-     * Implementation of the EEI_Event_Relation interface method
1615
-     *
1616
-     * @return EE_Event
1617
-     * @throws EE_Error
1618
-     * @throws UnexpectedEntityException
1619
-     * @throws ReflectionException
1620
-     * @see EEI_Event_Relation for comments
1621
-     */
1622
-    public function get_related_event()
1623
-    {
1624
-        // get one datetime to use for getting the event
1625
-        $datetime = $this->first_datetime();
1626
-        if (! $datetime instanceof EE_Datetime) {
1627
-            throw new UnexpectedEntityException(
1628
-                $datetime,
1629
-                'EE_Datetime',
1630
-                sprintf(
1631
-                    __('The ticket (%s) is not associated with any valid datetimes.', 'event_espresso'),
1632
-                    $this->name()
1633
-                )
1634
-            );
1635
-        }
1636
-        $event = $datetime->event();
1637
-        if (! $event instanceof EE_Event) {
1638
-            throw new UnexpectedEntityException(
1639
-                $event,
1640
-                'EE_Event',
1641
-                sprintf(
1642
-                    __('The ticket (%s) is not associated with a valid event.', 'event_espresso'),
1643
-                    $this->name()
1644
-                )
1645
-            );
1646
-        }
1647
-        return $event;
1648
-    }
1649
-
1650
-
1651
-    /**
1652
-     * Implementation of the EEI_Event_Relation interface method
1653
-     *
1654
-     * @return string
1655
-     * @throws UnexpectedEntityException
1656
-     * @throws EE_Error
1657
-     * @throws ReflectionException
1658
-     * @see EEI_Event_Relation for comments
1659
-     */
1660
-    public function get_event_name()
1661
-    {
1662
-        $event = $this->get_related_event();
1663
-        return $event instanceof EE_Event ? $event->name() : '';
1664
-    }
1665
-
1666
-
1667
-    /**
1668
-     * Implementation of the EEI_Event_Relation interface method
1669
-     *
1670
-     * @return int
1671
-     * @throws UnexpectedEntityException
1672
-     * @throws EE_Error
1673
-     * @throws ReflectionException
1674
-     * @see EEI_Event_Relation for comments
1675
-     */
1676
-    public function get_event_ID()
1677
-    {
1678
-        $event = $this->get_related_event();
1679
-        return $event instanceof EE_Event ? $event->ID() : 0;
1680
-    }
1681
-
1682
-
1683
-    /**
1684
-     * This simply returns whether a ticket can be permanently deleted or not.
1685
-     * The criteria for determining this is whether the ticket has any related registrations.
1686
-     * If there are none then it can be permanently deleted.
1687
-     *
1688
-     * @return bool
1689
-     * @throws EE_Error
1690
-     * @throws ReflectionException
1691
-     */
1692
-    public function is_permanently_deleteable()
1693
-    {
1694
-        return $this->count_registrations() === 0;
1695
-    }
1696
-
1697
-
1698
-    /**
1699
-     * @return int
1700
-     * @throws EE_Error
1701
-     * @throws ReflectionException
1702
-     * @since   $VID:$
1703
-     */
1704
-    public function visibility(): int
1705
-    {
1706
-        return $this->get('TKT_visibility');
1707
-    }
1708
-
1709
-
1710
-    /**
1711
-     * @return int
1712
-     * @throws EE_Error
1713
-     * @throws ReflectionException
1714
-     * @since   $VID:$
1715
-     */
1716
-    public function isHidden(): int
1717
-    {
1718
-        return $this->visibility() === EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE;
1719
-    }
1720
-
1721
-
1722
-    /**
1723
-     * @return int
1724
-     * @throws EE_Error
1725
-     * @throws ReflectionException
1726
-     * @since   $VID:$
1727
-     */
1728
-    public function isNotHidden(): int
1729
-    {
1730
-        return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE;
1731
-    }
1732
-
1733
-
1734
-    /**
1735
-     * @return int
1736
-     * @throws EE_Error
1737
-     * @throws ReflectionException
1738
-     * @since   $VID:$
1739
-     */
1740
-    public function isPublicOnly(): int
1741
-    {
1742
-        return $this->isNotHidden() && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_PUBLIC_VALUE;
1743
-    }
1744
-
1745
-
1746
-    /**
1747
-     * @return int
1748
-     * @throws EE_Error
1749
-     * @throws ReflectionException
1750
-     * @since   $VID:$
1751
-     */
1752
-    public function isMembersOnly(): int
1753
-    {
1754
-        return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_PUBLIC_VALUE
1755
-               && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_MEMBERS_ONLY_VALUE;
1756
-    }
1757
-
1758
-
1759
-    /**
1760
-     * @return int
1761
-     * @throws EE_Error
1762
-     * @throws ReflectionException
1763
-     * @since   $VID:$
1764
-     */
1765
-    public function isAdminsOnly(): int
1766
-    {
1767
-        return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_MEMBERS_ONLY_VALUE
1768
-               && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_ADMINS_ONLY_VALUE;
1769
-    }
1770
-
1771
-
1772
-    /**
1773
-     * @return int
1774
-     * @throws EE_Error
1775
-     * @throws ReflectionException
1776
-     * @since   $VID:$
1777
-     */
1778
-    public function isAdminUiOnly(): int
1779
-    {
1780
-        return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_ADMINS_ONLY_VALUE
1781
-               && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_ADMIN_UI_ONLY_VALUE;
1782
-    }
1783
-
1784
-
1785
-    /**
1786
-     * @param int $visibility
1787
-     * @throws EE_Error
1788
-     * @throws ReflectionException
1789
-     * @since   $VID:$
1790
-     */
1791
-    public function set_visibility(int $visibility)
1792
-    {
1793
-
1794
-        $ticket_visibility_options = $this->_model->ticketVisibilityOptions();
1795
-        $ticket_visibility         = -1;
1796
-        foreach ($ticket_visibility_options as $ticket_visibility_option) {
1797
-            if ($visibility === $ticket_visibility_option) {
1798
-                $ticket_visibility = $visibility;
1799
-            }
1800
-        }
1801
-        if ($ticket_visibility === -1) {
1802
-            throw new DomainException(
1803
-                sprintf(
1804
-                    esc_html__(
1805
-                        'The supplied ticket visibility setting of "%1$s" is not valid. It needs to match one of the keys in the following array:%2$s %3$s ',
1806
-                        'event_espresso'
1807
-                    ),
1808
-                    $visibility,
1809
-                    '<br />',
1810
-                    var_export($ticket_visibility_options, true)
1811
-                )
1812
-            );
1813
-        }
1814
-        $this->set('TKT_visibility', $ticket_visibility);
1815
-    }
1816
-
1817
-
1818
-    /*******************************************************************
17
+	/**
18
+	 * TicKet Sold out:
19
+	 * constant used by ticket_status() to indicate that a ticket is sold out
20
+	 * and no longer available for purchases
21
+	 */
22
+	const sold_out = 'TKS';
23
+
24
+	/**
25
+	 * TicKet Expired:
26
+	 * constant used by ticket_status() to indicate that a ticket is expired
27
+	 * and no longer available for purchase
28
+	 */
29
+	const expired = 'TKE';
30
+
31
+	/**
32
+	 * TicKet Archived:
33
+	 * constant used by ticket_status() to indicate that a ticket is archived
34
+	 * and no longer available for purchase
35
+	 */
36
+	const archived = 'TKA';
37
+
38
+	/**
39
+	 * TicKet Pending:
40
+	 * constant used by ticket_status() to indicate that a ticket is pending
41
+	 * and is NOT YET available for purchase
42
+	 */
43
+	const pending = 'TKP';
44
+
45
+	/**
46
+	 * TicKet On sale:
47
+	 * constant used by ticket_status() to indicate that a ticket is On Sale
48
+	 * and IS available for purchase
49
+	 */
50
+	const onsale = 'TKO';
51
+
52
+	/**
53
+	 * extra meta key for tracking ticket reservations
54
+	 *
55
+	 * @type string
56
+	 */
57
+	const META_KEY_TICKET_RESERVATIONS = 'ticket_reservations';
58
+
59
+	/**
60
+	 * override of parent property
61
+	 *
62
+	 * @var EEM_Ticket
63
+	 */
64
+	protected $_model;
65
+
66
+	/**
67
+	 * cached result from method of the same name
68
+	 *
69
+	 * @var float $_ticket_total_with_taxes
70
+	 */
71
+	private $_ticket_total_with_taxes;
72
+
73
+
74
+	/**
75
+	 * @param array  $props_n_values          incoming values
76
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
77
+	 *                                        used.)
78
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
79
+	 *                                        date_format and the second value is the time format
80
+	 * @return EE_Ticket
81
+	 * @throws EE_Error
82
+	 * @throws ReflectionException
83
+	 */
84
+	public static function new_instance($props_n_values = [], $timezone = null, $date_formats = [])
85
+	{
86
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
87
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
88
+	}
89
+
90
+
91
+	/**
92
+	 * @param array  $props_n_values  incoming values from the database
93
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
94
+	 *                                the website will be used.
95
+	 * @return EE_Ticket
96
+	 * @throws EE_Error
97
+	 * @throws ReflectionException
98
+	 */
99
+	public static function new_instance_from_db($props_n_values = [], $timezone = null)
100
+	{
101
+		return new self($props_n_values, true, $timezone);
102
+	}
103
+
104
+
105
+	/**
106
+	 * @return bool
107
+	 * @throws EE_Error
108
+	 * @throws ReflectionException
109
+	 */
110
+	public function parent()
111
+	{
112
+		return $this->get('TKT_parent');
113
+	}
114
+
115
+
116
+	/**
117
+	 * return if a ticket has quantities available for purchase
118
+	 *
119
+	 * @param int $DTT_ID the primary key for a particular datetime
120
+	 * @return boolean
121
+	 * @throws EE_Error
122
+	 * @throws ReflectionException
123
+	 */
124
+	public function available($DTT_ID = 0)
125
+	{
126
+		// are we checking availability for a particular datetime ?
127
+		if ($DTT_ID) {
128
+			// get that datetime object
129
+			$datetime = $this->get_first_related('Datetime', [['DTT_ID' => $DTT_ID]]);
130
+			// if  ticket sales for this datetime have exceeded the reg limit...
131
+			if ($datetime instanceof EE_Datetime && $datetime->sold_out()) {
132
+				return false;
133
+			}
134
+		}
135
+		// datetime is still open for registration, but is this ticket sold out ?
136
+		return $this->qty() < 1 || $this->qty() > $this->sold();
137
+	}
138
+
139
+
140
+	/**
141
+	 * Using the start date and end date this method calculates whether the ticket is On Sale, Pending, or Expired
142
+	 *
143
+	 * @param bool        $display   true = we'll return a localized string, otherwise we just return the value of the
144
+	 *                               relevant status const
145
+	 * @param bool | null $remaining if it is already known that tickets are available, then simply pass a bool to save
146
+	 *                               further processing
147
+	 * @return mixed status int if the display string isn't requested
148
+	 * @throws EE_Error
149
+	 * @throws ReflectionException
150
+	 */
151
+	public function ticket_status($display = false, $remaining = null)
152
+	{
153
+		$remaining = is_bool($remaining) ? $remaining : $this->is_remaining();
154
+		if (! $remaining) {
155
+			return $display ? EEH_Template::pretty_status(EE_Ticket::sold_out, false, 'sentence') : EE_Ticket::sold_out;
156
+		}
157
+		if ($this->get('TKT_deleted')) {
158
+			return $display ? EEH_Template::pretty_status(EE_Ticket::archived, false, 'sentence') : EE_Ticket::archived;
159
+		}
160
+		if ($this->is_expired()) {
161
+			return $display ? EEH_Template::pretty_status(EE_Ticket::expired, false, 'sentence') : EE_Ticket::expired;
162
+		}
163
+		if ($this->is_pending()) {
164
+			return $display ? EEH_Template::pretty_status(EE_Ticket::pending, false, 'sentence') : EE_Ticket::pending;
165
+		}
166
+		if ($this->is_on_sale()) {
167
+			return $display ? EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence') : EE_Ticket::onsale;
168
+		}
169
+		return '';
170
+	}
171
+
172
+
173
+	/**
174
+	 * The purpose of this method is to simply return a boolean for whether there are any tickets remaining for sale
175
+	 * considering ALL the factors used for figuring that out.
176
+	 *
177
+	 * @access public
178
+	 * @param int $DTT_ID if an int above 0 is included here then we get a specific dtt.
179
+	 * @return boolean         true = tickets remaining, false not.
180
+	 * @throws EE_Error
181
+	 * @throws ReflectionException
182
+	 */
183
+	public function is_remaining($DTT_ID = 0)
184
+	{
185
+		$num_remaining = $this->remaining($DTT_ID);
186
+		if ($num_remaining === 0) {
187
+			return false;
188
+		}
189
+		if ($num_remaining > 0 && $num_remaining < $this->min()) {
190
+			return false;
191
+		}
192
+		return true;
193
+	}
194
+
195
+
196
+	/**
197
+	 * return the total number of tickets available for purchase
198
+	 *
199
+	 * @param int $DTT_ID  the primary key for a particular datetime.
200
+	 *                     set to 0 for all related datetimes
201
+	 * @return int
202
+	 * @throws EE_Error
203
+	 * @throws ReflectionException
204
+	 */
205
+	public function remaining($DTT_ID = 0)
206
+	{
207
+		return $this->real_quantity_on_ticket('saleable', $DTT_ID);
208
+	}
209
+
210
+
211
+	/**
212
+	 * Gets min
213
+	 *
214
+	 * @return int
215
+	 * @throws EE_Error
216
+	 * @throws ReflectionException
217
+	 */
218
+	public function min()
219
+	{
220
+		return $this->get('TKT_min');
221
+	}
222
+
223
+
224
+	/**
225
+	 * return if a ticket is no longer available cause its available dates have expired.
226
+	 *
227
+	 * @return boolean
228
+	 * @throws EE_Error
229
+	 * @throws ReflectionException
230
+	 */
231
+	public function is_expired()
232
+	{
233
+		return ($this->get_raw('TKT_end_date') < time());
234
+	}
235
+
236
+
237
+	/**
238
+	 * Return if a ticket is yet to go on sale or not
239
+	 *
240
+	 * @return boolean
241
+	 * @throws EE_Error
242
+	 * @throws ReflectionException
243
+	 */
244
+	public function is_pending()
245
+	{
246
+		return ($this->get_raw('TKT_start_date') >= time());
247
+	}
248
+
249
+
250
+	/**
251
+	 * Return if a ticket is on sale or not
252
+	 *
253
+	 * @return boolean
254
+	 * @throws EE_Error
255
+	 * @throws ReflectionException
256
+	 */
257
+	public function is_on_sale()
258
+	{
259
+		return ($this->get_raw('TKT_start_date') <= time() && $this->get_raw('TKT_end_date') >= time());
260
+	}
261
+
262
+
263
+	/**
264
+	 * This returns the chronologically last datetime that this ticket is associated with
265
+	 *
266
+	 * @param string $date_format
267
+	 * @param string $conjunction - conjunction junction what's your function ? this string joins the start date with
268
+	 *                            the end date ie: Jan 01 "to" Dec 31
269
+	 * @return string
270
+	 * @throws EE_Error
271
+	 * @throws ReflectionException
272
+	 */
273
+	public function date_range($date_format = '', $conjunction = ' - ')
274
+	{
275
+		$date_format = ! empty($date_format) ? $date_format : $this->_dt_frmt;
276
+		$first_date  = $this->first_datetime() instanceof EE_Datetime
277
+			? $this->first_datetime()->get_i18n_datetime('DTT_EVT_start', $date_format)
278
+			: '';
279
+		$last_date   = $this->last_datetime() instanceof EE_Datetime
280
+			? $this->last_datetime()->get_i18n_datetime('DTT_EVT_end', $date_format)
281
+			: '';
282
+
283
+		return $first_date && $last_date ? $first_date . $conjunction . $last_date : '';
284
+	}
285
+
286
+
287
+	/**
288
+	 * This returns the chronologically first datetime that this ticket is associated with
289
+	 *
290
+	 * @return EE_Datetime
291
+	 * @throws EE_Error
292
+	 * @throws ReflectionException
293
+	 */
294
+	public function first_datetime()
295
+	{
296
+		$datetimes = $this->datetimes(['limit' => 1]);
297
+		return reset($datetimes);
298
+	}
299
+
300
+
301
+	/**
302
+	 * Gets all the datetimes this ticket can be used for attending.
303
+	 * Unless otherwise specified, orders datetimes by start date.
304
+	 *
305
+	 * @param array $query_params @see
306
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
307
+	 * @return EE_Datetime[]|EE_Base_Class[]
308
+	 * @throws EE_Error
309
+	 * @throws ReflectionException
310
+	 */
311
+	public function datetimes($query_params = [])
312
+	{
313
+		if (! isset($query_params['order_by'])) {
314
+			$query_params['order_by']['DTT_order'] = 'ASC';
315
+		}
316
+		return $this->get_many_related('Datetime', $query_params);
317
+	}
318
+
319
+
320
+	/**
321
+	 * This returns the chronologically last datetime that this ticket is associated with
322
+	 *
323
+	 * @return EE_Datetime
324
+	 * @throws EE_Error
325
+	 * @throws ReflectionException
326
+	 */
327
+	public function last_datetime()
328
+	{
329
+		$datetimes = $this->datetimes(['limit' => 1, 'order_by' => ['DTT_EVT_start' => 'DESC']]);
330
+		return end($datetimes);
331
+	}
332
+
333
+
334
+	/**
335
+	 * This returns the total tickets sold depending on the given parameters.
336
+	 *
337
+	 * @param string $what    Can be one of two options: 'ticket', 'datetime'.
338
+	 *                        'ticket' = total ticket sales for all datetimes this ticket is related to
339
+	 *                        'datetime' = total ticket sales for a specified datetime (required $dtt_id)
340
+	 *                        'datetime' = total ticket sales in the datetime_ticket table.
341
+	 *                        If $dtt_id is not given then we return an array of sales indexed by datetime.
342
+	 *                        If $dtt_id IS given then we return the tickets sold for that given datetime.
343
+	 * @param int    $dtt_id  [optional] include the dtt_id with $what = 'datetime'.
344
+	 * @return mixed (array|int)          how many tickets have sold
345
+	 * @throws EE_Error
346
+	 * @throws ReflectionException
347
+	 */
348
+	public function tickets_sold($what = 'ticket', $dtt_id = null)
349
+	{
350
+		$total        = 0;
351
+		$tickets_sold = $this->_all_tickets_sold();
352
+		switch ($what) {
353
+			case 'ticket':
354
+				return $tickets_sold['ticket'];
355
+				break;
356
+			case 'datetime':
357
+				if (empty($tickets_sold['datetime'])) {
358
+					return $total;
359
+				}
360
+				if (! empty($dtt_id) && ! isset($tickets_sold['datetime'][ $dtt_id ])) {
361
+					EE_Error::add_error(
362
+						__(
363
+							'You\'ve requested the amount of tickets sold for a given ticket and datetime, however there are no records for the datetime id you included.  Are you SURE that is a datetime related to this ticket?',
364
+							'event_espresso'
365
+						),
366
+						__FILE__,
367
+						__FUNCTION__,
368
+						__LINE__
369
+					);
370
+					return $total;
371
+				}
372
+				return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][ $dtt_id ];
373
+				break;
374
+			default:
375
+				return $total;
376
+		}
377
+	}
378
+
379
+
380
+	/**
381
+	 * This returns an array indexed by datetime_id for tickets sold with this ticket.
382
+	 *
383
+	 * @return EE_Ticket[]
384
+	 * @throws EE_Error
385
+	 * @throws ReflectionException
386
+	 */
387
+	protected function _all_tickets_sold()
388
+	{
389
+		$datetimes    = $this->get_many_related('Datetime');
390
+		$tickets_sold = [];
391
+		if (! empty($datetimes)) {
392
+			foreach ($datetimes as $datetime) {
393
+				$tickets_sold['datetime'][ $datetime->ID() ] = $datetime->get('DTT_sold');
394
+			}
395
+		}
396
+		// Tickets sold
397
+		$tickets_sold['ticket'] = $this->sold();
398
+		return $tickets_sold;
399
+	}
400
+
401
+
402
+	/**
403
+	 * This returns the base price object for the ticket.
404
+	 *
405
+	 * @param bool $return_array whether to return as an array indexed by price id or just the object.
406
+	 * @return EE_Price|EE_Base_Class|EE_Price[]|EE_Base_Class[]
407
+	 * @throws EE_Error
408
+	 * @throws ReflectionException
409
+	 */
410
+	public function base_price($return_array = false)
411
+	{
412
+		$_where = ['Price_Type.PBT_ID' => EEM_Price_Type::base_type_base_price];
413
+		return $return_array
414
+			? $this->get_many_related('Price', [$_where])
415
+			: $this->get_first_related('Price', [$_where]);
416
+	}
417
+
418
+
419
+	/**
420
+	 * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price)
421
+	 *
422
+	 * @access public
423
+	 * @return EE_Price[]
424
+	 * @throws EE_Error
425
+	 * @throws ReflectionException
426
+	 */
427
+	public function price_modifiers()
428
+	{
429
+		$query_params = [
430
+			0 => [
431
+				'Price_Type.PBT_ID' => [
432
+					'NOT IN',
433
+					[EEM_Price_Type::base_type_base_price, EEM_Price_Type::base_type_tax],
434
+				],
435
+			],
436
+		];
437
+		return $this->prices($query_params);
438
+	}
439
+
440
+
441
+	/**
442
+	 * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price)
443
+	 *
444
+	 * @access public
445
+	 * @return EE_Price[]
446
+	 * @throws EE_Error
447
+	 * @throws ReflectionException
448
+	 */
449
+	public function tax_price_modifiers()
450
+	{
451
+		$query_params = [
452
+			0 => [
453
+				'Price_Type.PBT_ID' => EEM_Price_Type::base_type_tax,
454
+			],
455
+		];
456
+		return $this->prices($query_params);
457
+	}
458
+
459
+
460
+	/**
461
+	 * Gets all the prices that combine to form the final price of this ticket
462
+	 *
463
+	 * @param array $query_params @see
464
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
465
+	 * @return EE_Price[]|EE_Base_Class[]
466
+	 * @throws EE_Error
467
+	 * @throws ReflectionException
468
+	 */
469
+	public function prices($query_params = [])
470
+	{
471
+		return $this->get_many_related('Price', $query_params);
472
+	}
473
+
474
+
475
+	/**
476
+	 * Gets all the ticket datetimes (ie, relations between datetimes and tickets)
477
+	 *
478
+	 * @param array $query_params @see
479
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
480
+	 * @return EE_Datetime_Ticket|EE_Base_Class[]
481
+	 * @throws EE_Error
482
+	 * @throws ReflectionException
483
+	 */
484
+	public function datetime_tickets($query_params = [])
485
+	{
486
+		return $this->get_many_related('Datetime_Ticket', $query_params);
487
+	}
488
+
489
+
490
+	/**
491
+	 * Gets all the datetimes from the db ordered by DTT_order
492
+	 *
493
+	 * @param boolean $show_expired
494
+	 * @param boolean $show_deleted
495
+	 * @return EE_Datetime[]
496
+	 * @throws EE_Error
497
+	 * @throws ReflectionException
498
+	 */
499
+	public function datetimes_ordered($show_expired = true, $show_deleted = false)
500
+	{
501
+		return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_ticket_ordered_by_DTT_order(
502
+			$this->ID(),
503
+			$show_expired,
504
+			$show_deleted
505
+		);
506
+	}
507
+
508
+
509
+	/**
510
+	 * Gets ID
511
+	 *
512
+	 * @return int
513
+	 * @throws EE_Error
514
+	 * @throws ReflectionException
515
+	 */
516
+	public function ID()
517
+	{
518
+		return $this->get('TKT_ID');
519
+	}
520
+
521
+
522
+	/**
523
+	 * get the author of the ticket.
524
+	 *
525
+	 * @return int
526
+	 * @throws EE_Error
527
+	 * @throws ReflectionException
528
+	 * @since 4.5.0
529
+	 */
530
+	public function wp_user()
531
+	{
532
+		return $this->get('TKT_wp_user');
533
+	}
534
+
535
+
536
+	/**
537
+	 * Gets the template for the ticket
538
+	 *
539
+	 * @return EE_Ticket_Template|EE_Base_Class
540
+	 * @throws EE_Error
541
+	 * @throws ReflectionException
542
+	 */
543
+	public function template()
544
+	{
545
+		return $this->get_first_related('Ticket_Template');
546
+	}
547
+
548
+
549
+	/**
550
+	 * Simply returns an array of EE_Price objects that are taxes.
551
+	 *
552
+	 * @return EE_Price[]
553
+	 * @throws EE_Error
554
+	 */
555
+	public function get_ticket_taxes_for_admin()
556
+	{
557
+		return EE_Taxes::get_taxes_for_admin();
558
+	}
559
+
560
+
561
+	/**
562
+	 * @return float
563
+	 * @throws EE_Error
564
+	 * @throws ReflectionException
565
+	 */
566
+	public function ticket_price()
567
+	{
568
+		return $this->get('TKT_price');
569
+	}
570
+
571
+
572
+	/**
573
+	 * @return mixed
574
+	 * @throws EE_Error
575
+	 * @throws ReflectionException
576
+	 */
577
+	public function pretty_price()
578
+	{
579
+		return $this->get_pretty('TKT_price');
580
+	}
581
+
582
+
583
+	/**
584
+	 * @return bool
585
+	 * @throws EE_Error
586
+	 * @throws ReflectionException
587
+	 */
588
+	public function is_free()
589
+	{
590
+		return $this->get_ticket_total_with_taxes() === (float) 0;
591
+	}
592
+
593
+
594
+	/**
595
+	 * get_ticket_total_with_taxes
596
+	 *
597
+	 * @param bool $no_cache
598
+	 * @return float
599
+	 * @throws EE_Error
600
+	 * @throws ReflectionException
601
+	 */
602
+	public function get_ticket_total_with_taxes($no_cache = false)
603
+	{
604
+		if ($this->_ticket_total_with_taxes === null || $no_cache) {
605
+			$this->_ticket_total_with_taxes = $this->get_ticket_subtotal() + $this->get_ticket_taxes_total_for_admin();
606
+		}
607
+		return (float) $this->_ticket_total_with_taxes;
608
+	}
609
+
610
+
611
+	/**
612
+	 * @throws EE_Error
613
+	 * @throws ReflectionException
614
+	 */
615
+	public function ensure_TKT_Price_correct()
616
+	{
617
+		$this->set('TKT_price', EE_Taxes::get_subtotal_for_admin($this));
618
+		$this->save();
619
+	}
620
+
621
+
622
+	/**
623
+	 * @return float
624
+	 * @throws EE_Error
625
+	 * @throws ReflectionException
626
+	 */
627
+	public function get_ticket_subtotal()
628
+	{
629
+		return EE_Taxes::get_subtotal_for_admin($this);
630
+	}
631
+
632
+
633
+	/**
634
+	 * Returns the total taxes applied to this ticket
635
+	 *
636
+	 * @return float
637
+	 * @throws EE_Error
638
+	 * @throws ReflectionException
639
+	 */
640
+	public function get_ticket_taxes_total_for_admin()
641
+	{
642
+		return EE_Taxes::get_total_taxes_for_admin($this);
643
+	}
644
+
645
+
646
+	/**
647
+	 * Sets name
648
+	 *
649
+	 * @param string $name
650
+	 * @throws EE_Error
651
+	 * @throws ReflectionException
652
+	 */
653
+	public function set_name($name)
654
+	{
655
+		$this->set('TKT_name', $name);
656
+	}
657
+
658
+
659
+	/**
660
+	 * Gets description
661
+	 *
662
+	 * @return string
663
+	 * @throws EE_Error
664
+	 * @throws ReflectionException
665
+	 */
666
+	public function description()
667
+	{
668
+		return $this->get('TKT_description');
669
+	}
670
+
671
+
672
+	/**
673
+	 * Sets description
674
+	 *
675
+	 * @param string $description
676
+	 * @throws EE_Error
677
+	 * @throws ReflectionException
678
+	 */
679
+	public function set_description($description)
680
+	{
681
+		$this->set('TKT_description', $description);
682
+	}
683
+
684
+
685
+	/**
686
+	 * Gets start_date
687
+	 *
688
+	 * @param string $date_format
689
+	 * @param string $time_format
690
+	 * @return string
691
+	 * @throws EE_Error
692
+	 * @throws ReflectionException
693
+	 */
694
+	public function start_date($date_format = '', $time_format = '')
695
+	{
696
+		return $this->_get_datetime('TKT_start_date', $date_format, $time_format);
697
+	}
698
+
699
+
700
+	/**
701
+	 * Sets start_date
702
+	 *
703
+	 * @param string $start_date
704
+	 * @return void
705
+	 * @throws EE_Error
706
+	 * @throws ReflectionException
707
+	 */
708
+	public function set_start_date($start_date)
709
+	{
710
+		$this->_set_date_time('B', $start_date, 'TKT_start_date');
711
+	}
712
+
713
+
714
+	/**
715
+	 * Gets end_date
716
+	 *
717
+	 * @param string $date_format
718
+	 * @param string $time_format
719
+	 * @return string
720
+	 * @throws EE_Error
721
+	 * @throws ReflectionException
722
+	 */
723
+	public function end_date($date_format = '', $time_format = '')
724
+	{
725
+		return $this->_get_datetime('TKT_end_date', $date_format, $time_format);
726
+	}
727
+
728
+
729
+	/**
730
+	 * Sets end_date
731
+	 *
732
+	 * @param string $end_date
733
+	 * @return void
734
+	 * @throws EE_Error
735
+	 * @throws ReflectionException
736
+	 */
737
+	public function set_end_date($end_date)
738
+	{
739
+		$this->_set_date_time('B', $end_date, 'TKT_end_date');
740
+	}
741
+
742
+
743
+	/**
744
+	 * Sets sell until time
745
+	 *
746
+	 * @param string $time a string representation of the sell until time (ex 9am or 7:30pm)
747
+	 * @throws EE_Error
748
+	 * @throws ReflectionException
749
+	 * @since 4.5.0
750
+	 */
751
+	public function set_end_time($time)
752
+	{
753
+		$this->_set_time_for($time, 'TKT_end_date');
754
+	}
755
+
756
+
757
+	/**
758
+	 * Sets min
759
+	 *
760
+	 * @param int $min
761
+	 * @return void
762
+	 * @throws EE_Error
763
+	 * @throws ReflectionException
764
+	 */
765
+	public function set_min($min)
766
+	{
767
+		$this->set('TKT_min', $min);
768
+	}
769
+
770
+
771
+	/**
772
+	 * Gets max
773
+	 *
774
+	 * @return int
775
+	 * @throws EE_Error
776
+	 * @throws ReflectionException
777
+	 */
778
+	public function max()
779
+	{
780
+		return $this->get('TKT_max');
781
+	}
782
+
783
+
784
+	/**
785
+	 * Sets max
786
+	 *
787
+	 * @param int $max
788
+	 * @return void
789
+	 * @throws EE_Error
790
+	 * @throws ReflectionException
791
+	 */
792
+	public function set_max($max)
793
+	{
794
+		$this->set('TKT_max', $max);
795
+	}
796
+
797
+
798
+	/**
799
+	 * Sets price
800
+	 *
801
+	 * @param float $price
802
+	 * @return void
803
+	 * @throws EE_Error
804
+	 * @throws ReflectionException
805
+	 */
806
+	public function set_price($price)
807
+	{
808
+		$this->set('TKT_price', $price);
809
+	}
810
+
811
+
812
+	/**
813
+	 * Gets sold
814
+	 *
815
+	 * @return int
816
+	 * @throws EE_Error
817
+	 * @throws ReflectionException
818
+	 */
819
+	public function sold()
820
+	{
821
+		return $this->get_raw('TKT_sold');
822
+	}
823
+
824
+
825
+	/**
826
+	 * Sets sold
827
+	 *
828
+	 * @param int $sold
829
+	 * @return void
830
+	 * @throws EE_Error
831
+	 * @throws ReflectionException
832
+	 */
833
+	public function set_sold($sold)
834
+	{
835
+		// sold can not go below zero
836
+		$sold = max(0, $sold);
837
+		$this->set('TKT_sold', $sold);
838
+	}
839
+
840
+
841
+	/**
842
+	 * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
843
+	 * associated datetimes.
844
+	 *
845
+	 * @param int $qty
846
+	 * @return boolean
847
+	 * @throws EE_Error
848
+	 * @throws InvalidArgumentException
849
+	 * @throws InvalidDataTypeException
850
+	 * @throws InvalidInterfaceException
851
+	 * @throws ReflectionException
852
+	 * @since 4.9.80.p
853
+	 */
854
+	public function increaseSold($qty = 1)
855
+	{
856
+		$qty = absint($qty);
857
+		// increment sold and decrement reserved datetime quantities simultaneously
858
+		// don't worry about failures, because they must have already had a spot reserved
859
+		$this->increaseSoldForDatetimes($qty);
860
+		// Increment and decrement ticket quantities simultaneously
861
+		$success = $this->adjustNumericFieldsInDb(
862
+			[
863
+				'TKT_reserved' => $qty * -1,
864
+				'TKT_sold'     => $qty,
865
+			]
866
+		);
867
+		do_action(
868
+			'AHEE__EE_Ticket__increase_sold',
869
+			$this,
870
+			$qty,
871
+			$this->sold(),
872
+			$success
873
+		);
874
+		return $success;
875
+	}
876
+
877
+
878
+	/**
879
+	 * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
880
+	 *
881
+	 * @param int           $qty positive or negative. Positive means to increase sold counts (and decrease reserved
882
+	 *                           counts), Negative means to decreases old counts (and increase reserved counts).
883
+	 * @param EE_Datetime[] $datetimes
884
+	 * @throws EE_Error
885
+	 * @throws InvalidArgumentException
886
+	 * @throws InvalidDataTypeException
887
+	 * @throws InvalidInterfaceException
888
+	 * @throws ReflectionException
889
+	 * @since 4.9.80.p
890
+	 */
891
+	protected function increaseSoldForDatetimes($qty, array $datetimes = [])
892
+	{
893
+		$datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
894
+		foreach ($datetimes as $datetime) {
895
+			$datetime->increaseSold($qty);
896
+		}
897
+	}
898
+
899
+
900
+	/**
901
+	 * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
902
+	 * DB and then updates the model objects.
903
+	 * Does not affect the reserved counts.
904
+	 *
905
+	 * @param int $qty
906
+	 * @return boolean
907
+	 * @throws EE_Error
908
+	 * @throws InvalidArgumentException
909
+	 * @throws InvalidDataTypeException
910
+	 * @throws InvalidInterfaceException
911
+	 * @throws ReflectionException
912
+	 * @since 4.9.80.p
913
+	 */
914
+	public function decreaseSold($qty = 1)
915
+	{
916
+		$qty = absint($qty);
917
+		$this->decreaseSoldForDatetimes($qty);
918
+		$success = $this->adjustNumericFieldsInDb(
919
+			[
920
+				'TKT_sold' => $qty * -1,
921
+			]
922
+		);
923
+		do_action(
924
+			'AHEE__EE_Ticket__decrease_sold',
925
+			$this,
926
+			$qty,
927
+			$this->sold(),
928
+			$success
929
+		);
930
+		return $success;
931
+	}
932
+
933
+
934
+	/**
935
+	 * Decreases sold on related datetimes
936
+	 *
937
+	 * @param int           $qty
938
+	 * @param EE_Datetime[] $datetimes
939
+	 * @return void
940
+	 * @throws EE_Error
941
+	 * @throws InvalidArgumentException
942
+	 * @throws InvalidDataTypeException
943
+	 * @throws InvalidInterfaceException
944
+	 * @throws ReflectionException
945
+	 * @since 4.9.80.p
946
+	 */
947
+	protected function decreaseSoldForDatetimes($qty = 1, array $datetimes = [])
948
+	{
949
+		$datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
950
+		if (is_array($datetimes)) {
951
+			foreach ($datetimes as $datetime) {
952
+				if ($datetime instanceof EE_Datetime) {
953
+					$datetime->decreaseSold($qty);
954
+				}
955
+			}
956
+		}
957
+	}
958
+
959
+
960
+	/**
961
+	 * Gets qty of reserved tickets
962
+	 *
963
+	 * @return int
964
+	 * @throws EE_Error
965
+	 * @throws ReflectionException
966
+	 */
967
+	public function reserved()
968
+	{
969
+		return $this->get_raw('TKT_reserved');
970
+	}
971
+
972
+
973
+	/**
974
+	 * Sets reserved
975
+	 *
976
+	 * @param int $reserved
977
+	 * @return void
978
+	 * @throws EE_Error
979
+	 * @throws ReflectionException
980
+	 */
981
+	public function set_reserved($reserved)
982
+	{
983
+		// reserved can not go below zero
984
+		$reserved = max(0, (int) $reserved);
985
+		$this->set('TKT_reserved', $reserved);
986
+	}
987
+
988
+
989
+	/**
990
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
991
+	 *
992
+	 * @param int    $qty
993
+	 * @param string $source
994
+	 * @return bool whether we successfully reserved the ticket or not.
995
+	 * @throws EE_Error
996
+	 * @throws InvalidArgumentException
997
+	 * @throws ReflectionException
998
+	 * @throws InvalidDataTypeException
999
+	 * @throws InvalidInterfaceException
1000
+	 * @since 4.9.80.p
1001
+	 */
1002
+	public function increaseReserved($qty = 1, $source = 'unknown')
1003
+	{
1004
+		$qty = absint($qty);
1005
+		do_action(
1006
+			'AHEE__EE_Ticket__increase_reserved__begin',
1007
+			$this,
1008
+			$qty,
1009
+			$source
1010
+		);
1011
+		$this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "{$qty} from {$source}");
1012
+		$success                         = false;
1013
+		$datetimes_adjusted_successfully = $this->increaseReservedForDatetimes($qty);
1014
+		if ($datetimes_adjusted_successfully) {
1015
+			$success = $this->incrementFieldConditionallyInDb(
1016
+				'TKT_reserved',
1017
+				'TKT_sold',
1018
+				'TKT_qty',
1019
+				$qty
1020
+			);
1021
+			if (! $success) {
1022
+				// The datetimes were successfully bumped, but not the
1023
+				// ticket. So we need to manually rollback the datetimes.
1024
+				$this->decreaseReservedForDatetimes($qty);
1025
+			}
1026
+		}
1027
+		do_action(
1028
+			'AHEE__EE_Ticket__increase_reserved',
1029
+			$this,
1030
+			$qty,
1031
+			$this->reserved(),
1032
+			$success
1033
+		);
1034
+		return $success;
1035
+	}
1036
+
1037
+
1038
+	/**
1039
+	 * Increases reserved counts on related datetimes
1040
+	 *
1041
+	 * @param int           $qty
1042
+	 * @param EE_Datetime[] $datetimes
1043
+	 * @return boolean indicating success
1044
+	 * @throws EE_Error
1045
+	 * @throws InvalidArgumentException
1046
+	 * @throws InvalidDataTypeException
1047
+	 * @throws InvalidInterfaceException
1048
+	 * @throws ReflectionException
1049
+	 * @since 4.9.80.p
1050
+	 */
1051
+	protected function increaseReservedForDatetimes($qty = 1, array $datetimes = [])
1052
+	{
1053
+		$datetimes         = ! empty($datetimes) ? $datetimes : $this->datetimes();
1054
+		$datetimes_updated = [];
1055
+		$limit_exceeded    = false;
1056
+		if (is_array($datetimes)) {
1057
+			foreach ($datetimes as $datetime) {
1058
+				if ($datetime instanceof EE_Datetime) {
1059
+					if ($datetime->increaseReserved($qty)) {
1060
+						$datetimes_updated[] = $datetime;
1061
+					} else {
1062
+						$limit_exceeded = true;
1063
+						break;
1064
+					}
1065
+				}
1066
+			}
1067
+			// If somewhere along the way we detected a datetime whose
1068
+			// limit was exceeded, do a manual rollback.
1069
+			if ($limit_exceeded) {
1070
+				$this->decreaseReservedForDatetimes($qty, $datetimes_updated);
1071
+				return false;
1072
+			}
1073
+		}
1074
+		return true;
1075
+	}
1076
+
1077
+
1078
+	/**
1079
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1080
+	 *
1081
+	 * @param int    $qty
1082
+	 * @param bool   $adjust_datetimes
1083
+	 * @param string $source
1084
+	 * @return boolean
1085
+	 * @throws EE_Error
1086
+	 * @throws InvalidArgumentException
1087
+	 * @throws ReflectionException
1088
+	 * @throws InvalidDataTypeException
1089
+	 * @throws InvalidInterfaceException
1090
+	 * @since 4.9.80.p
1091
+	 */
1092
+	public function decreaseReserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
1093
+	{
1094
+		$qty = absint($qty);
1095
+		$this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "-{$qty} from {$source}");
1096
+		if ($adjust_datetimes) {
1097
+			$this->decreaseReservedForDatetimes($qty);
1098
+		}
1099
+		$success = $this->adjustNumericFieldsInDb(
1100
+			[
1101
+				'TKT_reserved' => $qty * -1,
1102
+			]
1103
+		);
1104
+		do_action(
1105
+			'AHEE__EE_Ticket__decrease_reserved',
1106
+			$this,
1107
+			$qty,
1108
+			$this->reserved(),
1109
+			$success
1110
+		);
1111
+		return $success;
1112
+	}
1113
+
1114
+
1115
+	/**
1116
+	 * Decreases the reserved count on the specified datetimes.
1117
+	 *
1118
+	 * @param int           $qty
1119
+	 * @param EE_Datetime[] $datetimes
1120
+	 * @throws EE_Error
1121
+	 * @throws InvalidArgumentException
1122
+	 * @throws ReflectionException
1123
+	 * @throws InvalidDataTypeException
1124
+	 * @throws InvalidInterfaceException
1125
+	 * @since 4.9.80.p
1126
+	 */
1127
+	protected function decreaseReservedForDatetimes($qty = 1, array $datetimes = [])
1128
+	{
1129
+		$datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
1130
+		foreach ($datetimes as $datetime) {
1131
+			if ($datetime instanceof EE_Datetime) {
1132
+				$datetime->decreaseReserved($qty);
1133
+			}
1134
+		}
1135
+	}
1136
+
1137
+
1138
+	/**
1139
+	 * Gets ticket quantity
1140
+	 *
1141
+	 * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1142
+	 *                            therefore $context can be one of three values: '', 'reg_limit', or 'saleable'
1143
+	 *                            '' (default) quantity is the actual db value for TKT_qty, unaffected by other objects
1144
+	 *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1145
+	 *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1146
+	 *                            is therefore the truest measure of tickets that can be purchased at the moment
1147
+	 * @return int
1148
+	 * @throws EE_Error
1149
+	 * @throws ReflectionException
1150
+	 */
1151
+	public function qty($context = '')
1152
+	{
1153
+		switch ($context) {
1154
+			case 'reg_limit':
1155
+				return $this->real_quantity_on_ticket();
1156
+			case 'saleable':
1157
+				return $this->real_quantity_on_ticket('saleable');
1158
+			default:
1159
+				return $this->get_raw('TKT_qty');
1160
+		}
1161
+	}
1162
+
1163
+
1164
+	/**
1165
+	 * Gets ticket quantity
1166
+	 *
1167
+	 * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1168
+	 *                            therefore $context can be one of two values: 'reg_limit', or 'saleable'
1169
+	 *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1170
+	 *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1171
+	 *                            is therefore the truest measure of tickets that can be purchased at the moment
1172
+	 * @param int    $DTT_ID      the primary key for a particular datetime.
1173
+	 *                            set to 0 for all related datetimes
1174
+	 * @return int
1175
+	 * @throws EE_Error
1176
+	 * @throws ReflectionException
1177
+	 */
1178
+	public function real_quantity_on_ticket($context = 'reg_limit', $DTT_ID = 0)
1179
+	{
1180
+		$raw = $this->get_raw('TKT_qty');
1181
+		// return immediately if it's zero
1182
+		if ($raw === 0) {
1183
+			return $raw;
1184
+		}
1185
+		// echo "\n\n<br />Ticket: " . $this->name() . '<br />';
1186
+		// ensure qty doesn't exceed raw value for THIS ticket
1187
+		$qty = min(EE_INF, $raw);
1188
+		// echo "\n . qty: " . $qty . '<br />';
1189
+		// calculate this ticket's total sales and reservations
1190
+		$sold_and_reserved_for_this_ticket = $this->sold() + $this->reserved();
1191
+		// echo "\n . sold: " . $this->sold() . '<br />';
1192
+		// echo "\n . reserved: " . $this->reserved() . '<br />';
1193
+		// echo "\n . sold_and_reserved_for_this_ticket: " . $sold_and_reserved_for_this_ticket . '<br />';
1194
+		// first we need to calculate the maximum number of tickets available for the datetime
1195
+		// do we want data for one datetime or all of them ?
1196
+		$query_params = $DTT_ID ? [['DTT_ID' => $DTT_ID]] : [];
1197
+		$datetimes    = $this->datetimes($query_params);
1198
+		if (is_array($datetimes) && ! empty($datetimes)) {
1199
+			foreach ($datetimes as $datetime) {
1200
+				if ($datetime instanceof EE_Datetime) {
1201
+					$datetime->refresh_from_db();
1202
+					// echo "\n . . datetime name: " . $datetime->name() . '<br />';
1203
+					// echo "\n . . datetime ID: " . $datetime->ID() . '<br />';
1204
+					// initialize with no restrictions for each datetime
1205
+					// but adjust datetime qty based on datetime reg limit
1206
+					$datetime_qty = min(EE_INF, $datetime->reg_limit());
1207
+					// echo "\n . . . datetime reg_limit: " . $datetime->reg_limit() . '<br />';
1208
+					// echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1209
+					// if we want the actual saleable amount, then we need to consider OTHER ticket sales
1210
+					// and reservations for this datetime, that do NOT include sales and reservations
1211
+					// for this ticket (so we add $this->sold() and $this->reserved() back in)
1212
+					if ($context === 'saleable') {
1213
+						$datetime_qty = max(
1214
+							$datetime_qty - $datetime->sold_and_reserved() + $sold_and_reserved_for_this_ticket,
1215
+							0
1216
+						);
1217
+						// echo "\n . . . datetime sold: " . $datetime->sold() . '<br />';
1218
+						// echo "\n . . . datetime reserved: " . $datetime->reserved() . '<br />';
1219
+						// echo "\n . . . datetime sold_and_reserved: " . $datetime->sold_and_reserved() . '<br />';
1220
+						// echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1221
+						$datetime_qty = ! $datetime->sold_out() ? $datetime_qty : 0;
1222
+						// echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1223
+					}
1224
+					$qty = min($datetime_qty, $qty);
1225
+					// echo "\n . . qty: " . $qty . '<br />';
1226
+				}
1227
+			}
1228
+		}
1229
+		// NOW that we know the  maximum number of tickets available for the datetime
1230
+		// we can finally factor in the details for this specific ticket
1231
+		if ($qty > 0 && $context === 'saleable') {
1232
+			// and subtract the sales for THIS ticket
1233
+			$qty = max($qty - $sold_and_reserved_for_this_ticket, 0);
1234
+			// echo "\n . qty: " . $qty . '<br />';
1235
+		}
1236
+		// echo "\nFINAL QTY: " . $qty . "<br /><br />";
1237
+		return $qty;
1238
+	}
1239
+
1240
+
1241
+	/**
1242
+	 * Sets qty - IMPORTANT!!! Does NOT allow QTY to be set higher than the lowest reg limit of any related datetimes
1243
+	 *
1244
+	 * @param int $qty
1245
+	 * @return void
1246
+	 * @throws EE_Error
1247
+	 * @throws ReflectionException
1248
+	 */
1249
+	public function set_qty($qty)
1250
+	{
1251
+		$datetimes = $this->datetimes();
1252
+		foreach ($datetimes as $datetime) {
1253
+			if ($datetime instanceof EE_Datetime) {
1254
+				$qty = min($qty, $datetime->reg_limit());
1255
+			}
1256
+		}
1257
+		$this->set('TKT_qty', $qty);
1258
+	}
1259
+
1260
+
1261
+	/**
1262
+	 * Gets uses
1263
+	 *
1264
+	 * @return int
1265
+	 * @throws EE_Error
1266
+	 * @throws ReflectionException
1267
+	 */
1268
+	public function uses()
1269
+	{
1270
+		return $this->get('TKT_uses');
1271
+	}
1272
+
1273
+
1274
+	/**
1275
+	 * Sets uses
1276
+	 *
1277
+	 * @param int $uses
1278
+	 * @return void
1279
+	 * @throws EE_Error
1280
+	 * @throws ReflectionException
1281
+	 */
1282
+	public function set_uses($uses)
1283
+	{
1284
+		$this->set('TKT_uses', $uses);
1285
+	}
1286
+
1287
+
1288
+	/**
1289
+	 * returns whether ticket is required or not.
1290
+	 *
1291
+	 * @return boolean
1292
+	 * @throws EE_Error
1293
+	 * @throws ReflectionException
1294
+	 */
1295
+	public function required()
1296
+	{
1297
+		return $this->get('TKT_required');
1298
+	}
1299
+
1300
+
1301
+	/**
1302
+	 * sets the TKT_required property
1303
+	 *
1304
+	 * @param boolean $required
1305
+	 * @return void
1306
+	 * @throws EE_Error
1307
+	 * @throws ReflectionException
1308
+	 */
1309
+	public function set_required($required)
1310
+	{
1311
+		$this->set('TKT_required', $required);
1312
+	}
1313
+
1314
+
1315
+	/**
1316
+	 * Gets taxable
1317
+	 *
1318
+	 * @return boolean
1319
+	 * @throws EE_Error
1320
+	 * @throws ReflectionException
1321
+	 */
1322
+	public function taxable()
1323
+	{
1324
+		return $this->get('TKT_taxable');
1325
+	}
1326
+
1327
+
1328
+	/**
1329
+	 * Sets taxable
1330
+	 *
1331
+	 * @param boolean $taxable
1332
+	 * @return void
1333
+	 * @throws EE_Error
1334
+	 * @throws ReflectionException
1335
+	 */
1336
+	public function set_taxable($taxable)
1337
+	{
1338
+		$this->set('TKT_taxable', $taxable);
1339
+	}
1340
+
1341
+
1342
+	/**
1343
+	 * Gets is_default
1344
+	 *
1345
+	 * @return boolean
1346
+	 * @throws EE_Error
1347
+	 * @throws ReflectionException
1348
+	 */
1349
+	public function is_default()
1350
+	{
1351
+		return $this->get('TKT_is_default');
1352
+	}
1353
+
1354
+
1355
+	/**
1356
+	 * Sets is_default
1357
+	 *
1358
+	 * @param boolean $is_default
1359
+	 * @return void
1360
+	 * @throws EE_Error
1361
+	 * @throws ReflectionException
1362
+	 */
1363
+	public function set_is_default($is_default)
1364
+	{
1365
+		$this->set('TKT_is_default', $is_default);
1366
+	}
1367
+
1368
+
1369
+	/**
1370
+	 * Gets order
1371
+	 *
1372
+	 * @return int
1373
+	 * @throws EE_Error
1374
+	 * @throws ReflectionException
1375
+	 */
1376
+	public function order()
1377
+	{
1378
+		return $this->get('TKT_order');
1379
+	}
1380
+
1381
+
1382
+	/**
1383
+	 * Sets order
1384
+	 *
1385
+	 * @param int $order
1386
+	 * @return void
1387
+	 * @throws EE_Error
1388
+	 * @throws ReflectionException
1389
+	 */
1390
+	public function set_order($order)
1391
+	{
1392
+		$this->set('TKT_order', $order);
1393
+	}
1394
+
1395
+
1396
+	/**
1397
+	 * Gets row
1398
+	 *
1399
+	 * @return int
1400
+	 * @throws EE_Error
1401
+	 * @throws ReflectionException
1402
+	 */
1403
+	public function row()
1404
+	{
1405
+		return $this->get('TKT_row');
1406
+	}
1407
+
1408
+
1409
+	/**
1410
+	 * Sets row
1411
+	 *
1412
+	 * @param int $row
1413
+	 * @return void
1414
+	 * @throws EE_Error
1415
+	 * @throws ReflectionException
1416
+	 */
1417
+	public function set_row($row)
1418
+	{
1419
+		$this->set('TKT_row', $row);
1420
+	}
1421
+
1422
+
1423
+	/**
1424
+	 * Gets deleted
1425
+	 *
1426
+	 * @return boolean
1427
+	 * @throws EE_Error
1428
+	 * @throws ReflectionException
1429
+	 */
1430
+	public function deleted()
1431
+	{
1432
+		return $this->get('TKT_deleted');
1433
+	}
1434
+
1435
+
1436
+	/**
1437
+	 * Sets deleted
1438
+	 *
1439
+	 * @param boolean $deleted
1440
+	 * @return void
1441
+	 * @throws EE_Error
1442
+	 * @throws ReflectionException
1443
+	 */
1444
+	public function set_deleted($deleted)
1445
+	{
1446
+		$this->set('TKT_deleted', $deleted);
1447
+	}
1448
+
1449
+
1450
+	/**
1451
+	 * Gets parent
1452
+	 *
1453
+	 * @return int
1454
+	 * @throws EE_Error
1455
+	 * @throws ReflectionException
1456
+	 */
1457
+	public function parent_ID()
1458
+	{
1459
+		return $this->get('TKT_parent');
1460
+	}
1461
+
1462
+
1463
+	/**
1464
+	 * Sets parent
1465
+	 *
1466
+	 * @param int $parent
1467
+	 * @return void
1468
+	 * @throws EE_Error
1469
+	 * @throws ReflectionException
1470
+	 */
1471
+	public function set_parent_ID($parent)
1472
+	{
1473
+		$this->set('TKT_parent', $parent);
1474
+	}
1475
+
1476
+
1477
+	/**
1478
+	 * @return boolean
1479
+	 * @throws EE_Error
1480
+	 * @throws InvalidArgumentException
1481
+	 * @throws InvalidDataTypeException
1482
+	 * @throws InvalidInterfaceException
1483
+	 * @throws ReflectionException
1484
+	 */
1485
+	public function reverse_calculate()
1486
+	{
1487
+		return $this->get('TKT_reverse_calculate');
1488
+	}
1489
+
1490
+
1491
+	/**
1492
+	 * @param boolean $reverse_calculate
1493
+	 * @throws EE_Error
1494
+	 * @throws InvalidArgumentException
1495
+	 * @throws InvalidDataTypeException
1496
+	 * @throws InvalidInterfaceException
1497
+	 * @throws ReflectionException
1498
+	 */
1499
+	public function set_reverse_calculate($reverse_calculate)
1500
+	{
1501
+		$this->set('TKT_reverse_calculate', $reverse_calculate);
1502
+	}
1503
+
1504
+
1505
+	/**
1506
+	 * Gets a string which is handy for showing in gateways etc that describes the ticket.
1507
+	 *
1508
+	 * @return string
1509
+	 * @throws EE_Error
1510
+	 * @throws ReflectionException
1511
+	 */
1512
+	public function name_and_info()
1513
+	{
1514
+		$times = [];
1515
+		foreach ($this->datetimes() as $datetime) {
1516
+			$times[] = $datetime->start_date_and_time();
1517
+		}
1518
+		return $this->name() . ' @ ' . implode(', ', $times) . ' for ' . $this->pretty_price();
1519
+	}
1520
+
1521
+
1522
+	/**
1523
+	 * Gets name
1524
+	 *
1525
+	 * @return string
1526
+	 * @throws EE_Error
1527
+	 * @throws ReflectionException
1528
+	 */
1529
+	public function name()
1530
+	{
1531
+		return $this->get('TKT_name');
1532
+	}
1533
+
1534
+
1535
+	/**
1536
+	 * Gets price
1537
+	 *
1538
+	 * @return float
1539
+	 * @throws EE_Error
1540
+	 * @throws ReflectionException
1541
+	 */
1542
+	public function price()
1543
+	{
1544
+		return $this->get('TKT_price');
1545
+	}
1546
+
1547
+
1548
+	/**
1549
+	 * Gets all the registrations for this ticket
1550
+	 *
1551
+	 * @param array $query_params @see
1552
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1553
+	 * @return EE_Registration[]|EE_Base_Class[]
1554
+	 * @throws EE_Error
1555
+	 * @throws ReflectionException
1556
+	 */
1557
+	public function registrations($query_params = [])
1558
+	{
1559
+		return $this->get_many_related('Registration', $query_params);
1560
+	}
1561
+
1562
+
1563
+	/**
1564
+	 * Updates the TKT_sold attribute (and saves) based on the number of APPROVED registrations for this ticket.
1565
+	 *
1566
+	 * @return int
1567
+	 * @throws EE_Error
1568
+	 * @throws ReflectionException
1569
+	 */
1570
+	public function update_tickets_sold()
1571
+	{
1572
+		$count_regs_for_this_ticket = $this->count_registrations(
1573
+			[
1574
+				[
1575
+					'STS_ID'      => EEM_Registration::status_id_approved,
1576
+					'REG_deleted' => 0,
1577
+				],
1578
+			]
1579
+		);
1580
+		$this->set_sold($count_regs_for_this_ticket);
1581
+		$this->save();
1582
+		return $count_regs_for_this_ticket;
1583
+	}
1584
+
1585
+
1586
+	/**
1587
+	 * Counts the registrations for this ticket
1588
+	 *
1589
+	 * @param array $query_params @see
1590
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1591
+	 * @return int
1592
+	 * @throws EE_Error
1593
+	 * @throws ReflectionException
1594
+	 */
1595
+	public function count_registrations($query_params = [])
1596
+	{
1597
+		return $this->count_related('Registration', $query_params);
1598
+	}
1599
+
1600
+
1601
+	/**
1602
+	 * Implementation for EEI_Has_Icon interface method.
1603
+	 *
1604
+	 * @return string
1605
+	 * @see EEI_Visual_Representation for comments
1606
+	 */
1607
+	public function get_icon()
1608
+	{
1609
+		return '<span class="dashicons dashicons-tickets-alt"/>';
1610
+	}
1611
+
1612
+
1613
+	/**
1614
+	 * Implementation of the EEI_Event_Relation interface method
1615
+	 *
1616
+	 * @return EE_Event
1617
+	 * @throws EE_Error
1618
+	 * @throws UnexpectedEntityException
1619
+	 * @throws ReflectionException
1620
+	 * @see EEI_Event_Relation for comments
1621
+	 */
1622
+	public function get_related_event()
1623
+	{
1624
+		// get one datetime to use for getting the event
1625
+		$datetime = $this->first_datetime();
1626
+		if (! $datetime instanceof EE_Datetime) {
1627
+			throw new UnexpectedEntityException(
1628
+				$datetime,
1629
+				'EE_Datetime',
1630
+				sprintf(
1631
+					__('The ticket (%s) is not associated with any valid datetimes.', 'event_espresso'),
1632
+					$this->name()
1633
+				)
1634
+			);
1635
+		}
1636
+		$event = $datetime->event();
1637
+		if (! $event instanceof EE_Event) {
1638
+			throw new UnexpectedEntityException(
1639
+				$event,
1640
+				'EE_Event',
1641
+				sprintf(
1642
+					__('The ticket (%s) is not associated with a valid event.', 'event_espresso'),
1643
+					$this->name()
1644
+				)
1645
+			);
1646
+		}
1647
+		return $event;
1648
+	}
1649
+
1650
+
1651
+	/**
1652
+	 * Implementation of the EEI_Event_Relation interface method
1653
+	 *
1654
+	 * @return string
1655
+	 * @throws UnexpectedEntityException
1656
+	 * @throws EE_Error
1657
+	 * @throws ReflectionException
1658
+	 * @see EEI_Event_Relation for comments
1659
+	 */
1660
+	public function get_event_name()
1661
+	{
1662
+		$event = $this->get_related_event();
1663
+		return $event instanceof EE_Event ? $event->name() : '';
1664
+	}
1665
+
1666
+
1667
+	/**
1668
+	 * Implementation of the EEI_Event_Relation interface method
1669
+	 *
1670
+	 * @return int
1671
+	 * @throws UnexpectedEntityException
1672
+	 * @throws EE_Error
1673
+	 * @throws ReflectionException
1674
+	 * @see EEI_Event_Relation for comments
1675
+	 */
1676
+	public function get_event_ID()
1677
+	{
1678
+		$event = $this->get_related_event();
1679
+		return $event instanceof EE_Event ? $event->ID() : 0;
1680
+	}
1681
+
1682
+
1683
+	/**
1684
+	 * This simply returns whether a ticket can be permanently deleted or not.
1685
+	 * The criteria for determining this is whether the ticket has any related registrations.
1686
+	 * If there are none then it can be permanently deleted.
1687
+	 *
1688
+	 * @return bool
1689
+	 * @throws EE_Error
1690
+	 * @throws ReflectionException
1691
+	 */
1692
+	public function is_permanently_deleteable()
1693
+	{
1694
+		return $this->count_registrations() === 0;
1695
+	}
1696
+
1697
+
1698
+	/**
1699
+	 * @return int
1700
+	 * @throws EE_Error
1701
+	 * @throws ReflectionException
1702
+	 * @since   $VID:$
1703
+	 */
1704
+	public function visibility(): int
1705
+	{
1706
+		return $this->get('TKT_visibility');
1707
+	}
1708
+
1709
+
1710
+	/**
1711
+	 * @return int
1712
+	 * @throws EE_Error
1713
+	 * @throws ReflectionException
1714
+	 * @since   $VID:$
1715
+	 */
1716
+	public function isHidden(): int
1717
+	{
1718
+		return $this->visibility() === EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE;
1719
+	}
1720
+
1721
+
1722
+	/**
1723
+	 * @return int
1724
+	 * @throws EE_Error
1725
+	 * @throws ReflectionException
1726
+	 * @since   $VID:$
1727
+	 */
1728
+	public function isNotHidden(): int
1729
+	{
1730
+		return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE;
1731
+	}
1732
+
1733
+
1734
+	/**
1735
+	 * @return int
1736
+	 * @throws EE_Error
1737
+	 * @throws ReflectionException
1738
+	 * @since   $VID:$
1739
+	 */
1740
+	public function isPublicOnly(): int
1741
+	{
1742
+		return $this->isNotHidden() && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_PUBLIC_VALUE;
1743
+	}
1744
+
1745
+
1746
+	/**
1747
+	 * @return int
1748
+	 * @throws EE_Error
1749
+	 * @throws ReflectionException
1750
+	 * @since   $VID:$
1751
+	 */
1752
+	public function isMembersOnly(): int
1753
+	{
1754
+		return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_PUBLIC_VALUE
1755
+			   && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_MEMBERS_ONLY_VALUE;
1756
+	}
1757
+
1758
+
1759
+	/**
1760
+	 * @return int
1761
+	 * @throws EE_Error
1762
+	 * @throws ReflectionException
1763
+	 * @since   $VID:$
1764
+	 */
1765
+	public function isAdminsOnly(): int
1766
+	{
1767
+		return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_MEMBERS_ONLY_VALUE
1768
+			   && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_ADMINS_ONLY_VALUE;
1769
+	}
1770
+
1771
+
1772
+	/**
1773
+	 * @return int
1774
+	 * @throws EE_Error
1775
+	 * @throws ReflectionException
1776
+	 * @since   $VID:$
1777
+	 */
1778
+	public function isAdminUiOnly(): int
1779
+	{
1780
+		return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_ADMINS_ONLY_VALUE
1781
+			   && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_ADMIN_UI_ONLY_VALUE;
1782
+	}
1783
+
1784
+
1785
+	/**
1786
+	 * @param int $visibility
1787
+	 * @throws EE_Error
1788
+	 * @throws ReflectionException
1789
+	 * @since   $VID:$
1790
+	 */
1791
+	public function set_visibility(int $visibility)
1792
+	{
1793
+
1794
+		$ticket_visibility_options = $this->_model->ticketVisibilityOptions();
1795
+		$ticket_visibility         = -1;
1796
+		foreach ($ticket_visibility_options as $ticket_visibility_option) {
1797
+			if ($visibility === $ticket_visibility_option) {
1798
+				$ticket_visibility = $visibility;
1799
+			}
1800
+		}
1801
+		if ($ticket_visibility === -1) {
1802
+			throw new DomainException(
1803
+				sprintf(
1804
+					esc_html__(
1805
+						'The supplied ticket visibility setting of "%1$s" is not valid. It needs to match one of the keys in the following array:%2$s %3$s ',
1806
+						'event_espresso'
1807
+					),
1808
+					$visibility,
1809
+					'<br />',
1810
+					var_export($ticket_visibility_options, true)
1811
+				)
1812
+			);
1813
+		}
1814
+		$this->set('TKT_visibility', $ticket_visibility);
1815
+	}
1816
+
1817
+
1818
+	/*******************************************************************
1819 1819
      ***********************  DEPRECATED METHODS  **********************
1820 1820
      *******************************************************************/
1821 1821
 
1822 1822
 
1823
-    /**
1824
-     * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
1825
-     * associated datetimes.
1826
-     *
1827
-     * @param int $qty
1828
-     * @return void
1829
-     * @throws EE_Error
1830
-     * @throws InvalidArgumentException
1831
-     * @throws InvalidDataTypeException
1832
-     * @throws InvalidInterfaceException
1833
-     * @throws ReflectionException
1834
-     * @deprecated 4.9.80.p
1835
-     */
1836
-    public function increase_sold($qty = 1)
1837
-    {
1838
-        EE_Error::doing_it_wrong(
1839
-            __FUNCTION__,
1840
-            esc_html__('Please use EE_Ticket::increaseSold() instead', 'event_espresso'),
1841
-            '4.9.80.p',
1842
-            '5.0.0.p'
1843
-        );
1844
-        $this->increaseSold($qty);
1845
-    }
1846
-
1847
-
1848
-    /**
1849
-     * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
1850
-     *
1851
-     * @param int $qty positive or negative. Positive means to increase sold counts (and decrease reserved counts),
1852
-     *                 Negative means to decreases old counts (and increase reserved counts).
1853
-     * @throws EE_Error
1854
-     * @throws InvalidArgumentException
1855
-     * @throws InvalidDataTypeException
1856
-     * @throws InvalidInterfaceException
1857
-     * @throws ReflectionException
1858
-     * @deprecated 4.9.80.p
1859
-     */
1860
-    protected function _increase_sold_for_datetimes($qty)
1861
-    {
1862
-        EE_Error::doing_it_wrong(
1863
-            __FUNCTION__,
1864
-            esc_html__('Please use EE_Ticket::increaseSoldForDatetimes() instead', 'event_espresso'),
1865
-            '4.9.80.p',
1866
-            '5.0.0.p'
1867
-        );
1868
-        $this->increaseSoldForDatetimes($qty);
1869
-    }
1870
-
1871
-
1872
-    /**
1873
-     * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
1874
-     * DB and then updates the model objects.
1875
-     * Does not affect the reserved counts.
1876
-     *
1877
-     * @param int $qty
1878
-     * @return void
1879
-     * @throws EE_Error
1880
-     * @throws InvalidArgumentException
1881
-     * @throws InvalidDataTypeException
1882
-     * @throws InvalidInterfaceException
1883
-     * @throws ReflectionException
1884
-     * @deprecated 4.9.80.p
1885
-     */
1886
-    public function decrease_sold($qty = 1)
1887
-    {
1888
-        EE_Error::doing_it_wrong(
1889
-            __FUNCTION__,
1890
-            esc_html__('Please use EE_Ticket::decreaseSold() instead', 'event_espresso'),
1891
-            '4.9.80.p',
1892
-            '5.0.0.p'
1893
-        );
1894
-        $this->decreaseSold($qty);
1895
-    }
1896
-
1897
-
1898
-    /**
1899
-     * Decreases sold on related datetimes
1900
-     *
1901
-     * @param int $qty
1902
-     * @return void
1903
-     * @throws EE_Error
1904
-     * @throws InvalidArgumentException
1905
-     * @throws InvalidDataTypeException
1906
-     * @throws InvalidInterfaceException
1907
-     * @throws ReflectionException
1908
-     * @deprecated 4.9.80.p
1909
-     */
1910
-    protected function _decrease_sold_for_datetimes($qty = 1)
1911
-    {
1912
-        EE_Error::doing_it_wrong(
1913
-            __FUNCTION__,
1914
-            esc_html__('Please use EE_Ticket::decreaseSoldForDatetimes() instead', 'event_espresso'),
1915
-            '4.9.80.p',
1916
-            '5.0.0.p'
1917
-        );
1918
-        $this->decreaseSoldForDatetimes($qty);
1919
-    }
1920
-
1921
-
1922
-    /**
1923
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1924
-     *
1925
-     * @param int    $qty
1926
-     * @param string $source
1927
-     * @return bool whether we successfully reserved the ticket or not.
1928
-     * @throws EE_Error
1929
-     * @throws InvalidArgumentException
1930
-     * @throws ReflectionException
1931
-     * @throws InvalidDataTypeException
1932
-     * @throws InvalidInterfaceException
1933
-     * @deprecated 4.9.80.p
1934
-     */
1935
-    public function increase_reserved($qty = 1, $source = 'unknown')
1936
-    {
1937
-        EE_Error::doing_it_wrong(
1938
-            __FUNCTION__,
1939
-            esc_html__('Please use EE_Ticket::increaseReserved() instead', 'event_espresso'),
1940
-            '4.9.80.p',
1941
-            '5.0.0.p'
1942
-        );
1943
-        return $this->increaseReserved($qty);
1944
-    }
1945
-
1946
-
1947
-    /**
1948
-     * Increases sold on related datetimes
1949
-     *
1950
-     * @param int $qty
1951
-     * @return boolean indicating success
1952
-     * @throws EE_Error
1953
-     * @throws InvalidArgumentException
1954
-     * @throws InvalidDataTypeException
1955
-     * @throws InvalidInterfaceException
1956
-     * @throws ReflectionException
1957
-     * @deprecated 4.9.80.p
1958
-     */
1959
-    protected function _increase_reserved_for_datetimes($qty = 1)
1960
-    {
1961
-        EE_Error::doing_it_wrong(
1962
-            __FUNCTION__,
1963
-            esc_html__('Please use EE_Ticket::increaseReservedForDatetimes() instead', 'event_espresso'),
1964
-            '4.9.80.p',
1965
-            '5.0.0.p'
1966
-        );
1967
-        return $this->increaseReservedForDatetimes($qty);
1968
-    }
1969
-
1970
-
1971
-    /**
1972
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1973
-     *
1974
-     * @param int    $qty
1975
-     * @param bool   $adjust_datetimes
1976
-     * @param string $source
1977
-     * @return void
1978
-     * @throws EE_Error
1979
-     * @throws InvalidArgumentException
1980
-     * @throws ReflectionException
1981
-     * @throws InvalidDataTypeException
1982
-     * @throws InvalidInterfaceException
1983
-     * @deprecated 4.9.80.p
1984
-     */
1985
-    public function decrease_reserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
1986
-    {
1987
-        EE_Error::doing_it_wrong(
1988
-            __FUNCTION__,
1989
-            esc_html__('Please use EE_Ticket::decreaseReserved() instead', 'event_espresso'),
1990
-            '4.9.80.p',
1991
-            '5.0.0.p'
1992
-        );
1993
-        $this->decreaseReserved($qty);
1994
-    }
1995
-
1996
-
1997
-    /**
1998
-     * Decreases reserved on related datetimes
1999
-     *
2000
-     * @param int $qty
2001
-     * @return void
2002
-     * @throws EE_Error
2003
-     * @throws InvalidArgumentException
2004
-     * @throws ReflectionException
2005
-     * @throws InvalidDataTypeException
2006
-     * @throws InvalidInterfaceException
2007
-     * @deprecated 4.9.80.p
2008
-     */
2009
-    protected function _decrease_reserved_for_datetimes($qty = 1)
2010
-    {
2011
-        EE_Error::doing_it_wrong(
2012
-            __FUNCTION__,
2013
-            esc_html__('Please use EE_Ticket::decreaseReservedForDatetimes() instead', 'event_espresso'),
2014
-            '4.9.80.p',
2015
-            '5.0.0.p'
2016
-        );
2017
-        $this->decreaseReservedForDatetimes($qty);
2018
-    }
1823
+	/**
1824
+	 * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
1825
+	 * associated datetimes.
1826
+	 *
1827
+	 * @param int $qty
1828
+	 * @return void
1829
+	 * @throws EE_Error
1830
+	 * @throws InvalidArgumentException
1831
+	 * @throws InvalidDataTypeException
1832
+	 * @throws InvalidInterfaceException
1833
+	 * @throws ReflectionException
1834
+	 * @deprecated 4.9.80.p
1835
+	 */
1836
+	public function increase_sold($qty = 1)
1837
+	{
1838
+		EE_Error::doing_it_wrong(
1839
+			__FUNCTION__,
1840
+			esc_html__('Please use EE_Ticket::increaseSold() instead', 'event_espresso'),
1841
+			'4.9.80.p',
1842
+			'5.0.0.p'
1843
+		);
1844
+		$this->increaseSold($qty);
1845
+	}
1846
+
1847
+
1848
+	/**
1849
+	 * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
1850
+	 *
1851
+	 * @param int $qty positive or negative. Positive means to increase sold counts (and decrease reserved counts),
1852
+	 *                 Negative means to decreases old counts (and increase reserved counts).
1853
+	 * @throws EE_Error
1854
+	 * @throws InvalidArgumentException
1855
+	 * @throws InvalidDataTypeException
1856
+	 * @throws InvalidInterfaceException
1857
+	 * @throws ReflectionException
1858
+	 * @deprecated 4.9.80.p
1859
+	 */
1860
+	protected function _increase_sold_for_datetimes($qty)
1861
+	{
1862
+		EE_Error::doing_it_wrong(
1863
+			__FUNCTION__,
1864
+			esc_html__('Please use EE_Ticket::increaseSoldForDatetimes() instead', 'event_espresso'),
1865
+			'4.9.80.p',
1866
+			'5.0.0.p'
1867
+		);
1868
+		$this->increaseSoldForDatetimes($qty);
1869
+	}
1870
+
1871
+
1872
+	/**
1873
+	 * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
1874
+	 * DB and then updates the model objects.
1875
+	 * Does not affect the reserved counts.
1876
+	 *
1877
+	 * @param int $qty
1878
+	 * @return void
1879
+	 * @throws EE_Error
1880
+	 * @throws InvalidArgumentException
1881
+	 * @throws InvalidDataTypeException
1882
+	 * @throws InvalidInterfaceException
1883
+	 * @throws ReflectionException
1884
+	 * @deprecated 4.9.80.p
1885
+	 */
1886
+	public function decrease_sold($qty = 1)
1887
+	{
1888
+		EE_Error::doing_it_wrong(
1889
+			__FUNCTION__,
1890
+			esc_html__('Please use EE_Ticket::decreaseSold() instead', 'event_espresso'),
1891
+			'4.9.80.p',
1892
+			'5.0.0.p'
1893
+		);
1894
+		$this->decreaseSold($qty);
1895
+	}
1896
+
1897
+
1898
+	/**
1899
+	 * Decreases sold on related datetimes
1900
+	 *
1901
+	 * @param int $qty
1902
+	 * @return void
1903
+	 * @throws EE_Error
1904
+	 * @throws InvalidArgumentException
1905
+	 * @throws InvalidDataTypeException
1906
+	 * @throws InvalidInterfaceException
1907
+	 * @throws ReflectionException
1908
+	 * @deprecated 4.9.80.p
1909
+	 */
1910
+	protected function _decrease_sold_for_datetimes($qty = 1)
1911
+	{
1912
+		EE_Error::doing_it_wrong(
1913
+			__FUNCTION__,
1914
+			esc_html__('Please use EE_Ticket::decreaseSoldForDatetimes() instead', 'event_espresso'),
1915
+			'4.9.80.p',
1916
+			'5.0.0.p'
1917
+		);
1918
+		$this->decreaseSoldForDatetimes($qty);
1919
+	}
1920
+
1921
+
1922
+	/**
1923
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1924
+	 *
1925
+	 * @param int    $qty
1926
+	 * @param string $source
1927
+	 * @return bool whether we successfully reserved the ticket or not.
1928
+	 * @throws EE_Error
1929
+	 * @throws InvalidArgumentException
1930
+	 * @throws ReflectionException
1931
+	 * @throws InvalidDataTypeException
1932
+	 * @throws InvalidInterfaceException
1933
+	 * @deprecated 4.9.80.p
1934
+	 */
1935
+	public function increase_reserved($qty = 1, $source = 'unknown')
1936
+	{
1937
+		EE_Error::doing_it_wrong(
1938
+			__FUNCTION__,
1939
+			esc_html__('Please use EE_Ticket::increaseReserved() instead', 'event_espresso'),
1940
+			'4.9.80.p',
1941
+			'5.0.0.p'
1942
+		);
1943
+		return $this->increaseReserved($qty);
1944
+	}
1945
+
1946
+
1947
+	/**
1948
+	 * Increases sold on related datetimes
1949
+	 *
1950
+	 * @param int $qty
1951
+	 * @return boolean indicating success
1952
+	 * @throws EE_Error
1953
+	 * @throws InvalidArgumentException
1954
+	 * @throws InvalidDataTypeException
1955
+	 * @throws InvalidInterfaceException
1956
+	 * @throws ReflectionException
1957
+	 * @deprecated 4.9.80.p
1958
+	 */
1959
+	protected function _increase_reserved_for_datetimes($qty = 1)
1960
+	{
1961
+		EE_Error::doing_it_wrong(
1962
+			__FUNCTION__,
1963
+			esc_html__('Please use EE_Ticket::increaseReservedForDatetimes() instead', 'event_espresso'),
1964
+			'4.9.80.p',
1965
+			'5.0.0.p'
1966
+		);
1967
+		return $this->increaseReservedForDatetimes($qty);
1968
+	}
1969
+
1970
+
1971
+	/**
1972
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1973
+	 *
1974
+	 * @param int    $qty
1975
+	 * @param bool   $adjust_datetimes
1976
+	 * @param string $source
1977
+	 * @return void
1978
+	 * @throws EE_Error
1979
+	 * @throws InvalidArgumentException
1980
+	 * @throws ReflectionException
1981
+	 * @throws InvalidDataTypeException
1982
+	 * @throws InvalidInterfaceException
1983
+	 * @deprecated 4.9.80.p
1984
+	 */
1985
+	public function decrease_reserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
1986
+	{
1987
+		EE_Error::doing_it_wrong(
1988
+			__FUNCTION__,
1989
+			esc_html__('Please use EE_Ticket::decreaseReserved() instead', 'event_espresso'),
1990
+			'4.9.80.p',
1991
+			'5.0.0.p'
1992
+		);
1993
+		$this->decreaseReserved($qty);
1994
+	}
1995
+
1996
+
1997
+	/**
1998
+	 * Decreases reserved on related datetimes
1999
+	 *
2000
+	 * @param int $qty
2001
+	 * @return void
2002
+	 * @throws EE_Error
2003
+	 * @throws InvalidArgumentException
2004
+	 * @throws ReflectionException
2005
+	 * @throws InvalidDataTypeException
2006
+	 * @throws InvalidInterfaceException
2007
+	 * @deprecated 4.9.80.p
2008
+	 */
2009
+	protected function _decrease_reserved_for_datetimes($qty = 1)
2010
+	{
2011
+		EE_Error::doing_it_wrong(
2012
+			__FUNCTION__,
2013
+			esc_html__('Please use EE_Ticket::decreaseReservedForDatetimes() instead', 'event_espresso'),
2014
+			'4.9.80.p',
2015
+			'5.0.0.p'
2016
+		);
2017
+		$this->decreaseReservedForDatetimes($qty);
2018
+	}
2019 2019
 }
Please login to merge, or discard this patch.
core/services/converters/date_time_formats/PhpToUnicode.php 2 patches
Indentation   +85 added lines, -85 removed lines patch added patch discarded remove patch
@@ -4,97 +4,97 @@
 block discarded – undo
4 4
 
5 5
 class PhpToUnicode
6 6
 {
7
-    /**
8
-     * array where keys are PHP date format parameters
9
-     * and values are Unicode Date Format substitutions
10
-     */
11
-    public static $date_formats = [
12
-        // YEAR
13
-        'y' => 'yy',    // 00, 01, ..., 99
14
-        'Y' => 'yyyy',  // 2000, 2001, ..., 2099
15
-        'o' => 'GGGG',  // ISO "week-numbering year" 2000, 2001, ..., 2099
16
-        // MONTH
17
-        'M' => 'MMM',   // Jan, Feb, ..., Dec
18
-        'n' => 'M',     // 1, 2, ..., 12
19
-        'm' => 'MM',    // 01, 02, ..., 12
20
-        'F' => 'MMMM',  // January, February, ..., December
21
-        // DAY
22
-        'd' => 'dd',    // 01, 02, ..., 31
23
-        'D' => 'eee',   // Sun, Mon, ..., Sat
24
-        'jS' => 'do',   // 1st, 2nd, ..., 31st
25
-        'j' => 'd',     // 1, 2, ..., 31
26
-        'l' => 'eeee',  // Sunday, Monday, ..., Saturday
27
-        'N' => 'e',     // Day of week 0, 1, ..., 6
28
-        'w' => 'i',     // ISO Day of week 1, 2, ..., 7
29
-        'z' => 'D',   // day of the year 0 - 365 to 1 - 366
30
-        // WEEK
31
-        'W' => 'w',
32
-    ];
7
+	/**
8
+	 * array where keys are PHP date format parameters
9
+	 * and values are Unicode Date Format substitutions
10
+	 */
11
+	public static $date_formats = [
12
+		// YEAR
13
+		'y' => 'yy',    // 00, 01, ..., 99
14
+		'Y' => 'yyyy',  // 2000, 2001, ..., 2099
15
+		'o' => 'GGGG',  // ISO "week-numbering year" 2000, 2001, ..., 2099
16
+		// MONTH
17
+		'M' => 'MMM',   // Jan, Feb, ..., Dec
18
+		'n' => 'M',     // 1, 2, ..., 12
19
+		'm' => 'MM',    // 01, 02, ..., 12
20
+		'F' => 'MMMM',  // January, February, ..., December
21
+		// DAY
22
+		'd' => 'dd',    // 01, 02, ..., 31
23
+		'D' => 'eee',   // Sun, Mon, ..., Sat
24
+		'jS' => 'do',   // 1st, 2nd, ..., 31st
25
+		'j' => 'd',     // 1, 2, ..., 31
26
+		'l' => 'eeee',  // Sunday, Monday, ..., Saturday
27
+		'N' => 'e',     // Day of week 0, 1, ..., 6
28
+		'w' => 'i',     // ISO Day of week 1, 2, ..., 7
29
+		'z' => 'D',   // day of the year 0 - 365 to 1 - 366
30
+		// WEEK
31
+		'W' => 'w',
32
+	];
33 33
 
34 34
 
35
-    /**
36
-     * array where keys are PHP time format parameters
37
-     * and values are Unicode Time Format substitutions
38
-     */
39
-    public static $time_formats = [
40
-        // 'a' => 'a', // am, pm, no pecific JS alternative
41
-        'A' => 'a', // AM, PM
42
-        // HOUR
43
-        // convert "g" to an intermediary format
44
-        // to avoid its result getting replaced by "h"
45
-        'g' => '@',     // 1, 2, ..., 12
46
-        'h' => 'hh',    // 01, 02, ..., 12
47
-        '@' => 'h',     // 1, 2, ..., 12
48
-        'G' => '#',     // 0, 1, ... 23
49
-        'H' => 'HH',    // 00, 01, ... 23
50
-        '#' => 'H',     // 0, 1, ... 23
51
-        // MINUTES & SECONDS
52
-        'i' => 'mm',    // minutes 00, 01, ..., 59
53
-        's' => 'ss',    // seconds 00, 01, ..., 59
54
-        'v' => 'SSS',   // milliseconds 000, 001, ..., 999
55
-        'u' => 'SSS',   // microseconds (not in unicode) 000, 001, ..., 999
56
-    ];
35
+	/**
36
+	 * array where keys are PHP time format parameters
37
+	 * and values are Unicode Time Format substitutions
38
+	 */
39
+	public static $time_formats = [
40
+		// 'a' => 'a', // am, pm, no pecific JS alternative
41
+		'A' => 'a', // AM, PM
42
+		// HOUR
43
+		// convert "g" to an intermediary format
44
+		// to avoid its result getting replaced by "h"
45
+		'g' => '@',     // 1, 2, ..., 12
46
+		'h' => 'hh',    // 01, 02, ..., 12
47
+		'@' => 'h',     // 1, 2, ..., 12
48
+		'G' => '#',     // 0, 1, ... 23
49
+		'H' => 'HH',    // 00, 01, ... 23
50
+		'#' => 'H',     // 0, 1, ... 23
51
+		// MINUTES & SECONDS
52
+		'i' => 'mm',    // minutes 00, 01, ..., 59
53
+		's' => 'ss',    // seconds 00, 01, ..., 59
54
+		'v' => 'SSS',   // milliseconds 000, 001, ..., 999
55
+		'u' => 'SSS',   // microseconds (not in unicode) 000, 001, ..., 999
56
+	];
57 57
 
58 58
 
59
-    /**
60
-     * array where keys are PHP timezone format parameters
61
-     * and values are Unicode Timezone Format substitutions
62
-     */
63
-    public static $timezone_formats = [
64
-        'Z' => 'ZZ',    // -0100, +0000, ..., +1200
65
-        'e' => 'Z',     // Timezone identifier UTC, GMT, Atlantic/Azores to -01:00, +00:00, ... +12:00
66
-        'T' => 'Z',     // Timezone abbreviation EST, MDT to -01:00, +00:00, ... +12:00
67
-        'P' => 'Z',     // -01:00, +00:00, ... +12:00
68
-        'O' => 'ZZ',    // -0100, +0000, ..., +1200
69
-    ];
59
+	/**
60
+	 * array where keys are PHP timezone format parameters
61
+	 * and values are Unicode Timezone Format substitutions
62
+	 */
63
+	public static $timezone_formats = [
64
+		'Z' => 'ZZ',    // -0100, +0000, ..., +1200
65
+		'e' => 'Z',     // Timezone identifier UTC, GMT, Atlantic/Azores to -01:00, +00:00, ... +12:00
66
+		'T' => 'Z',     // Timezone abbreviation EST, MDT to -01:00, +00:00, ... +12:00
67
+		'P' => 'Z',     // -01:00, +00:00, ... +12:00
68
+		'O' => 'ZZ',    // -0100, +0000, ..., +1200
69
+	];
70 70
 
71 71
 
72
-    /**
73
-     * @param string $date_format
74
-     * @return string
75
-     */
76
-    public function convertDateFormat($date_format)
77
-    {
78
-        foreach (PhpToUnicode::$date_formats as $find => $replace) {
79
-            $date_format = (string) str_replace($find, $replace, $date_format);
80
-        }
81
-        return $date_format;
82
-    }
72
+	/**
73
+	 * @param string $date_format
74
+	 * @return string
75
+	 */
76
+	public function convertDateFormat($date_format)
77
+	{
78
+		foreach (PhpToUnicode::$date_formats as $find => $replace) {
79
+			$date_format = (string) str_replace($find, $replace, $date_format);
80
+		}
81
+		return $date_format;
82
+	}
83 83
 
84 84
 
85
-    /**
86
-     * @param string $time_format
87
-     * @return string
88
-     */
89
-    public function convertTimeFormat($time_format)
90
-    {
91
-        foreach (PhpToUnicode::$time_formats as $find => $replace) {
92
-            $time_format = (string) str_replace($find, $replace, $time_format);
93
-        }
94
-        // and just in case the timezone has been added
95
-        foreach (PhpToUnicode::$timezone_formats as $find => $replace) {
96
-            $time_format = (string) str_replace($find, $replace, $time_format);
97
-        }
98
-        return $time_format;
99
-    }
85
+	/**
86
+	 * @param string $time_format
87
+	 * @return string
88
+	 */
89
+	public function convertTimeFormat($time_format)
90
+	{
91
+		foreach (PhpToUnicode::$time_formats as $find => $replace) {
92
+			$time_format = (string) str_replace($find, $replace, $time_format);
93
+		}
94
+		// and just in case the timezone has been added
95
+		foreach (PhpToUnicode::$timezone_formats as $find => $replace) {
96
+			$time_format = (string) str_replace($find, $replace, $time_format);
97
+		}
98
+		return $time_format;
99
+	}
100 100
 }
Please login to merge, or discard this patch.
Spacing   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -10,23 +10,23 @@  discard block
 block discarded – undo
10 10
      */
11 11
     public static $date_formats = [
12 12
         // YEAR
13
-        'y' => 'yy',    // 00, 01, ..., 99
14
-        'Y' => 'yyyy',  // 2000, 2001, ..., 2099
15
-        'o' => 'GGGG',  // ISO "week-numbering year" 2000, 2001, ..., 2099
13
+        'y' => 'yy', // 00, 01, ..., 99
14
+        'Y' => 'yyyy', // 2000, 2001, ..., 2099
15
+        'o' => 'GGGG', // ISO "week-numbering year" 2000, 2001, ..., 2099
16 16
         // MONTH
17
-        'M' => 'MMM',   // Jan, Feb, ..., Dec
18
-        'n' => 'M',     // 1, 2, ..., 12
19
-        'm' => 'MM',    // 01, 02, ..., 12
20
-        'F' => 'MMMM',  // January, February, ..., December
17
+        'M' => 'MMM', // Jan, Feb, ..., Dec
18
+        'n' => 'M', // 1, 2, ..., 12
19
+        'm' => 'MM', // 01, 02, ..., 12
20
+        'F' => 'MMMM', // January, February, ..., December
21 21
         // DAY
22
-        'd' => 'dd',    // 01, 02, ..., 31
23
-        'D' => 'eee',   // Sun, Mon, ..., Sat
24
-        'jS' => 'do',   // 1st, 2nd, ..., 31st
25
-        'j' => 'd',     // 1, 2, ..., 31
26
-        'l' => 'eeee',  // Sunday, Monday, ..., Saturday
27
-        'N' => 'e',     // Day of week 0, 1, ..., 6
28
-        'w' => 'i',     // ISO Day of week 1, 2, ..., 7
29
-        'z' => 'D',   // day of the year 0 - 365 to 1 - 366
22
+        'd' => 'dd', // 01, 02, ..., 31
23
+        'D' => 'eee', // Sun, Mon, ..., Sat
24
+        'jS' => 'do', // 1st, 2nd, ..., 31st
25
+        'j' => 'd', // 1, 2, ..., 31
26
+        'l' => 'eeee', // Sunday, Monday, ..., Saturday
27
+        'N' => 'e', // Day of week 0, 1, ..., 6
28
+        'w' => 'i', // ISO Day of week 1, 2, ..., 7
29
+        'z' => 'D', // day of the year 0 - 365 to 1 - 366
30 30
         // WEEK
31 31
         'W' => 'w',
32 32
     ];
@@ -42,17 +42,17 @@  discard block
 block discarded – undo
42 42
         // HOUR
43 43
         // convert "g" to an intermediary format
44 44
         // to avoid its result getting replaced by "h"
45
-        'g' => '@',     // 1, 2, ..., 12
46
-        'h' => 'hh',    // 01, 02, ..., 12
47
-        '@' => 'h',     // 1, 2, ..., 12
48
-        'G' => '#',     // 0, 1, ... 23
49
-        'H' => 'HH',    // 00, 01, ... 23
50
-        '#' => 'H',     // 0, 1, ... 23
45
+        'g' => '@', // 1, 2, ..., 12
46
+        'h' => 'hh', // 01, 02, ..., 12
47
+        '@' => 'h', // 1, 2, ..., 12
48
+        'G' => '#', // 0, 1, ... 23
49
+        'H' => 'HH', // 00, 01, ... 23
50
+        '#' => 'H', // 0, 1, ... 23
51 51
         // MINUTES & SECONDS
52
-        'i' => 'mm',    // minutes 00, 01, ..., 59
53
-        's' => 'ss',    // seconds 00, 01, ..., 59
54
-        'v' => 'SSS',   // milliseconds 000, 001, ..., 999
55
-        'u' => 'SSS',   // microseconds (not in unicode) 000, 001, ..., 999
52
+        'i' => 'mm', // minutes 00, 01, ..., 59
53
+        's' => 'ss', // seconds 00, 01, ..., 59
54
+        'v' => 'SSS', // milliseconds 000, 001, ..., 999
55
+        'u' => 'SSS', // microseconds (not in unicode) 000, 001, ..., 999
56 56
     ];
57 57
 
58 58
 
@@ -61,11 +61,11 @@  discard block
 block discarded – undo
61 61
      * and values are Unicode Timezone Format substitutions
62 62
      */
63 63
     public static $timezone_formats = [
64
-        'Z' => 'ZZ',    // -0100, +0000, ..., +1200
65
-        'e' => 'Z',     // Timezone identifier UTC, GMT, Atlantic/Azores to -01:00, +00:00, ... +12:00
66
-        'T' => 'Z',     // Timezone abbreviation EST, MDT to -01:00, +00:00, ... +12:00
67
-        'P' => 'Z',     // -01:00, +00:00, ... +12:00
68
-        'O' => 'ZZ',    // -0100, +0000, ..., +1200
64
+        'Z' => 'ZZ', // -0100, +0000, ..., +1200
65
+        'e' => 'Z', // Timezone identifier UTC, GMT, Atlantic/Azores to -01:00, +00:00, ... +12:00
66
+        'T' => 'Z', // Timezone abbreviation EST, MDT to -01:00, +00:00, ... +12:00
67
+        'P' => 'Z', // -01:00, +00:00, ... +12:00
68
+        'O' => 'ZZ', // -0100, +0000, ..., +1200
69 69
     ];
70 70
 
71 71
 
Please login to merge, or discard this patch.
core/domain/entities/routing/data_nodes/core/GeneralSettings.php 1 patch
Indentation   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -16,37 +16,37 @@
 block discarded – undo
16 16
 class GeneralSettings extends JsonDataNode
17 17
 {
18 18
 
19
-    const NODE_NAME = 'generalSettings';
20
-
21
-    /**
22
-     * @var PhpToUnicode $converter
23
-    */
24
-    private $converter;
25
-
26
-
27
-    /**
28
-     * @param JsonDataNodeValidator $validator
29
-     * @param PhpToUnicode $converter
30
-     */
31
-    public function __construct(JsonDataNodeValidator $validator, PhpToUnicode $converter)
32
-    {
33
-        $this->converter = $converter;
34
-        parent::__construct($validator);
35
-        $this->setNodeName(GeneralSettings::NODE_NAME);
36
-    }
37
-
38
-
39
-    /**
40
-     * @inheritDoc
41
-     */
42
-    public function initialize()
43
-    {
44
-        $wpDateFormat = get_option('date_format');
45
-        $wpTimeFormat = get_option('time_format');
46
-        $this->addData('dateFormat', $this->converter->convertDateFormat($wpDateFormat));
47
-        $this->addData('timeFormat', $this->converter->convertTimeFormat($wpTimeFormat));
48
-        $this->addData('timezone', get_option('timezone_string'));
49
-        $this->addData('__typename', 'GeneralSettings');
50
-        $this->setInitialized(true);
51
-    }
19
+	const NODE_NAME = 'generalSettings';
20
+
21
+	/**
22
+	 * @var PhpToUnicode $converter
23
+	 */
24
+	private $converter;
25
+
26
+
27
+	/**
28
+	 * @param JsonDataNodeValidator $validator
29
+	 * @param PhpToUnicode $converter
30
+	 */
31
+	public function __construct(JsonDataNodeValidator $validator, PhpToUnicode $converter)
32
+	{
33
+		$this->converter = $converter;
34
+		parent::__construct($validator);
35
+		$this->setNodeName(GeneralSettings::NODE_NAME);
36
+	}
37
+
38
+
39
+	/**
40
+	 * @inheritDoc
41
+	 */
42
+	public function initialize()
43
+	{
44
+		$wpDateFormat = get_option('date_format');
45
+		$wpTimeFormat = get_option('time_format');
46
+		$this->addData('dateFormat', $this->converter->convertDateFormat($wpDateFormat));
47
+		$this->addData('timeFormat', $this->converter->convertTimeFormat($wpTimeFormat));
48
+		$this->addData('timezone', get_option('timezone_string'));
49
+		$this->addData('__typename', 'GeneralSettings');
50
+		$this->setInitialized(true);
51
+	}
52 52
 }
Please login to merge, or discard this patch.
core/domain/services/assets/EspressoLegacyAdminAssetManager.php 2 patches
Spacing   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -74,7 +74,7 @@  discard block
 block discarded – undo
74 74
     {
75 75
         $this->addJavascript(
76 76
             EspressoLegacyAdminAssetManager::JS_HANDLE_EE_DIALOG,
77
-            EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
77
+            EE_ADMIN_URL.'assets/ee-dialog-helper.js',
78 78
             [
79 79
                 JqueryAssetManager::JS_HANDLE_JQUERY,
80 80
                 JqueryAssetManager::JS_HANDLE_JQUERY_UI_DRAGGABLE,
@@ -83,7 +83,7 @@  discard block
 block discarded – undo
83 83
 
84 84
         $this->addJavascript(
85 85
             EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
86
-            EE_ADMIN_URL . 'assets/ee-admin-page.js',
86
+            EE_ADMIN_URL.'assets/ee-admin-page.js',
87 87
             [
88 88
                 CoreAssetManager::JS_HANDLE_CORE,
89 89
                 EspressoLegacyAdminAssetManager::JS_HANDLE_PARSE_URI,
@@ -94,7 +94,7 @@  discard block
 block discarded – undo
94 94
         // script for sorting tables
95 95
         $this->addJavascript(
96 96
             EspressoLegacyAdminAssetManager::JS_HANDLE_EE_AJAX_TABLE_SORTING,
97
-            EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
97
+            EE_ADMIN_URL.'assets/espresso_ajax_table_sorting.js',
98 98
             [
99 99
                 EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
100 100
                 JqueryAssetManager::JS_HANDLE_JQUERY_UI_SORTABLE,
@@ -104,13 +104,13 @@  discard block
 block discarded – undo
104 104
         // script for parsing uri's
105 105
         $this->addJavascript(
106 106
             EspressoLegacyAdminAssetManager::JS_HANDLE_PARSE_URI,
107
-            EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js'
107
+            EE_GLOBAL_ASSETS_URL.'scripts/parseuri.js'
108 108
         );
109 109
 
110 110
         // and parsing associative serialized form elements
111 111
         $this->addJavascript(
112 112
             EspressoLegacyAdminAssetManager::JS_HANDLE_EE_SERIALIZE_FULL_ARRAY,
113
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
113
+            EE_GLOBAL_ASSETS_URL.'scripts/jquery.serializefullarray.js',
114 114
             [JqueryAssetManager::JS_HANDLE_JQUERY]
115 115
 
116 116
         );
@@ -118,24 +118,24 @@  discard block
 block discarded – undo
118 118
         // helpers scripts
119 119
         $this->addJavascript(
120 120
             EspressoLegacyAdminAssetManager::JS_HANDLE_EE_TEXT_LINKS,
121
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
121
+            EE_PLUGIN_DIR_URL.'core/helpers/assets/ee_text_list_helper.js',
122 122
             [JqueryAssetManager::JS_HANDLE_JQUERY]
123 123
         );
124 124
 
125 125
         $this->addJavascript(
126 126
             EspressoLegacyAdminAssetManager::JS_HANDLE_MOMENT_CORE,
127
-            EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js'
127
+            EE_THIRD_PARTY_URL.'moment/moment-with-locales.min.js'
128 128
         );
129 129
 
130 130
         $this->addJavascript(
131 131
             EspressoLegacyAdminAssetManager::JS_HANDLE_MOMENT,
132
-            EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js',
132
+            EE_THIRD_PARTY_URL.'moment/moment-timezone-with-data.min.js',
133 133
             [EspressoLegacyAdminAssetManager::JS_HANDLE_MOMENT_CORE]
134 134
         );
135 135
 
136 136
         $this->addJavascript(
137 137
             EspressoLegacyAdminAssetManager::JS_HANDLE_EE_DATEPICKER,
138
-            EE_ADMIN_URL . 'assets/ee-datepicker.js',
138
+            EE_ADMIN_URL.'assets/ee-datepicker.js',
139 139
             [
140 140
                 JqueryAssetManager::JS_HANDLE_JQUERY_UI_TIMEPICKER_ADDON,
141 141
                 EspressoLegacyAdminAssetManager::JS_HANDLE_MOMENT,
@@ -153,7 +153,7 @@  discard block
 block discarded – undo
153 153
         //ie: only injecting on certain script calls.
154 154
         $this->addJavascript(
155 155
             EspressoLegacyAdminAssetManager::JS_HANDLE_EE_INJECT_WP,
156
-            EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
156
+            EE_ADMIN_URL.'assets/ee-cpt-wp-injects.js',
157 157
             [JqueryAssetManager::JS_HANDLE_JQUERY]
158 158
         );
159 159
 
@@ -161,13 +161,13 @@  discard block
 block discarded – undo
161 161
 
162 162
         // joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook,
163 163
         // can be turned back on again via: add_filter('FHEE_load_joyride', '__return_true' );
164
-        if (! $joyride) {
164
+        if ( ! $joyride) {
165 165
             return;
166 166
         }
167 167
 
168 168
         $this->addJavascript(
169 169
             EspressoLegacyAdminAssetManager::JS_HANDLE_JOYRIDE_MODERNIZR,
170
-            EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
170
+            EE_THIRD_PARTY_URL.'joyride/modernizr.mq.js',
171 171
             [],
172 172
             true,
173 173
             '2.1'
@@ -176,7 +176,7 @@  discard block
 block discarded – undo
176 176
         // wanna go for a joyride?
177 177
         $this->addJavascript(
178 178
             EspressoLegacyAdminAssetManager::JS_HANDLE_JQUERY_JOYRIDE,
179
-            EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
179
+            EE_THIRD_PARTY_URL.'joyride/jquery.joyride-2.1.js',
180 180
             [
181 181
                 JqueryAssetManager::JS_HANDLE_JQUERY_COOKIE,
182 182
                 EspressoLegacyAdminAssetManager::JS_HANDLE_JOYRIDE_MODERNIZR,
@@ -187,7 +187,7 @@  discard block
 block discarded – undo
187 187
 
188 188
         $this->addJavascript(
189 189
             EspressoLegacyAdminAssetManager::JS_HANDLE_EE_HELP_TOUR,
190
-            EE_ADMIN_URL . 'assets/ee-help-tour.js',
190
+            EE_ADMIN_URL.'assets/ee-help-tour.js',
191 191
             [
192 192
                 EspressoLegacyAdminAssetManager::JS_HANDLE_JQUERY_JOYRIDE,
193 193
             ],
@@ -207,26 +207,26 @@  discard block
 block discarded – undo
207 207
 
208 208
         $this->addStylesheet(
209 209
             EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_UI_THEME,
210
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css'
210
+            EE_GLOBAL_ASSETS_URL.'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css'
211 211
         );
212 212
 
213 213
         $this->addStylesheet(
214 214
             EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_TEXT_LINKS,
215
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css'
215
+            EE_PLUGIN_DIR_URL.'core/helpers/assets/ee_text_list_helper.css'
216 216
         );
217 217
 
218 218
         $this->addStylesheet(
219 219
             EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN,
220
-            EE_ADMIN_URL . 'assets/ee-admin-page.css'
220
+            EE_ADMIN_URL.'assets/ee-admin-page.css'
221 221
         )->setEnqueueImmediately();
222 222
 
223
-        if (! $joyride) {
223
+        if ( ! $joyride) {
224 224
             return;
225 225
         }
226 226
         // joyride style
227 227
         $this->addStylesheet(
228 228
             EspressoLegacyAdminAssetManager::CSS_HANDLE_JOYRIDE,
229
-            EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css',
229
+            EE_THIRD_PARTY_URL.'joyride/joyride-2.1.css',
230 230
             [],
231 231
             'all',
232 232
             '2.1'
@@ -234,7 +234,7 @@  discard block
 block discarded – undo
234 234
 
235 235
         $this->addStylesheet(
236 236
             EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_JOYRIDE,
237
-            EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
237
+            EE_GLOBAL_ASSETS_URL.'css/ee-joyride-styles.css',
238 238
             [EspressoLegacyAdminAssetManager::CSS_HANDLE_JOYRIDE],
239 239
             'all',
240 240
             EVENT_ESPRESSO_VERSION
Please login to merge, or discard this patch.
Indentation   +225 added lines, -225 removed lines patch added patch discarded remove patch
@@ -15,245 +15,245 @@
 block discarded – undo
15 15
 class EspressoLegacyAdminAssetManager extends AssetManager
16 16
 {
17 17
 
18
-    const JS_HANDLE_EE_ADMIN                = 'ee_admin_js';
18
+	const JS_HANDLE_EE_ADMIN                = 'ee_admin_js';
19 19
 
20
-    const JS_HANDLE_EE_AJAX_TABLE_SORTING   = 'espresso_ajax_table_sorting';
20
+	const JS_HANDLE_EE_AJAX_TABLE_SORTING   = 'espresso_ajax_table_sorting';
21 21
 
22
-    const JS_HANDLE_EE_DATEPICKER           = 'ee-datepicker';
22
+	const JS_HANDLE_EE_DATEPICKER           = 'ee-datepicker';
23 23
 
24
-    const JS_HANDLE_EE_DIALOG               = 'ee-dialog';
24
+	const JS_HANDLE_EE_DIALOG               = 'ee-dialog';
25 25
 
26
-    const JS_HANDLE_EE_HELP_TOUR            = 'ee-help-tour';
26
+	const JS_HANDLE_EE_HELP_TOUR            = 'ee-help-tour';
27 27
 
28
-    const JS_HANDLE_EE_INJECT_WP            = 'ee-inject-wp';
28
+	const JS_HANDLE_EE_INJECT_WP            = 'ee-inject-wp';
29 29
 
30
-    const JS_HANDLE_GOOGLE_CHARTS           = 'google-charts';
30
+	const JS_HANDLE_GOOGLE_CHARTS           = 'google-charts';
31 31
 
32
-    const JS_HANDLE_MOMENT                  = 'ee-moment';
32
+	const JS_HANDLE_MOMENT                  = 'ee-moment';
33 33
 
34
-    const JS_HANDLE_MOMENT_CORE             = 'ee-moment-core';
34
+	const JS_HANDLE_MOMENT_CORE             = 'ee-moment-core';
35 35
 
36
-    const JS_HANDLE_PARSE_URI               = 'ee-parse-uri';
36
+	const JS_HANDLE_PARSE_URI               = 'ee-parse-uri';
37 37
 
38
-    const JS_HANDLE_EE_TEXT_LINKS           = 'ee-text-links';
38
+	const JS_HANDLE_EE_TEXT_LINKS           = 'ee-text-links';
39 39
 
40
-    const JS_HANDLE_EE_SERIALIZE_FULL_ARRAY = 'ee-serialize-full-array';
40
+	const JS_HANDLE_EE_SERIALIZE_FULL_ARRAY = 'ee-serialize-full-array';
41 41
 
42
-    const JS_HANDLE_JOYRIDE_MODERNIZR       = 'joyride-modernizr';
42
+	const JS_HANDLE_JOYRIDE_MODERNIZR       = 'joyride-modernizr';
43 43
 
44
-    const JS_HANDLE_JQUERY_JOYRIDE          = 'jquery-joyride';
44
+	const JS_HANDLE_JQUERY_JOYRIDE          = 'jquery-joyride';
45 45
 
46
-    const CSS_HANDLE_EE_ADMIN               = 'ee-admin-css';
46
+	const CSS_HANDLE_EE_ADMIN               = 'ee-admin-css';
47 47
 
48
-    const CSS_HANDLE_EE_JOYRIDE             = 'ee-joyride-css';
49
-
50
-    const CSS_HANDLE_EE_TEXT_LINKS          = 'ee-text-links';
48
+	const CSS_HANDLE_EE_JOYRIDE             = 'ee-joyride-css';
49
+
50
+	const CSS_HANDLE_EE_TEXT_LINKS          = 'ee-text-links';
51 51
 
52
-    const CSS_HANDLE_EE_UI_THEME            = 'espresso-ui-theme';
53
-
54
-    const CSS_HANDLE_JOYRIDE                = 'joyride-css';
55
-
56
-
57
-    /**
58
-     * @inheritDoc
59
-     */
60
-    public function addAssets()
61
-    {
62
-        $joyride = filter_var(apply_filters('FHEE_load_joyride', false), FILTER_VALIDATE_BOOLEAN);
63
-        $this->registerJavascript($joyride);
64
-        $this->registerStyleSheets($joyride);
65
-    }
66
-
67
-
68
-    /**
69
-     * Register javascript assets
70
-     *
71
-     * @param bool $joyride
72
-     */
73
-    private function registerJavascript($joyride = false)
74
-    {
75
-        $this->addJavascript(
76
-            EspressoLegacyAdminAssetManager::JS_HANDLE_EE_DIALOG,
77
-            EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
78
-            [
79
-                JqueryAssetManager::JS_HANDLE_JQUERY,
80
-                JqueryAssetManager::JS_HANDLE_JQUERY_UI_DRAGGABLE,
81
-            ]
82
-        );
83
-
84
-        $this->addJavascript(
85
-            EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
86
-            EE_ADMIN_URL . 'assets/ee-admin-page.js',
87
-            [
88
-                CoreAssetManager::JS_HANDLE_CORE,
89
-                EspressoLegacyAdminAssetManager::JS_HANDLE_PARSE_URI,
90
-                EspressoLegacyAdminAssetManager::JS_HANDLE_EE_DIALOG,
91
-            ]
92
-        );
93
-
94
-        // script for sorting tables
95
-        $this->addJavascript(
96
-            EspressoLegacyAdminAssetManager::JS_HANDLE_EE_AJAX_TABLE_SORTING,
97
-            EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
98
-            [
99
-                EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
100
-                JqueryAssetManager::JS_HANDLE_JQUERY_UI_SORTABLE,
101
-            ]
102
-        );
103
-
104
-        // script for parsing uri's
105
-        $this->addJavascript(
106
-            EspressoLegacyAdminAssetManager::JS_HANDLE_PARSE_URI,
107
-            EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js'
108
-        );
109
-
110
-        // and parsing associative serialized form elements
111
-        $this->addJavascript(
112
-            EspressoLegacyAdminAssetManager::JS_HANDLE_EE_SERIALIZE_FULL_ARRAY,
113
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
114
-            [JqueryAssetManager::JS_HANDLE_JQUERY]
115
-
116
-        );
117
-
118
-        // helpers scripts
119
-        $this->addJavascript(
120
-            EspressoLegacyAdminAssetManager::JS_HANDLE_EE_TEXT_LINKS,
121
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
122
-            [JqueryAssetManager::JS_HANDLE_JQUERY]
123
-        );
124
-
125
-        $this->addJavascript(
126
-            EspressoLegacyAdminAssetManager::JS_HANDLE_MOMENT_CORE,
127
-            EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js'
128
-        );
129
-
130
-        $this->addJavascript(
131
-            EspressoLegacyAdminAssetManager::JS_HANDLE_MOMENT,
132
-            EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js',
133
-            [EspressoLegacyAdminAssetManager::JS_HANDLE_MOMENT_CORE]
134
-        );
135
-
136
-        $this->addJavascript(
137
-            EspressoLegacyAdminAssetManager::JS_HANDLE_EE_DATEPICKER,
138
-            EE_ADMIN_URL . 'assets/ee-datepicker.js',
139
-            [
140
-                JqueryAssetManager::JS_HANDLE_JQUERY_UI_TIMEPICKER_ADDON,
141
-                EspressoLegacyAdminAssetManager::JS_HANDLE_MOMENT,
142
-            ]
143
-        );
144
-
145
-        // google charts
146
-        $this->addJavascript(
147
-            EspressoLegacyAdminAssetManager::JS_HANDLE_GOOGLE_CHARTS,
148
-            'https://www.gstatic.com/charts/loader.js'
149
-        );
150
-
151
-        // this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
152
-        // Note: the intention of this script is to only do TARGETED injections.
153
-        //ie: only injecting on certain script calls.
154
-        $this->addJavascript(
155
-            EspressoLegacyAdminAssetManager::JS_HANDLE_EE_INJECT_WP,
156
-            EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
157
-            [JqueryAssetManager::JS_HANDLE_JQUERY]
158
-        );
159
-
160
-        $this->loadQtipJs();
161
-
162
-        // joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook,
163
-        // can be turned back on again via: add_filter('FHEE_load_joyride', '__return_true' );
164
-        if (! $joyride) {
165
-            return;
166
-        }
167
-
168
-        $this->addJavascript(
169
-            EspressoLegacyAdminAssetManager::JS_HANDLE_JOYRIDE_MODERNIZR,
170
-            EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
171
-            [],
172
-            true,
173
-            '2.1'
174
-        );
175
-
176
-        // wanna go for a joyride?
177
-        $this->addJavascript(
178
-            EspressoLegacyAdminAssetManager::JS_HANDLE_JQUERY_JOYRIDE,
179
-            EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
180
-            [
181
-                JqueryAssetManager::JS_HANDLE_JQUERY_COOKIE,
182
-                EspressoLegacyAdminAssetManager::JS_HANDLE_JOYRIDE_MODERNIZR,
183
-            ],
184
-            true,
185
-            '2.1'
186
-        )->setEnqueueImmediately();
187
-
188
-        $this->addJavascript(
189
-            EspressoLegacyAdminAssetManager::JS_HANDLE_EE_HELP_TOUR,
190
-            EE_ADMIN_URL . 'assets/ee-help-tour.js',
191
-            [
192
-                EspressoLegacyAdminAssetManager::JS_HANDLE_JQUERY_JOYRIDE,
193
-            ],
194
-            true,
195
-            '2.1'
196
-        )->setEnqueueImmediately();
197
-    }
198
-
199
-
200
-    /**
201
-     * Register CSS assets.
202
-     *
203
-     * @param bool $joyride
204
-     */
205
-    private function registerStyleSheets($joyride = false)
206
-    {
207
-
208
-        $this->addStylesheet(
209
-            EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_UI_THEME,
210
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css'
211
-        );
212
-
213
-        $this->addStylesheet(
214
-            EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_TEXT_LINKS,
215
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css'
216
-        );
217
-
218
-        $this->addStylesheet(
219
-            EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN,
220
-            EE_ADMIN_URL . 'assets/ee-admin-page.css'
221
-        )->setEnqueueImmediately();
222
-
223
-        if (! $joyride) {
224
-            return;
225
-        }
226
-        // joyride style
227
-        $this->addStylesheet(
228
-            EspressoLegacyAdminAssetManager::CSS_HANDLE_JOYRIDE,
229
-            EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css',
230
-            [],
231
-            'all',
232
-            '2.1'
233
-        );
234
-
235
-        $this->addStylesheet(
236
-            EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_JOYRIDE,
237
-            EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
238
-            [EspressoLegacyAdminAssetManager::CSS_HANDLE_JOYRIDE],
239
-            'all',
240
-            EVENT_ESPRESSO_VERSION
241
-        )->setEnqueueImmediately();
242
-    }
243
-
244
-
245
-    /**
246
-     * registers assets for cleaning your ears
247
-     */
248
-    public function loadQtipJs()
249
-    {
250
-        // qtip is turned OFF by default, but prior to the wp_enqueue_scripts hook,
251
-        // can be turned back on again via: add_filter('FHEE_load_qtip', '__return_true' );
252
-        if (apply_filters('FHEE_load_qtip', false)) {
253
-            $qtip_loader = EEH_Qtip_Loader::instance();
254
-            if ($qtip_loader instanceof EEH_Qtip_Loader) {
255
-                $qtip_loader->register_and_enqueue();
256
-            }
257
-        }
258
-    }
52
+	const CSS_HANDLE_EE_UI_THEME            = 'espresso-ui-theme';
53
+
54
+	const CSS_HANDLE_JOYRIDE                = 'joyride-css';
55
+
56
+
57
+	/**
58
+	 * @inheritDoc
59
+	 */
60
+	public function addAssets()
61
+	{
62
+		$joyride = filter_var(apply_filters('FHEE_load_joyride', false), FILTER_VALIDATE_BOOLEAN);
63
+		$this->registerJavascript($joyride);
64
+		$this->registerStyleSheets($joyride);
65
+	}
66
+
67
+
68
+	/**
69
+	 * Register javascript assets
70
+	 *
71
+	 * @param bool $joyride
72
+	 */
73
+	private function registerJavascript($joyride = false)
74
+	{
75
+		$this->addJavascript(
76
+			EspressoLegacyAdminAssetManager::JS_HANDLE_EE_DIALOG,
77
+			EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
78
+			[
79
+				JqueryAssetManager::JS_HANDLE_JQUERY,
80
+				JqueryAssetManager::JS_HANDLE_JQUERY_UI_DRAGGABLE,
81
+			]
82
+		);
83
+
84
+		$this->addJavascript(
85
+			EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
86
+			EE_ADMIN_URL . 'assets/ee-admin-page.js',
87
+			[
88
+				CoreAssetManager::JS_HANDLE_CORE,
89
+				EspressoLegacyAdminAssetManager::JS_HANDLE_PARSE_URI,
90
+				EspressoLegacyAdminAssetManager::JS_HANDLE_EE_DIALOG,
91
+			]
92
+		);
93
+
94
+		// script for sorting tables
95
+		$this->addJavascript(
96
+			EspressoLegacyAdminAssetManager::JS_HANDLE_EE_AJAX_TABLE_SORTING,
97
+			EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
98
+			[
99
+				EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
100
+				JqueryAssetManager::JS_HANDLE_JQUERY_UI_SORTABLE,
101
+			]
102
+		);
103
+
104
+		// script for parsing uri's
105
+		$this->addJavascript(
106
+			EspressoLegacyAdminAssetManager::JS_HANDLE_PARSE_URI,
107
+			EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js'
108
+		);
109
+
110
+		// and parsing associative serialized form elements
111
+		$this->addJavascript(
112
+			EspressoLegacyAdminAssetManager::JS_HANDLE_EE_SERIALIZE_FULL_ARRAY,
113
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
114
+			[JqueryAssetManager::JS_HANDLE_JQUERY]
115
+
116
+		);
117
+
118
+		// helpers scripts
119
+		$this->addJavascript(
120
+			EspressoLegacyAdminAssetManager::JS_HANDLE_EE_TEXT_LINKS,
121
+			EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
122
+			[JqueryAssetManager::JS_HANDLE_JQUERY]
123
+		);
124
+
125
+		$this->addJavascript(
126
+			EspressoLegacyAdminAssetManager::JS_HANDLE_MOMENT_CORE,
127
+			EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js'
128
+		);
129
+
130
+		$this->addJavascript(
131
+			EspressoLegacyAdminAssetManager::JS_HANDLE_MOMENT,
132
+			EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js',
133
+			[EspressoLegacyAdminAssetManager::JS_HANDLE_MOMENT_CORE]
134
+		);
135
+
136
+		$this->addJavascript(
137
+			EspressoLegacyAdminAssetManager::JS_HANDLE_EE_DATEPICKER,
138
+			EE_ADMIN_URL . 'assets/ee-datepicker.js',
139
+			[
140
+				JqueryAssetManager::JS_HANDLE_JQUERY_UI_TIMEPICKER_ADDON,
141
+				EspressoLegacyAdminAssetManager::JS_HANDLE_MOMENT,
142
+			]
143
+		);
144
+
145
+		// google charts
146
+		$this->addJavascript(
147
+			EspressoLegacyAdminAssetManager::JS_HANDLE_GOOGLE_CHARTS,
148
+			'https://www.gstatic.com/charts/loader.js'
149
+		);
150
+
151
+		// this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
152
+		// Note: the intention of this script is to only do TARGETED injections.
153
+		//ie: only injecting on certain script calls.
154
+		$this->addJavascript(
155
+			EspressoLegacyAdminAssetManager::JS_HANDLE_EE_INJECT_WP,
156
+			EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
157
+			[JqueryAssetManager::JS_HANDLE_JQUERY]
158
+		);
159
+
160
+		$this->loadQtipJs();
161
+
162
+		// joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook,
163
+		// can be turned back on again via: add_filter('FHEE_load_joyride', '__return_true' );
164
+		if (! $joyride) {
165
+			return;
166
+		}
167
+
168
+		$this->addJavascript(
169
+			EspressoLegacyAdminAssetManager::JS_HANDLE_JOYRIDE_MODERNIZR,
170
+			EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
171
+			[],
172
+			true,
173
+			'2.1'
174
+		);
175
+
176
+		// wanna go for a joyride?
177
+		$this->addJavascript(
178
+			EspressoLegacyAdminAssetManager::JS_HANDLE_JQUERY_JOYRIDE,
179
+			EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
180
+			[
181
+				JqueryAssetManager::JS_HANDLE_JQUERY_COOKIE,
182
+				EspressoLegacyAdminAssetManager::JS_HANDLE_JOYRIDE_MODERNIZR,
183
+			],
184
+			true,
185
+			'2.1'
186
+		)->setEnqueueImmediately();
187
+
188
+		$this->addJavascript(
189
+			EspressoLegacyAdminAssetManager::JS_HANDLE_EE_HELP_TOUR,
190
+			EE_ADMIN_URL . 'assets/ee-help-tour.js',
191
+			[
192
+				EspressoLegacyAdminAssetManager::JS_HANDLE_JQUERY_JOYRIDE,
193
+			],
194
+			true,
195
+			'2.1'
196
+		)->setEnqueueImmediately();
197
+	}
198
+
199
+
200
+	/**
201
+	 * Register CSS assets.
202
+	 *
203
+	 * @param bool $joyride
204
+	 */
205
+	private function registerStyleSheets($joyride = false)
206
+	{
207
+
208
+		$this->addStylesheet(
209
+			EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_UI_THEME,
210
+			EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css'
211
+		);
212
+
213
+		$this->addStylesheet(
214
+			EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_TEXT_LINKS,
215
+			EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css'
216
+		);
217
+
218
+		$this->addStylesheet(
219
+			EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_ADMIN,
220
+			EE_ADMIN_URL . 'assets/ee-admin-page.css'
221
+		)->setEnqueueImmediately();
222
+
223
+		if (! $joyride) {
224
+			return;
225
+		}
226
+		// joyride style
227
+		$this->addStylesheet(
228
+			EspressoLegacyAdminAssetManager::CSS_HANDLE_JOYRIDE,
229
+			EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css',
230
+			[],
231
+			'all',
232
+			'2.1'
233
+		);
234
+
235
+		$this->addStylesheet(
236
+			EspressoLegacyAdminAssetManager::CSS_HANDLE_EE_JOYRIDE,
237
+			EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
238
+			[EspressoLegacyAdminAssetManager::CSS_HANDLE_JOYRIDE],
239
+			'all',
240
+			EVENT_ESPRESSO_VERSION
241
+		)->setEnqueueImmediately();
242
+	}
243
+
244
+
245
+	/**
246
+	 * registers assets for cleaning your ears
247
+	 */
248
+	public function loadQtipJs()
249
+	{
250
+		// qtip is turned OFF by default, but prior to the wp_enqueue_scripts hook,
251
+		// can be turned back on again via: add_filter('FHEE_load_qtip', '__return_true' );
252
+		if (apply_filters('FHEE_load_qtip', false)) {
253
+			$qtip_loader = EEH_Qtip_Loader::instance();
254
+			if ($qtip_loader instanceof EEH_Qtip_Loader) {
255
+				$qtip_loader->register_and_enqueue();
256
+			}
257
+		}
258
+	}
259 259
 }
Please login to merge, or discard this patch.
core/services/assets/AssetManagerInterface.php 1 patch
Indentation   +61 added lines, -61 removed lines patch added patch discarded remove patch
@@ -18,75 +18,75 @@
 block discarded – undo
18 18
  */
19 19
 interface AssetManagerInterface
20 20
 {
21
-    /**
22
-     * @since 4.9.71.p
23
-     * @return string
24
-     */
25
-    public function assetNamespace();
21
+	/**
22
+	 * @since 4.9.71.p
23
+	 * @return string
24
+	 */
25
+	public function assetNamespace();
26 26
 
27
-    /**
28
-     * @since 4.9.62.p
29
-     */
30
-    public function addAssets();
27
+	/**
28
+	 * @since 4.9.62.p
29
+	 */
30
+	public function addAssets();
31 31
 
32 32
 
33
-    /**
34
-     * @param string $handle
35
-     * @param string $source
36
-     * @param array  $dependencies
37
-     * @param bool   $load_in_footer
38
-     * @return JavascriptAsset
39
-     * @throws DuplicateCollectionIdentifierException
40
-     * @throws InvalidDataTypeException
41
-     * @throws InvalidEntityException
42
-     * @since 4.9.62.p
43
-     */
44
-    public function addJavascript(
45
-        $handle,
46
-        $source,
47
-        array $dependencies = array(),
48
-        $load_in_footer = true
49
-    );
33
+	/**
34
+	 * @param string $handle
35
+	 * @param string $source
36
+	 * @param array  $dependencies
37
+	 * @param bool   $load_in_footer
38
+	 * @return JavascriptAsset
39
+	 * @throws DuplicateCollectionIdentifierException
40
+	 * @throws InvalidDataTypeException
41
+	 * @throws InvalidEntityException
42
+	 * @since 4.9.62.p
43
+	 */
44
+	public function addJavascript(
45
+		$handle,
46
+		$source,
47
+		array $dependencies = array(),
48
+		$load_in_footer = true
49
+	);
50 50
 
51 51
 
52
-    /**
53
-     * @since 4.9.71.p
54
-     * @param string $handle
55
-     * @param array  $dependencies
56
-     * @param bool   $load_in_footer
57
-     * @return JavascriptAsset
58
-     */
59
-    public function addVendorJavascript(
60
-        $handle,
61
-        array $dependencies = array(),
62
-        $load_in_footer = true
63
-    );
52
+	/**
53
+	 * @since 4.9.71.p
54
+	 * @param string $handle
55
+	 * @param array  $dependencies
56
+	 * @param bool   $load_in_footer
57
+	 * @return JavascriptAsset
58
+	 */
59
+	public function addVendorJavascript(
60
+		$handle,
61
+		array $dependencies = array(),
62
+		$load_in_footer = true
63
+	);
64 64
 
65 65
 
66 66
 
67
-    /**
68
-     * @param string $handle
69
-     * @param string $source
70
-     * @param array  $dependencies
71
-     * @param string $media
72
-     * @return StylesheetAsset
73
-     * @throws DuplicateCollectionIdentifierException
74
-     * @throws InvalidDataTypeException
75
-     * @throws InvalidEntityException
76
-     * @since 4.9.62.p
77
-     */
78
-    public function addStylesheet(
79
-        $handle,
80
-        $source,
81
-        array $dependencies = array(),
82
-        $media = 'all'
83
-    );
67
+	/**
68
+	 * @param string $handle
69
+	 * @param string $source
70
+	 * @param array  $dependencies
71
+	 * @param string $media
72
+	 * @return StylesheetAsset
73
+	 * @throws DuplicateCollectionIdentifierException
74
+	 * @throws InvalidDataTypeException
75
+	 * @throws InvalidEntityException
76
+	 * @since 4.9.62.p
77
+	 */
78
+	public function addStylesheet(
79
+		$handle,
80
+		$source,
81
+		array $dependencies = array(),
82
+		$media = 'all'
83
+	);
84 84
 
85 85
 
86
-    /**
87
-     * @param string $handle
88
-     * @return bool
89
-     * @since 4.9.62.p
90
-     */
91
-    public function enqueueAsset($handle);
86
+	/**
87
+	 * @param string $handle
88
+	 * @return bool
89
+	 * @since 4.9.62.p
90
+	 */
91
+	public function enqueueAsset($handle);
92 92
 }
Please login to merge, or discard this patch.
core/domain/values/assets/ManifestFile.php 1 patch
Indentation   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -16,32 +16,32 @@
 block discarded – undo
16 16
 class ManifestFile extends Asset
17 17
 {
18 18
 
19
-    /**
20
-     * Asset constructor.
21
-     *
22
-     * @param DomainInterface $domain
23
-     * @throws InvalidDataTypeException
24
-     */
25
-    public function __construct(DomainInterface $domain)
26
-    {
27
-        parent::__construct(Asset::TYPE_MANIFEST, $domain->assetNamespace(), $domain);
28
-    }
29
-
30
-
31
-    /**
32
-     * @return string
33
-     */
34
-    public function urlBase()
35
-    {
36
-        return $this->domain->distributionAssetsUrl();
37
-    }
38
-
39
-
40
-    /**
41
-     * @return string
42
-     */
43
-    public function filepath()
44
-    {
45
-        return $this->domain->distributionAssetsPath();
46
-    }
19
+	/**
20
+	 * Asset constructor.
21
+	 *
22
+	 * @param DomainInterface $domain
23
+	 * @throws InvalidDataTypeException
24
+	 */
25
+	public function __construct(DomainInterface $domain)
26
+	{
27
+		parent::__construct(Asset::TYPE_MANIFEST, $domain->assetNamespace(), $domain);
28
+	}
29
+
30
+
31
+	/**
32
+	 * @return string
33
+	 */
34
+	public function urlBase()
35
+	{
36
+		return $this->domain->distributionAssetsUrl();
37
+	}
38
+
39
+
40
+	/**
41
+	 * @return string
42
+	 */
43
+	public function filepath()
44
+	{
45
+		return $this->domain->distributionAssetsPath();
46
+	}
47 47
 }
Please login to merge, or discard this patch.
core/services/factory/StaticFactoryInterface.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -11,10 +11,10 @@
 block discarded – undo
11 11
 interface StaticFactoryInterface
12 12
 {
13 13
 
14
-    /**
15
-     * @param string $fqcn      Fully Qualified Class Name
16
-     * @param array  $arguments [optional] array of data required for construction
17
-     * @return mixed
18
-     */
19
-    public static function create($fqcn, array $arguments = []);
14
+	/**
15
+	 * @param string $fqcn      Fully Qualified Class Name
16
+	 * @param array  $arguments [optional] array of data required for construction
17
+	 * @return mixed
18
+	 */
19
+	public static function create($fqcn, array $arguments = []);
20 20
 }
Please login to merge, or discard this patch.