Completed
Branch back-compat-edtr-taxes (752e0e)
by
unknown
12:08 queued 09:43
created
caffeinated/modules/recaptcha_invisible/EED_Recaptcha_Invisible.module.php 2 patches
Indentation   +328 added lines, -328 removed lines patch added patch discarded remove patch
@@ -18,332 +18,332 @@
 block discarded – undo
18 18
 class EED_Recaptcha_Invisible extends EED_Module
19 19
 {
20 20
 
21
-    /**
22
-     * @var EE_Registration_Config $config
23
-     */
24
-    private static $config;
25
-
26
-
27
-    /**
28
-     * @return EED_Module|EED_Recaptcha
29
-     */
30
-    public static function instance()
31
-    {
32
-        return parent::get_instance(__CLASS__);
33
-    }
34
-
35
-
36
-    /**
37
-     * @return void
38
-     * @throws InvalidInterfaceException
39
-     * @throws InvalidDataTypeException
40
-     * @throws InvalidArgumentException
41
-     */
42
-    public static function set_hooks()
43
-    {
44
-        EED_Recaptcha_Invisible::setProperties();
45
-        if (EED_Recaptcha_Invisible::useInvisibleRecaptcha()) {
46
-            if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) {
47
-                // ticket selection
48
-                add_filter(
49
-                    'FHEE__EE_Ticket_Selector__after_ticket_selector_submit',
50
-                    array('EED_Recaptcha_Invisible', 'ticketSelectorForm'),
51
-                    10,
52
-                    3
53
-                );
54
-                add_action(
55
-                    'EED_Ticket_Selector__process_ticket_selections__before',
56
-                    array('EED_Recaptcha_Invisible', 'processTicketSelectorForm')
57
-                );
58
-            }
59
-            if (EED_Recaptcha_Invisible::protectForm('registration_form')) {
60
-                // checkout
61
-                add_action(
62
-                    'AHEE__EE_SPCO_Reg_Step__display_reg_form__reg_form',
63
-                    array('EED_Recaptcha_Invisible', 'spcoRegStepForm')
64
-                );
65
-                add_filter(
66
-                    'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
67
-                    array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'),
68
-                    10,
69
-                    2
70
-                );
71
-            }
72
-            add_action('loop_end', array('EED_Recaptcha_Invisible', 'localizeScriptVars'));
73
-        }
74
-    }
75
-
76
-
77
-    /**
78
-     * @return void
79
-     * @throws InvalidInterfaceException
80
-     * @throws InvalidDataTypeException
81
-     * @throws InvalidArgumentException
82
-     */
83
-    public static function set_hooks_admin()
84
-    {
85
-        EED_Recaptcha_Invisible::setProperties();
86
-        if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) {
87
-            add_action(
88
-                'EED_Ticket_Selector__process_ticket_selections__before',
89
-                array('EED_Recaptcha_Invisible', 'processTicketSelectorForm')
90
-            );
91
-        }
92
-        if (EED_Recaptcha_Invisible::protectForm('registration_form')) {
93
-            add_filter(
94
-                'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
95
-                array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'),
96
-                10,
97
-                2
98
-            );
99
-        }
100
-        // admin settings
101
-        add_action(
102
-            'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
103
-            array('EED_Recaptcha_Invisible', 'adminSettings')
104
-        );
105
-        add_filter(
106
-            'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration',
107
-            array('EED_Recaptcha_Invisible', 'updateAdminSettings')
108
-        );
109
-    }
110
-
111
-
112
-    /**
113
-     * @return void
114
-     * @throws InvalidInterfaceException
115
-     * @throws InvalidDataTypeException
116
-     * @throws InvalidArgumentException
117
-     */
118
-    public static function setProperties()
119
-    {
120
-
121
-        EED_Recaptcha_Invisible::$config = EE_Registry::instance()->CFG->registration;
122
-    }
123
-
124
-
125
-    /**
126
-     * @return boolean
127
-     */
128
-    public static function useInvisibleRecaptcha()
129
-    {
130
-        return EED_Recaptcha_Invisible::$config->use_captcha
131
-               && EED_Recaptcha_Invisible::$config->recaptcha_theme === 'invisible';
132
-    }
133
-
134
-
135
-    /**
136
-     * @param string $form
137
-     * @return boolean
138
-     */
139
-    public static function protectForm($form)
140
-    {
141
-        return is_array(EED_Recaptcha_Invisible::$config->recaptcha_protected_forms)
142
-               && in_array($form, EED_Recaptcha_Invisible::$config->recaptcha_protected_forms, true);
143
-    }
144
-
145
-
146
-    /**
147
-     * @return void
148
-     * @throws InvalidInterfaceException
149
-     * @throws InvalidDataTypeException
150
-     * @throws InvalidArgumentException
151
-     */
152
-    public static function localizeScriptVars()
153
-    {
154
-        /** @var \EventEspresso\core\services\request\Request $request */
155
-        $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request');
156
-        // Invisible Recaptcha is ONLY ever required for the frontend and admin
157
-        // so we don't need to load any JS assets for other types of requests (like AJAX or API).
158
-        if (! ($request->isAdmin() || $request->isFrontend())) {
159
-            return;
160
-        }
161
-        wp_localize_script(
162
-            EE_Invisible_Recaptcha_Input::SCRIPT_HANDLE_ESPRESSO_INVISIBLE_RECAPTCHA,
163
-            'eeRecaptcha',
164
-            RecaptchaFactory::create()->getLocalizedVars()
165
-        );
166
-    }
167
-
168
-
169
-    /**
170
-     * @return string
171
-     */
172
-    public static function assetsUrl()
173
-    {
174
-        return plugin_dir_url(__FILE__) . 'assets/';
175
-    }
176
-
177
-
178
-    /**
179
-     * @param \WP $WP
180
-     */
181
-    public function run($WP)
182
-    {
183
-    }
184
-
185
-
186
-    /**
187
-     * @param RequestInterface $request
188
-     * @return bool
189
-     * @throws InvalidArgumentException
190
-     * @throws InvalidDataTypeException
191
-     * @throws InvalidInterfaceException
192
-     * @throws RuntimeException
193
-     */
194
-    public static function verifyToken(RequestInterface $request)
195
-    {
196
-        return RecaptchaFactory::create()->verifyToken($request);
197
-    }
198
-
199
-
200
-    /**
201
-     * @param EE_Form_Section_Proper $reg_form
202
-     * @return void
203
-     * @throws EE_Error
204
-     * @throws InvalidArgumentException
205
-     * @throws InvalidDataTypeException
206
-     * @throws InvalidInterfaceException
207
-     * @throws DomainException
208
-     */
209
-    public static function spcoRegStepForm(EE_Form_Section_Proper $reg_form)
210
-    {
211
-        // do nothing if form isn't for a reg step or test has already been passed
212
-        if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
213
-            return;
214
-        }
215
-        $default_hidden_inputs = $reg_form->get_subsection('default_hidden_inputs');
216
-        if ($default_hidden_inputs instanceof EE_Form_Section_Proper) {
217
-            $invisible_recaptcha = RecaptchaFactory::create();
218
-            $invisible_recaptcha->addToFormSection($default_hidden_inputs);
219
-        }
220
-    }
221
-
222
-
223
-    /**
224
-     * @param EE_Form_Section_Proper $reg_form
225
-     * @return bool
226
-     * @throws InvalidDataTypeException
227
-     * @throws InvalidInterfaceException
228
-     * @throws EE_Error
229
-     * @throws InvalidArgumentException
230
-     */
231
-    public static function processSpcoRegStepForm(EE_Form_Section_Proper $reg_form)
232
-    {
233
-        return strpos($reg_form->name(), 'reg-step-form') !== false
234
-               && ! RecaptchaFactory::create()->recaptchaPassed();
235
-    }
236
-
237
-
238
-    /**
239
-     * @param array|null             $req_data
240
-     * @param EE_Form_Section_Proper $reg_form
241
-     * @return array
242
-     * @throws EE_Error
243
-     * @throws InvalidArgumentException
244
-     * @throws InvalidDataTypeException
245
-     * @throws InvalidInterfaceException
246
-     * @throws RuntimeException
247
-     */
248
-    public static function receiveSpcoRegStepForm($req_data = array(), EE_Form_Section_Proper $reg_form)
249
-    {
250
-        // do nothing if form isn't for a reg step or test has already been passed
251
-        if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
252
-            return $req_data;
253
-        }
254
-        /** @var RequestInterface $request */
255
-        $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
256
-        if (! EED_Recaptcha_Invisible::verifyToken($request)) {
257
-            if ($request->isAjax()) {
258
-                $json_response = new EE_SPCO_JSON_Response();
259
-                $json_response->echoAndExit();
260
-            }
261
-            EEH_URL::safeRedirectAndExit(
262
-                EE_Registry::instance()->CFG->core->reg_page_url()
263
-            );
264
-        }
265
-        return $req_data;
266
-    }
267
-
268
-
269
-    /**
270
-     * @param string   $html
271
-     * @param EE_Event $event
272
-     * @param bool     $iframe
273
-     * @return string
274
-     * @throws EE_Error
275
-     * @throws InvalidArgumentException
276
-     * @throws InvalidDataTypeException
277
-     * @throws InvalidInterfaceException
278
-     * @throws ReflectionException
279
-     * @throws DomainException
280
-     */
281
-    public static function ticketSelectorForm($html = '', EE_Event $event, $iframe = false)
282
-    {
283
-        $recaptcha = RecaptchaFactory::create();
284
-        // do nothing if test has  already  been passed
285
-        if ($recaptcha->recaptchaPassed()) {
286
-            return $html;
287
-        }
288
-        $html .= $recaptcha->getInputHtml(
289
-            array(
290
-                'recaptcha_id'   => $event->ID(),
291
-                'iframe'         => $iframe,
292
-                'localized_vars' => $recaptcha->getLocalizedVars(),
293
-            )
294
-        );
295
-        return $html;
296
-    }
297
-
298
-
299
-    /**
300
-     * @return void
301
-     * @throws InvalidArgumentException
302
-     * @throws InvalidInterfaceException
303
-     * @throws InvalidDataTypeException
304
-     * @throws RuntimeException
305
-     */
306
-    public static function processTicketSelectorForm()
307
-    {
308
-        // do nothing if test has  already  been passed
309
-        if (RecaptchaFactory::create()->recaptchaPassed()) {
310
-            return;
311
-        }
312
-        /** @var RequestInterface $request */
313
-        $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
314
-        if (! EED_Recaptcha_Invisible::verifyToken($request)) {
315
-            $event_id = $request->getRequestParam('tkt-slctr-event-id', 0, 'int');
316
-            $return_url = $request->requestParamIsSet("tkt-slctr-return-url-{$event_id}")
317
-                ? $request->getRequestParam("tkt-slctr-return-url-{$event_id}")
318
-                : get_permalink($event_id);
319
-            EEH_URL::safeRedirectAndExit($return_url);
320
-        }
321
-    }
322
-
323
-
324
-    /**
325
-     * @throws EE_Error
326
-     * @throws InvalidArgumentException
327
-     * @throws InvalidDataTypeException
328
-     * @throws InvalidInterfaceException
329
-     */
330
-    public static function adminSettings()
331
-    {
332
-        RecaptchaFactory::getAdminModule()->adminSettings();
333
-    }
334
-
335
-
336
-    /**
337
-     * @param EE_Registration_Config $EE_Registration_Config
338
-     * @return EE_Registration_Config
339
-     * @throws EE_Error
340
-     * @throws InvalidArgumentException
341
-     * @throws InvalidDataTypeException
342
-     * @throws InvalidInterfaceException
343
-     * @throws ReflectionException
344
-     */
345
-    public static function updateAdminSettings(EE_Registration_Config $EE_Registration_Config)
346
-    {
347
-        return RecaptchaFactory::getAdminModule()->updateAdminSettings($EE_Registration_Config);
348
-    }
21
+	/**
22
+	 * @var EE_Registration_Config $config
23
+	 */
24
+	private static $config;
25
+
26
+
27
+	/**
28
+	 * @return EED_Module|EED_Recaptcha
29
+	 */
30
+	public static function instance()
31
+	{
32
+		return parent::get_instance(__CLASS__);
33
+	}
34
+
35
+
36
+	/**
37
+	 * @return void
38
+	 * @throws InvalidInterfaceException
39
+	 * @throws InvalidDataTypeException
40
+	 * @throws InvalidArgumentException
41
+	 */
42
+	public static function set_hooks()
43
+	{
44
+		EED_Recaptcha_Invisible::setProperties();
45
+		if (EED_Recaptcha_Invisible::useInvisibleRecaptcha()) {
46
+			if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) {
47
+				// ticket selection
48
+				add_filter(
49
+					'FHEE__EE_Ticket_Selector__after_ticket_selector_submit',
50
+					array('EED_Recaptcha_Invisible', 'ticketSelectorForm'),
51
+					10,
52
+					3
53
+				);
54
+				add_action(
55
+					'EED_Ticket_Selector__process_ticket_selections__before',
56
+					array('EED_Recaptcha_Invisible', 'processTicketSelectorForm')
57
+				);
58
+			}
59
+			if (EED_Recaptcha_Invisible::protectForm('registration_form')) {
60
+				// checkout
61
+				add_action(
62
+					'AHEE__EE_SPCO_Reg_Step__display_reg_form__reg_form',
63
+					array('EED_Recaptcha_Invisible', 'spcoRegStepForm')
64
+				);
65
+				add_filter(
66
+					'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
67
+					array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'),
68
+					10,
69
+					2
70
+				);
71
+			}
72
+			add_action('loop_end', array('EED_Recaptcha_Invisible', 'localizeScriptVars'));
73
+		}
74
+	}
75
+
76
+
77
+	/**
78
+	 * @return void
79
+	 * @throws InvalidInterfaceException
80
+	 * @throws InvalidDataTypeException
81
+	 * @throws InvalidArgumentException
82
+	 */
83
+	public static function set_hooks_admin()
84
+	{
85
+		EED_Recaptcha_Invisible::setProperties();
86
+		if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) {
87
+			add_action(
88
+				'EED_Ticket_Selector__process_ticket_selections__before',
89
+				array('EED_Recaptcha_Invisible', 'processTicketSelectorForm')
90
+			);
91
+		}
92
+		if (EED_Recaptcha_Invisible::protectForm('registration_form')) {
93
+			add_filter(
94
+				'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
95
+				array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'),
96
+				10,
97
+				2
98
+			);
99
+		}
100
+		// admin settings
101
+		add_action(
102
+			'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
103
+			array('EED_Recaptcha_Invisible', 'adminSettings')
104
+		);
105
+		add_filter(
106
+			'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration',
107
+			array('EED_Recaptcha_Invisible', 'updateAdminSettings')
108
+		);
109
+	}
110
+
111
+
112
+	/**
113
+	 * @return void
114
+	 * @throws InvalidInterfaceException
115
+	 * @throws InvalidDataTypeException
116
+	 * @throws InvalidArgumentException
117
+	 */
118
+	public static function setProperties()
119
+	{
120
+
121
+		EED_Recaptcha_Invisible::$config = EE_Registry::instance()->CFG->registration;
122
+	}
123
+
124
+
125
+	/**
126
+	 * @return boolean
127
+	 */
128
+	public static function useInvisibleRecaptcha()
129
+	{
130
+		return EED_Recaptcha_Invisible::$config->use_captcha
131
+			   && EED_Recaptcha_Invisible::$config->recaptcha_theme === 'invisible';
132
+	}
133
+
134
+
135
+	/**
136
+	 * @param string $form
137
+	 * @return boolean
138
+	 */
139
+	public static function protectForm($form)
140
+	{
141
+		return is_array(EED_Recaptcha_Invisible::$config->recaptcha_protected_forms)
142
+			   && in_array($form, EED_Recaptcha_Invisible::$config->recaptcha_protected_forms, true);
143
+	}
144
+
145
+
146
+	/**
147
+	 * @return void
148
+	 * @throws InvalidInterfaceException
149
+	 * @throws InvalidDataTypeException
150
+	 * @throws InvalidArgumentException
151
+	 */
152
+	public static function localizeScriptVars()
153
+	{
154
+		/** @var \EventEspresso\core\services\request\Request $request */
155
+		$request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request');
156
+		// Invisible Recaptcha is ONLY ever required for the frontend and admin
157
+		// so we don't need to load any JS assets for other types of requests (like AJAX or API).
158
+		if (! ($request->isAdmin() || $request->isFrontend())) {
159
+			return;
160
+		}
161
+		wp_localize_script(
162
+			EE_Invisible_Recaptcha_Input::SCRIPT_HANDLE_ESPRESSO_INVISIBLE_RECAPTCHA,
163
+			'eeRecaptcha',
164
+			RecaptchaFactory::create()->getLocalizedVars()
165
+		);
166
+	}
167
+
168
+
169
+	/**
170
+	 * @return string
171
+	 */
172
+	public static function assetsUrl()
173
+	{
174
+		return plugin_dir_url(__FILE__) . 'assets/';
175
+	}
176
+
177
+
178
+	/**
179
+	 * @param \WP $WP
180
+	 */
181
+	public function run($WP)
182
+	{
183
+	}
184
+
185
+
186
+	/**
187
+	 * @param RequestInterface $request
188
+	 * @return bool
189
+	 * @throws InvalidArgumentException
190
+	 * @throws InvalidDataTypeException
191
+	 * @throws InvalidInterfaceException
192
+	 * @throws RuntimeException
193
+	 */
194
+	public static function verifyToken(RequestInterface $request)
195
+	{
196
+		return RecaptchaFactory::create()->verifyToken($request);
197
+	}
198
+
199
+
200
+	/**
201
+	 * @param EE_Form_Section_Proper $reg_form
202
+	 * @return void
203
+	 * @throws EE_Error
204
+	 * @throws InvalidArgumentException
205
+	 * @throws InvalidDataTypeException
206
+	 * @throws InvalidInterfaceException
207
+	 * @throws DomainException
208
+	 */
209
+	public static function spcoRegStepForm(EE_Form_Section_Proper $reg_form)
210
+	{
211
+		// do nothing if form isn't for a reg step or test has already been passed
212
+		if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
213
+			return;
214
+		}
215
+		$default_hidden_inputs = $reg_form->get_subsection('default_hidden_inputs');
216
+		if ($default_hidden_inputs instanceof EE_Form_Section_Proper) {
217
+			$invisible_recaptcha = RecaptchaFactory::create();
218
+			$invisible_recaptcha->addToFormSection($default_hidden_inputs);
219
+		}
220
+	}
221
+
222
+
223
+	/**
224
+	 * @param EE_Form_Section_Proper $reg_form
225
+	 * @return bool
226
+	 * @throws InvalidDataTypeException
227
+	 * @throws InvalidInterfaceException
228
+	 * @throws EE_Error
229
+	 * @throws InvalidArgumentException
230
+	 */
231
+	public static function processSpcoRegStepForm(EE_Form_Section_Proper $reg_form)
232
+	{
233
+		return strpos($reg_form->name(), 'reg-step-form') !== false
234
+			   && ! RecaptchaFactory::create()->recaptchaPassed();
235
+	}
236
+
237
+
238
+	/**
239
+	 * @param array|null             $req_data
240
+	 * @param EE_Form_Section_Proper $reg_form
241
+	 * @return array
242
+	 * @throws EE_Error
243
+	 * @throws InvalidArgumentException
244
+	 * @throws InvalidDataTypeException
245
+	 * @throws InvalidInterfaceException
246
+	 * @throws RuntimeException
247
+	 */
248
+	public static function receiveSpcoRegStepForm($req_data = array(), EE_Form_Section_Proper $reg_form)
249
+	{
250
+		// do nothing if form isn't for a reg step or test has already been passed
251
+		if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
252
+			return $req_data;
253
+		}
254
+		/** @var RequestInterface $request */
255
+		$request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
256
+		if (! EED_Recaptcha_Invisible::verifyToken($request)) {
257
+			if ($request->isAjax()) {
258
+				$json_response = new EE_SPCO_JSON_Response();
259
+				$json_response->echoAndExit();
260
+			}
261
+			EEH_URL::safeRedirectAndExit(
262
+				EE_Registry::instance()->CFG->core->reg_page_url()
263
+			);
264
+		}
265
+		return $req_data;
266
+	}
267
+
268
+
269
+	/**
270
+	 * @param string   $html
271
+	 * @param EE_Event $event
272
+	 * @param bool     $iframe
273
+	 * @return string
274
+	 * @throws EE_Error
275
+	 * @throws InvalidArgumentException
276
+	 * @throws InvalidDataTypeException
277
+	 * @throws InvalidInterfaceException
278
+	 * @throws ReflectionException
279
+	 * @throws DomainException
280
+	 */
281
+	public static function ticketSelectorForm($html = '', EE_Event $event, $iframe = false)
282
+	{
283
+		$recaptcha = RecaptchaFactory::create();
284
+		// do nothing if test has  already  been passed
285
+		if ($recaptcha->recaptchaPassed()) {
286
+			return $html;
287
+		}
288
+		$html .= $recaptcha->getInputHtml(
289
+			array(
290
+				'recaptcha_id'   => $event->ID(),
291
+				'iframe'         => $iframe,
292
+				'localized_vars' => $recaptcha->getLocalizedVars(),
293
+			)
294
+		);
295
+		return $html;
296
+	}
297
+
298
+
299
+	/**
300
+	 * @return void
301
+	 * @throws InvalidArgumentException
302
+	 * @throws InvalidInterfaceException
303
+	 * @throws InvalidDataTypeException
304
+	 * @throws RuntimeException
305
+	 */
306
+	public static function processTicketSelectorForm()
307
+	{
308
+		// do nothing if test has  already  been passed
309
+		if (RecaptchaFactory::create()->recaptchaPassed()) {
310
+			return;
311
+		}
312
+		/** @var RequestInterface $request */
313
+		$request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
314
+		if (! EED_Recaptcha_Invisible::verifyToken($request)) {
315
+			$event_id = $request->getRequestParam('tkt-slctr-event-id', 0, 'int');
316
+			$return_url = $request->requestParamIsSet("tkt-slctr-return-url-{$event_id}")
317
+				? $request->getRequestParam("tkt-slctr-return-url-{$event_id}")
318
+				: get_permalink($event_id);
319
+			EEH_URL::safeRedirectAndExit($return_url);
320
+		}
321
+	}
322
+
323
+
324
+	/**
325
+	 * @throws EE_Error
326
+	 * @throws InvalidArgumentException
327
+	 * @throws InvalidDataTypeException
328
+	 * @throws InvalidInterfaceException
329
+	 */
330
+	public static function adminSettings()
331
+	{
332
+		RecaptchaFactory::getAdminModule()->adminSettings();
333
+	}
334
+
335
+
336
+	/**
337
+	 * @param EE_Registration_Config $EE_Registration_Config
338
+	 * @return EE_Registration_Config
339
+	 * @throws EE_Error
340
+	 * @throws InvalidArgumentException
341
+	 * @throws InvalidDataTypeException
342
+	 * @throws InvalidInterfaceException
343
+	 * @throws ReflectionException
344
+	 */
345
+	public static function updateAdminSettings(EE_Registration_Config $EE_Registration_Config)
346
+	{
347
+		return RecaptchaFactory::getAdminModule()->updateAdminSettings($EE_Registration_Config);
348
+	}
349 349
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -155,7 +155,7 @@  discard block
 block discarded – undo
155 155
         $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request');
156 156
         // Invisible Recaptcha is ONLY ever required for the frontend and admin
157 157
         // so we don't need to load any JS assets for other types of requests (like AJAX or API).
158
-        if (! ($request->isAdmin() || $request->isFrontend())) {
158
+        if ( ! ($request->isAdmin() || $request->isFrontend())) {
159 159
             return;
160 160
         }
161 161
         wp_localize_script(
@@ -171,7 +171,7 @@  discard block
 block discarded – undo
171 171
      */
172 172
     public static function assetsUrl()
173 173
     {
174
-        return plugin_dir_url(__FILE__) . 'assets/';
174
+        return plugin_dir_url(__FILE__).'assets/';
175 175
     }
176 176
 
177 177
 
@@ -209,7 +209,7 @@  discard block
 block discarded – undo
209 209
     public static function spcoRegStepForm(EE_Form_Section_Proper $reg_form)
210 210
     {
211 211
         // do nothing if form isn't for a reg step or test has already been passed
212
-        if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
212
+        if ( ! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
213 213
             return;
214 214
         }
215 215
         $default_hidden_inputs = $reg_form->get_subsection('default_hidden_inputs');
@@ -248,12 +248,12 @@  discard block
 block discarded – undo
248 248
     public static function receiveSpcoRegStepForm($req_data = array(), EE_Form_Section_Proper $reg_form)
249 249
     {
250 250
         // do nothing if form isn't for a reg step or test has already been passed
251
-        if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
251
+        if ( ! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) {
252 252
             return $req_data;
253 253
         }
254 254
         /** @var RequestInterface $request */
255 255
         $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
256
-        if (! EED_Recaptcha_Invisible::verifyToken($request)) {
256
+        if ( ! EED_Recaptcha_Invisible::verifyToken($request)) {
257 257
             if ($request->isAjax()) {
258 258
                 $json_response = new EE_SPCO_JSON_Response();
259 259
                 $json_response->echoAndExit();
@@ -311,7 +311,7 @@  discard block
 block discarded – undo
311 311
         }
312 312
         /** @var RequestInterface $request */
313 313
         $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
314
-        if (! EED_Recaptcha_Invisible::verifyToken($request)) {
314
+        if ( ! EED_Recaptcha_Invisible::verifyToken($request)) {
315 315
             $event_id = $request->getRequestParam('tkt-slctr-event-id', 0, 'int');
316 316
             $return_url = $request->requestParamIsSet("tkt-slctr-return-url-{$event_id}")
317 317
                 ? $request->getRequestParam("tkt-slctr-return-url-{$event_id}")
Please login to merge, or discard this patch.
core/db_classes/EE_Import.class.php 2 patches
Spacing   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -141,7 +141,7 @@  discard block
 block discarded – undo
141 141
     public function import()
142 142
     {
143 143
 
144
-        require_once(EE_CLASSES . 'EE_CSV.class.php');
144
+        require_once(EE_CLASSES.'EE_CSV.class.php');
145 145
         $this->EE_CSV = EE_CSV::instance();
146 146
 
147 147
         /** @var RequestInterface $request */
@@ -188,18 +188,18 @@  discard block
 block discarded – undo
188 188
                     break;
189 189
             }
190 190
 
191
-            if (! $error_msg) {
191
+            if ( ! $error_msg) {
192 192
                 $filename = $files['file']['name'][0];
193 193
                 $file_ext = substr(strrchr($filename, '.'), 1);
194 194
                 $file_type = $files['file']['type'][0];
195 195
                 $temp_file = $files['file']['tmp_name'][0];
196
-                $filesize = $files['file']['size'][0] / 1024;// convert from bytes to KB
196
+                $filesize = $files['file']['size'][0] / 1024; // convert from bytes to KB
197 197
 
198 198
                 if ($file_ext == 'csv') {
199
-                    $max_upload = $this->EE_CSV->get_max_upload_size();// max upload size in KB
199
+                    $max_upload = $this->EE_CSV->get_max_upload_size(); // max upload size in KB
200 200
                     if ($filesize < $max_upload || true) {
201 201
                         $wp_upload_dir = str_replace(array('\\', '/'), '/', wp_upload_dir());
202
-                        $path_to_file = $wp_upload_dir['basedir'] . '/espresso/' . $filename;
202
+                        $path_to_file = $wp_upload_dir['basedir'].'/espresso/'.$filename;
203 203
 
204 204
                         if (move_uploaded_file($temp_file, $path_to_file)) {
205 205
                             // convert csv to array
@@ -334,8 +334,8 @@  discard block
 block discarded – undo
334 334
         // begin looking through the $csv_data_array, expecting the toplevel key to be the model's name...
335 335
         $old_site_url = 'none-specified';
336 336
         // hanlde metadata
337
-        if (isset($csv_data_array[ EE_CSV::metadata_header ])) {
338
-            $csv_metadata = array_shift($csv_data_array[ EE_CSV::metadata_header ]);
337
+        if (isset($csv_data_array[EE_CSV::metadata_header])) {
338
+            $csv_metadata = array_shift($csv_data_array[EE_CSV::metadata_header]);
339 339
             // ok so its metadata, dont try to save it to ehte db obviously...
340 340
             if (isset($csv_metadata['site_url']) && $csv_metadata['site_url'] == site_url()) {
341 341
                 EE_Error::add_attention(
@@ -360,14 +360,14 @@  discard block
 block discarded – undo
360 360
                     )
361 361
                 );
362 362
             };
363
-            unset($csv_data_array[ EE_CSV::metadata_header ]);
363
+            unset($csv_data_array[EE_CSV::metadata_header]);
364 364
         }
365 365
         /**
366 366
          * @var $old_db_to_new_db_mapping 2d array: toplevel keys being model names, bottom-level keys being the original key, and
367 367
          * the value will be the newly-inserted ID.
368 368
          * If we have already imported data from the same website via CSV, it shoudl be kept in this wp option
369 369
          */
370
-        $old_db_to_new_db_mapping = get_option('ee_id_mapping_from' . sanitize_title($old_site_url), array());
370
+        $old_db_to_new_db_mapping = get_option('ee_id_mapping_from'.sanitize_title($old_site_url), array());
371 371
         if ($old_db_to_new_db_mapping) {
372 372
             EE_Error::add_attention(
373 373
                 sprintf(
@@ -387,7 +387,7 @@  discard block
 block discarded – undo
387 387
         );
388 388
 
389 389
         // save the mapping from old db to new db in case they try re-importing the same data from the same website again
390
-        update_option('ee_id_mapping_from' . sanitize_title($old_site_url), $old_db_to_new_db_mapping);
390
+        update_option('ee_id_mapping_from'.sanitize_title($old_site_url), $old_db_to_new_db_mapping);
391 391
 
392 392
         if ($this->_total_updates > 0) {
393 393
             EE_Error::add_success(
@@ -510,7 +510,7 @@  discard block
 block discarded – undo
510 510
                 // find the PK in the row of data (or a combined key if
511 511
                 // there is no primary key)
512 512
                 if ($model->has_primary_key_field()) {
513
-                    $id_in_csv = $model_object_data[ $model->primary_key_name() ];
513
+                    $id_in_csv = $model_object_data[$model->primary_key_name()];
514 514
                 } else {
515 515
                     $id_in_csv = $model->get_index_primary_key_string($model_object_data);
516 516
                 }
@@ -554,14 +554,14 @@  discard block
 block discarded – undo
554 554
                         $what_to_do = self::do_update;
555 555
                         // and if this model has a primary key, remember its mapping
556 556
                         if ($model->has_primary_key_field()) {
557
-                            $old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ] = $conflicting->ID();
558
-                            $model_object_data[ $model->primary_key_name() ] = $conflicting->ID();
557
+                            $old_db_to_new_db_mapping[$model_name][$id_in_csv] = $conflicting->ID();
558
+                            $model_object_data[$model->primary_key_name()] = $conflicting->ID();
559 559
                         } else {
560 560
                             // we want to update this conflicting item, instead of inserting a conflicting item
561 561
                             // so we need to make sure they match entirely (its possible that they only conflicted on one field, but we need them to match on other fields
562 562
                             // for the WHERE conditions in the update). At the time of this comment, there were no models like this
563 563
                             foreach ($model->get_combined_primary_key_fields() as $key_field) {
564
-                                $model_object_data[ $key_field->get_name() ] = $conflicting->get(
564
+                                $model_object_data[$key_field->get_name()] = $conflicting->get(
565 565
                                     $key_field->get_name()
566 566
                                 );
567 567
                             }
@@ -621,7 +621,7 @@  discard block
 block discarded – undo
621 621
         $model_name = $model->get_this_model_name();
622 622
         // if it's a site-to-site export-and-import, see if this modelobject's id
623 623
         // in the old data that we know of
624
-        if (isset($old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ])) {
624
+        if (isset($old_db_to_new_db_mapping[$model_name][$id_in_csv])) {
625 625
             return self::do_update;
626 626
         } else {
627 627
             return self::do_insert;
@@ -677,13 +677,13 @@  discard block
 block discarded – undo
677 677
         if (
678 678
             $model->has_primary_key_field() &&
679 679
             $model->get_primary_key_field()->is_auto_increment() &&
680
-            isset($old_db_to_new_db_mapping[ $model->get_this_model_name() ]) &&
680
+            isset($old_db_to_new_db_mapping[$model->get_this_model_name()]) &&
681 681
             isset(
682
-                $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $model_object_data[ $model->primary_key_name() ] ]
682
+                $old_db_to_new_db_mapping[$model->get_this_model_name()][$model_object_data[$model->primary_key_name()]]
683 683
             )
684 684
         ) {
685
-            $model_object_data[ $model->primary_key_name() ] = $old_db_to_new_db_mapping[ $model->get_this_model_name(
686
-            ) ][ $model_object_data[ $model->primary_key_name() ] ];
685
+            $model_object_data[$model->primary_key_name()] = $old_db_to_new_db_mapping[$model->get_this_model_name(
686
+            )][$model_object_data[$model->primary_key_name()]];
687 687
         }
688 688
 
689 689
         try {
@@ -699,10 +699,10 @@  discard block
 block discarded – undo
699 699
                 $found_a_mapping = false;
700 700
                 foreach ($models_pointed_to as $model_pointed_to_by_fk) {
701 701
                     if ($model_name_field) {
702
-                        $value_of_model_name_field = $model_object_data[ $model_name_field->get_name() ];
702
+                        $value_of_model_name_field = $model_object_data[$model_name_field->get_name()];
703 703
                         if ($value_of_model_name_field == $model_pointed_to_by_fk) {
704
-                            $model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in(
705
-                                $model_object_data[ $field_obj->get_name() ],
704
+                            $model_object_data[$field_obj->get_name()] = $this->_find_mapping_in(
705
+                                $model_object_data[$field_obj->get_name()],
706 706
                                 $model_pointed_to_by_fk,
707 707
                                 $old_db_to_new_db_mapping,
708 708
                                 $export_from_site_a_to_b
@@ -711,8 +711,8 @@  discard block
 block discarded – undo
711 711
                             break;
712 712
                         }
713 713
                     } else {
714
-                        $model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in(
715
-                            $model_object_data[ $field_obj->get_name() ],
714
+                        $model_object_data[$field_obj->get_name()] = $this->_find_mapping_in(
715
+                            $model_object_data[$field_obj->get_name()],
716 716
                             $model_pointed_to_by_fk,
717 717
                             $old_db_to_new_db_mapping,
718 718
                             $export_from_site_a_to_b
@@ -777,8 +777,8 @@  discard block
 block discarded – undo
777 777
      */
778 778
     protected function _find_mapping_in($object_id, $model_name, $old_db_to_new_db_mapping, $export_from_site_a_to_b)
779 779
     {
780
-        if (isset($old_db_to_new_db_mapping[ $model_name ][ $object_id ])) {
781
-            return $old_db_to_new_db_mapping[ $model_name ][ $object_id ];
780
+        if (isset($old_db_to_new_db_mapping[$model_name][$object_id])) {
781
+            return $old_db_to_new_db_mapping[$model_name][$object_id];
782 782
         } elseif ($object_id == '0' || $object_id == '') {
783 783
             // leave as-is
784 784
             return $object_id;
@@ -786,7 +786,7 @@  discard block
 block discarded – undo
786 786
             // we couldn't find a mapping for this, and it's from a different site,
787 787
             // so blank it out
788 788
             return null;
789
-        } elseif (! $export_from_site_a_to_b) {
789
+        } elseif ( ! $export_from_site_a_to_b) {
790 790
             // we coudln't find a mapping for this, but it's from thsi DB anyway
791 791
             // so let's just leave it as-is
792 792
             return $object_id;
@@ -806,8 +806,8 @@  discard block
 block discarded – undo
806 806
         // remove the primary key, if there is one (we don't want it for inserts OR updates)
807 807
         // we'll put it back in if we need it
808 808
         if ($model->has_primary_key_field() && $model->get_primary_key_field()->is_auto_increment()) {
809
-            $effective_id = $model_object_data[ $model->primary_key_name() ];
810
-            unset($model_object_data[ $model->primary_key_name() ]);
809
+            $effective_id = $model_object_data[$model->primary_key_name()];
810
+            unset($model_object_data[$model->primary_key_name()]);
811 811
         } else {
812 812
             $effective_id = $model->get_index_primary_key_string($model_object_data);
813 813
         }
@@ -815,7 +815,7 @@  discard block
 block discarded – undo
815 815
         try {
816 816
             $new_id = $model->insert($model_object_data);
817 817
             if ($new_id) {
818
-                $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_id;
818
+                $old_db_to_new_db_mapping[$model->get_this_model_name()][$id_in_csv] = $new_id;
819 819
                 $this->_total_inserts++;
820 820
                 EE_Error::add_success(
821 821
                     sprintf(
@@ -829,7 +829,7 @@  discard block
 block discarded – undo
829 829
                 $this->_total_insert_errors++;
830 830
                 // put the ID used back in there for the error message
831 831
                 if ($model->has_primary_key_field()) {
832
-                    $model_object_data[ $model->primary_key_name() ] = $effective_id;
832
+                    $model_object_data[$model->primary_key_name()] = $effective_id;
833 833
                 }
834 834
                 EE_Error::add_error(
835 835
                     sprintf(
@@ -845,7 +845,7 @@  discard block
 block discarded – undo
845 845
         } catch (EE_Error $e) {
846 846
             $this->_total_insert_errors++;
847 847
             if ($model->has_primary_key_field()) {
848
-                $model_object_data[ $model->primary_key_name() ] = $effective_id;
848
+                $model_object_data[$model->primary_key_name()] = $effective_id;
849 849
             }
850 850
             EE_Error::add_error(
851 851
                 sprintf(
@@ -878,17 +878,17 @@  discard block
 block discarded – undo
878 878
             // one for performing an update, one for everthing else
879 879
             $model_object_data_for_update = $model_object_data;
880 880
             if ($model->has_primary_key_field()) {
881
-                $conditions = array($model->primary_key_name() => $model_object_data[ $model->primary_key_name() ]);
881
+                $conditions = array($model->primary_key_name() => $model_object_data[$model->primary_key_name()]);
882 882
                 // remove the primary key because we shouldn't use it for updating
883
-                unset($model_object_data_for_update[ $model->primary_key_name() ]);
883
+                unset($model_object_data_for_update[$model->primary_key_name()]);
884 884
             } elseif ($model->get_combined_primary_key_fields() > 1) {
885 885
                 $conditions = array();
886 886
                 foreach ($model->get_combined_primary_key_fields() as $key_field) {
887
-                    $conditions[ $key_field->get_name() ] = $model_object_data[ $key_field->get_name() ];
887
+                    $conditions[$key_field->get_name()] = $model_object_data[$key_field->get_name()];
888 888
                 }
889 889
             } else {
890 890
                 $model->primary_key_name(
891
-                );// this shoudl just throw an exception, explaining that we dont have a primary key (or a combine dkey)
891
+                ); // this shoudl just throw an exception, explaining that we dont have a primary key (or a combine dkey)
892 892
             }
893 893
 
894 894
             $success = $model->update($model_object_data_for_update, array($conditions));
@@ -906,15 +906,15 @@  discard block
 block discarded – undo
906 906
                 // we would have last-minute decided to update. So we'd like to know what we updated
907 907
                 // and so we record what record ended up being updated using the mapping
908 908
                 if ($model->has_primary_key_field()) {
909
-                    $new_key_for_mapping = $model_object_data[ $model->primary_key_name() ];
909
+                    $new_key_for_mapping = $model_object_data[$model->primary_key_name()];
910 910
                 } else {
911 911
                     // no primary key just a combined key
912 912
                     $new_key_for_mapping = $model->get_index_primary_key_string($model_object_data);
913 913
                 }
914
-                $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_key_for_mapping;
914
+                $old_db_to_new_db_mapping[$model->get_this_model_name()][$id_in_csv] = $new_key_for_mapping;
915 915
             } else {
916 916
                 $matched_items = $model->get_all(array($conditions));
917
-                if (! $matched_items) {
917
+                if ( ! $matched_items) {
918 918
                     // no items were matched (so we shouldn't have updated)... but then we should have inserted? what the heck?
919 919
                     $this->_total_update_errors++;
920 920
                     EE_Error::add_error(
@@ -953,7 +953,7 @@  discard block
 block discarded – undo
953 953
                 implode(",", $model_object_data),
954 954
                 $e->getMessage()
955 955
             );
956
-            $debug_message = $basic_message . ' Stack trace: ' . $e->getTraceAsString();
956
+            $debug_message = $basic_message.' Stack trace: '.$e->getTraceAsString();
957 957
             EE_Error::add_error("$basic_message | $debug_message", __FILE__, __FUNCTION__, __LINE__);
958 958
         }
959 959
         return $old_db_to_new_db_mapping;
Please login to merge, or discard this patch.
Indentation   +964 added lines, -964 removed lines patch added patch discarded remove patch
@@ -14,97 +14,97 @@  discard block
 block discarded – undo
14 14
 class EE_Import implements ResettableInterface
15 15
 {
16 16
 
17
-    const do_insert = 'insert';
18
-    const do_update = 'update';
19
-    const do_nothing = 'nothing';
20
-
21
-
22
-    // instance of the EE_Import object
23
-    private static $_instance;
24
-
25
-    private static $_csv_array = array();
26
-
27
-    /**
28
-     *
29
-     * @var array of model names
30
-     */
31
-    private static $_model_list = array();
32
-
33
-    private static $_columns_to_save = array();
34
-
35
-    protected $_total_inserts = 0;
36
-    protected $_total_updates = 0;
37
-    protected $_total_insert_errors = 0;
38
-    protected $_total_update_errors = 0;
39
-
40
-    /**
41
-     * @var EE_CSV
42
-     * @since 4.10.14.p
43
-     */
44
-    private $EE_CSV;
45
-
46
-
47
-    /**
48
-     *        private constructor to prevent direct creation
49
-     *
50
-     * @Constructor
51
-     * @access private
52
-     * @return void
53
-     */
54
-    private function __construct()
55
-    {
56
-        $this->_total_inserts = 0;
57
-        $this->_total_updates = 0;
58
-        $this->_total_insert_errors = 0;
59
-        $this->_total_update_errors = 0;
60
-    }
61
-
62
-
63
-    /**
64
-     *    @ singleton method used to instantiate class object
65
-     *    @ access public
66
-     *
67
-     * @return EE_Import
68
-     */
69
-    public static function instance()
70
-    {
71
-        // check if class object is instantiated
72
-        if (self::$_instance === null or ! is_object(self::$_instance) or ! (self::$_instance instanceof EE_Import)) {
73
-            self::$_instance = new self();
74
-        }
75
-        return self::$_instance;
76
-    }
77
-
78
-    /**
79
-     * Resets the importer
80
-     *
81
-     * @return EE_Import
82
-     */
83
-    public static function reset()
84
-    {
85
-        self::$_instance = null;
86
-        return self::instance();
87
-    }
88
-
89
-
90
-    /**
91
-     *    @ generates HTML for a file upload input and form
92
-     *    @ access    public
93
-     *
94
-     * @param    string $title  - heading for the form
95
-     * @param    string $intro  - additional text explaing what to do
96
-     * @param    string $page   - EE Admin page to direct form to - in the form "espresso_{pageslug}"
97
-     * @param    string $action - EE Admin page route array "action" that form will direct to
98
-     * @param    string $type   - type of file to import
99
-     *                          @ return    string
100
-     */
101
-    public function upload_form($title, $intro, $form_url, $action, $type)
102
-    {
103
-
104
-        $form_url = EE_Admin_Page::add_query_args_and_nonce(array('action' => $action), $form_url);
105
-
106
-        ob_start();
107
-        ?>
17
+	const do_insert = 'insert';
18
+	const do_update = 'update';
19
+	const do_nothing = 'nothing';
20
+
21
+
22
+	// instance of the EE_Import object
23
+	private static $_instance;
24
+
25
+	private static $_csv_array = array();
26
+
27
+	/**
28
+	 *
29
+	 * @var array of model names
30
+	 */
31
+	private static $_model_list = array();
32
+
33
+	private static $_columns_to_save = array();
34
+
35
+	protected $_total_inserts = 0;
36
+	protected $_total_updates = 0;
37
+	protected $_total_insert_errors = 0;
38
+	protected $_total_update_errors = 0;
39
+
40
+	/**
41
+	 * @var EE_CSV
42
+	 * @since 4.10.14.p
43
+	 */
44
+	private $EE_CSV;
45
+
46
+
47
+	/**
48
+	 *        private constructor to prevent direct creation
49
+	 *
50
+	 * @Constructor
51
+	 * @access private
52
+	 * @return void
53
+	 */
54
+	private function __construct()
55
+	{
56
+		$this->_total_inserts = 0;
57
+		$this->_total_updates = 0;
58
+		$this->_total_insert_errors = 0;
59
+		$this->_total_update_errors = 0;
60
+	}
61
+
62
+
63
+	/**
64
+	 *    @ singleton method used to instantiate class object
65
+	 *    @ access public
66
+	 *
67
+	 * @return EE_Import
68
+	 */
69
+	public static function instance()
70
+	{
71
+		// check if class object is instantiated
72
+		if (self::$_instance === null or ! is_object(self::$_instance) or ! (self::$_instance instanceof EE_Import)) {
73
+			self::$_instance = new self();
74
+		}
75
+		return self::$_instance;
76
+	}
77
+
78
+	/**
79
+	 * Resets the importer
80
+	 *
81
+	 * @return EE_Import
82
+	 */
83
+	public static function reset()
84
+	{
85
+		self::$_instance = null;
86
+		return self::instance();
87
+	}
88
+
89
+
90
+	/**
91
+	 *    @ generates HTML for a file upload input and form
92
+	 *    @ access    public
93
+	 *
94
+	 * @param    string $title  - heading for the form
95
+	 * @param    string $intro  - additional text explaing what to do
96
+	 * @param    string $page   - EE Admin page to direct form to - in the form "espresso_{pageslug}"
97
+	 * @param    string $action - EE Admin page route array "action" that form will direct to
98
+	 * @param    string $type   - type of file to import
99
+	 *                          @ return    string
100
+	 */
101
+	public function upload_form($title, $intro, $form_url, $action, $type)
102
+	{
103
+
104
+		$form_url = EE_Admin_Page::add_query_args_and_nonce(array('action' => $action), $form_url);
105
+
106
+		ob_start();
107
+		?>
108 108
         <div class="ee-upload-form-dv">
109 109
             <h3><?php echo esc_html($title); ?></h3>
110 110
             <p><?php echo esc_html($intro); ?></p>
@@ -120,882 +120,882 @@  discard block
 block discarded – undo
120 120
                 <b><?php esc_html_e('Attention', 'event_espresso'); ?></b><br/>
121 121
                 <?php echo sprintf(esc_html__('Accepts .%s file types only.', 'event_espresso'), $type); ?>
122 122
                 <?php echo esc_html__(
123
-                    'Please only import CSV files exported from Event Espresso, or compatible 3rd-party software.',
124
-                    'event_espresso'
125
-                ); ?>
123
+					'Please only import CSV files exported from Event Espresso, or compatible 3rd-party software.',
124
+					'event_espresso'
125
+				); ?>
126 126
             </p>
127 127
 
128 128
         </div>
129 129
 
130 130
         <?php
131
-        $uploader = ob_get_clean();
132
-        return $uploader;
133
-    }
134
-
135
-
136
-    /**
137
-     * @Import Event Espresso data - some code "borrowed" from event espresso csv_import.php
138
-     * @access public
139
-     * @return boolean success
140
-     */
141
-    public function import()
142
-    {
143
-
144
-        require_once(EE_CLASSES . 'EE_CSV.class.php');
145
-        $this->EE_CSV = EE_CSV::instance();
146
-
147
-        /** @var RequestInterface $request */
148
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
149
-
150
-        if ($request->requestParamIsSet('import') && $request->requestParamIsSet('csv_submitted')) {
151
-            $files = $request->filesParams();
152
-            switch ($files['file']['error'][0]) {
153
-                case UPLOAD_ERR_OK:
154
-                    $error_msg = false;
155
-                    break;
156
-                case UPLOAD_ERR_INI_SIZE:
157
-                    $error_msg = esc_html__(
158
-                        "'The uploaded file exceeds the upload_max_filesize directive in php.ini.'",
159
-                        "event_espresso"
160
-                    );
161
-                    break;
162
-                case UPLOAD_ERR_FORM_SIZE:
163
-                    $error_msg = esc_html__(
164
-                        'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.',
165
-                        "event_espresso"
166
-                    );
167
-                    break;
168
-                case UPLOAD_ERR_PARTIAL:
169
-                    $error_msg = esc_html__('The uploaded file was only partially uploaded.', "event_espresso");
170
-                    break;
171
-                case UPLOAD_ERR_NO_FILE:
172
-                    $error_msg = esc_html__('No file was uploaded.', "event_espresso");
173
-                    break;
174
-                case UPLOAD_ERR_NO_TMP_DIR:
175
-                    $error_msg = esc_html__('Missing a temporary folder.', "event_espresso");
176
-                    break;
177
-                case UPLOAD_ERR_CANT_WRITE:
178
-                    $error_msg = esc_html__('Failed to write file to disk.', "event_espresso");
179
-                    break;
180
-                case UPLOAD_ERR_EXTENSION:
181
-                    $error_msg = esc_html__('File upload stopped by extension.', "event_espresso");
182
-                    break;
183
-                default:
184
-                    $error_msg = esc_html__(
185
-                        'An unknown error occurred and the file could not be uploaded',
186
-                        "event_espresso"
187
-                    );
188
-                    break;
189
-            }
190
-
191
-            if (! $error_msg) {
192
-                $filename = $files['file']['name'][0];
193
-                $file_ext = substr(strrchr($filename, '.'), 1);
194
-                $file_type = $files['file']['type'][0];
195
-                $temp_file = $files['file']['tmp_name'][0];
196
-                $filesize = $files['file']['size'][0] / 1024;// convert from bytes to KB
197
-
198
-                if ($file_ext == 'csv') {
199
-                    $max_upload = $this->EE_CSV->get_max_upload_size();// max upload size in KB
200
-                    if ($filesize < $max_upload || true) {
201
-                        $wp_upload_dir = str_replace(array('\\', '/'), '/', wp_upload_dir());
202
-                        $path_to_file = $wp_upload_dir['basedir'] . '/espresso/' . $filename;
203
-
204
-                        if (move_uploaded_file($temp_file, $path_to_file)) {
205
-                            // convert csv to array
206
-                            $this->csv_array = $this->EE_CSV->import_csv_to_model_data_array($path_to_file);
207
-
208
-                            $action = $request->getRequestParam('action');
209
-
210
-                            // was data successfully stored in an array?
211
-                            if (is_array($this->csv_array)) {
212
-                                $import_what = str_replace('csv_import_', '', $action);
213
-                                $import_what = str_replace('_', ' ', ucwords($import_what));
214
-                                $processed_data = $this->csv_array;
215
-                                $this->columns_to_save = false;
216
-
217
-                                // if any imports require funky processing, we'll catch them in the switch
218
-                                switch ($action) {
219
-                                    case "import_events":
220
-                                    case "event_list":
221
-                                        $import_what = 'Event Details';
222
-                                        break;
223
-
224
-                                    case 'groupon_import_csv':
225
-                                        $import_what = 'Groupon Codes';
226
-                                        $processed_data = $this->process_groupon_codes();
227
-                                        break;
228
-                                }
229
-                                // save processed codes to db
230
-                                if ($this->save_csv_data_array_to_db($processed_data, $this->columns_to_save)) {
231
-                                    return true;
232
-                                }
233
-                            } else {
234
-                                // no array? must be an error
235
-                                EE_Error::add_error(
236
-                                    sprintf(esc_html__("No file seems to have been uploaded", "event_espresso")),
237
-                                    __FILE__,
238
-                                    __FUNCTION__,
239
-                                    __LINE__
240
-                                );
241
-                                return false;
242
-                            }
243
-                        } else {
244
-                            EE_Error::add_error(
245
-                                sprintf(esc_html__("%s was not successfully uploaded", "event_espresso"), $filename),
246
-                                __FILE__,
247
-                                __FUNCTION__,
248
-                                __LINE__
249
-                            );
250
-                            return false;
251
-                        }
252
-                    } else {
253
-                        EE_Error::add_error(
254
-                            sprintf(
255
-                                esc_html__(
256
-                                    "%s was too large of a file and could not be uploaded. The max filesize is %s' KB.",
257
-                                    "event_espresso"
258
-                                ),
259
-                                $filename,
260
-                                $max_upload
261
-                            ),
262
-                            __FILE__,
263
-                            __FUNCTION__,
264
-                            __LINE__
265
-                        );
266
-                        return false;
267
-                    }
268
-                } else {
269
-                    EE_Error::add_error(
270
-                        sprintf(esc_html__("%s  had an invalid file extension, not uploaded", "event_espresso"), $filename),
271
-                        __FILE__,
272
-                        __FUNCTION__,
273
-                        __LINE__
274
-                    );
275
-                    return false;
276
-                }
277
-            } else {
278
-                EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
279
-                return false;
280
-            }
281
-        }
282
-        return false;
283
-    }
284
-
285
-
286
-    /**
287
-     *    Given an array of data (usually from a CSV import) attempts to save that data to the db.
288
-     *    If $model_name ISN'T provided, assumes that this is a 3d array, with toplevel keys being model names,
289
-     *    next level being numeric indexes adn each value representing a model object, and the last layer down
290
-     *    being keys of model fields and their proposed values.
291
-     *    If $model_name IS provided, assumes a 2d array of the bottom two layers previously mentioned.
292
-     *    If the CSV data says (in the metadata row) that it's from the SAME database,
293
-     *    we treat the IDs in the CSV as the normal IDs, and try to update those records. However, if those
294
-     *    IDs DON'T exist in the database, they're treated as temporary IDs,
295
-     *    which can used elsewhere to refer to the same object. Once an item
296
-     *    with a temporary ID gets inserted, we record its mapping from temporary
297
-     *    ID to real ID, and use the real ID in place of the temporary ID
298
-     *    when that temporary ID was used as a foreign key.
299
-     *    If the CSV data says (in the metadata again) that it's from a DIFFERENT database,
300
-     *    we treat all the IDs in the CSV as temporary ID- eg, if the CSV specifies an event with
301
-     *    ID 1, and the database already has an event with ID 1, we assume that's just a coincidence,
302
-     *    and insert a new event, and map it's temporary ID of 1 over to its new real ID.
303
-     *    An important exception are non-auto-increment primary keys. If one entry in the
304
-     *    CSV file has the same ID as one in the DB, we assume they are meant to be
305
-     *    the same item, and instead update the item in the DB with that same ID.
306
-     *    Also note, we remember the mappings permanently. So the 2nd, 3rd, and 10000th
307
-     *    time you import a CSV from a different site, we remember their mappings, and
308
-     * will try to update the item in the DB instead of inserting another item (eg
309
-     * if we previously imported an event with temporary ID 1, and then it got a
310
-     * real ID of 123, we remember that. So the next time we import an event with
311
-     * temporary ID, from the same site, we know that it's real ID is 123, and will
312
-     * update that event, instead of adding a new event).
313
-     *
314
-     * @access public
315
-     * @param array $csv_data_array - the array containing the csv data produced from
316
-     *                              EE_CSV::import_csv_to_model_data_array()
317
-     * @param array $fields_to_save - an array containing the csv column names as keys with the corresponding db table
318
-     *                              fields they will be saved to
319
-     * @return TRUE on success, FALSE on fail
320
-     * @throws \EE_Error
321
-     */
322
-    public function save_csv_data_array_to_db($csv_data_array, $model_name = false)
323
-    {
324
-        $success = false;
325
-        $error = false;
326
-        // whther to treat this import as if it's data froma different database or not
327
-        // ie, if it IS from a different database, ignore foreign keys whihf
328
-        $export_from_site_a_to_b = true;
329
-        // first level of array is not table information but a table name was passed to the function
330
-        // array is only two levels deep, so let's fix that by adding a level, else the next steps will fail
331
-        if ($model_name) {
332
-            $csv_data_array = array($csv_data_array);
333
-        }
334
-        // begin looking through the $csv_data_array, expecting the toplevel key to be the model's name...
335
-        $old_site_url = 'none-specified';
336
-        // hanlde metadata
337
-        if (isset($csv_data_array[ EE_CSV::metadata_header ])) {
338
-            $csv_metadata = array_shift($csv_data_array[ EE_CSV::metadata_header ]);
339
-            // ok so its metadata, dont try to save it to ehte db obviously...
340
-            if (isset($csv_metadata['site_url']) && $csv_metadata['site_url'] == site_url()) {
341
-                EE_Error::add_attention(
342
-                    sprintf(
343
-                        esc_html__(
344
-                            "CSV Data appears to be from the same database, so attempting to update data",
345
-                            "event_espresso"
346
-                        )
347
-                    )
348
-                );
349
-                $export_from_site_a_to_b = false;
350
-            } else {
351
-                $old_site_url = isset($csv_metadata['site_url']) ? $csv_metadata['site_url'] : $old_site_url;
352
-                EE_Error::add_attention(
353
-                    sprintf(
354
-                        esc_html__(
355
-                            "CSV Data appears to be from a different database (%s instead of %s), so we assume IDs in the CSV data DO NOT correspond to IDs in this database",
356
-                            "event_espresso"
357
-                        ),
358
-                        $old_site_url,
359
-                        site_url()
360
-                    )
361
-                );
362
-            };
363
-            unset($csv_data_array[ EE_CSV::metadata_header ]);
364
-        }
365
-        /**
366
-         * @var $old_db_to_new_db_mapping 2d array: toplevel keys being model names, bottom-level keys being the original key, and
367
-         * the value will be the newly-inserted ID.
368
-         * If we have already imported data from the same website via CSV, it shoudl be kept in this wp option
369
-         */
370
-        $old_db_to_new_db_mapping = get_option('ee_id_mapping_from' . sanitize_title($old_site_url), array());
371
-        if ($old_db_to_new_db_mapping) {
372
-            EE_Error::add_attention(
373
-                sprintf(
374
-                    esc_html__(
375
-                        "We noticed you have imported data via CSV from %s before. Because of this, IDs in your CSV have been mapped to their new IDs in %s",
376
-                        "event_espresso"
377
-                    ),
378
-                    $old_site_url,
379
-                    site_url()
380
-                )
381
-            );
382
-        }
383
-        $old_db_to_new_db_mapping = $this->save_data_rows_to_db(
384
-            $csv_data_array,
385
-            $export_from_site_a_to_b,
386
-            $old_db_to_new_db_mapping
387
-        );
388
-
389
-        // save the mapping from old db to new db in case they try re-importing the same data from the same website again
390
-        update_option('ee_id_mapping_from' . sanitize_title($old_site_url), $old_db_to_new_db_mapping);
391
-
392
-        if ($this->_total_updates > 0) {
393
-            EE_Error::add_success(
394
-                sprintf(
395
-                    esc_html__("%s existing records in the database were updated.", "event_espresso"),
396
-                    $this->_total_updates
397
-                )
398
-            );
399
-            $success = true;
400
-        }
401
-        if ($this->_total_inserts > 0) {
402
-            EE_Error::add_success(
403
-                sprintf(esc_html__("%s new records were added to the database.", "event_espresso"), $this->_total_inserts)
404
-            );
405
-            $success = true;
406
-        }
407
-
408
-        if ($this->_total_update_errors > 0) {
409
-            EE_Error::add_error(
410
-                sprintf(
411
-                    esc_html__(
412
-                        "'One or more errors occurred, and a total of %s existing records in the database were <strong>not</strong> updated.'",
413
-                        "event_espresso"
414
-                    ),
415
-                    $this->_total_update_errors
416
-                ),
417
-                __FILE__,
418
-                __FUNCTION__,
419
-                __LINE__
420
-            );
421
-            $error = true;
422
-        }
423
-        if ($this->_total_insert_errors > 0) {
424
-            EE_Error::add_error(
425
-                sprintf(
426
-                    esc_html__(
427
-                        "One or more errors occurred, and a total of %s new records were <strong>not</strong> added to the database.'",
428
-                        "event_espresso"
429
-                    ),
430
-                    $this->_total_insert_errors
431
-                ),
432
-                __FILE__,
433
-                __FUNCTION__,
434
-                __LINE__
435
-            );
436
-            $error = true;
437
-        }
438
-
439
-        // lastly, we need to update the datetime and ticket sold amounts
440
-        // as those may have been affected by this
441
-        EEM_Ticket::instance()->update_tickets_sold(EEM_Ticket::instance()->get_all());
442
-
443
-        // if there was at least one success and absolutely no errors
444
-        if ($success && ! $error) {
445
-            return true;
446
-        } else {
447
-            return false;
448
-        }
449
-    }
450
-
451
-
452
-    /**
453
-     * Processes the array of data, given the knowledge that it's from the same database or a different one,
454
-     * and the mapping from temporary IDs to real IDs.
455
-     * If the data is from a different database, we treat the primary keys and their corresponding
456
-     * foreign keys as "temp Ids", basically identifiers that get mapped to real primary keys
457
-     * in the real target database. As items are inserted, their temporary primary keys
458
-     * are mapped to the real IDs in the target database. Also, before doing any update or
459
-     * insert, we replace all the temp ID which are foreign keys with their mapped real IDs.
460
-     * An exception: string primary keys are treated as real IDs, or else we'd need to
461
-     * dynamically generate new string primary keys which would be very awkard for the country table etc.
462
-     * Also, models with no primary key are strange too. We combine use their primar key INDEX (a
463
-     * combination of fields) to create a unique string identifying the row and store
464
-     * those in the mapping.
465
-     *
466
-     * If the data is from the same database, we usually treat primary keys as real IDs.
467
-     * An exception is if there is nothing in the database for that ID. If that's the case,
468
-     * we need to insert a new row for that ID, and then map from the non-existent ID
469
-     * to the newly-inserted real ID.
470
-     *
471
-     * @param type $csv_data_array
472
-     * @param type $export_from_site_a_to_b
473
-     * @param type $old_db_to_new_db_mapping
474
-     * @return array updated $old_db_to_new_db_mapping
475
-     */
476
-    public function save_data_rows_to_db($csv_data_array, $export_from_site_a_to_b, $old_db_to_new_db_mapping)
477
-    {
478
-        foreach ($csv_data_array as $model_name_in_csv_data => $model_data_from_import) {
479
-            // now check that assumption was correct. If
480
-            if (EE_Registry::instance()->is_model_name($model_name_in_csv_data)) {
481
-                $model_name = $model_name_in_csv_data;
482
-            } else {
483
-                // no table info in the array and no table name passed to the function?? FAIL
484
-                EE_Error::add_error(
485
-                    esc_html__(
486
-                        'No table information was specified and/or found, therefore the import could not be completed',
487
-                        'event_espresso'
488
-                    ),
489
-                    __FILE__,
490
-                    __FUNCTION__,
491
-                    __LINE__
492
-                );
493
-                return false;
494
-            }
495
-            /* @var $model EEM_Base */
496
-            $model = EE_Registry::instance()->load_model($model_name);
497
-
498
-            // so without further ado, scanning all the data provided for primary keys and their inital values
499
-            foreach ($model_data_from_import as $model_object_data) {
500
-                // before we do ANYTHING, make sure the csv row wasn't just completely blank
501
-                $row_is_completely_empty = true;
502
-                foreach ($model_object_data as $field) {
503
-                    if ($field) {
504
-                        $row_is_completely_empty = false;
505
-                    }
506
-                }
507
-                if ($row_is_completely_empty) {
508
-                    continue;
509
-                }
510
-                // find the PK in the row of data (or a combined key if
511
-                // there is no primary key)
512
-                if ($model->has_primary_key_field()) {
513
-                    $id_in_csv = $model_object_data[ $model->primary_key_name() ];
514
-                } else {
515
-                    $id_in_csv = $model->get_index_primary_key_string($model_object_data);
516
-                }
517
-
518
-
519
-                $model_object_data = $this->_replace_temp_ids_with_mappings(
520
-                    $model_object_data,
521
-                    $model,
522
-                    $old_db_to_new_db_mapping,
523
-                    $export_from_site_a_to_b
524
-                );
525
-                // now we need to decide if we're going to add a new model object given the $model_object_data,
526
-                // or just update.
527
-                if ($export_from_site_a_to_b) {
528
-                    $what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_other_db(
529
-                        $id_in_csv,
530
-                        $model_object_data,
531
-                        $model,
532
-                        $old_db_to_new_db_mapping
533
-                    );
534
-                } else {// this is just a re-import
535
-                    $what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_same_db(
536
-                        $id_in_csv,
537
-                        $model_object_data,
538
-                        $model,
539
-                        $old_db_to_new_db_mapping
540
-                    );
541
-                }
542
-                if ($what_to_do == self::do_nothing) {
543
-                    continue;
544
-                }
545
-
546
-                // double-check we actually want to insert, if that's what we're planning
547
-                // based on whether this item would be unique in the DB or not
548
-                if ($what_to_do == self::do_insert) {
549
-                    // we're supposed to be inserting. But wait, will this thing
550
-                    // be acceptable if inserted?
551
-                    $conflicting = $model->get_one_conflicting($model_object_data, false);
552
-                    if ($conflicting) {
553
-                        // ok, this item would conflict if inserted. Just update the item that it conflicts with.
554
-                        $what_to_do = self::do_update;
555
-                        // and if this model has a primary key, remember its mapping
556
-                        if ($model->has_primary_key_field()) {
557
-                            $old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ] = $conflicting->ID();
558
-                            $model_object_data[ $model->primary_key_name() ] = $conflicting->ID();
559
-                        } else {
560
-                            // we want to update this conflicting item, instead of inserting a conflicting item
561
-                            // so we need to make sure they match entirely (its possible that they only conflicted on one field, but we need them to match on other fields
562
-                            // for the WHERE conditions in the update). At the time of this comment, there were no models like this
563
-                            foreach ($model->get_combined_primary_key_fields() as $key_field) {
564
-                                $model_object_data[ $key_field->get_name() ] = $conflicting->get(
565
-                                    $key_field->get_name()
566
-                                );
567
-                            }
568
-                        }
569
-                    }
570
-                }
571
-                if ($what_to_do == self::do_insert) {
572
-                    $old_db_to_new_db_mapping = $this->_insert_from_data_array(
573
-                        $id_in_csv,
574
-                        $model_object_data,
575
-                        $model,
576
-                        $old_db_to_new_db_mapping
577
-                    );
578
-                } elseif ($what_to_do == self::do_update) {
579
-                    $old_db_to_new_db_mapping = $this->_update_from_data_array(
580
-                        $id_in_csv,
581
-                        $model_object_data,
582
-                        $model,
583
-                        $old_db_to_new_db_mapping
584
-                    );
585
-                } else {
586
-                    throw new EE_Error(
587
-                        sprintf(
588
-                            esc_html__(
589
-                                'Programming error. We shoudl be inserting or updating, but instead we are being told to "%s", whifh is invalid',
590
-                                'event_espresso'
591
-                            ),
592
-                            $what_to_do
593
-                        )
594
-                    );
595
-                }
596
-            }
597
-        }
598
-        return $old_db_to_new_db_mapping;
599
-    }
600
-
601
-
602
-    /**
603
-     * Decides whether or not to insert, given that this data is from another database.
604
-     * So, if the primary key of this $model_object_data already exists in the database,
605
-     * it's just a coincidence and we should still insert. The only time we should
606
-     * update is when we know what it maps to, or there's something that would
607
-     * conflict (and we should instead just update that conflicting thing)
608
-     *
609
-     * @param string   $id_in_csv
610
-     * @param array    $model_object_data        by reference so it can be modified
611
-     * @param EEM_Base $model
612
-     * @param array    $old_db_to_new_db_mapping by reference so it can be modified
613
-     * @return string one of the consts on this class that starts with do_*
614
-     */
615
-    protected function _decide_whether_to_insert_or_update_given_data_from_other_db(
616
-        $id_in_csv,
617
-        $model_object_data,
618
-        $model,
619
-        $old_db_to_new_db_mapping
620
-    ) {
621
-        $model_name = $model->get_this_model_name();
622
-        // if it's a site-to-site export-and-import, see if this modelobject's id
623
-        // in the old data that we know of
624
-        if (isset($old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ])) {
625
-            return self::do_update;
626
-        } else {
627
-            return self::do_insert;
628
-        }
629
-    }
630
-
631
-    /**
632
-     * If this thing basically already exists in the database, we want to update it;
633
-     * otherwise insert it (ie, someone tweaked the CSV file, or the item was
634
-     * deleted in the database so it should be re-inserted)
635
-     *
636
-     * @param type     $id_in_csv
637
-     * @param type     $model_object_data
638
-     * @param EEM_Base $model
639
-     * @param type     $old_db_to_new_db_mapping
640
-     * @return
641
-     */
642
-    protected function _decide_whether_to_insert_or_update_given_data_from_same_db(
643
-        $id_in_csv,
644
-        $model_object_data,
645
-        $model
646
-    ) {
647
-        // in this case, check if this thing ACTUALLY exists in the database
648
-        if ($model->get_one_conflicting($model_object_data)) {
649
-            return self::do_update;
650
-        } else {
651
-            return self::do_insert;
652
-        }
653
-    }
654
-
655
-    /**
656
-     * Using the $old_db_to_new_db_mapping array, replaces all the temporary IDs
657
-     * with their mapped real IDs. Eg, if importing from site A to B, the mapping
658
-     * file may indicate that the ID "my_event_id" maps to an actual event ID of 123.
659
-     * So this function searches for any event temp Ids called "my_event_id" and
660
-     * replaces them with 123.
661
-     * Also, if there is no temp ID for the INT foreign keys from another database,
662
-     * replaces them with 0 or the field's default.
663
-     *
664
-     * @param type     $model_object_data
665
-     * @param EEM_Base $model
666
-     * @param type     $old_db_to_new_db_mapping
667
-     * @param boolean  $export_from_site_a_to_b
668
-     * @return array updated model object data with temp IDs removed
669
-     */
670
-    protected function _replace_temp_ids_with_mappings(
671
-        $model_object_data,
672
-        $model,
673
-        $old_db_to_new_db_mapping,
674
-        $export_from_site_a_to_b
675
-    ) {
676
-        // if this model object's primary key is in the mapping, replace it
677
-        if (
678
-            $model->has_primary_key_field() &&
679
-            $model->get_primary_key_field()->is_auto_increment() &&
680
-            isset($old_db_to_new_db_mapping[ $model->get_this_model_name() ]) &&
681
-            isset(
682
-                $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $model_object_data[ $model->primary_key_name() ] ]
683
-            )
684
-        ) {
685
-            $model_object_data[ $model->primary_key_name() ] = $old_db_to_new_db_mapping[ $model->get_this_model_name(
686
-            ) ][ $model_object_data[ $model->primary_key_name() ] ];
687
-        }
688
-
689
-        try {
690
-            $model_name_field = $model->get_field_containing_related_model_name();
691
-            $models_pointed_to_by_model_name_field = $model_name_field->get_model_names_pointed_to();
692
-        } catch (EE_Error $e) {
693
-            $model_name_field = null;
694
-            $models_pointed_to_by_model_name_field = array();
695
-        }
696
-        foreach ($model->field_settings(true) as $field_obj) {
697
-            if ($field_obj instanceof EE_Foreign_Key_Int_Field) {
698
-                $models_pointed_to = $field_obj->get_model_names_pointed_to();
699
-                $found_a_mapping = false;
700
-                foreach ($models_pointed_to as $model_pointed_to_by_fk) {
701
-                    if ($model_name_field) {
702
-                        $value_of_model_name_field = $model_object_data[ $model_name_field->get_name() ];
703
-                        if ($value_of_model_name_field == $model_pointed_to_by_fk) {
704
-                            $model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in(
705
-                                $model_object_data[ $field_obj->get_name() ],
706
-                                $model_pointed_to_by_fk,
707
-                                $old_db_to_new_db_mapping,
708
-                                $export_from_site_a_to_b
709
-                            );
710
-                            $found_a_mapping = true;
711
-                            break;
712
-                        }
713
-                    } else {
714
-                        $model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in(
715
-                            $model_object_data[ $field_obj->get_name() ],
716
-                            $model_pointed_to_by_fk,
717
-                            $old_db_to_new_db_mapping,
718
-                            $export_from_site_a_to_b
719
-                        );
720
-                        $found_a_mapping = true;
721
-                    }
722
-                    // once we've found a mapping for this field no need to continue
723
-                    if ($found_a_mapping) {
724
-                        break;
725
-                    }
726
-                }
727
-            } else {
728
-                // it's a string foreign key (which we leave alone, because those are things
729
-                // like country names, which we'd really rather not make 2 USAs etc (we'd actually
730
-                // prefer to just update one)
731
-                // or it's just a regular value that ought to be replaced
732
-            }
733
-        }
734
-        //
735
-        if ($model instanceof EEM_Term_Taxonomy) {
736
-            $model_object_data = $this->_handle_split_term_ids($model_object_data);
737
-        }
738
-        return $model_object_data;
739
-    }
740
-
741
-    /**
742
-     * If the data was exported PRE-4.2, but then imported POST-4.2, then the term_id
743
-     * this term-taxonomy refers to may be out-of-date so we need to update it.
744
-     * see https://make.wordpress.org/core/2015/02/16/taxonomy-term-splitting-in-4-2-a-developer-guide/
745
-     *
746
-     * @param type $model_object_data
747
-     * @return array new model object data
748
-     */
749
-    protected function _handle_split_term_ids($model_object_data)
750
-    {
751
-        if (
752
-            isset($model_object_data['term_id'])
753
-            && isset($model_object_data['taxonomy'])
754
-            && apply_filters(
755
-                'FHEE__EE_Import__handle_split_term_ids__function_exists',
756
-                function_exists('wp_get_split_term'),
757
-                $model_object_data
758
-            )
759
-        ) {
760
-            $new_term_id = wp_get_split_term($model_object_data['term_id'], $model_object_data['taxonomy']);
761
-            if ($new_term_id) {
762
-                $model_object_data['term_id'] = $new_term_id;
763
-            }
764
-        }
765
-        return $model_object_data;
766
-    }
767
-
768
-    /**
769
-     * Given the object's ID and its model's name, find it int he mapping data,
770
-     * bearing in mind where it came from
771
-     *
772
-     * @param type   $object_id
773
-     * @param string $model_name
774
-     * @param array  $old_db_to_new_db_mapping
775
-     * @param type   $export_from_site_a_to_b
776
-     * @return int
777
-     */
778
-    protected function _find_mapping_in($object_id, $model_name, $old_db_to_new_db_mapping, $export_from_site_a_to_b)
779
-    {
780
-        if (isset($old_db_to_new_db_mapping[ $model_name ][ $object_id ])) {
781
-            return $old_db_to_new_db_mapping[ $model_name ][ $object_id ];
782
-        } elseif ($object_id == '0' || $object_id == '') {
783
-            // leave as-is
784
-            return $object_id;
785
-        } elseif ($export_from_site_a_to_b) {
786
-            // we couldn't find a mapping for this, and it's from a different site,
787
-            // so blank it out
788
-            return null;
789
-        } elseif (! $export_from_site_a_to_b) {
790
-            // we coudln't find a mapping for this, but it's from thsi DB anyway
791
-            // so let's just leave it as-is
792
-            return $object_id;
793
-        }
794
-    }
795
-
796
-    /**
797
-     *
798
-     * @param type     $id_in_csv
799
-     * @param type     $model_object_data
800
-     * @param EEM_Base $model
801
-     * @param type     $old_db_to_new_db_mapping
802
-     * @return array updated $old_db_to_new_db_mapping
803
-     */
804
-    protected function _insert_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping)
805
-    {
806
-        // remove the primary key, if there is one (we don't want it for inserts OR updates)
807
-        // we'll put it back in if we need it
808
-        if ($model->has_primary_key_field() && $model->get_primary_key_field()->is_auto_increment()) {
809
-            $effective_id = $model_object_data[ $model->primary_key_name() ];
810
-            unset($model_object_data[ $model->primary_key_name() ]);
811
-        } else {
812
-            $effective_id = $model->get_index_primary_key_string($model_object_data);
813
-        }
814
-        // the model takes care of validating the CSV's input
815
-        try {
816
-            $new_id = $model->insert($model_object_data);
817
-            if ($new_id) {
818
-                $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_id;
819
-                $this->_total_inserts++;
820
-                EE_Error::add_success(
821
-                    sprintf(
822
-                        esc_html__("Successfully added new %s (with id %s) with csv data %s", "event_espresso"),
823
-                        $model->get_this_model_name(),
824
-                        $new_id,
825
-                        implode(",", $model_object_data)
826
-                    )
827
-                );
828
-            } else {
829
-                $this->_total_insert_errors++;
830
-                // put the ID used back in there for the error message
831
-                if ($model->has_primary_key_field()) {
832
-                    $model_object_data[ $model->primary_key_name() ] = $effective_id;
833
-                }
834
-                EE_Error::add_error(
835
-                    sprintf(
836
-                        esc_html__("Could not insert new %s with the csv data: %s", "event_espresso"),
837
-                        $model->get_this_model_name(),
838
-                        http_build_query($model_object_data)
839
-                    ),
840
-                    __FILE__,
841
-                    __FUNCTION__,
842
-                    __LINE__
843
-                );
844
-            }
845
-        } catch (EE_Error $e) {
846
-            $this->_total_insert_errors++;
847
-            if ($model->has_primary_key_field()) {
848
-                $model_object_data[ $model->primary_key_name() ] = $effective_id;
849
-            }
850
-            EE_Error::add_error(
851
-                sprintf(
852
-                    esc_html__("Could not insert new %s with the csv data: %s because %s", "event_espresso"),
853
-                    $model->get_this_model_name(),
854
-                    implode(",", $model_object_data),
855
-                    $e->getMessage()
856
-                ),
857
-                __FILE__,
858
-                __FUNCTION__,
859
-                __LINE__
860
-            );
861
-        }
862
-        return $old_db_to_new_db_mapping;
863
-    }
864
-
865
-    /**
866
-     * Given the model object data, finds the row to update and updates it
867
-     *
868
-     * @param string|int $id_in_csv
869
-     * @param array      $model_object_data
870
-     * @param EEM_Base   $model
871
-     * @param array      $old_db_to_new_db_mapping
872
-     * @return array updated $old_db_to_new_db_mapping
873
-     */
874
-    protected function _update_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping)
875
-    {
876
-        try {
877
-            // let's keep two copies of the model object data:
878
-            // one for performing an update, one for everthing else
879
-            $model_object_data_for_update = $model_object_data;
880
-            if ($model->has_primary_key_field()) {
881
-                $conditions = array($model->primary_key_name() => $model_object_data[ $model->primary_key_name() ]);
882
-                // remove the primary key because we shouldn't use it for updating
883
-                unset($model_object_data_for_update[ $model->primary_key_name() ]);
884
-            } elseif ($model->get_combined_primary_key_fields() > 1) {
885
-                $conditions = array();
886
-                foreach ($model->get_combined_primary_key_fields() as $key_field) {
887
-                    $conditions[ $key_field->get_name() ] = $model_object_data[ $key_field->get_name() ];
888
-                }
889
-            } else {
890
-                $model->primary_key_name(
891
-                );// this shoudl just throw an exception, explaining that we dont have a primary key (or a combine dkey)
892
-            }
893
-
894
-            $success = $model->update($model_object_data_for_update, array($conditions));
895
-            if ($success) {
896
-                $this->_total_updates++;
897
-                EE_Error::add_success(
898
-                    sprintf(
899
-                        esc_html__("Successfully updated %s with csv data %s", "event_espresso"),
900
-                        $model->get_this_model_name(),
901
-                        implode(",", $model_object_data_for_update)
902
-                    )
903
-                );
904
-                // we should still record the mapping even though it was an update
905
-                // because if we were going to insert somethign but it was going to conflict
906
-                // we would have last-minute decided to update. So we'd like to know what we updated
907
-                // and so we record what record ended up being updated using the mapping
908
-                if ($model->has_primary_key_field()) {
909
-                    $new_key_for_mapping = $model_object_data[ $model->primary_key_name() ];
910
-                } else {
911
-                    // no primary key just a combined key
912
-                    $new_key_for_mapping = $model->get_index_primary_key_string($model_object_data);
913
-                }
914
-                $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_key_for_mapping;
915
-            } else {
916
-                $matched_items = $model->get_all(array($conditions));
917
-                if (! $matched_items) {
918
-                    // no items were matched (so we shouldn't have updated)... but then we should have inserted? what the heck?
919
-                    $this->_total_update_errors++;
920
-                    EE_Error::add_error(
921
-                        sprintf(
922
-                            esc_html__(
923
-                                "Could not update %s with the csv data: '%s' for an unknown reason (using WHERE conditions %s)",
924
-                                "event_espresso"
925
-                            ),
926
-                            $model->get_this_model_name(),
927
-                            http_build_query($model_object_data),
928
-                            http_build_query($conditions)
929
-                        ),
930
-                        __FILE__,
931
-                        __FUNCTION__,
932
-                        __LINE__
933
-                    );
934
-                } else {
935
-                    $this->_total_updates++;
936
-                    EE_Error::add_success(
937
-                        sprintf(
938
-                            esc_html__(
939
-                                "%s with csv data '%s' was found in the database and didn't need updating because all the data is identical.",
940
-                                "event_espresso"
941
-                            ),
942
-                            $model->get_this_model_name(),
943
-                            implode(",", $model_object_data)
944
-                        )
945
-                    );
946
-                }
947
-            }
948
-        } catch (EE_Error $e) {
949
-            $this->_total_update_errors++;
950
-            $basic_message = sprintf(
951
-                esc_html__("Could not update %s with the csv data: %s because %s", "event_espresso"),
952
-                $model->get_this_model_name(),
953
-                implode(",", $model_object_data),
954
-                $e->getMessage()
955
-            );
956
-            $debug_message = $basic_message . ' Stack trace: ' . $e->getTraceAsString();
957
-            EE_Error::add_error("$basic_message | $debug_message", __FILE__, __FUNCTION__, __LINE__);
958
-        }
959
-        return $old_db_to_new_db_mapping;
960
-    }
961
-
962
-    /**
963
-     * Gets the number of inserts performed since importer was instantiated or reset
964
-     *
965
-     * @return int
966
-     */
967
-    public function get_total_inserts()
968
-    {
969
-        return $this->_total_inserts;
970
-    }
971
-
972
-    /**
973
-     *  Gets the number of insert errors since importer was instantiated or reset
974
-     *
975
-     * @return int
976
-     */
977
-    public function get_total_insert_errors()
978
-    {
979
-        return $this->_total_insert_errors;
980
-    }
981
-
982
-    /**
983
-     *  Gets the number of updates performed since importer was instantiated or reset
984
-     *
985
-     * @return int
986
-     */
987
-    public function get_total_updates()
988
-    {
989
-        return $this->_total_updates;
990
-    }
991
-
992
-    /**
993
-     *  Gets the number of update errors since importer was instantiated or reset
994
-     *
995
-     * @return int
996
-     */
997
-    public function get_total_update_errors()
998
-    {
999
-        return $this->_total_update_errors;
1000
-    }
131
+		$uploader = ob_get_clean();
132
+		return $uploader;
133
+	}
134
+
135
+
136
+	/**
137
+	 * @Import Event Espresso data - some code "borrowed" from event espresso csv_import.php
138
+	 * @access public
139
+	 * @return boolean success
140
+	 */
141
+	public function import()
142
+	{
143
+
144
+		require_once(EE_CLASSES . 'EE_CSV.class.php');
145
+		$this->EE_CSV = EE_CSV::instance();
146
+
147
+		/** @var RequestInterface $request */
148
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
149
+
150
+		if ($request->requestParamIsSet('import') && $request->requestParamIsSet('csv_submitted')) {
151
+			$files = $request->filesParams();
152
+			switch ($files['file']['error'][0]) {
153
+				case UPLOAD_ERR_OK:
154
+					$error_msg = false;
155
+					break;
156
+				case UPLOAD_ERR_INI_SIZE:
157
+					$error_msg = esc_html__(
158
+						"'The uploaded file exceeds the upload_max_filesize directive in php.ini.'",
159
+						"event_espresso"
160
+					);
161
+					break;
162
+				case UPLOAD_ERR_FORM_SIZE:
163
+					$error_msg = esc_html__(
164
+						'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.',
165
+						"event_espresso"
166
+					);
167
+					break;
168
+				case UPLOAD_ERR_PARTIAL:
169
+					$error_msg = esc_html__('The uploaded file was only partially uploaded.', "event_espresso");
170
+					break;
171
+				case UPLOAD_ERR_NO_FILE:
172
+					$error_msg = esc_html__('No file was uploaded.', "event_espresso");
173
+					break;
174
+				case UPLOAD_ERR_NO_TMP_DIR:
175
+					$error_msg = esc_html__('Missing a temporary folder.', "event_espresso");
176
+					break;
177
+				case UPLOAD_ERR_CANT_WRITE:
178
+					$error_msg = esc_html__('Failed to write file to disk.', "event_espresso");
179
+					break;
180
+				case UPLOAD_ERR_EXTENSION:
181
+					$error_msg = esc_html__('File upload stopped by extension.', "event_espresso");
182
+					break;
183
+				default:
184
+					$error_msg = esc_html__(
185
+						'An unknown error occurred and the file could not be uploaded',
186
+						"event_espresso"
187
+					);
188
+					break;
189
+			}
190
+
191
+			if (! $error_msg) {
192
+				$filename = $files['file']['name'][0];
193
+				$file_ext = substr(strrchr($filename, '.'), 1);
194
+				$file_type = $files['file']['type'][0];
195
+				$temp_file = $files['file']['tmp_name'][0];
196
+				$filesize = $files['file']['size'][0] / 1024;// convert from bytes to KB
197
+
198
+				if ($file_ext == 'csv') {
199
+					$max_upload = $this->EE_CSV->get_max_upload_size();// max upload size in KB
200
+					if ($filesize < $max_upload || true) {
201
+						$wp_upload_dir = str_replace(array('\\', '/'), '/', wp_upload_dir());
202
+						$path_to_file = $wp_upload_dir['basedir'] . '/espresso/' . $filename;
203
+
204
+						if (move_uploaded_file($temp_file, $path_to_file)) {
205
+							// convert csv to array
206
+							$this->csv_array = $this->EE_CSV->import_csv_to_model_data_array($path_to_file);
207
+
208
+							$action = $request->getRequestParam('action');
209
+
210
+							// was data successfully stored in an array?
211
+							if (is_array($this->csv_array)) {
212
+								$import_what = str_replace('csv_import_', '', $action);
213
+								$import_what = str_replace('_', ' ', ucwords($import_what));
214
+								$processed_data = $this->csv_array;
215
+								$this->columns_to_save = false;
216
+
217
+								// if any imports require funky processing, we'll catch them in the switch
218
+								switch ($action) {
219
+									case "import_events":
220
+									case "event_list":
221
+										$import_what = 'Event Details';
222
+										break;
223
+
224
+									case 'groupon_import_csv':
225
+										$import_what = 'Groupon Codes';
226
+										$processed_data = $this->process_groupon_codes();
227
+										break;
228
+								}
229
+								// save processed codes to db
230
+								if ($this->save_csv_data_array_to_db($processed_data, $this->columns_to_save)) {
231
+									return true;
232
+								}
233
+							} else {
234
+								// no array? must be an error
235
+								EE_Error::add_error(
236
+									sprintf(esc_html__("No file seems to have been uploaded", "event_espresso")),
237
+									__FILE__,
238
+									__FUNCTION__,
239
+									__LINE__
240
+								);
241
+								return false;
242
+							}
243
+						} else {
244
+							EE_Error::add_error(
245
+								sprintf(esc_html__("%s was not successfully uploaded", "event_espresso"), $filename),
246
+								__FILE__,
247
+								__FUNCTION__,
248
+								__LINE__
249
+							);
250
+							return false;
251
+						}
252
+					} else {
253
+						EE_Error::add_error(
254
+							sprintf(
255
+								esc_html__(
256
+									"%s was too large of a file and could not be uploaded. The max filesize is %s' KB.",
257
+									"event_espresso"
258
+								),
259
+								$filename,
260
+								$max_upload
261
+							),
262
+							__FILE__,
263
+							__FUNCTION__,
264
+							__LINE__
265
+						);
266
+						return false;
267
+					}
268
+				} else {
269
+					EE_Error::add_error(
270
+						sprintf(esc_html__("%s  had an invalid file extension, not uploaded", "event_espresso"), $filename),
271
+						__FILE__,
272
+						__FUNCTION__,
273
+						__LINE__
274
+					);
275
+					return false;
276
+				}
277
+			} else {
278
+				EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
279
+				return false;
280
+			}
281
+		}
282
+		return false;
283
+	}
284
+
285
+
286
+	/**
287
+	 *    Given an array of data (usually from a CSV import) attempts to save that data to the db.
288
+	 *    If $model_name ISN'T provided, assumes that this is a 3d array, with toplevel keys being model names,
289
+	 *    next level being numeric indexes adn each value representing a model object, and the last layer down
290
+	 *    being keys of model fields and their proposed values.
291
+	 *    If $model_name IS provided, assumes a 2d array of the bottom two layers previously mentioned.
292
+	 *    If the CSV data says (in the metadata row) that it's from the SAME database,
293
+	 *    we treat the IDs in the CSV as the normal IDs, and try to update those records. However, if those
294
+	 *    IDs DON'T exist in the database, they're treated as temporary IDs,
295
+	 *    which can used elsewhere to refer to the same object. Once an item
296
+	 *    with a temporary ID gets inserted, we record its mapping from temporary
297
+	 *    ID to real ID, and use the real ID in place of the temporary ID
298
+	 *    when that temporary ID was used as a foreign key.
299
+	 *    If the CSV data says (in the metadata again) that it's from a DIFFERENT database,
300
+	 *    we treat all the IDs in the CSV as temporary ID- eg, if the CSV specifies an event with
301
+	 *    ID 1, and the database already has an event with ID 1, we assume that's just a coincidence,
302
+	 *    and insert a new event, and map it's temporary ID of 1 over to its new real ID.
303
+	 *    An important exception are non-auto-increment primary keys. If one entry in the
304
+	 *    CSV file has the same ID as one in the DB, we assume they are meant to be
305
+	 *    the same item, and instead update the item in the DB with that same ID.
306
+	 *    Also note, we remember the mappings permanently. So the 2nd, 3rd, and 10000th
307
+	 *    time you import a CSV from a different site, we remember their mappings, and
308
+	 * will try to update the item in the DB instead of inserting another item (eg
309
+	 * if we previously imported an event with temporary ID 1, and then it got a
310
+	 * real ID of 123, we remember that. So the next time we import an event with
311
+	 * temporary ID, from the same site, we know that it's real ID is 123, and will
312
+	 * update that event, instead of adding a new event).
313
+	 *
314
+	 * @access public
315
+	 * @param array $csv_data_array - the array containing the csv data produced from
316
+	 *                              EE_CSV::import_csv_to_model_data_array()
317
+	 * @param array $fields_to_save - an array containing the csv column names as keys with the corresponding db table
318
+	 *                              fields they will be saved to
319
+	 * @return TRUE on success, FALSE on fail
320
+	 * @throws \EE_Error
321
+	 */
322
+	public function save_csv_data_array_to_db($csv_data_array, $model_name = false)
323
+	{
324
+		$success = false;
325
+		$error = false;
326
+		// whther to treat this import as if it's data froma different database or not
327
+		// ie, if it IS from a different database, ignore foreign keys whihf
328
+		$export_from_site_a_to_b = true;
329
+		// first level of array is not table information but a table name was passed to the function
330
+		// array is only two levels deep, so let's fix that by adding a level, else the next steps will fail
331
+		if ($model_name) {
332
+			$csv_data_array = array($csv_data_array);
333
+		}
334
+		// begin looking through the $csv_data_array, expecting the toplevel key to be the model's name...
335
+		$old_site_url = 'none-specified';
336
+		// hanlde metadata
337
+		if (isset($csv_data_array[ EE_CSV::metadata_header ])) {
338
+			$csv_metadata = array_shift($csv_data_array[ EE_CSV::metadata_header ]);
339
+			// ok so its metadata, dont try to save it to ehte db obviously...
340
+			if (isset($csv_metadata['site_url']) && $csv_metadata['site_url'] == site_url()) {
341
+				EE_Error::add_attention(
342
+					sprintf(
343
+						esc_html__(
344
+							"CSV Data appears to be from the same database, so attempting to update data",
345
+							"event_espresso"
346
+						)
347
+					)
348
+				);
349
+				$export_from_site_a_to_b = false;
350
+			} else {
351
+				$old_site_url = isset($csv_metadata['site_url']) ? $csv_metadata['site_url'] : $old_site_url;
352
+				EE_Error::add_attention(
353
+					sprintf(
354
+						esc_html__(
355
+							"CSV Data appears to be from a different database (%s instead of %s), so we assume IDs in the CSV data DO NOT correspond to IDs in this database",
356
+							"event_espresso"
357
+						),
358
+						$old_site_url,
359
+						site_url()
360
+					)
361
+				);
362
+			};
363
+			unset($csv_data_array[ EE_CSV::metadata_header ]);
364
+		}
365
+		/**
366
+		 * @var $old_db_to_new_db_mapping 2d array: toplevel keys being model names, bottom-level keys being the original key, and
367
+		 * the value will be the newly-inserted ID.
368
+		 * If we have already imported data from the same website via CSV, it shoudl be kept in this wp option
369
+		 */
370
+		$old_db_to_new_db_mapping = get_option('ee_id_mapping_from' . sanitize_title($old_site_url), array());
371
+		if ($old_db_to_new_db_mapping) {
372
+			EE_Error::add_attention(
373
+				sprintf(
374
+					esc_html__(
375
+						"We noticed you have imported data via CSV from %s before. Because of this, IDs in your CSV have been mapped to their new IDs in %s",
376
+						"event_espresso"
377
+					),
378
+					$old_site_url,
379
+					site_url()
380
+				)
381
+			);
382
+		}
383
+		$old_db_to_new_db_mapping = $this->save_data_rows_to_db(
384
+			$csv_data_array,
385
+			$export_from_site_a_to_b,
386
+			$old_db_to_new_db_mapping
387
+		);
388
+
389
+		// save the mapping from old db to new db in case they try re-importing the same data from the same website again
390
+		update_option('ee_id_mapping_from' . sanitize_title($old_site_url), $old_db_to_new_db_mapping);
391
+
392
+		if ($this->_total_updates > 0) {
393
+			EE_Error::add_success(
394
+				sprintf(
395
+					esc_html__("%s existing records in the database were updated.", "event_espresso"),
396
+					$this->_total_updates
397
+				)
398
+			);
399
+			$success = true;
400
+		}
401
+		if ($this->_total_inserts > 0) {
402
+			EE_Error::add_success(
403
+				sprintf(esc_html__("%s new records were added to the database.", "event_espresso"), $this->_total_inserts)
404
+			);
405
+			$success = true;
406
+		}
407
+
408
+		if ($this->_total_update_errors > 0) {
409
+			EE_Error::add_error(
410
+				sprintf(
411
+					esc_html__(
412
+						"'One or more errors occurred, and a total of %s existing records in the database were <strong>not</strong> updated.'",
413
+						"event_espresso"
414
+					),
415
+					$this->_total_update_errors
416
+				),
417
+				__FILE__,
418
+				__FUNCTION__,
419
+				__LINE__
420
+			);
421
+			$error = true;
422
+		}
423
+		if ($this->_total_insert_errors > 0) {
424
+			EE_Error::add_error(
425
+				sprintf(
426
+					esc_html__(
427
+						"One or more errors occurred, and a total of %s new records were <strong>not</strong> added to the database.'",
428
+						"event_espresso"
429
+					),
430
+					$this->_total_insert_errors
431
+				),
432
+				__FILE__,
433
+				__FUNCTION__,
434
+				__LINE__
435
+			);
436
+			$error = true;
437
+		}
438
+
439
+		// lastly, we need to update the datetime and ticket sold amounts
440
+		// as those may have been affected by this
441
+		EEM_Ticket::instance()->update_tickets_sold(EEM_Ticket::instance()->get_all());
442
+
443
+		// if there was at least one success and absolutely no errors
444
+		if ($success && ! $error) {
445
+			return true;
446
+		} else {
447
+			return false;
448
+		}
449
+	}
450
+
451
+
452
+	/**
453
+	 * Processes the array of data, given the knowledge that it's from the same database or a different one,
454
+	 * and the mapping from temporary IDs to real IDs.
455
+	 * If the data is from a different database, we treat the primary keys and their corresponding
456
+	 * foreign keys as "temp Ids", basically identifiers that get mapped to real primary keys
457
+	 * in the real target database. As items are inserted, their temporary primary keys
458
+	 * are mapped to the real IDs in the target database. Also, before doing any update or
459
+	 * insert, we replace all the temp ID which are foreign keys with their mapped real IDs.
460
+	 * An exception: string primary keys are treated as real IDs, or else we'd need to
461
+	 * dynamically generate new string primary keys which would be very awkard for the country table etc.
462
+	 * Also, models with no primary key are strange too. We combine use their primar key INDEX (a
463
+	 * combination of fields) to create a unique string identifying the row and store
464
+	 * those in the mapping.
465
+	 *
466
+	 * If the data is from the same database, we usually treat primary keys as real IDs.
467
+	 * An exception is if there is nothing in the database for that ID. If that's the case,
468
+	 * we need to insert a new row for that ID, and then map from the non-existent ID
469
+	 * to the newly-inserted real ID.
470
+	 *
471
+	 * @param type $csv_data_array
472
+	 * @param type $export_from_site_a_to_b
473
+	 * @param type $old_db_to_new_db_mapping
474
+	 * @return array updated $old_db_to_new_db_mapping
475
+	 */
476
+	public function save_data_rows_to_db($csv_data_array, $export_from_site_a_to_b, $old_db_to_new_db_mapping)
477
+	{
478
+		foreach ($csv_data_array as $model_name_in_csv_data => $model_data_from_import) {
479
+			// now check that assumption was correct. If
480
+			if (EE_Registry::instance()->is_model_name($model_name_in_csv_data)) {
481
+				$model_name = $model_name_in_csv_data;
482
+			} else {
483
+				// no table info in the array and no table name passed to the function?? FAIL
484
+				EE_Error::add_error(
485
+					esc_html__(
486
+						'No table information was specified and/or found, therefore the import could not be completed',
487
+						'event_espresso'
488
+					),
489
+					__FILE__,
490
+					__FUNCTION__,
491
+					__LINE__
492
+				);
493
+				return false;
494
+			}
495
+			/* @var $model EEM_Base */
496
+			$model = EE_Registry::instance()->load_model($model_name);
497
+
498
+			// so without further ado, scanning all the data provided for primary keys and their inital values
499
+			foreach ($model_data_from_import as $model_object_data) {
500
+				// before we do ANYTHING, make sure the csv row wasn't just completely blank
501
+				$row_is_completely_empty = true;
502
+				foreach ($model_object_data as $field) {
503
+					if ($field) {
504
+						$row_is_completely_empty = false;
505
+					}
506
+				}
507
+				if ($row_is_completely_empty) {
508
+					continue;
509
+				}
510
+				// find the PK in the row of data (or a combined key if
511
+				// there is no primary key)
512
+				if ($model->has_primary_key_field()) {
513
+					$id_in_csv = $model_object_data[ $model->primary_key_name() ];
514
+				} else {
515
+					$id_in_csv = $model->get_index_primary_key_string($model_object_data);
516
+				}
517
+
518
+
519
+				$model_object_data = $this->_replace_temp_ids_with_mappings(
520
+					$model_object_data,
521
+					$model,
522
+					$old_db_to_new_db_mapping,
523
+					$export_from_site_a_to_b
524
+				);
525
+				// now we need to decide if we're going to add a new model object given the $model_object_data,
526
+				// or just update.
527
+				if ($export_from_site_a_to_b) {
528
+					$what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_other_db(
529
+						$id_in_csv,
530
+						$model_object_data,
531
+						$model,
532
+						$old_db_to_new_db_mapping
533
+					);
534
+				} else {// this is just a re-import
535
+					$what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_same_db(
536
+						$id_in_csv,
537
+						$model_object_data,
538
+						$model,
539
+						$old_db_to_new_db_mapping
540
+					);
541
+				}
542
+				if ($what_to_do == self::do_nothing) {
543
+					continue;
544
+				}
545
+
546
+				// double-check we actually want to insert, if that's what we're planning
547
+				// based on whether this item would be unique in the DB or not
548
+				if ($what_to_do == self::do_insert) {
549
+					// we're supposed to be inserting. But wait, will this thing
550
+					// be acceptable if inserted?
551
+					$conflicting = $model->get_one_conflicting($model_object_data, false);
552
+					if ($conflicting) {
553
+						// ok, this item would conflict if inserted. Just update the item that it conflicts with.
554
+						$what_to_do = self::do_update;
555
+						// and if this model has a primary key, remember its mapping
556
+						if ($model->has_primary_key_field()) {
557
+							$old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ] = $conflicting->ID();
558
+							$model_object_data[ $model->primary_key_name() ] = $conflicting->ID();
559
+						} else {
560
+							// we want to update this conflicting item, instead of inserting a conflicting item
561
+							// so we need to make sure they match entirely (its possible that they only conflicted on one field, but we need them to match on other fields
562
+							// for the WHERE conditions in the update). At the time of this comment, there were no models like this
563
+							foreach ($model->get_combined_primary_key_fields() as $key_field) {
564
+								$model_object_data[ $key_field->get_name() ] = $conflicting->get(
565
+									$key_field->get_name()
566
+								);
567
+							}
568
+						}
569
+					}
570
+				}
571
+				if ($what_to_do == self::do_insert) {
572
+					$old_db_to_new_db_mapping = $this->_insert_from_data_array(
573
+						$id_in_csv,
574
+						$model_object_data,
575
+						$model,
576
+						$old_db_to_new_db_mapping
577
+					);
578
+				} elseif ($what_to_do == self::do_update) {
579
+					$old_db_to_new_db_mapping = $this->_update_from_data_array(
580
+						$id_in_csv,
581
+						$model_object_data,
582
+						$model,
583
+						$old_db_to_new_db_mapping
584
+					);
585
+				} else {
586
+					throw new EE_Error(
587
+						sprintf(
588
+							esc_html__(
589
+								'Programming error. We shoudl be inserting or updating, but instead we are being told to "%s", whifh is invalid',
590
+								'event_espresso'
591
+							),
592
+							$what_to_do
593
+						)
594
+					);
595
+				}
596
+			}
597
+		}
598
+		return $old_db_to_new_db_mapping;
599
+	}
600
+
601
+
602
+	/**
603
+	 * Decides whether or not to insert, given that this data is from another database.
604
+	 * So, if the primary key of this $model_object_data already exists in the database,
605
+	 * it's just a coincidence and we should still insert. The only time we should
606
+	 * update is when we know what it maps to, or there's something that would
607
+	 * conflict (and we should instead just update that conflicting thing)
608
+	 *
609
+	 * @param string   $id_in_csv
610
+	 * @param array    $model_object_data        by reference so it can be modified
611
+	 * @param EEM_Base $model
612
+	 * @param array    $old_db_to_new_db_mapping by reference so it can be modified
613
+	 * @return string one of the consts on this class that starts with do_*
614
+	 */
615
+	protected function _decide_whether_to_insert_or_update_given_data_from_other_db(
616
+		$id_in_csv,
617
+		$model_object_data,
618
+		$model,
619
+		$old_db_to_new_db_mapping
620
+	) {
621
+		$model_name = $model->get_this_model_name();
622
+		// if it's a site-to-site export-and-import, see if this modelobject's id
623
+		// in the old data that we know of
624
+		if (isset($old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ])) {
625
+			return self::do_update;
626
+		} else {
627
+			return self::do_insert;
628
+		}
629
+	}
630
+
631
+	/**
632
+	 * If this thing basically already exists in the database, we want to update it;
633
+	 * otherwise insert it (ie, someone tweaked the CSV file, or the item was
634
+	 * deleted in the database so it should be re-inserted)
635
+	 *
636
+	 * @param type     $id_in_csv
637
+	 * @param type     $model_object_data
638
+	 * @param EEM_Base $model
639
+	 * @param type     $old_db_to_new_db_mapping
640
+	 * @return
641
+	 */
642
+	protected function _decide_whether_to_insert_or_update_given_data_from_same_db(
643
+		$id_in_csv,
644
+		$model_object_data,
645
+		$model
646
+	) {
647
+		// in this case, check if this thing ACTUALLY exists in the database
648
+		if ($model->get_one_conflicting($model_object_data)) {
649
+			return self::do_update;
650
+		} else {
651
+			return self::do_insert;
652
+		}
653
+	}
654
+
655
+	/**
656
+	 * Using the $old_db_to_new_db_mapping array, replaces all the temporary IDs
657
+	 * with their mapped real IDs. Eg, if importing from site A to B, the mapping
658
+	 * file may indicate that the ID "my_event_id" maps to an actual event ID of 123.
659
+	 * So this function searches for any event temp Ids called "my_event_id" and
660
+	 * replaces them with 123.
661
+	 * Also, if there is no temp ID for the INT foreign keys from another database,
662
+	 * replaces them with 0 or the field's default.
663
+	 *
664
+	 * @param type     $model_object_data
665
+	 * @param EEM_Base $model
666
+	 * @param type     $old_db_to_new_db_mapping
667
+	 * @param boolean  $export_from_site_a_to_b
668
+	 * @return array updated model object data with temp IDs removed
669
+	 */
670
+	protected function _replace_temp_ids_with_mappings(
671
+		$model_object_data,
672
+		$model,
673
+		$old_db_to_new_db_mapping,
674
+		$export_from_site_a_to_b
675
+	) {
676
+		// if this model object's primary key is in the mapping, replace it
677
+		if (
678
+			$model->has_primary_key_field() &&
679
+			$model->get_primary_key_field()->is_auto_increment() &&
680
+			isset($old_db_to_new_db_mapping[ $model->get_this_model_name() ]) &&
681
+			isset(
682
+				$old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $model_object_data[ $model->primary_key_name() ] ]
683
+			)
684
+		) {
685
+			$model_object_data[ $model->primary_key_name() ] = $old_db_to_new_db_mapping[ $model->get_this_model_name(
686
+			) ][ $model_object_data[ $model->primary_key_name() ] ];
687
+		}
688
+
689
+		try {
690
+			$model_name_field = $model->get_field_containing_related_model_name();
691
+			$models_pointed_to_by_model_name_field = $model_name_field->get_model_names_pointed_to();
692
+		} catch (EE_Error $e) {
693
+			$model_name_field = null;
694
+			$models_pointed_to_by_model_name_field = array();
695
+		}
696
+		foreach ($model->field_settings(true) as $field_obj) {
697
+			if ($field_obj instanceof EE_Foreign_Key_Int_Field) {
698
+				$models_pointed_to = $field_obj->get_model_names_pointed_to();
699
+				$found_a_mapping = false;
700
+				foreach ($models_pointed_to as $model_pointed_to_by_fk) {
701
+					if ($model_name_field) {
702
+						$value_of_model_name_field = $model_object_data[ $model_name_field->get_name() ];
703
+						if ($value_of_model_name_field == $model_pointed_to_by_fk) {
704
+							$model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in(
705
+								$model_object_data[ $field_obj->get_name() ],
706
+								$model_pointed_to_by_fk,
707
+								$old_db_to_new_db_mapping,
708
+								$export_from_site_a_to_b
709
+							);
710
+							$found_a_mapping = true;
711
+							break;
712
+						}
713
+					} else {
714
+						$model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in(
715
+							$model_object_data[ $field_obj->get_name() ],
716
+							$model_pointed_to_by_fk,
717
+							$old_db_to_new_db_mapping,
718
+							$export_from_site_a_to_b
719
+						);
720
+						$found_a_mapping = true;
721
+					}
722
+					// once we've found a mapping for this field no need to continue
723
+					if ($found_a_mapping) {
724
+						break;
725
+					}
726
+				}
727
+			} else {
728
+				// it's a string foreign key (which we leave alone, because those are things
729
+				// like country names, which we'd really rather not make 2 USAs etc (we'd actually
730
+				// prefer to just update one)
731
+				// or it's just a regular value that ought to be replaced
732
+			}
733
+		}
734
+		//
735
+		if ($model instanceof EEM_Term_Taxonomy) {
736
+			$model_object_data = $this->_handle_split_term_ids($model_object_data);
737
+		}
738
+		return $model_object_data;
739
+	}
740
+
741
+	/**
742
+	 * If the data was exported PRE-4.2, but then imported POST-4.2, then the term_id
743
+	 * this term-taxonomy refers to may be out-of-date so we need to update it.
744
+	 * see https://make.wordpress.org/core/2015/02/16/taxonomy-term-splitting-in-4-2-a-developer-guide/
745
+	 *
746
+	 * @param type $model_object_data
747
+	 * @return array new model object data
748
+	 */
749
+	protected function _handle_split_term_ids($model_object_data)
750
+	{
751
+		if (
752
+			isset($model_object_data['term_id'])
753
+			&& isset($model_object_data['taxonomy'])
754
+			&& apply_filters(
755
+				'FHEE__EE_Import__handle_split_term_ids__function_exists',
756
+				function_exists('wp_get_split_term'),
757
+				$model_object_data
758
+			)
759
+		) {
760
+			$new_term_id = wp_get_split_term($model_object_data['term_id'], $model_object_data['taxonomy']);
761
+			if ($new_term_id) {
762
+				$model_object_data['term_id'] = $new_term_id;
763
+			}
764
+		}
765
+		return $model_object_data;
766
+	}
767
+
768
+	/**
769
+	 * Given the object's ID and its model's name, find it int he mapping data,
770
+	 * bearing in mind where it came from
771
+	 *
772
+	 * @param type   $object_id
773
+	 * @param string $model_name
774
+	 * @param array  $old_db_to_new_db_mapping
775
+	 * @param type   $export_from_site_a_to_b
776
+	 * @return int
777
+	 */
778
+	protected function _find_mapping_in($object_id, $model_name, $old_db_to_new_db_mapping, $export_from_site_a_to_b)
779
+	{
780
+		if (isset($old_db_to_new_db_mapping[ $model_name ][ $object_id ])) {
781
+			return $old_db_to_new_db_mapping[ $model_name ][ $object_id ];
782
+		} elseif ($object_id == '0' || $object_id == '') {
783
+			// leave as-is
784
+			return $object_id;
785
+		} elseif ($export_from_site_a_to_b) {
786
+			// we couldn't find a mapping for this, and it's from a different site,
787
+			// so blank it out
788
+			return null;
789
+		} elseif (! $export_from_site_a_to_b) {
790
+			// we coudln't find a mapping for this, but it's from thsi DB anyway
791
+			// so let's just leave it as-is
792
+			return $object_id;
793
+		}
794
+	}
795
+
796
+	/**
797
+	 *
798
+	 * @param type     $id_in_csv
799
+	 * @param type     $model_object_data
800
+	 * @param EEM_Base $model
801
+	 * @param type     $old_db_to_new_db_mapping
802
+	 * @return array updated $old_db_to_new_db_mapping
803
+	 */
804
+	protected function _insert_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping)
805
+	{
806
+		// remove the primary key, if there is one (we don't want it for inserts OR updates)
807
+		// we'll put it back in if we need it
808
+		if ($model->has_primary_key_field() && $model->get_primary_key_field()->is_auto_increment()) {
809
+			$effective_id = $model_object_data[ $model->primary_key_name() ];
810
+			unset($model_object_data[ $model->primary_key_name() ]);
811
+		} else {
812
+			$effective_id = $model->get_index_primary_key_string($model_object_data);
813
+		}
814
+		// the model takes care of validating the CSV's input
815
+		try {
816
+			$new_id = $model->insert($model_object_data);
817
+			if ($new_id) {
818
+				$old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_id;
819
+				$this->_total_inserts++;
820
+				EE_Error::add_success(
821
+					sprintf(
822
+						esc_html__("Successfully added new %s (with id %s) with csv data %s", "event_espresso"),
823
+						$model->get_this_model_name(),
824
+						$new_id,
825
+						implode(",", $model_object_data)
826
+					)
827
+				);
828
+			} else {
829
+				$this->_total_insert_errors++;
830
+				// put the ID used back in there for the error message
831
+				if ($model->has_primary_key_field()) {
832
+					$model_object_data[ $model->primary_key_name() ] = $effective_id;
833
+				}
834
+				EE_Error::add_error(
835
+					sprintf(
836
+						esc_html__("Could not insert new %s with the csv data: %s", "event_espresso"),
837
+						$model->get_this_model_name(),
838
+						http_build_query($model_object_data)
839
+					),
840
+					__FILE__,
841
+					__FUNCTION__,
842
+					__LINE__
843
+				);
844
+			}
845
+		} catch (EE_Error $e) {
846
+			$this->_total_insert_errors++;
847
+			if ($model->has_primary_key_field()) {
848
+				$model_object_data[ $model->primary_key_name() ] = $effective_id;
849
+			}
850
+			EE_Error::add_error(
851
+				sprintf(
852
+					esc_html__("Could not insert new %s with the csv data: %s because %s", "event_espresso"),
853
+					$model->get_this_model_name(),
854
+					implode(",", $model_object_data),
855
+					$e->getMessage()
856
+				),
857
+				__FILE__,
858
+				__FUNCTION__,
859
+				__LINE__
860
+			);
861
+		}
862
+		return $old_db_to_new_db_mapping;
863
+	}
864
+
865
+	/**
866
+	 * Given the model object data, finds the row to update and updates it
867
+	 *
868
+	 * @param string|int $id_in_csv
869
+	 * @param array      $model_object_data
870
+	 * @param EEM_Base   $model
871
+	 * @param array      $old_db_to_new_db_mapping
872
+	 * @return array updated $old_db_to_new_db_mapping
873
+	 */
874
+	protected function _update_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping)
875
+	{
876
+		try {
877
+			// let's keep two copies of the model object data:
878
+			// one for performing an update, one for everthing else
879
+			$model_object_data_for_update = $model_object_data;
880
+			if ($model->has_primary_key_field()) {
881
+				$conditions = array($model->primary_key_name() => $model_object_data[ $model->primary_key_name() ]);
882
+				// remove the primary key because we shouldn't use it for updating
883
+				unset($model_object_data_for_update[ $model->primary_key_name() ]);
884
+			} elseif ($model->get_combined_primary_key_fields() > 1) {
885
+				$conditions = array();
886
+				foreach ($model->get_combined_primary_key_fields() as $key_field) {
887
+					$conditions[ $key_field->get_name() ] = $model_object_data[ $key_field->get_name() ];
888
+				}
889
+			} else {
890
+				$model->primary_key_name(
891
+				);// this shoudl just throw an exception, explaining that we dont have a primary key (or a combine dkey)
892
+			}
893
+
894
+			$success = $model->update($model_object_data_for_update, array($conditions));
895
+			if ($success) {
896
+				$this->_total_updates++;
897
+				EE_Error::add_success(
898
+					sprintf(
899
+						esc_html__("Successfully updated %s with csv data %s", "event_espresso"),
900
+						$model->get_this_model_name(),
901
+						implode(",", $model_object_data_for_update)
902
+					)
903
+				);
904
+				// we should still record the mapping even though it was an update
905
+				// because if we were going to insert somethign but it was going to conflict
906
+				// we would have last-minute decided to update. So we'd like to know what we updated
907
+				// and so we record what record ended up being updated using the mapping
908
+				if ($model->has_primary_key_field()) {
909
+					$new_key_for_mapping = $model_object_data[ $model->primary_key_name() ];
910
+				} else {
911
+					// no primary key just a combined key
912
+					$new_key_for_mapping = $model->get_index_primary_key_string($model_object_data);
913
+				}
914
+				$old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_key_for_mapping;
915
+			} else {
916
+				$matched_items = $model->get_all(array($conditions));
917
+				if (! $matched_items) {
918
+					// no items were matched (so we shouldn't have updated)... but then we should have inserted? what the heck?
919
+					$this->_total_update_errors++;
920
+					EE_Error::add_error(
921
+						sprintf(
922
+							esc_html__(
923
+								"Could not update %s with the csv data: '%s' for an unknown reason (using WHERE conditions %s)",
924
+								"event_espresso"
925
+							),
926
+							$model->get_this_model_name(),
927
+							http_build_query($model_object_data),
928
+							http_build_query($conditions)
929
+						),
930
+						__FILE__,
931
+						__FUNCTION__,
932
+						__LINE__
933
+					);
934
+				} else {
935
+					$this->_total_updates++;
936
+					EE_Error::add_success(
937
+						sprintf(
938
+							esc_html__(
939
+								"%s with csv data '%s' was found in the database and didn't need updating because all the data is identical.",
940
+								"event_espresso"
941
+							),
942
+							$model->get_this_model_name(),
943
+							implode(",", $model_object_data)
944
+						)
945
+					);
946
+				}
947
+			}
948
+		} catch (EE_Error $e) {
949
+			$this->_total_update_errors++;
950
+			$basic_message = sprintf(
951
+				esc_html__("Could not update %s with the csv data: %s because %s", "event_espresso"),
952
+				$model->get_this_model_name(),
953
+				implode(",", $model_object_data),
954
+				$e->getMessage()
955
+			);
956
+			$debug_message = $basic_message . ' Stack trace: ' . $e->getTraceAsString();
957
+			EE_Error::add_error("$basic_message | $debug_message", __FILE__, __FUNCTION__, __LINE__);
958
+		}
959
+		return $old_db_to_new_db_mapping;
960
+	}
961
+
962
+	/**
963
+	 * Gets the number of inserts performed since importer was instantiated or reset
964
+	 *
965
+	 * @return int
966
+	 */
967
+	public function get_total_inserts()
968
+	{
969
+		return $this->_total_inserts;
970
+	}
971
+
972
+	/**
973
+	 *  Gets the number of insert errors since importer was instantiated or reset
974
+	 *
975
+	 * @return int
976
+	 */
977
+	public function get_total_insert_errors()
978
+	{
979
+		return $this->_total_insert_errors;
980
+	}
981
+
982
+	/**
983
+	 *  Gets the number of updates performed since importer was instantiated or reset
984
+	 *
985
+	 * @return int
986
+	 */
987
+	public function get_total_updates()
988
+	{
989
+		return $this->_total_updates;
990
+	}
991
+
992
+	/**
993
+	 *  Gets the number of update errors since importer was instantiated or reset
994
+	 *
995
+	 * @return int
996
+	 */
997
+	public function get_total_update_errors()
998
+	{
999
+		return $this->_total_update_errors;
1000
+	}
1001 1001
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Question_Form_Input.class.php 2 patches
Spacing   +32 added lines, -32 removed lines patch added patch discarded remove patch
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
      */
115 115
     public function set_question_form_input_meta($q_meta = [])
116 116
     {
117
-        $default_q_meta  = [
117
+        $default_q_meta = [
118 118
             'att_nmbr'       => 1,
119 119
             'ticket_id'      => '',
120 120
             'date'           => '',
@@ -160,13 +160,13 @@  discard block
 block discarded – undo
160 160
      */
161 161
     private function _set_input_name($qstn_id)
162 162
     {
163
-        if (! empty($qstn_id)) {
163
+        if ( ! empty($qstn_id)) {
164 164
             $ANS_ID  = $this->get('ANS_ID');
165
-            $qstn_id = ! empty($ANS_ID) ? '[' . $qstn_id . '][' . $ANS_ID . ']' : '[' . $qstn_id . ']';
165
+            $qstn_id = ! empty($ANS_ID) ? '['.$qstn_id.']['.$ANS_ID.']' : '['.$qstn_id.']';
166 166
         }
167 167
         $this->QST_input_name = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id)
168
-            ? $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name'] . $qstn_id
169
-            : $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name'];
168
+            ? $this->_QST_meta['input_prefix'].$this->_QST_meta['input_name'].$qstn_id
169
+            : $this->_QST_meta['input_prefix'].$this->_QST_meta['input_name'];
170 170
     }
171 171
 
172 172
 
@@ -181,7 +181,7 @@  discard block
 block discarded – undo
181 181
      */
182 182
     public function get($property = null)
183 183
     {
184
-        if (! empty($property)) {
184
+        if ( ! empty($property)) {
185 185
             if (EEM_Question::instance()->has_field($property)) {
186 186
                 return $this->_QST->get($property);
187 187
             } elseif (EEM_Answer::instance()->has_field($property)) {
@@ -207,7 +207,7 @@  discard block
 block discarded – undo
207 207
     {
208 208
         // first try regular property exists method which works as expected in PHP 5.3+
209 209
         $prop = EEH_Class_Tools::has_property($classname, $property);
210
-        if (! $prop) {
210
+        if ( ! $prop) {
211 211
             // use reflection for < PHP 5.3 as a double check when property is not found, possible due to access restriction
212 212
             $reflector = new ReflectionClass($classname);
213 213
             $prop      = $reflector->hasProperty($property);
@@ -231,7 +231,7 @@  discard block
 block discarded – undo
231 231
             ? $this->_QST_meta['input_id']
232 232
             : sanitize_key(strip_tags($this->_QST->get('QST_display_text')));
233 233
         $this->QST_input_id = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id)
234
-            ? $input_id . '-' . $qstn_id
234
+            ? $input_id.'-'.$qstn_id
235 235
             : $input_id;
236 236
     }
237 237
 
@@ -272,8 +272,8 @@  discard block
 block discarded – undo
272 272
             $date = $this->_QST_meta['date'];
273 273
             $time = $this->_QST_meta['time'];
274 274
             $price_id = $this->_QST_meta['price_id'];
275
-            if (isset($this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ])) {
276
-                $answer = $this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ];
275
+            if (isset($this->form_data['qstn'][$EVT_ID][$att_nmbr][$date][$time][$price_id][$qstn_id])) {
276
+                $answer = $this->form_data['qstn'][$EVT_ID][$att_nmbr][$date][$time][$price_id][$qstn_id];
277 277
                 $this->_ANS->set('ANS_value', $answer);
278 278
             }
279 279
         }
@@ -292,42 +292,42 @@  discard block
 block discarded – undo
292 292
      */
293 293
     public static function generate_question_form_inputs_for_object($object = false, $input_types = [])
294 294
     {
295
-        if (! is_object($object)) {
295
+        if ( ! is_object($object)) {
296 296
             return [];
297 297
         }
298 298
         $inputs = [];
299 299
         $fields = $object->get_model()->field_settings(false);
300 300
         foreach ($fields as $field_ID => $field) {
301 301
             if ($field instanceof EE_Model_Field_Base) {
302
-                if (isset($input_types[ $field_ID ])) {
302
+                if (isset($input_types[$field_ID])) {
303 303
                     // get saved value for field
304 304
                     $value = $object->get($field_ID);
305 305
                     // if no saved value, then use default
306 306
                     $value = $value !== null ? $value : $field->get_default_value();
307 307
                     // determine question type
308
-                    $type = isset($input_types[ $field_ID ]) ? $input_types[ $field_ID ]['type'] : 'TEXT';
308
+                    $type = isset($input_types[$field_ID]) ? $input_types[$field_ID]['type'] : 'TEXT';
309 309
                     // input name
310
-                    $input_name = isset($input_types[ $field_ID ]) && isset($input_types[ $field_ID ]['input_name'])
311
-                        ? $input_types[ $field_ID ]['input_name'] . '[' . $field_ID . ']'
310
+                    $input_name = isset($input_types[$field_ID]) && isset($input_types[$field_ID]['input_name'])
311
+                        ? $input_types[$field_ID]['input_name'].'['.$field_ID.']'
312 312
                         : $field_ID;
313 313
                     // css class for input
314
-                    $class = isset($input_types[ $field_ID ]['class']) && ! empty($input_types[ $field_ID ]['class'])
315
-                        ? ' ' . $input_types[ $field_ID ]['class']
314
+                    $class = isset($input_types[$field_ID]['class']) && ! empty($input_types[$field_ID]['class'])
315
+                        ? ' '.$input_types[$field_ID]['class']
316 316
                         : '';
317 317
                     // whether to apply htmlentities to answer
318
-                    $htmlentities = isset($input_types[ $field_ID ]['htmlentities'])
319
-                        ? $input_types[ $field_ID ]['htmlentities']
318
+                    $htmlentities = isset($input_types[$field_ID]['htmlentities'])
319
+                        ? $input_types[$field_ID]['htmlentities']
320 320
                         : true;
321 321
                     // whether to apply htmlentities to answer
322
-                    $label_b4 = isset($input_types[ $field_ID ]['label_b4'])
323
-                        ? $input_types[ $field_ID ]['label_b4']
322
+                    $label_b4 = isset($input_types[$field_ID]['label_b4'])
323
+                        ? $input_types[$field_ID]['label_b4']
324 324
                         : false;
325 325
                     // whether to apply htmlentities to answer
326
-                    $use_desc_4_label = isset($input_types[ $field_ID ]['use_desc_4_label'])
327
-                        ? $input_types[ $field_ID ]['use_desc_4_label']
326
+                    $use_desc_4_label = isset($input_types[$field_ID]['use_desc_4_label'])
327
+                        ? $input_types[$field_ID]['use_desc_4_label']
328 328
                         : false;
329 329
                     // whether input is disabled
330
-                    $disabled = isset($input_types[ $field_ID ]['disabled']) && $input_types[ $field_ID ]['disabled'];
330
+                    $disabled = isset($input_types[$field_ID]['disabled']) && $input_types[$field_ID]['disabled'];
331 331
 
332 332
                     // create EE_Question_Form_Input object
333 333
                     $QFI = new EE_Question_Form_Input(
@@ -347,9 +347,9 @@  discard block
 block discarded – undo
347 347
                             ]
348 348
                         ),
349 349
                         [
350
-                            'input_id'         => $field_ID . '-' . $object->ID(),
350
+                            'input_id'         => $field_ID.'-'.$object->ID(),
351 351
                             'input_name'       => $input_name,
352
-                            'input_class'      => $field_ID . $class,
352
+                            'input_class'      => $field_ID.$class,
353 353
                             'input_prefix'     => '',
354 354
                             'append_qstn_id'   => false,
355 355
                             'htmlentities'     => $htmlentities,
@@ -360,10 +360,10 @@  discard block
 block discarded – undo
360 360
                     // does question type have options ?
361 361
                     if (
362 362
                         in_array($type, ['DROPDOWN', 'RADIO_BTN', 'CHECKBOX'])
363
-                        && isset($input_types[ $field_ID ])
364
-                        && isset($input_types[ $field_ID ]['options'])
363
+                        && isset($input_types[$field_ID])
364
+                        && isset($input_types[$field_ID]['options'])
365 365
                     ) {
366
-                        foreach ($input_types[ $field_ID ]['options'] as $option) {
366
+                        foreach ($input_types[$field_ID]['options'] as $option) {
367 367
                             $option    = stripslashes_deep($option);
368 368
                             $option_id = ! empty($option['id']) ? $option['id'] : 0;
369 369
                             $QSO       = EE_Question_Option::new_instance(
@@ -381,7 +381,7 @@  discard block
 block discarded – undo
381 381
                     if ($disabled || $field_ID == $object->get_model()->primary_key_name()) {
382 382
                         $QFI->set('QST_disabled', true);
383 383
                     }
384
-                    $inputs[ $field_ID ] = $QFI;
384
+                    $inputs[$field_ID] = $QFI;
385 385
                 }
386 386
             }
387 387
         }
@@ -414,7 +414,7 @@  discard block
 block discarded – undo
414 414
      */
415 415
     public function set($property = null, $value = null)
416 416
     {
417
-        if (! empty($property)) {
417
+        if ( ! empty($property)) {
418 418
             if (EEM_Question::instance()->has_field($property)) {
419 419
                 $this->_QST->set($property, $value);
420 420
             } elseif (EEM_Answer::instance()->has_field($property)) {
@@ -460,6 +460,6 @@  discard block
 block discarded – undo
460 460
      */
461 461
     public function get_meta($key = false)
462 462
     {
463
-        return $key && isset($this->_QST_meta[ $key ]) ? $this->_QST_meta[ $key ] : false;
463
+        return $key && isset($this->_QST_meta[$key]) ? $this->_QST_meta[$key] : false;
464 464
     }
465 465
 }
Please login to merge, or discard this patch.
Indentation   +446 added lines, -446 removed lines patch added patch discarded remove patch
@@ -16,450 +16,450 @@
 block discarded – undo
16 16
 class EE_Question_Form_Input
17 17
 {
18 18
 
19
-    /**
20
-     *    EE_Question object
21
-     *
22
-     * @access private
23
-     * @var object
24
-     */
25
-    private $_QST = null;
26
-
27
-    /**
28
-     *    EE_Answer object
29
-     *
30
-     * @access private
31
-     * @var object
32
-     */
33
-    private $_ANS = null;
34
-
35
-    /**
36
-     *    $_QST_meta
37
-     * @access private
38
-     * @var array
39
-     */
40
-    private $_QST_meta = [];
41
-
42
-    /**
43
-     *    $QST_input_name
44
-     * @access private
45
-     * @var string
46
-     */
47
-    private $QST_input_name = '';
48
-
49
-    /**
50
-     *    $QST_input_id
51
-     * @access private
52
-     * @var string
53
-     */
54
-    private $QST_input_id = '';
55
-
56
-    /**
57
-     *    $QST_input_class
58
-     * @access private
59
-     * @var string
60
-     */
61
-    private $QST_input_class = '';
62
-
63
-    /**
64
-     * @var bool $QST_disabled
65
-     */
66
-    private $QST_disabled = false;
67
-
68
-    /**
69
-     * @var RequestInterface
70
-     */
71
-    protected $request;
72
-
73
-    /**
74
-     * @var array
75
-     */
76
-    protected $form_data;
77
-
78
-
79
-    /**
80
-     * constructor for questions
81
-     *
82
-     * @param EE_Question $QST EE_Question object
83
-     * @param EE_Answer   $ANS EE_Answer object
84
-     * @param array       $q_meta
85
-     * @throws EE_Error
86
-     * @throws ReflectionException
87
-     */
88
-    public function __construct(EE_Question $QST = null, EE_Answer $ANS = null, $q_meta = [])
89
-    {
90
-        $this->request   = LoaderFactory::getLoader()->getShared(RequestInterface::class);
91
-        $this->form_data = $this->request->requestParams();
92
-        if (empty($QST) || empty($ANS)) {
93
-            EE_Error::add_error(
94
-                esc_html__('An error occurred. A valid EE_Question or EE_Answer object was not received.', 'event_espresso'),
95
-                __FILE__,
96
-                __FUNCTION__,
97
-                __LINE__
98
-            );
99
-            return null;
100
-        }
101
-        $this->_QST = $QST;
102
-        $this->_ANS = $ANS;
103
-        $this->set_question_form_input_meta($q_meta);
104
-        $this->set_question_form_input_init();
105
-    }
106
-
107
-
108
-    /**
109
-     * sets meta data for the question form input
110
-     *
111
-     * @access public
112
-     * @param array $q_meta
113
-     * @return void
114
-     */
115
-    public function set_question_form_input_meta($q_meta = [])
116
-    {
117
-        $default_q_meta  = [
118
-            'att_nmbr'       => 1,
119
-            'ticket_id'      => '',
120
-            'date'           => '',
121
-            'time'           => '',
122
-            'input_name'     => '',
123
-            'input_id'       => '',
124
-            'input_class'    => '',
125
-            'input_prefix'   => 'qstn',
126
-            'append_qstn_id' => true,
127
-            'htmlentities'   => true,
128
-            'allow_null'     => false,
129
-        ];
130
-        $this->_QST_meta = array_merge($default_q_meta, $q_meta);
131
-    }
132
-
133
-
134
-    /**
135
-     * set_question_form_input_init
136
-     *
137
-     * @access public
138
-     * @return void
139
-     * @throws EE_Error
140
-     * @throws ReflectionException
141
-     */
142
-    public function set_question_form_input_init()
143
-    {
144
-        $qstn_id = $this->_QST->system_ID() ? $this->_QST->system_ID() : $this->_QST->ID();
145
-        $this->_set_input_name($qstn_id);
146
-        $this->_set_input_id($qstn_id);
147
-        $this->_set_input_class();
148
-        $this->set_question_form_input_answer($qstn_id);
149
-    }
150
-
151
-
152
-    /**
153
-     * set_input_name
154
-     *
155
-     * @access private
156
-     * @param $qstn_id
157
-     * @return void
158
-     * @throws EE_Error
159
-     * @throws ReflectionException
160
-     */
161
-    private function _set_input_name($qstn_id)
162
-    {
163
-        if (! empty($qstn_id)) {
164
-            $ANS_ID  = $this->get('ANS_ID');
165
-            $qstn_id = ! empty($ANS_ID) ? '[' . $qstn_id . '][' . $ANS_ID . ']' : '[' . $qstn_id . ']';
166
-        }
167
-        $this->QST_input_name = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id)
168
-            ? $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name'] . $qstn_id
169
-            : $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name'];
170
-    }
171
-
172
-
173
-    /**
174
-     * get property values for question form input
175
-     *
176
-     * @access public
177
-     * @param string $property
178
-     * @return mixed
179
-     * @throws EE_Error
180
-     * @throws ReflectionException
181
-     */
182
-    public function get($property = null)
183
-    {
184
-        if (! empty($property)) {
185
-            if (EEM_Question::instance()->has_field($property)) {
186
-                return $this->_QST->get($property);
187
-            } elseif (EEM_Answer::instance()->has_field($property)) {
188
-                return $this->_ANS->get($property);
189
-            } elseif ($this->_question_form_input_property_exists(__CLASS__, $property)) {
190
-                return $this->{$property};
191
-            }
192
-        }
193
-        return null;
194
-    }
195
-
196
-
197
-    /**
198
-     *    _question_form_input_property_exists
199
-     *
200
-     * @access private
201
-     * @param string $classname
202
-     * @param string $property
203
-     * @return boolean
204
-     * @throws ReflectionException
205
-     */
206
-    private function _question_form_input_property_exists($classname, $property)
207
-    {
208
-        // first try regular property exists method which works as expected in PHP 5.3+
209
-        $prop = EEH_Class_Tools::has_property($classname, $property);
210
-        if (! $prop) {
211
-            // use reflection for < PHP 5.3 as a double check when property is not found, possible due to access restriction
212
-            $reflector = new ReflectionClass($classname);
213
-            $prop      = $reflector->hasProperty($property);
214
-        }
215
-        return $prop;
216
-    }
217
-
218
-
219
-    /**
220
-     * set_input_id
221
-     *
222
-     * @access private
223
-     * @param $qstn_id
224
-     * @return void
225
-     * @throws EE_Error
226
-     * @throws ReflectionException
227
-     */
228
-    private function _set_input_id($qstn_id)
229
-    {
230
-        $input_id           = isset($this->_QST_meta['input_id']) && ! empty($this->_QST_meta['input_id'])
231
-            ? $this->_QST_meta['input_id']
232
-            : sanitize_key(strip_tags($this->_QST->get('QST_display_text')));
233
-        $this->QST_input_id = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id)
234
-            ? $input_id . '-' . $qstn_id
235
-            : $input_id;
236
-    }
237
-
238
-
239
-    /**
240
-     * set_input_class
241
-     *
242
-     * @access private
243
-     * @return void
244
-     */
245
-    private function _set_input_class()
246
-    {
247
-        $this->QST_input_class = isset($this->_QST_meta['input_class']) ? $this->_QST_meta['input_class'] : '';
248
-    }
249
-
250
-
251
-    /**
252
-     * set_question_form_input_answer
253
-     *
254
-     * @access public
255
-     * @param mixed    int | string    $qstn_id
256
-     * @return void
257
-     * @throws EE_Error
258
-     * @throws ReflectionException
259
-     */
260
-    public function set_question_form_input_answer($qstn_id)
261
-    {
262
-        // check for answer in $this->form_data in case we are reprocessing a form after an error
263
-        if (
264
-            isset($this->_QST_meta['EVT_ID'])
265
-            && isset($this->_QST_meta['att_nmbr'])
266
-            && isset($this->_QST_meta['date'])
267
-            && isset($this->_QST_meta['time'])
268
-            && isset($this->_QST_meta['price_id'])
269
-        ) {
270
-            $EVT_ID = $this->_QST_meta['EVT_ID'];
271
-            $att_nmbr = $this->_QST_meta['att_nmbr'];
272
-            $date = $this->_QST_meta['date'];
273
-            $time = $this->_QST_meta['time'];
274
-            $price_id = $this->_QST_meta['price_id'];
275
-            if (isset($this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ])) {
276
-                $answer = $this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ];
277
-                $this->_ANS->set('ANS_value', $answer);
278
-            }
279
-        }
280
-    }
281
-
282
-
283
-    /**
284
-     *        generate_question_form_inputs_for_object
285
-     *
286
-     * @access    protected
287
-     * @param bool|object $object $object
288
-     * @param array       $input_types
289
-     * @return        array
290
-     * @throws EE_Error
291
-     * @throws ReflectionException
292
-     */
293
-    public static function generate_question_form_inputs_for_object($object = false, $input_types = [])
294
-    {
295
-        if (! is_object($object)) {
296
-            return [];
297
-        }
298
-        $inputs = [];
299
-        $fields = $object->get_model()->field_settings(false);
300
-        foreach ($fields as $field_ID => $field) {
301
-            if ($field instanceof EE_Model_Field_Base) {
302
-                if (isset($input_types[ $field_ID ])) {
303
-                    // get saved value for field
304
-                    $value = $object->get($field_ID);
305
-                    // if no saved value, then use default
306
-                    $value = $value !== null ? $value : $field->get_default_value();
307
-                    // determine question type
308
-                    $type = isset($input_types[ $field_ID ]) ? $input_types[ $field_ID ]['type'] : 'TEXT';
309
-                    // input name
310
-                    $input_name = isset($input_types[ $field_ID ]) && isset($input_types[ $field_ID ]['input_name'])
311
-                        ? $input_types[ $field_ID ]['input_name'] . '[' . $field_ID . ']'
312
-                        : $field_ID;
313
-                    // css class for input
314
-                    $class = isset($input_types[ $field_ID ]['class']) && ! empty($input_types[ $field_ID ]['class'])
315
-                        ? ' ' . $input_types[ $field_ID ]['class']
316
-                        : '';
317
-                    // whether to apply htmlentities to answer
318
-                    $htmlentities = isset($input_types[ $field_ID ]['htmlentities'])
319
-                        ? $input_types[ $field_ID ]['htmlentities']
320
-                        : true;
321
-                    // whether to apply htmlentities to answer
322
-                    $label_b4 = isset($input_types[ $field_ID ]['label_b4'])
323
-                        ? $input_types[ $field_ID ]['label_b4']
324
-                        : false;
325
-                    // whether to apply htmlentities to answer
326
-                    $use_desc_4_label = isset($input_types[ $field_ID ]['use_desc_4_label'])
327
-                        ? $input_types[ $field_ID ]['use_desc_4_label']
328
-                        : false;
329
-                    // whether input is disabled
330
-                    $disabled = isset($input_types[ $field_ID ]['disabled']) && $input_types[ $field_ID ]['disabled'];
331
-
332
-                    // create EE_Question_Form_Input object
333
-                    $QFI = new EE_Question_Form_Input(
334
-                        EE_Question::new_instance(
335
-                            [
336
-                                'QST_ID'           => 0,
337
-                                'QST_display_text' => $field->get_nicename(),
338
-                                'QST_type'         => $type,
339
-                            ]
340
-                        ),
341
-                        EE_Answer::new_instance(
342
-                            [
343
-                                'ANS_ID'    => 0,
344
-                                'QST_ID'    => 0,
345
-                                'REG_ID'    => 0,
346
-                                'ANS_value' => $value,
347
-                            ]
348
-                        ),
349
-                        [
350
-                            'input_id'         => $field_ID . '-' . $object->ID(),
351
-                            'input_name'       => $input_name,
352
-                            'input_class'      => $field_ID . $class,
353
-                            'input_prefix'     => '',
354
-                            'append_qstn_id'   => false,
355
-                            'htmlentities'     => $htmlentities,
356
-                            'label_b4'         => $label_b4,
357
-                            'use_desc_4_label' => $use_desc_4_label,
358
-                        ]
359
-                    );
360
-                    // does question type have options ?
361
-                    if (
362
-                        in_array($type, ['DROPDOWN', 'RADIO_BTN', 'CHECKBOX'])
363
-                        && isset($input_types[ $field_ID ])
364
-                        && isset($input_types[ $field_ID ]['options'])
365
-                    ) {
366
-                        foreach ($input_types[ $field_ID ]['options'] as $option) {
367
-                            $option    = stripslashes_deep($option);
368
-                            $option_id = ! empty($option['id']) ? $option['id'] : 0;
369
-                            $QSO       = EE_Question_Option::new_instance(
370
-                                [
371
-                                    'QSO_value'   => (string) $option_id,
372
-                                    'QSO_desc'    => $option['text'],
373
-                                    'QSO_deleted' => false,
374
-                                ]
375
-                            );
376
-                            // all QST (and ANS) properties can be accessed indirectly thru QFI
377
-                            $QFI->add_temp_option($QSO);
378
-                        }
379
-                    }
380
-                    // we don't want ppl manually changing primary keys cuz that would just lead to total craziness man
381
-                    if ($disabled || $field_ID == $object->get_model()->primary_key_name()) {
382
-                        $QFI->set('QST_disabled', true);
383
-                    }
384
-                    $inputs[ $field_ID ] = $QFI;
385
-                }
386
-            }
387
-        }
388
-        return $inputs;
389
-    }
390
-
391
-
392
-    /**
393
-     *    add_temp_option
394
-     *
395
-     * @access public
396
-     * @param EE_Question_Option $QSO EE_Question_Option
397
-     * @return void
398
-     */
399
-    public function add_temp_option(EE_Question_Option $QSO)
400
-    {
401
-        $this->_QST->add_temp_option($QSO);
402
-    }
403
-
404
-
405
-    /**
406
-     * set property values for question form input
407
-     *
408
-     * @access public
409
-     * @param string $property
410
-     * @param mixed  $value
411
-     * @return void
412
-     * @throws EE_Error
413
-     * @throws ReflectionException
414
-     */
415
-    public function set($property = null, $value = null)
416
-    {
417
-        if (! empty($property)) {
418
-            if (EEM_Question::instance()->has_field($property)) {
419
-                $this->_QST->set($property, $value);
420
-            } elseif (EEM_Answer::instance()->has_field($property)) {
421
-                $this->_ANS->set($property, $value);
422
-            } elseif ($this->_question_form_input_property_exists(__CLASS__, $property)) {
423
-                $this->{$property} = $value;
424
-            }
425
-        }
426
-    }
427
-
428
-
429
-    /**
430
-     *    _question_form_input_property_exists
431
-     *
432
-     * @access public
433
-     * @param boolean      $notDeletedOptionsOnly            1
434
-     *                                                       whether to return ALL options, or only the ones which have
435
-     *                                                       not yet been deleted
436
-     * @param string|array $selected_value_to_always_include , when retrieving options to an ANSWERED question,
437
-     *                                                       we want to usually only show non-deleted options AND the
438
-     *                                                       value that was selected for the answer, whether it was
439
-     *                                                       trashed or not.
440
-     * @return EE_Question_Option
441
-     */
442
-    public function options($notDeletedOptionsOnly = true, $selected_value_to_always_include = null)
443
-    {
444
-        $temp_options = $this->_QST->temp_options();
445
-        return ! empty($temp_options)
446
-            ? $temp_options
447
-            : $this->_QST->options(
448
-                $notDeletedOptionsOnly,
449
-                $selected_value_to_always_include
450
-            );
451
-    }
452
-
453
-
454
-    /**
455
-     *    get_meta
456
-     *
457
-     * @access public
458
-     * @param mixed $key
459
-     * @return mixed
460
-     */
461
-    public function get_meta($key = false)
462
-    {
463
-        return $key && isset($this->_QST_meta[ $key ]) ? $this->_QST_meta[ $key ] : false;
464
-    }
19
+	/**
20
+	 *    EE_Question object
21
+	 *
22
+	 * @access private
23
+	 * @var object
24
+	 */
25
+	private $_QST = null;
26
+
27
+	/**
28
+	 *    EE_Answer object
29
+	 *
30
+	 * @access private
31
+	 * @var object
32
+	 */
33
+	private $_ANS = null;
34
+
35
+	/**
36
+	 *    $_QST_meta
37
+	 * @access private
38
+	 * @var array
39
+	 */
40
+	private $_QST_meta = [];
41
+
42
+	/**
43
+	 *    $QST_input_name
44
+	 * @access private
45
+	 * @var string
46
+	 */
47
+	private $QST_input_name = '';
48
+
49
+	/**
50
+	 *    $QST_input_id
51
+	 * @access private
52
+	 * @var string
53
+	 */
54
+	private $QST_input_id = '';
55
+
56
+	/**
57
+	 *    $QST_input_class
58
+	 * @access private
59
+	 * @var string
60
+	 */
61
+	private $QST_input_class = '';
62
+
63
+	/**
64
+	 * @var bool $QST_disabled
65
+	 */
66
+	private $QST_disabled = false;
67
+
68
+	/**
69
+	 * @var RequestInterface
70
+	 */
71
+	protected $request;
72
+
73
+	/**
74
+	 * @var array
75
+	 */
76
+	protected $form_data;
77
+
78
+
79
+	/**
80
+	 * constructor for questions
81
+	 *
82
+	 * @param EE_Question $QST EE_Question object
83
+	 * @param EE_Answer   $ANS EE_Answer object
84
+	 * @param array       $q_meta
85
+	 * @throws EE_Error
86
+	 * @throws ReflectionException
87
+	 */
88
+	public function __construct(EE_Question $QST = null, EE_Answer $ANS = null, $q_meta = [])
89
+	{
90
+		$this->request   = LoaderFactory::getLoader()->getShared(RequestInterface::class);
91
+		$this->form_data = $this->request->requestParams();
92
+		if (empty($QST) || empty($ANS)) {
93
+			EE_Error::add_error(
94
+				esc_html__('An error occurred. A valid EE_Question or EE_Answer object was not received.', 'event_espresso'),
95
+				__FILE__,
96
+				__FUNCTION__,
97
+				__LINE__
98
+			);
99
+			return null;
100
+		}
101
+		$this->_QST = $QST;
102
+		$this->_ANS = $ANS;
103
+		$this->set_question_form_input_meta($q_meta);
104
+		$this->set_question_form_input_init();
105
+	}
106
+
107
+
108
+	/**
109
+	 * sets meta data for the question form input
110
+	 *
111
+	 * @access public
112
+	 * @param array $q_meta
113
+	 * @return void
114
+	 */
115
+	public function set_question_form_input_meta($q_meta = [])
116
+	{
117
+		$default_q_meta  = [
118
+			'att_nmbr'       => 1,
119
+			'ticket_id'      => '',
120
+			'date'           => '',
121
+			'time'           => '',
122
+			'input_name'     => '',
123
+			'input_id'       => '',
124
+			'input_class'    => '',
125
+			'input_prefix'   => 'qstn',
126
+			'append_qstn_id' => true,
127
+			'htmlentities'   => true,
128
+			'allow_null'     => false,
129
+		];
130
+		$this->_QST_meta = array_merge($default_q_meta, $q_meta);
131
+	}
132
+
133
+
134
+	/**
135
+	 * set_question_form_input_init
136
+	 *
137
+	 * @access public
138
+	 * @return void
139
+	 * @throws EE_Error
140
+	 * @throws ReflectionException
141
+	 */
142
+	public function set_question_form_input_init()
143
+	{
144
+		$qstn_id = $this->_QST->system_ID() ? $this->_QST->system_ID() : $this->_QST->ID();
145
+		$this->_set_input_name($qstn_id);
146
+		$this->_set_input_id($qstn_id);
147
+		$this->_set_input_class();
148
+		$this->set_question_form_input_answer($qstn_id);
149
+	}
150
+
151
+
152
+	/**
153
+	 * set_input_name
154
+	 *
155
+	 * @access private
156
+	 * @param $qstn_id
157
+	 * @return void
158
+	 * @throws EE_Error
159
+	 * @throws ReflectionException
160
+	 */
161
+	private function _set_input_name($qstn_id)
162
+	{
163
+		if (! empty($qstn_id)) {
164
+			$ANS_ID  = $this->get('ANS_ID');
165
+			$qstn_id = ! empty($ANS_ID) ? '[' . $qstn_id . '][' . $ANS_ID . ']' : '[' . $qstn_id . ']';
166
+		}
167
+		$this->QST_input_name = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id)
168
+			? $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name'] . $qstn_id
169
+			: $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name'];
170
+	}
171
+
172
+
173
+	/**
174
+	 * get property values for question form input
175
+	 *
176
+	 * @access public
177
+	 * @param string $property
178
+	 * @return mixed
179
+	 * @throws EE_Error
180
+	 * @throws ReflectionException
181
+	 */
182
+	public function get($property = null)
183
+	{
184
+		if (! empty($property)) {
185
+			if (EEM_Question::instance()->has_field($property)) {
186
+				return $this->_QST->get($property);
187
+			} elseif (EEM_Answer::instance()->has_field($property)) {
188
+				return $this->_ANS->get($property);
189
+			} elseif ($this->_question_form_input_property_exists(__CLASS__, $property)) {
190
+				return $this->{$property};
191
+			}
192
+		}
193
+		return null;
194
+	}
195
+
196
+
197
+	/**
198
+	 *    _question_form_input_property_exists
199
+	 *
200
+	 * @access private
201
+	 * @param string $classname
202
+	 * @param string $property
203
+	 * @return boolean
204
+	 * @throws ReflectionException
205
+	 */
206
+	private function _question_form_input_property_exists($classname, $property)
207
+	{
208
+		// first try regular property exists method which works as expected in PHP 5.3+
209
+		$prop = EEH_Class_Tools::has_property($classname, $property);
210
+		if (! $prop) {
211
+			// use reflection for < PHP 5.3 as a double check when property is not found, possible due to access restriction
212
+			$reflector = new ReflectionClass($classname);
213
+			$prop      = $reflector->hasProperty($property);
214
+		}
215
+		return $prop;
216
+	}
217
+
218
+
219
+	/**
220
+	 * set_input_id
221
+	 *
222
+	 * @access private
223
+	 * @param $qstn_id
224
+	 * @return void
225
+	 * @throws EE_Error
226
+	 * @throws ReflectionException
227
+	 */
228
+	private function _set_input_id($qstn_id)
229
+	{
230
+		$input_id           = isset($this->_QST_meta['input_id']) && ! empty($this->_QST_meta['input_id'])
231
+			? $this->_QST_meta['input_id']
232
+			: sanitize_key(strip_tags($this->_QST->get('QST_display_text')));
233
+		$this->QST_input_id = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id)
234
+			? $input_id . '-' . $qstn_id
235
+			: $input_id;
236
+	}
237
+
238
+
239
+	/**
240
+	 * set_input_class
241
+	 *
242
+	 * @access private
243
+	 * @return void
244
+	 */
245
+	private function _set_input_class()
246
+	{
247
+		$this->QST_input_class = isset($this->_QST_meta['input_class']) ? $this->_QST_meta['input_class'] : '';
248
+	}
249
+
250
+
251
+	/**
252
+	 * set_question_form_input_answer
253
+	 *
254
+	 * @access public
255
+	 * @param mixed    int | string    $qstn_id
256
+	 * @return void
257
+	 * @throws EE_Error
258
+	 * @throws ReflectionException
259
+	 */
260
+	public function set_question_form_input_answer($qstn_id)
261
+	{
262
+		// check for answer in $this->form_data in case we are reprocessing a form after an error
263
+		if (
264
+			isset($this->_QST_meta['EVT_ID'])
265
+			&& isset($this->_QST_meta['att_nmbr'])
266
+			&& isset($this->_QST_meta['date'])
267
+			&& isset($this->_QST_meta['time'])
268
+			&& isset($this->_QST_meta['price_id'])
269
+		) {
270
+			$EVT_ID = $this->_QST_meta['EVT_ID'];
271
+			$att_nmbr = $this->_QST_meta['att_nmbr'];
272
+			$date = $this->_QST_meta['date'];
273
+			$time = $this->_QST_meta['time'];
274
+			$price_id = $this->_QST_meta['price_id'];
275
+			if (isset($this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ])) {
276
+				$answer = $this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ];
277
+				$this->_ANS->set('ANS_value', $answer);
278
+			}
279
+		}
280
+	}
281
+
282
+
283
+	/**
284
+	 *        generate_question_form_inputs_for_object
285
+	 *
286
+	 * @access    protected
287
+	 * @param bool|object $object $object
288
+	 * @param array       $input_types
289
+	 * @return        array
290
+	 * @throws EE_Error
291
+	 * @throws ReflectionException
292
+	 */
293
+	public static function generate_question_form_inputs_for_object($object = false, $input_types = [])
294
+	{
295
+		if (! is_object($object)) {
296
+			return [];
297
+		}
298
+		$inputs = [];
299
+		$fields = $object->get_model()->field_settings(false);
300
+		foreach ($fields as $field_ID => $field) {
301
+			if ($field instanceof EE_Model_Field_Base) {
302
+				if (isset($input_types[ $field_ID ])) {
303
+					// get saved value for field
304
+					$value = $object->get($field_ID);
305
+					// if no saved value, then use default
306
+					$value = $value !== null ? $value : $field->get_default_value();
307
+					// determine question type
308
+					$type = isset($input_types[ $field_ID ]) ? $input_types[ $field_ID ]['type'] : 'TEXT';
309
+					// input name
310
+					$input_name = isset($input_types[ $field_ID ]) && isset($input_types[ $field_ID ]['input_name'])
311
+						? $input_types[ $field_ID ]['input_name'] . '[' . $field_ID . ']'
312
+						: $field_ID;
313
+					// css class for input
314
+					$class = isset($input_types[ $field_ID ]['class']) && ! empty($input_types[ $field_ID ]['class'])
315
+						? ' ' . $input_types[ $field_ID ]['class']
316
+						: '';
317
+					// whether to apply htmlentities to answer
318
+					$htmlentities = isset($input_types[ $field_ID ]['htmlentities'])
319
+						? $input_types[ $field_ID ]['htmlentities']
320
+						: true;
321
+					// whether to apply htmlentities to answer
322
+					$label_b4 = isset($input_types[ $field_ID ]['label_b4'])
323
+						? $input_types[ $field_ID ]['label_b4']
324
+						: false;
325
+					// whether to apply htmlentities to answer
326
+					$use_desc_4_label = isset($input_types[ $field_ID ]['use_desc_4_label'])
327
+						? $input_types[ $field_ID ]['use_desc_4_label']
328
+						: false;
329
+					// whether input is disabled
330
+					$disabled = isset($input_types[ $field_ID ]['disabled']) && $input_types[ $field_ID ]['disabled'];
331
+
332
+					// create EE_Question_Form_Input object
333
+					$QFI = new EE_Question_Form_Input(
334
+						EE_Question::new_instance(
335
+							[
336
+								'QST_ID'           => 0,
337
+								'QST_display_text' => $field->get_nicename(),
338
+								'QST_type'         => $type,
339
+							]
340
+						),
341
+						EE_Answer::new_instance(
342
+							[
343
+								'ANS_ID'    => 0,
344
+								'QST_ID'    => 0,
345
+								'REG_ID'    => 0,
346
+								'ANS_value' => $value,
347
+							]
348
+						),
349
+						[
350
+							'input_id'         => $field_ID . '-' . $object->ID(),
351
+							'input_name'       => $input_name,
352
+							'input_class'      => $field_ID . $class,
353
+							'input_prefix'     => '',
354
+							'append_qstn_id'   => false,
355
+							'htmlentities'     => $htmlentities,
356
+							'label_b4'         => $label_b4,
357
+							'use_desc_4_label' => $use_desc_4_label,
358
+						]
359
+					);
360
+					// does question type have options ?
361
+					if (
362
+						in_array($type, ['DROPDOWN', 'RADIO_BTN', 'CHECKBOX'])
363
+						&& isset($input_types[ $field_ID ])
364
+						&& isset($input_types[ $field_ID ]['options'])
365
+					) {
366
+						foreach ($input_types[ $field_ID ]['options'] as $option) {
367
+							$option    = stripslashes_deep($option);
368
+							$option_id = ! empty($option['id']) ? $option['id'] : 0;
369
+							$QSO       = EE_Question_Option::new_instance(
370
+								[
371
+									'QSO_value'   => (string) $option_id,
372
+									'QSO_desc'    => $option['text'],
373
+									'QSO_deleted' => false,
374
+								]
375
+							);
376
+							// all QST (and ANS) properties can be accessed indirectly thru QFI
377
+							$QFI->add_temp_option($QSO);
378
+						}
379
+					}
380
+					// we don't want ppl manually changing primary keys cuz that would just lead to total craziness man
381
+					if ($disabled || $field_ID == $object->get_model()->primary_key_name()) {
382
+						$QFI->set('QST_disabled', true);
383
+					}
384
+					$inputs[ $field_ID ] = $QFI;
385
+				}
386
+			}
387
+		}
388
+		return $inputs;
389
+	}
390
+
391
+
392
+	/**
393
+	 *    add_temp_option
394
+	 *
395
+	 * @access public
396
+	 * @param EE_Question_Option $QSO EE_Question_Option
397
+	 * @return void
398
+	 */
399
+	public function add_temp_option(EE_Question_Option $QSO)
400
+	{
401
+		$this->_QST->add_temp_option($QSO);
402
+	}
403
+
404
+
405
+	/**
406
+	 * set property values for question form input
407
+	 *
408
+	 * @access public
409
+	 * @param string $property
410
+	 * @param mixed  $value
411
+	 * @return void
412
+	 * @throws EE_Error
413
+	 * @throws ReflectionException
414
+	 */
415
+	public function set($property = null, $value = null)
416
+	{
417
+		if (! empty($property)) {
418
+			if (EEM_Question::instance()->has_field($property)) {
419
+				$this->_QST->set($property, $value);
420
+			} elseif (EEM_Answer::instance()->has_field($property)) {
421
+				$this->_ANS->set($property, $value);
422
+			} elseif ($this->_question_form_input_property_exists(__CLASS__, $property)) {
423
+				$this->{$property} = $value;
424
+			}
425
+		}
426
+	}
427
+
428
+
429
+	/**
430
+	 *    _question_form_input_property_exists
431
+	 *
432
+	 * @access public
433
+	 * @param boolean      $notDeletedOptionsOnly            1
434
+	 *                                                       whether to return ALL options, or only the ones which have
435
+	 *                                                       not yet been deleted
436
+	 * @param string|array $selected_value_to_always_include , when retrieving options to an ANSWERED question,
437
+	 *                                                       we want to usually only show non-deleted options AND the
438
+	 *                                                       value that was selected for the answer, whether it was
439
+	 *                                                       trashed or not.
440
+	 * @return EE_Question_Option
441
+	 */
442
+	public function options($notDeletedOptionsOnly = true, $selected_value_to_always_include = null)
443
+	{
444
+		$temp_options = $this->_QST->temp_options();
445
+		return ! empty($temp_options)
446
+			? $temp_options
447
+			: $this->_QST->options(
448
+				$notDeletedOptionsOnly,
449
+				$selected_value_to_always_include
450
+			);
451
+	}
452
+
453
+
454
+	/**
455
+	 *    get_meta
456
+	 *
457
+	 * @access public
458
+	 * @param mixed $key
459
+	 * @return mixed
460
+	 */
461
+	public function get_meta($key = false)
462
+	{
463
+		return $key && isset($this->_QST_meta[ $key ]) ? $this->_QST_meta[ $key ] : false;
464
+	}
465 465
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Line_Item.class.php 2 patches
Indentation   +1738 added lines, -1738 removed lines patch added patch discarded remove patch
@@ -14,1742 +14,1742 @@
 block discarded – undo
14 14
 class EE_Line_Item extends EE_Base_Class implements EEI_Line_Item
15 15
 {
16 16
 
17
-    /**
18
-     * for children line items (currently not a normal relation)
19
-     *
20
-     * @type EE_Line_Item[]
21
-     */
22
-    protected $_children = array();
23
-
24
-    /**
25
-     * for the parent line item
26
-     *
27
-     * @var EE_Line_Item
28
-     */
29
-    protected $_parent;
30
-
31
-
32
-    /**
33
-     * @param array  $props_n_values          incoming values
34
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
35
-     *                                        used.)
36
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
37
-     *                                        date_format and the second value is the time format
38
-     * @return EE_Line_Item
39
-     * @throws EE_Error
40
-     * @throws InvalidArgumentException
41
-     * @throws InvalidDataTypeException
42
-     * @throws InvalidInterfaceException
43
-     * @throws ReflectionException
44
-     */
45
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
46
-    {
47
-        $has_object = parent::_check_for_object(
48
-            $props_n_values,
49
-            __CLASS__,
50
-            $timezone,
51
-            $date_formats
52
-        );
53
-        return $has_object
54
-            ? $has_object
55
-            : new self($props_n_values, false, $timezone);
56
-    }
57
-
58
-
59
-    /**
60
-     * @param array  $props_n_values  incoming values from the database
61
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
62
-     *                                the website will be used.
63
-     * @return EE_Line_Item
64
-     * @throws EE_Error
65
-     * @throws InvalidArgumentException
66
-     * @throws InvalidDataTypeException
67
-     * @throws InvalidInterfaceException
68
-     * @throws ReflectionException
69
-     */
70
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
71
-    {
72
-        return new self($props_n_values, true, $timezone);
73
-    }
74
-
75
-
76
-    /**
77
-     * Adds some defaults if they're not specified
78
-     *
79
-     * @param array  $fieldValues
80
-     * @param bool   $bydb
81
-     * @param string $timezone
82
-     * @throws EE_Error
83
-     * @throws InvalidArgumentException
84
-     * @throws InvalidDataTypeException
85
-     * @throws InvalidInterfaceException
86
-     * @throws ReflectionException
87
-     */
88
-    protected function __construct($fieldValues = array(), $bydb = false, $timezone = '')
89
-    {
90
-        parent::__construct($fieldValues, $bydb, $timezone);
91
-        if (! $this->get('LIN_code')) {
92
-            $this->set_code($this->generate_code());
93
-        }
94
-    }
95
-
96
-
97
-    /**
98
-     * Gets ID
99
-     *
100
-     * @return int
101
-     * @throws EE_Error
102
-     * @throws InvalidArgumentException
103
-     * @throws InvalidDataTypeException
104
-     * @throws InvalidInterfaceException
105
-     * @throws ReflectionException
106
-     */
107
-    public function ID()
108
-    {
109
-        return $this->get('LIN_ID');
110
-    }
111
-
112
-
113
-    /**
114
-     * Gets TXN_ID
115
-     *
116
-     * @return int
117
-     * @throws EE_Error
118
-     * @throws InvalidArgumentException
119
-     * @throws InvalidDataTypeException
120
-     * @throws InvalidInterfaceException
121
-     * @throws ReflectionException
122
-     */
123
-    public function TXN_ID()
124
-    {
125
-        return $this->get('TXN_ID');
126
-    }
127
-
128
-
129
-    /**
130
-     * Sets TXN_ID
131
-     *
132
-     * @param int $TXN_ID
133
-     * @throws EE_Error
134
-     * @throws InvalidArgumentException
135
-     * @throws InvalidDataTypeException
136
-     * @throws InvalidInterfaceException
137
-     * @throws ReflectionException
138
-     */
139
-    public function set_TXN_ID($TXN_ID)
140
-    {
141
-        $this->set('TXN_ID', $TXN_ID);
142
-    }
143
-
144
-
145
-    /**
146
-     * Gets name
147
-     *
148
-     * @return string
149
-     * @throws EE_Error
150
-     * @throws InvalidArgumentException
151
-     * @throws InvalidDataTypeException
152
-     * @throws InvalidInterfaceException
153
-     * @throws ReflectionException
154
-     */
155
-    public function name()
156
-    {
157
-        $name = $this->get('LIN_name');
158
-        if (! $name) {
159
-            $name = ucwords(str_replace('-', ' ', $this->type()));
160
-        }
161
-        return $name;
162
-    }
163
-
164
-
165
-    /**
166
-     * Sets name
167
-     *
168
-     * @param string $name
169
-     * @throws EE_Error
170
-     * @throws InvalidArgumentException
171
-     * @throws InvalidDataTypeException
172
-     * @throws InvalidInterfaceException
173
-     * @throws ReflectionException
174
-     */
175
-    public function set_name($name)
176
-    {
177
-        $this->set('LIN_name', $name);
178
-    }
179
-
180
-
181
-    /**
182
-     * Gets desc
183
-     *
184
-     * @return string
185
-     * @throws EE_Error
186
-     * @throws InvalidArgumentException
187
-     * @throws InvalidDataTypeException
188
-     * @throws InvalidInterfaceException
189
-     * @throws ReflectionException
190
-     */
191
-    public function desc()
192
-    {
193
-        return $this->get('LIN_desc');
194
-    }
195
-
196
-
197
-    /**
198
-     * Sets desc
199
-     *
200
-     * @param string $desc
201
-     * @throws EE_Error
202
-     * @throws InvalidArgumentException
203
-     * @throws InvalidDataTypeException
204
-     * @throws InvalidInterfaceException
205
-     * @throws ReflectionException
206
-     */
207
-    public function set_desc($desc)
208
-    {
209
-        $this->set('LIN_desc', $desc);
210
-    }
211
-
212
-
213
-    /**
214
-     * Gets quantity
215
-     *
216
-     * @return int
217
-     * @throws EE_Error
218
-     * @throws InvalidArgumentException
219
-     * @throws InvalidDataTypeException
220
-     * @throws InvalidInterfaceException
221
-     * @throws ReflectionException
222
-     */
223
-    public function quantity()
224
-    {
225
-        return $this->get('LIN_quantity');
226
-    }
227
-
228
-
229
-    /**
230
-     * Sets quantity
231
-     *
232
-     * @param int $quantity
233
-     * @throws EE_Error
234
-     * @throws InvalidArgumentException
235
-     * @throws InvalidDataTypeException
236
-     * @throws InvalidInterfaceException
237
-     * @throws ReflectionException
238
-     */
239
-    public function set_quantity($quantity)
240
-    {
241
-        $this->set('LIN_quantity', max($quantity, 0));
242
-    }
243
-
244
-
245
-    /**
246
-     * Gets item_id
247
-     *
248
-     * @return string
249
-     * @throws EE_Error
250
-     * @throws InvalidArgumentException
251
-     * @throws InvalidDataTypeException
252
-     * @throws InvalidInterfaceException
253
-     * @throws ReflectionException
254
-     */
255
-    public function OBJ_ID()
256
-    {
257
-        return $this->get('OBJ_ID');
258
-    }
259
-
260
-
261
-    /**
262
-     * Sets item_id
263
-     *
264
-     * @param string $item_id
265
-     * @throws EE_Error
266
-     * @throws InvalidArgumentException
267
-     * @throws InvalidDataTypeException
268
-     * @throws InvalidInterfaceException
269
-     * @throws ReflectionException
270
-     */
271
-    public function set_OBJ_ID($item_id)
272
-    {
273
-        $this->set('OBJ_ID', $item_id);
274
-    }
275
-
276
-
277
-    /**
278
-     * Gets item_type
279
-     *
280
-     * @return string
281
-     * @throws EE_Error
282
-     * @throws InvalidArgumentException
283
-     * @throws InvalidDataTypeException
284
-     * @throws InvalidInterfaceException
285
-     * @throws ReflectionException
286
-     */
287
-    public function OBJ_type()
288
-    {
289
-        return $this->get('OBJ_type');
290
-    }
291
-
292
-
293
-    /**
294
-     * Gets item_type
295
-     *
296
-     * @return string
297
-     * @throws EE_Error
298
-     * @throws InvalidArgumentException
299
-     * @throws InvalidDataTypeException
300
-     * @throws InvalidInterfaceException
301
-     * @throws ReflectionException
302
-     */
303
-    public function OBJ_type_i18n()
304
-    {
305
-        $obj_type = $this->OBJ_type();
306
-        switch ($obj_type) {
307
-            case EEM_Line_Item::OBJ_TYPE_EVENT:
308
-                $obj_type = esc_html__('Event', 'event_espresso');
309
-                break;
310
-            case EEM_Line_Item::OBJ_TYPE_PRICE:
311
-                $obj_type = esc_html__('Price', 'event_espresso');
312
-                break;
313
-            case EEM_Line_Item::OBJ_TYPE_PROMOTION:
314
-                $obj_type = esc_html__('Promotion', 'event_espresso');
315
-                break;
316
-            case EEM_Line_Item::OBJ_TYPE_TICKET:
317
-                $obj_type = esc_html__('Ticket', 'event_espresso');
318
-                break;
319
-            case EEM_Line_Item::OBJ_TYPE_TRANSACTION:
320
-                $obj_type = esc_html__('Transaction', 'event_espresso');
321
-                break;
322
-        }
323
-        return apply_filters('FHEE__EE_Line_Item__OBJ_type_i18n', $obj_type, $this);
324
-    }
325
-
326
-
327
-    /**
328
-     * Sets item_type
329
-     *
330
-     * @param string $OBJ_type
331
-     * @throws EE_Error
332
-     * @throws InvalidArgumentException
333
-     * @throws InvalidDataTypeException
334
-     * @throws InvalidInterfaceException
335
-     * @throws ReflectionException
336
-     */
337
-    public function set_OBJ_type($OBJ_type)
338
-    {
339
-        $this->set('OBJ_type', $OBJ_type);
340
-    }
341
-
342
-
343
-    /**
344
-     * Gets unit_price
345
-     *
346
-     * @return float
347
-     * @throws EE_Error
348
-     * @throws InvalidArgumentException
349
-     * @throws InvalidDataTypeException
350
-     * @throws InvalidInterfaceException
351
-     * @throws ReflectionException
352
-     */
353
-    public function unit_price()
354
-    {
355
-        return $this->get('LIN_unit_price');
356
-    }
357
-
358
-
359
-    /**
360
-     * Sets unit_price
361
-     *
362
-     * @param float $unit_price
363
-     * @throws EE_Error
364
-     * @throws InvalidArgumentException
365
-     * @throws InvalidDataTypeException
366
-     * @throws InvalidInterfaceException
367
-     * @throws ReflectionException
368
-     */
369
-    public function set_unit_price($unit_price)
370
-    {
371
-        $this->set('LIN_unit_price', $unit_price);
372
-    }
373
-
374
-
375
-    /**
376
-     * Checks if this item is a percentage modifier or not
377
-     *
378
-     * @return boolean
379
-     * @throws EE_Error
380
-     * @throws InvalidArgumentException
381
-     * @throws InvalidDataTypeException
382
-     * @throws InvalidInterfaceException
383
-     * @throws ReflectionException
384
-     */
385
-    public function is_percent()
386
-    {
387
-        if ($this->is_tax_sub_total()) {
388
-            // tax subtotals HAVE a percent on them, that percentage only applies
389
-            // to taxable items, so its' an exception. Treat it like a flat line item
390
-            return false;
391
-        }
392
-        $unit_price = abs($this->get('LIN_unit_price'));
393
-        $percent = abs($this->get('LIN_percent'));
394
-        if ($unit_price < .001 && $percent) {
395
-            return true;
396
-        }
397
-        if ($unit_price >= .001 && ! $percent) {
398
-            return false;
399
-        }
400
-        if ($unit_price >= .001 && $percent) {
401
-            throw new EE_Error(
402
-                sprintf(
403
-                    esc_html__(
404
-                        'A Line Item can not have a unit price of (%s) AND a percent (%s)!',
405
-                        'event_espresso'
406
-                    ),
407
-                    $unit_price,
408
-                    $percent
409
-                )
410
-            );
411
-        }
412
-        // if they're both 0, assume its not a percent item
413
-        return false;
414
-    }
415
-
416
-
417
-    /**
418
-     * Gets percent (between 100-.001)
419
-     *
420
-     * @return float
421
-     * @throws EE_Error
422
-     * @throws InvalidArgumentException
423
-     * @throws InvalidDataTypeException
424
-     * @throws InvalidInterfaceException
425
-     * @throws ReflectionException
426
-     */
427
-    public function percent()
428
-    {
429
-        return $this->get('LIN_percent');
430
-    }
431
-
432
-
433
-    /**
434
-     * Sets percent (between 100-0.01)
435
-     *
436
-     * @param float $percent
437
-     * @throws EE_Error
438
-     * @throws InvalidArgumentException
439
-     * @throws InvalidDataTypeException
440
-     * @throws InvalidInterfaceException
441
-     * @throws ReflectionException
442
-     */
443
-    public function set_percent($percent)
444
-    {
445
-        $this->set('LIN_percent', $percent);
446
-    }
447
-
448
-
449
-    /**
450
-     * Gets total
451
-     *
452
-     * @return float
453
-     * @throws EE_Error
454
-     * @throws InvalidArgumentException
455
-     * @throws InvalidDataTypeException
456
-     * @throws InvalidInterfaceException
457
-     * @throws ReflectionException
458
-     */
459
-    public function total()
460
-    {
461
-        return $this->get('LIN_total');
462
-    }
463
-
464
-
465
-    /**
466
-     * Sets total
467
-     *
468
-     * @param float $total
469
-     * @throws EE_Error
470
-     * @throws InvalidArgumentException
471
-     * @throws InvalidDataTypeException
472
-     * @throws InvalidInterfaceException
473
-     * @throws ReflectionException
474
-     */
475
-    public function set_total($total)
476
-    {
477
-        $this->set('LIN_total', $total);
478
-    }
479
-
480
-
481
-    /**
482
-     * Gets order
483
-     *
484
-     * @return int
485
-     * @throws EE_Error
486
-     * @throws InvalidArgumentException
487
-     * @throws InvalidDataTypeException
488
-     * @throws InvalidInterfaceException
489
-     * @throws ReflectionException
490
-     */
491
-    public function order()
492
-    {
493
-        return $this->get('LIN_order');
494
-    }
495
-
496
-
497
-    /**
498
-     * Sets order
499
-     *
500
-     * @param int $order
501
-     * @throws EE_Error
502
-     * @throws InvalidArgumentException
503
-     * @throws InvalidDataTypeException
504
-     * @throws InvalidInterfaceException
505
-     * @throws ReflectionException
506
-     */
507
-    public function set_order($order)
508
-    {
509
-        $this->set('LIN_order', $order);
510
-    }
511
-
512
-
513
-    /**
514
-     * Gets parent
515
-     *
516
-     * @return int
517
-     * @throws EE_Error
518
-     * @throws InvalidArgumentException
519
-     * @throws InvalidDataTypeException
520
-     * @throws InvalidInterfaceException
521
-     * @throws ReflectionException
522
-     */
523
-    public function parent_ID()
524
-    {
525
-        return $this->get('LIN_parent');
526
-    }
527
-
528
-
529
-    /**
530
-     * Sets parent
531
-     *
532
-     * @param int $parent
533
-     * @throws EE_Error
534
-     * @throws InvalidArgumentException
535
-     * @throws InvalidDataTypeException
536
-     * @throws InvalidInterfaceException
537
-     * @throws ReflectionException
538
-     */
539
-    public function set_parent_ID($parent)
540
-    {
541
-        $this->set('LIN_parent', $parent);
542
-    }
543
-
544
-
545
-    /**
546
-     * Gets type
547
-     *
548
-     * @return string
549
-     * @throws EE_Error
550
-     * @throws InvalidArgumentException
551
-     * @throws InvalidDataTypeException
552
-     * @throws InvalidInterfaceException
553
-     * @throws ReflectionException
554
-     */
555
-    public function type()
556
-    {
557
-        return $this->get('LIN_type');
558
-    }
559
-
560
-
561
-    /**
562
-     * Sets type
563
-     *
564
-     * @param string $type
565
-     * @throws EE_Error
566
-     * @throws InvalidArgumentException
567
-     * @throws InvalidDataTypeException
568
-     * @throws InvalidInterfaceException
569
-     * @throws ReflectionException
570
-     */
571
-    public function set_type($type)
572
-    {
573
-        $this->set('LIN_type', $type);
574
-    }
575
-
576
-
577
-    /**
578
-     * Gets the line item of which this item is a composite. Eg, if this is a subtotal, the parent might be a total\
579
-     * If this line item is saved to the DB, fetches the parent from the DB. However, if this line item isn't in the DB
580
-     * it uses its cached reference to its parent line item (which would have been set by `EE_Line_Item::set_parent()`
581
-     * or indirectly by `EE_Line_item::add_child_line_item()`)
582
-     *
583
-     * @return EE_Base_Class|EE_Line_Item
584
-     * @throws EE_Error
585
-     * @throws InvalidArgumentException
586
-     * @throws InvalidDataTypeException
587
-     * @throws InvalidInterfaceException
588
-     * @throws ReflectionException
589
-     */
590
-    public function parent()
591
-    {
592
-        return $this->ID()
593
-            ? $this->get_model()->get_one_by_ID($this->parent_ID())
594
-            : $this->_parent;
595
-    }
596
-
597
-
598
-    /**
599
-     * Gets ALL the children of this line item (ie, all the parts that contribute towards this total).
600
-     *
601
-     * @return EE_Base_Class[]|EE_Line_Item[]
602
-     * @throws EE_Error
603
-     * @throws InvalidArgumentException
604
-     * @throws InvalidDataTypeException
605
-     * @throws InvalidInterfaceException
606
-     * @throws ReflectionException
607
-     */
608
-    public function children()
609
-    {
610
-        if ($this->ID()) {
611
-            return $this->get_model()->get_all(
612
-                array(
613
-                    array('LIN_parent' => $this->ID()),
614
-                    'order_by' => array('LIN_order' => 'ASC'),
615
-                )
616
-            );
617
-        }
618
-        if (! is_array($this->_children)) {
619
-            $this->_children = array();
620
-        }
621
-        return $this->_children;
622
-    }
623
-
624
-
625
-    /**
626
-     * Gets code
627
-     *
628
-     * @return string
629
-     * @throws EE_Error
630
-     * @throws InvalidArgumentException
631
-     * @throws InvalidDataTypeException
632
-     * @throws InvalidInterfaceException
633
-     * @throws ReflectionException
634
-     */
635
-    public function code()
636
-    {
637
-        return $this->get('LIN_code');
638
-    }
639
-
640
-
641
-    /**
642
-     * Sets code
643
-     *
644
-     * @param string $code
645
-     * @throws EE_Error
646
-     * @throws InvalidArgumentException
647
-     * @throws InvalidDataTypeException
648
-     * @throws InvalidInterfaceException
649
-     * @throws ReflectionException
650
-     */
651
-    public function set_code($code)
652
-    {
653
-        $this->set('LIN_code', $code);
654
-    }
655
-
656
-
657
-    /**
658
-     * Gets is_taxable
659
-     *
660
-     * @return boolean
661
-     * @throws EE_Error
662
-     * @throws InvalidArgumentException
663
-     * @throws InvalidDataTypeException
664
-     * @throws InvalidInterfaceException
665
-     * @throws ReflectionException
666
-     */
667
-    public function is_taxable()
668
-    {
669
-        return $this->get('LIN_is_taxable');
670
-    }
671
-
672
-
673
-    /**
674
-     * Sets is_taxable
675
-     *
676
-     * @param boolean $is_taxable
677
-     * @throws EE_Error
678
-     * @throws InvalidArgumentException
679
-     * @throws InvalidDataTypeException
680
-     * @throws InvalidInterfaceException
681
-     * @throws ReflectionException
682
-     */
683
-    public function set_is_taxable($is_taxable)
684
-    {
685
-        $this->set('LIN_is_taxable', $is_taxable);
686
-    }
687
-
688
-
689
-    /**
690
-     * Gets the object that this model-joins-to.
691
-     * returns one of the model objects that the field OBJ_ID can point to... see the 'OBJ_ID' field on
692
-     * EEM_Promotion_Object
693
-     *        Eg, if this line item join model object is for a ticket, this will return the EE_Ticket object
694
-     *
695
-     * @return EE_Base_Class | NULL
696
-     * @throws EE_Error
697
-     * @throws InvalidArgumentException
698
-     * @throws InvalidDataTypeException
699
-     * @throws InvalidInterfaceException
700
-     * @throws ReflectionException
701
-     */
702
-    public function get_object()
703
-    {
704
-        $model_name_of_related_obj = $this->OBJ_type();
705
-        return $this->get_model()->has_relation($model_name_of_related_obj)
706
-            ? $this->get_first_related($model_name_of_related_obj)
707
-            : null;
708
-    }
709
-
710
-
711
-    /**
712
-     * Like EE_Line_Item::get_object(), but can only ever actually return an EE_Ticket.
713
-     * (IE, if this line item is for a price or something else, will return NULL)
714
-     *
715
-     * @param array $query_params
716
-     * @return EE_Base_Class|EE_Ticket
717
-     * @throws EE_Error
718
-     * @throws InvalidArgumentException
719
-     * @throws InvalidDataTypeException
720
-     * @throws InvalidInterfaceException
721
-     * @throws ReflectionException
722
-     */
723
-    public function ticket($query_params = array())
724
-    {
725
-        // we're going to assume that when this method is called
726
-        // we always want to receive the attached ticket EVEN if that ticket is archived.
727
-        // This can be overridden via the incoming $query_params argument
728
-        $remove_defaults = array('default_where_conditions' => 'none');
729
-        $query_params = array_merge($remove_defaults, $query_params);
730
-        return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TICKET, $query_params);
731
-    }
732
-
733
-
734
-    /**
735
-     * Gets the EE_Datetime that's related to the ticket, IF this is for a ticket
736
-     *
737
-     * @return EE_Datetime | NULL
738
-     * @throws EE_Error
739
-     * @throws InvalidArgumentException
740
-     * @throws InvalidDataTypeException
741
-     * @throws InvalidInterfaceException
742
-     * @throws ReflectionException
743
-     */
744
-    public function get_ticket_datetime()
745
-    {
746
-        if ($this->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) {
747
-            $ticket = $this->ticket();
748
-            if ($ticket instanceof EE_Ticket) {
749
-                $datetime = $ticket->first_datetime();
750
-                if ($datetime instanceof EE_Datetime) {
751
-                    return $datetime;
752
-                }
753
-            }
754
-        }
755
-        return null;
756
-    }
757
-
758
-
759
-    /**
760
-     * Gets the event's name that's related to the ticket, if this is for
761
-     * a ticket
762
-     *
763
-     * @return string
764
-     * @throws EE_Error
765
-     * @throws InvalidArgumentException
766
-     * @throws InvalidDataTypeException
767
-     * @throws InvalidInterfaceException
768
-     * @throws ReflectionException
769
-     */
770
-    public function ticket_event_name()
771
-    {
772
-        $event_name = esc_html__('Unknown', 'event_espresso');
773
-        $event = $this->ticket_event();
774
-        if ($event instanceof EE_Event) {
775
-            $event_name = $event->name();
776
-        }
777
-        return $event_name;
778
-    }
779
-
780
-
781
-    /**
782
-     * Gets the event that's related to the ticket, if this line item represents a ticket.
783
-     *
784
-     * @return EE_Event|null
785
-     * @throws EE_Error
786
-     * @throws InvalidArgumentException
787
-     * @throws InvalidDataTypeException
788
-     * @throws InvalidInterfaceException
789
-     * @throws ReflectionException
790
-     */
791
-    public function ticket_event()
792
-    {
793
-        $event = null;
794
-        $ticket = $this->ticket();
795
-        if ($ticket instanceof EE_Ticket) {
796
-            $datetime = $ticket->first_datetime();
797
-            if ($datetime instanceof EE_Datetime) {
798
-                $event = $datetime->event();
799
-            }
800
-        }
801
-        return $event;
802
-    }
803
-
804
-
805
-    /**
806
-     * Gets the first datetime for this lien item, assuming it's for a ticket
807
-     *
808
-     * @param string $date_format
809
-     * @param string $time_format
810
-     * @return string
811
-     * @throws EE_Error
812
-     * @throws InvalidArgumentException
813
-     * @throws InvalidDataTypeException
814
-     * @throws InvalidInterfaceException
815
-     * @throws ReflectionException
816
-     */
817
-    public function ticket_datetime_start($date_format = '', $time_format = '')
818
-    {
819
-        $first_datetime_string = esc_html__('Unknown', 'event_espresso');
820
-        $datetime = $this->get_ticket_datetime();
821
-        if ($datetime) {
822
-            $first_datetime_string = $datetime->start_date_and_time($date_format, $time_format);
823
-        }
824
-        return $first_datetime_string;
825
-    }
826
-
827
-
828
-    /**
829
-     * Adds the line item as a child to this line item. If there is another child line
830
-     * item with the same LIN_code, it is overwritten by this new one
831
-     *
832
-     * @param EEI_Line_Item $line_item
833
-     * @param bool          $set_order
834
-     * @return bool success
835
-     * @throws EE_Error
836
-     * @throws InvalidArgumentException
837
-     * @throws InvalidDataTypeException
838
-     * @throws InvalidInterfaceException
839
-     * @throws ReflectionException
840
-     */
841
-    public function add_child_line_item(EEI_Line_Item $line_item, $set_order = true)
842
-    {
843
-        // should we calculate the LIN_order for this line item ?
844
-        if ($set_order || $line_item->order() === null) {
845
-            $line_item->set_order(count($this->children()));
846
-        }
847
-        if ($this->ID()) {
848
-            // check for any duplicate line items (with the same code), if so, this replaces it
849
-            $line_item_with_same_code = $this->get_child_line_item($line_item->code());
850
-            if ($line_item_with_same_code instanceof EE_Line_Item && $line_item_with_same_code !== $line_item) {
851
-                $this->delete_child_line_item($line_item_with_same_code->code());
852
-            }
853
-            $line_item->set_parent_ID($this->ID());
854
-            if ($this->TXN_ID()) {
855
-                $line_item->set_TXN_ID($this->TXN_ID());
856
-            }
857
-            return $line_item->save();
858
-        }
859
-        $this->_children[ $line_item->code() ] = $line_item;
860
-        if ($line_item->parent() !== $this) {
861
-            $line_item->set_parent($this);
862
-        }
863
-        return true;
864
-    }
865
-
866
-
867
-    /**
868
-     * Similar to EE_Base_Class::_add_relation_to, except this isn't a normal relation.
869
-     * If this line item is saved to the DB, this is just a wrapper for set_parent_ID() and save()
870
-     * However, if this line item is NOT saved to the DB, this just caches the parent on
871
-     * the EE_Line_Item::_parent property.
872
-     *
873
-     * @param EE_Line_Item $line_item
874
-     * @throws EE_Error
875
-     * @throws InvalidArgumentException
876
-     * @throws InvalidDataTypeException
877
-     * @throws InvalidInterfaceException
878
-     * @throws ReflectionException
879
-     */
880
-    public function set_parent($line_item)
881
-    {
882
-        if ($this->ID()) {
883
-            if (! $line_item->ID()) {
884
-                $line_item->save();
885
-            }
886
-            $this->set_parent_ID($line_item->ID());
887
-            $this->save();
888
-        } else {
889
-            $this->_parent = $line_item;
890
-            $this->set_parent_ID($line_item->ID());
891
-        }
892
-    }
893
-
894
-
895
-    /**
896
-     * Gets the child line item as specified by its code. Because this returns an object (by reference)
897
-     * you can modify this child line item and the parent (this object) can know about them
898
-     * because it also has a reference to that line item
899
-     *
900
-     * @param string $code
901
-     * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL
902
-     * @throws EE_Error
903
-     * @throws InvalidArgumentException
904
-     * @throws InvalidDataTypeException
905
-     * @throws InvalidInterfaceException
906
-     * @throws ReflectionException
907
-     */
908
-    public function get_child_line_item($code)
909
-    {
910
-        if ($this->ID()) {
911
-            return $this->get_model()->get_one(
912
-                array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code))
913
-            );
914
-        }
915
-        return isset($this->_children[ $code ])
916
-            ? $this->_children[ $code ]
917
-            : null;
918
-    }
919
-
920
-
921
-    /**
922
-     * Returns how many items are deleted (or, if this item has not been saved ot the DB yet, just how many it HAD
923
-     * cached on it)
924
-     *
925
-     * @return int
926
-     * @throws EE_Error
927
-     * @throws InvalidArgumentException
928
-     * @throws InvalidDataTypeException
929
-     * @throws InvalidInterfaceException
930
-     * @throws ReflectionException
931
-     */
932
-    public function delete_children_line_items()
933
-    {
934
-        if ($this->ID()) {
935
-            return $this->get_model()->delete(array(array('LIN_parent' => $this->ID())));
936
-        }
937
-        $count = count($this->_children);
938
-        $this->_children = array();
939
-        return $count;
940
-    }
941
-
942
-
943
-    /**
944
-     * If this line item has been saved to the DB, deletes its child with LIN_code == $code. If this line
945
-     * HAS NOT been saved to the DB, removes the child line item with index $code.
946
-     * Also searches through the child's children for a matching line item. However, once a line item has been found
947
-     * and deleted, stops searching (so if there are line items with duplicate codes, only the first one found will be
948
-     * deleted)
949
-     *
950
-     * @param string $code
951
-     * @param bool   $stop_search_once_found
952
-     * @return int count of items deleted (or simply removed from the line item's cache, if not has not been saved to
953
-     *             the DB yet)
954
-     * @throws EE_Error
955
-     * @throws InvalidArgumentException
956
-     * @throws InvalidDataTypeException
957
-     * @throws InvalidInterfaceException
958
-     * @throws ReflectionException
959
-     */
960
-    public function delete_child_line_item($code, $stop_search_once_found = true)
961
-    {
962
-        if ($this->ID()) {
963
-            $items_deleted = 0;
964
-            if ($this->code() === $code) {
965
-                $items_deleted += EEH_Line_Item::delete_all_child_items($this);
966
-                $items_deleted += (int) $this->delete();
967
-                if ($stop_search_once_found) {
968
-                    return $items_deleted;
969
-                }
970
-            }
971
-            foreach ($this->children() as $child_line_item) {
972
-                $items_deleted += $child_line_item->delete_child_line_item($code, $stop_search_once_found);
973
-            }
974
-            return $items_deleted;
975
-        }
976
-        if (isset($this->_children[ $code ])) {
977
-            unset($this->_children[ $code ]);
978
-            return 1;
979
-        }
980
-        return 0;
981
-    }
982
-
983
-
984
-    /**
985
-     * If this line item is in the database, is of the type subtotal, and
986
-     * has no children, why do we have it? It should be deleted so this function
987
-     * does that
988
-     *
989
-     * @return boolean
990
-     * @throws EE_Error
991
-     * @throws InvalidArgumentException
992
-     * @throws InvalidDataTypeException
993
-     * @throws InvalidInterfaceException
994
-     * @throws ReflectionException
995
-     */
996
-    public function delete_if_childless_subtotal()
997
-    {
998
-        if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && ! $this->children()) {
999
-            return $this->delete();
1000
-        }
1001
-        return false;
1002
-    }
1003
-
1004
-
1005
-    /**
1006
-     * Creates a code and returns a string. doesn't assign the code to this model object
1007
-     *
1008
-     * @return string
1009
-     * @throws EE_Error
1010
-     * @throws InvalidArgumentException
1011
-     * @throws InvalidDataTypeException
1012
-     * @throws InvalidInterfaceException
1013
-     * @throws ReflectionException
1014
-     */
1015
-    public function generate_code()
1016
-    {
1017
-        // each line item in the cart requires a unique identifier
1018
-        return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime());
1019
-    }
1020
-
1021
-
1022
-    /**
1023
-     * @return bool
1024
-     * @throws EE_Error
1025
-     * @throws InvalidArgumentException
1026
-     * @throws InvalidDataTypeException
1027
-     * @throws InvalidInterfaceException
1028
-     * @throws ReflectionException
1029
-     */
1030
-    public function is_tax()
1031
-    {
1032
-        return $this->type() === EEM_Line_Item::type_tax;
1033
-    }
1034
-
1035
-
1036
-    /**
1037
-     * @return bool
1038
-     * @throws EE_Error
1039
-     * @throws InvalidArgumentException
1040
-     * @throws InvalidDataTypeException
1041
-     * @throws InvalidInterfaceException
1042
-     * @throws ReflectionException
1043
-     */
1044
-    public function is_tax_sub_total()
1045
-    {
1046
-        return $this->type() === EEM_Line_Item::type_tax_sub_total;
1047
-    }
1048
-
1049
-
1050
-    /**
1051
-     * @return bool
1052
-     * @throws EE_Error
1053
-     * @throws InvalidArgumentException
1054
-     * @throws InvalidDataTypeException
1055
-     * @throws InvalidInterfaceException
1056
-     * @throws ReflectionException
1057
-     */
1058
-    public function is_line_item()
1059
-    {
1060
-        return $this->type() === EEM_Line_Item::type_line_item;
1061
-    }
1062
-
1063
-
1064
-    /**
1065
-     * @return bool
1066
-     * @throws EE_Error
1067
-     * @throws InvalidArgumentException
1068
-     * @throws InvalidDataTypeException
1069
-     * @throws InvalidInterfaceException
1070
-     * @throws ReflectionException
1071
-     */
1072
-    public function is_sub_line_item()
1073
-    {
1074
-        return $this->type() === EEM_Line_Item::type_sub_line_item;
1075
-    }
1076
-
1077
-
1078
-    /**
1079
-     * @return bool
1080
-     * @throws EE_Error
1081
-     * @throws InvalidArgumentException
1082
-     * @throws InvalidDataTypeException
1083
-     * @throws InvalidInterfaceException
1084
-     * @throws ReflectionException
1085
-     */
1086
-    public function is_sub_total()
1087
-    {
1088
-        return $this->type() === EEM_Line_Item::type_sub_total;
1089
-    }
1090
-
1091
-
1092
-    /**
1093
-     * Whether or not this line item is a cancellation line item
1094
-     *
1095
-     * @return boolean
1096
-     * @throws EE_Error
1097
-     * @throws InvalidArgumentException
1098
-     * @throws InvalidDataTypeException
1099
-     * @throws InvalidInterfaceException
1100
-     * @throws ReflectionException
1101
-     */
1102
-    public function is_cancellation()
1103
-    {
1104
-        return EEM_Line_Item::type_cancellation === $this->type();
1105
-    }
1106
-
1107
-
1108
-    /**
1109
-     * @return bool
1110
-     * @throws EE_Error
1111
-     * @throws InvalidArgumentException
1112
-     * @throws InvalidDataTypeException
1113
-     * @throws InvalidInterfaceException
1114
-     * @throws ReflectionException
1115
-     */
1116
-    public function is_total()
1117
-    {
1118
-        return $this->type() === EEM_Line_Item::type_total;
1119
-    }
1120
-
1121
-
1122
-    /**
1123
-     * @return bool
1124
-     * @throws EE_Error
1125
-     * @throws InvalidArgumentException
1126
-     * @throws InvalidDataTypeException
1127
-     * @throws InvalidInterfaceException
1128
-     * @throws ReflectionException
1129
-     */
1130
-    public function is_cancelled()
1131
-    {
1132
-        return $this->type() === EEM_Line_Item::type_cancellation;
1133
-    }
1134
-
1135
-
1136
-    /**
1137
-     * @return string like '2, 004.00', formatted according to the localized currency
1138
-     * @throws EE_Error
1139
-     * @throws InvalidArgumentException
1140
-     * @throws InvalidDataTypeException
1141
-     * @throws InvalidInterfaceException
1142
-     * @throws ReflectionException
1143
-     */
1144
-    public function unit_price_no_code()
1145
-    {
1146
-        return $this->get_pretty('LIN_unit_price', 'no_currency_code');
1147
-    }
1148
-
1149
-
1150
-    /**
1151
-     * @return string like '2, 004.00', formatted according to the localized currency
1152
-     * @throws EE_Error
1153
-     * @throws InvalidArgumentException
1154
-     * @throws InvalidDataTypeException
1155
-     * @throws InvalidInterfaceException
1156
-     * @throws ReflectionException
1157
-     */
1158
-    public function total_no_code()
1159
-    {
1160
-        return $this->get_pretty('LIN_total', 'no_currency_code');
1161
-    }
1162
-
1163
-
1164
-    /**
1165
-     * Gets the final total on this item, taking taxes into account.
1166
-     * Has the side-effect of setting the sub-total as it was just calculated.
1167
-     * If this is used on a grand-total line item, also updates the transaction's
1168
-     * TXN_total (provided this line item is allowed to persist, otherwise we don't
1169
-     * want to change a persistable transaction with info from a non-persistent line item)
1170
-     *
1171
-     * @param bool $update_txn_status
1172
-     * @return float
1173
-     * @throws EE_Error
1174
-     * @throws InvalidArgumentException
1175
-     * @throws InvalidDataTypeException
1176
-     * @throws InvalidInterfaceException
1177
-     * @throws ReflectionException
1178
-     * @throws RuntimeException
1179
-     */
1180
-    public function recalculate_total_including_taxes($update_txn_status = false)
1181
-    {
1182
-        $pre_tax_total = $this->recalculate_pre_tax_total();
1183
-        $tax_total = $this->recalculate_taxes_and_tax_total();
1184
-        $total = $pre_tax_total + $tax_total;
1185
-        // no negative totals plz
1186
-        $total = max($total, 0);
1187
-        $this->set_total($total);
1188
-        // only update the related transaction's total
1189
-        // if we intend to save this line item and its a grand total
1190
-        if (
1191
-            $this->allow_persist() && $this->type() === EEM_Line_Item::type_total
1192
-            && $this->transaction()
1193
-               instanceof
1194
-               EE_Transaction
1195
-        ) {
1196
-            $this->transaction()->set_total($total);
1197
-            if ($update_txn_status) {
1198
-                // don't save the TXN because that will be done below
1199
-                // and the following method only saves if the status changes
1200
-                $this->transaction()->update_status_based_on_total_paid(false);
1201
-            }
1202
-            if ($this->transaction()->ID()) {
1203
-                $this->transaction()->save();
1204
-            }
1205
-        }
1206
-        $this->maybe_save();
1207
-        return $total;
1208
-    }
1209
-
1210
-
1211
-    /**
1212
-     * Recursively goes through all the children and recalculates sub-totals EXCEPT for
1213
-     * tax-sub-totals (they're a an odd beast). Updates the 'total' on each line item according to either its
1214
-     * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and
1215
-     * when this is called on the grand total
1216
-     *
1217
-     * @return float
1218
-     * @throws EE_Error
1219
-     * @throws InvalidArgumentException
1220
-     * @throws InvalidDataTypeException
1221
-     * @throws InvalidInterfaceException
1222
-     * @throws ReflectionException
1223
-     */
1224
-    public function recalculate_pre_tax_total()
1225
-    {
1226
-        $total = 0;
1227
-        $my_children = $this->children();
1228
-        $has_children = ! empty($my_children);
1229
-        if ($has_children && $this->is_line_item()) {
1230
-            $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children);
1231
-        } elseif (! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) {
1232
-            $total = $this->unit_price() * $this->quantity();
1233
-        } elseif ($this->is_sub_total() || $this->is_total()) {
1234
-            $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children);
1235
-        } elseif ($this->is_tax_sub_total() || $this->is_tax() || $this->is_cancelled()) {
1236
-            // completely ignore tax totals, tax sub-totals, and cancelled line items, when calculating the pre-tax-total
1237
-            return 0;
1238
-        }
1239
-        // ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events)
1240
-        if (
1241
-            ! $this->is_line_item() && ! $this->is_sub_line_item() && ! $this->is_cancellation()
1242
-        ) {
1243
-            if ($this->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_EVENT) {
1244
-                $this->set_quantity(1);
1245
-            }
1246
-            if (! $this->is_percent()) {
1247
-                $this->set_unit_price($total);
1248
-            }
1249
-        }
1250
-        // we don't want to bother saving grand totals, because that needs to factor in taxes anyways
1251
-        // so it ought to be
1252
-        if (! $this->is_total()) {
1253
-            $this->set_total($total);
1254
-            // if not a percent line item, make sure we keep the unit price in sync
1255
-            if (
1256
-                $has_children
1257
-                && $this->is_line_item()
1258
-                && ! $this->is_percent()
1259
-            ) {
1260
-                if ($this->quantity() === 0) {
1261
-                    $new_unit_price = 0;
1262
-                } else {
1263
-                    $new_unit_price = $this->total() / $this->quantity();
1264
-                }
1265
-                $this->set_unit_price($new_unit_price);
1266
-            }
1267
-            $this->maybe_save();
1268
-        }
1269
-        return $total;
1270
-    }
1271
-
1272
-
1273
-    /**
1274
-     * Calculates the pretax total when this line item is a subtotal or total line item.
1275
-     * Basically does a sum-then-round approach (ie, any percent line item that are children
1276
-     * will calculate their total based on the un-rounded total we're working with so far, and
1277
-     * THEN round the result; instead of rounding as we go like with sub-line-items)
1278
-     *
1279
-     * @param float          $calculated_total_so_far
1280
-     * @param EE_Line_Item[] $my_children
1281
-     * @return float
1282
-     * @throws EE_Error
1283
-     * @throws InvalidArgumentException
1284
-     * @throws InvalidDataTypeException
1285
-     * @throws InvalidInterfaceException
1286
-     * @throws ReflectionException
1287
-     */
1288
-    protected function _recalculate_pretax_total_for_subtotal($calculated_total_so_far, $my_children = null)
1289
-    {
1290
-        if ($my_children === null) {
1291
-            $my_children = $this->children();
1292
-        }
1293
-        $subtotal_quantity = 0;
1294
-        // get the total of all its children
1295
-        foreach ($my_children as $child_line_item) {
1296
-            if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) {
1297
-                // percentage line items are based on total so far
1298
-                if ($child_line_item->is_percent()) {
1299
-                    // round as we go so that the line items add up ok
1300
-                    $percent_total = round(
1301
-                        $calculated_total_so_far * $child_line_item->percent() / 100,
1302
-                        EE_Registry::instance()->CFG->currency->dec_plc
1303
-                    );
1304
-                    $child_line_item->set_total($percent_total);
1305
-                    // so far all percent line items should have a quantity of 1
1306
-                    // (ie, no double percent discounts. Although that might be requested someday)
1307
-                    $child_line_item->set_quantity(1);
1308
-                    $child_line_item->maybe_save();
1309
-                    $calculated_total_so_far += $percent_total;
1310
-                } else {
1311
-                    // verify flat sub-line-item quantities match their parent
1312
-                    if ($child_line_item->is_sub_line_item()) {
1313
-                        $child_line_item->set_quantity($this->quantity());
1314
-                    }
1315
-                    $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total();
1316
-                    $subtotal_quantity += $child_line_item->quantity();
1317
-                }
1318
-            }
1319
-        }
1320
-        if ($this->is_sub_total()) {
1321
-            // no negative totals plz
1322
-            $calculated_total_so_far = max($calculated_total_so_far, 0);
1323
-            $subtotal_quantity = $subtotal_quantity > 0 ? 1 : 0;
1324
-            $this->set_quantity($subtotal_quantity);
1325
-            $this->maybe_save();
1326
-        }
1327
-        return $calculated_total_so_far;
1328
-    }
1329
-
1330
-
1331
-    /**
1332
-     * Calculates the pretax total for a normal line item, in a round-then-sum approach
1333
-     * (where each sub-line-item is applied to the base price for the line item
1334
-     * and the result is immediately rounded, rather than summing all the sub-line-items
1335
-     * then rounding, like we do when recalculating pretax totals on totals and subtotals).
1336
-     *
1337
-     * @param float          $calculated_total_so_far
1338
-     * @param EE_Line_Item[] $my_children
1339
-     * @return float
1340
-     * @throws EE_Error
1341
-     * @throws InvalidArgumentException
1342
-     * @throws InvalidDataTypeException
1343
-     * @throws InvalidInterfaceException
1344
-     * @throws ReflectionException
1345
-     */
1346
-    protected function _recalculate_pretax_total_for_line_item($calculated_total_so_far, $my_children = null)
1347
-    {
1348
-        if ($my_children === null) {
1349
-            $my_children = $this->children();
1350
-        }
1351
-        // we need to keep track of the running total for a single item,
1352
-        // because we need to round as we go
1353
-        $unit_price_for_total = 0;
1354
-        $quantity_for_total = 1;
1355
-        // get the total of all its children
1356
-        foreach ($my_children as $child_line_item) {
1357
-            if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) {
1358
-                if ($child_line_item->is_percent()) {
1359
-                    // it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity
1360
-                    // not total multiplied by percent, because that ignores rounding along-the-way
1361
-                    $percent_unit_price = round(
1362
-                        $unit_price_for_total * $child_line_item->percent() / 100,
1363
-                        EE_Registry::instance()->CFG->currency->dec_plc
1364
-                    );
1365
-                    $percent_total = $percent_unit_price * $quantity_for_total;
1366
-                    $child_line_item->set_total($percent_total);
1367
-                    // so far all percent line items should have a quantity of 1
1368
-                    // (ie, no double percent discounts. Although that might be requested someday)
1369
-                    $child_line_item->set_quantity(1);
1370
-                    $child_line_item->maybe_save();
1371
-                    $calculated_total_so_far += $percent_total;
1372
-                    $unit_price_for_total += $percent_unit_price;
1373
-                } else {
1374
-                    // verify flat sub-line-item quantities match their parent
1375
-                    if ($child_line_item->is_sub_line_item()) {
1376
-                        $child_line_item->set_quantity($this->quantity());
1377
-                    }
1378
-                    $quantity_for_total = $child_line_item->quantity();
1379
-                    $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total();
1380
-                    $unit_price_for_total += $child_line_item->unit_price();
1381
-                }
1382
-            }
1383
-        }
1384
-        return $calculated_total_so_far;
1385
-    }
1386
-
1387
-
1388
-    /**
1389
-     * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets
1390
-     * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items
1391
-     * and tax sub-total if already in the DB
1392
-     *
1393
-     * @return float
1394
-     * @throws EE_Error
1395
-     * @throws InvalidArgumentException
1396
-     * @throws InvalidDataTypeException
1397
-     * @throws InvalidInterfaceException
1398
-     * @throws ReflectionException
1399
-     */
1400
-    public function recalculate_taxes_and_tax_total()
1401
-    {
1402
-        // get all taxes
1403
-        $taxes = $this->tax_descendants();
1404
-        // calculate the pretax total
1405
-        $taxable_total = $this->taxable_total();
1406
-        $tax_total = 0;
1407
-        foreach ($taxes as $tax) {
1408
-            $total_on_this_tax = $taxable_total * $tax->percent() / 100;
1409
-            // remember the total on this line item
1410
-            $tax->set_total($total_on_this_tax);
1411
-            $tax->maybe_save();
1412
-            $tax_total += $tax->total();
1413
-        }
1414
-        $this->_recalculate_tax_sub_total();
1415
-        return $tax_total;
1416
-    }
1417
-
1418
-
1419
-    /**
1420
-     * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated
1421
-     *
1422
-     * @return void
1423
-     * @throws EE_Error
1424
-     * @throws InvalidArgumentException
1425
-     * @throws InvalidDataTypeException
1426
-     * @throws InvalidInterfaceException
1427
-     * @throws ReflectionException
1428
-     */
1429
-    private function _recalculate_tax_sub_total()
1430
-    {
1431
-        if ($this->is_tax_sub_total()) {
1432
-            $total = 0;
1433
-            $total_percent = 0;
1434
-            // simply loop through all its children (which should be taxes) and sum their total
1435
-            foreach ($this->children() as $child_tax) {
1436
-                if ($child_tax instanceof EE_Line_Item) {
1437
-                    $total += $child_tax->total();
1438
-                    $total_percent += $child_tax->percent();
1439
-                }
1440
-            }
1441
-            $this->set_total($total);
1442
-            $this->set_percent($total_percent);
1443
-            $this->maybe_save();
1444
-        } elseif ($this->is_total()) {
1445
-            foreach ($this->children() as $maybe_tax_subtotal) {
1446
-                if ($maybe_tax_subtotal instanceof EE_Line_Item) {
1447
-                    $maybe_tax_subtotal->_recalculate_tax_sub_total();
1448
-                }
1449
-            }
1450
-        }
1451
-    }
1452
-
1453
-
1454
-    /**
1455
-     * Gets the total tax on this line item. Assumes taxes have already been calculated using
1456
-     * recalculate_taxes_and_total
1457
-     *
1458
-     * @return float
1459
-     * @throws EE_Error
1460
-     * @throws InvalidArgumentException
1461
-     * @throws InvalidDataTypeException
1462
-     * @throws InvalidInterfaceException
1463
-     * @throws ReflectionException
1464
-     */
1465
-    public function get_total_tax()
1466
-    {
1467
-        $this->_recalculate_tax_sub_total();
1468
-        $total = 0;
1469
-        foreach ($this->tax_descendants() as $tax_line_item) {
1470
-            if ($tax_line_item instanceof EE_Line_Item) {
1471
-                $total += $tax_line_item->total();
1472
-            }
1473
-        }
1474
-        return $total;
1475
-    }
1476
-
1477
-
1478
-    /**
1479
-     * Gets the total for all the items purchased only
1480
-     *
1481
-     * @return float
1482
-     * @throws EE_Error
1483
-     * @throws InvalidArgumentException
1484
-     * @throws InvalidDataTypeException
1485
-     * @throws InvalidInterfaceException
1486
-     * @throws ReflectionException
1487
-     */
1488
-    public function get_items_total()
1489
-    {
1490
-        // by default, let's make sure we're consistent with the existing line item
1491
-        if ($this->is_total()) {
1492
-            $pretax_subtotal_li = EEH_Line_Item::get_pre_tax_subtotal($this);
1493
-            if ($pretax_subtotal_li instanceof EE_Line_Item) {
1494
-                return $pretax_subtotal_li->total();
1495
-            }
1496
-        }
1497
-        $total = 0;
1498
-        foreach ($this->get_items() as $item) {
1499
-            if ($item instanceof EE_Line_Item) {
1500
-                $total += $item->total();
1501
-            }
1502
-        }
1503
-        return $total;
1504
-    }
1505
-
1506
-
1507
-    /**
1508
-     * Gets all the descendants (ie, children or children of children etc) that
1509
-     * are of the type 'tax'
1510
-     *
1511
-     * @return EE_Line_Item[]
1512
-     * @throws EE_Error
1513
-     */
1514
-    public function tax_descendants()
1515
-    {
1516
-        return EEH_Line_Item::get_tax_descendants($this);
1517
-    }
1518
-
1519
-
1520
-    /**
1521
-     * Gets all the real items purchased which are children of this item
1522
-     *
1523
-     * @return EE_Line_Item[]
1524
-     * @throws EE_Error
1525
-     */
1526
-    public function get_items()
1527
-    {
1528
-        return EEH_Line_Item::get_line_item_descendants($this);
1529
-    }
1530
-
1531
-
1532
-    /**
1533
-     * Returns the amount taxable among this line item's children (or if it has no children,
1534
-     * how much of it is taxable). Does not recalculate totals or subtotals.
1535
-     * If the taxable total is negative, (eg, if none of the tickets were taxable,
1536
-     * but there is a "Taxable" discount), returns 0.
1537
-     *
1538
-     * @return float
1539
-     * @throws EE_Error
1540
-     * @throws InvalidArgumentException
1541
-     * @throws InvalidDataTypeException
1542
-     * @throws InvalidInterfaceException
1543
-     * @throws ReflectionException
1544
-     */
1545
-    public function taxable_total()
1546
-    {
1547
-        $total = 0;
1548
-        if ($this->children()) {
1549
-            foreach ($this->children() as $child_line_item) {
1550
-                if ($child_line_item->type() === EEM_Line_Item::type_line_item && $child_line_item->is_taxable()) {
1551
-                    // if it's a percent item, only take into account the percent
1552
-                    // that's taxable too (the taxable total so far)
1553
-                    if ($child_line_item->is_percent()) {
1554
-                        $total += ($total * $child_line_item->percent() / 100);
1555
-                    } else {
1556
-                        $total += $child_line_item->total();
1557
-                    }
1558
-                } elseif ($child_line_item->type() === EEM_Line_Item::type_sub_total) {
1559
-                    $total += $child_line_item->taxable_total();
1560
-                }
1561
-            }
1562
-        }
1563
-        return max($total, 0);
1564
-    }
1565
-
1566
-
1567
-    /**
1568
-     * Gets the transaction for this line item
1569
-     *
1570
-     * @return EE_Base_Class|EE_Transaction
1571
-     * @throws EE_Error
1572
-     * @throws InvalidArgumentException
1573
-     * @throws InvalidDataTypeException
1574
-     * @throws InvalidInterfaceException
1575
-     * @throws ReflectionException
1576
-     */
1577
-    public function transaction()
1578
-    {
1579
-        return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TRANSACTION);
1580
-    }
1581
-
1582
-
1583
-    /**
1584
-     * Saves this line item to the DB, and recursively saves its descendants.
1585
-     * Because there currently is no proper parent-child relation on the model,
1586
-     * save_this_and_cached() will NOT save the descendants.
1587
-     * Also sets the transaction on this line item and all its descendants before saving
1588
-     *
1589
-     * @param int $txn_id if none is provided, assumes $this->TXN_ID()
1590
-     * @return int count of items saved
1591
-     * @throws EE_Error
1592
-     * @throws InvalidArgumentException
1593
-     * @throws InvalidDataTypeException
1594
-     * @throws InvalidInterfaceException
1595
-     * @throws ReflectionException
1596
-     */
1597
-    public function save_this_and_descendants_to_txn($txn_id = null)
1598
-    {
1599
-        $count = 0;
1600
-        if (! $txn_id) {
1601
-            $txn_id = $this->TXN_ID();
1602
-        }
1603
-        $this->set_TXN_ID($txn_id);
1604
-        $children = $this->children();
1605
-        $count += $this->save()
1606
-            ? 1
1607
-            : 0;
1608
-        foreach ($children as $child_line_item) {
1609
-            if ($child_line_item instanceof EE_Line_Item) {
1610
-                $child_line_item->set_parent_ID($this->ID());
1611
-                $count += $child_line_item->save_this_and_descendants_to_txn($txn_id);
1612
-            }
1613
-        }
1614
-        return $count;
1615
-    }
1616
-
1617
-
1618
-    /**
1619
-     * Saves this line item to the DB, and recursively saves its descendants.
1620
-     *
1621
-     * @return int count of items saved
1622
-     * @throws EE_Error
1623
-     * @throws InvalidArgumentException
1624
-     * @throws InvalidDataTypeException
1625
-     * @throws InvalidInterfaceException
1626
-     * @throws ReflectionException
1627
-     */
1628
-    public function save_this_and_descendants()
1629
-    {
1630
-        $count = 0;
1631
-        $children = $this->children();
1632
-        $count += $this->save()
1633
-            ? 1
1634
-            : 0;
1635
-        foreach ($children as $child_line_item) {
1636
-            if ($child_line_item instanceof EE_Line_Item) {
1637
-                $child_line_item->set_parent_ID($this->ID());
1638
-                $count += $child_line_item->save_this_and_descendants();
1639
-            }
1640
-        }
1641
-        return $count;
1642
-    }
1643
-
1644
-
1645
-    /**
1646
-     * returns the cancellation line item if this item was cancelled
1647
-     *
1648
-     * @return EE_Line_Item[]
1649
-     * @throws InvalidArgumentException
1650
-     * @throws InvalidInterfaceException
1651
-     * @throws InvalidDataTypeException
1652
-     * @throws ReflectionException
1653
-     * @throws EE_Error
1654
-     */
1655
-    public function get_cancellations()
1656
-    {
1657
-        EE_Registry::instance()->load_helper('Line_Item');
1658
-        return EEH_Line_Item::get_descendants_of_type($this, EEM_Line_Item::type_cancellation);
1659
-    }
1660
-
1661
-
1662
-    /**
1663
-     * If this item has an ID, then this saves it again to update the db
1664
-     *
1665
-     * @return int count of items saved
1666
-     * @throws EE_Error
1667
-     * @throws InvalidArgumentException
1668
-     * @throws InvalidDataTypeException
1669
-     * @throws InvalidInterfaceException
1670
-     * @throws ReflectionException
1671
-     */
1672
-    public function maybe_save()
1673
-    {
1674
-        if ($this->ID()) {
1675
-            return $this->save();
1676
-        }
1677
-        return false;
1678
-    }
1679
-
1680
-
1681
-    /**
1682
-     * clears the cached children and parent from the line item
1683
-     *
1684
-     * @return void
1685
-     */
1686
-    public function clear_related_line_item_cache()
1687
-    {
1688
-        $this->_children = array();
1689
-        $this->_parent = null;
1690
-    }
1691
-
1692
-
1693
-    /**
1694
-     * @param bool $raw
1695
-     * @return int
1696
-     * @throws EE_Error
1697
-     * @throws InvalidArgumentException
1698
-     * @throws InvalidDataTypeException
1699
-     * @throws InvalidInterfaceException
1700
-     * @throws ReflectionException
1701
-     */
1702
-    public function timestamp($raw = false)
1703
-    {
1704
-        return $raw
1705
-            ? $this->get_raw('LIN_timestamp')
1706
-            : $this->get('LIN_timestamp');
1707
-    }
1708
-
1709
-
1710
-
1711
-
1712
-    /************************* DEPRECATED *************************/
1713
-    /**
1714
-     * @deprecated 4.6.0
1715
-     * @param string $type one of the constants on EEM_Line_Item
1716
-     * @return EE_Line_Item[]
1717
-     * @throws EE_Error
1718
-     */
1719
-    protected function _get_descendants_of_type($type)
1720
-    {
1721
-        EE_Error::doing_it_wrong(
1722
-            'EE_Line_Item::_get_descendants_of_type()',
1723
-            sprintf(
1724
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
1725
-                'EEH_Line_Item::get_descendants_of_type()'
1726
-            ),
1727
-            '4.6.0'
1728
-        );
1729
-        return EEH_Line_Item::get_descendants_of_type($this, $type);
1730
-    }
1731
-
1732
-
1733
-    /**
1734
-     * @deprecated 4.6.0
1735
-     * @param string $type like one of the EEM_Line_Item::type_*
1736
-     * @return EE_Line_Item
1737
-     * @throws EE_Error
1738
-     * @throws InvalidArgumentException
1739
-     * @throws InvalidDataTypeException
1740
-     * @throws InvalidInterfaceException
1741
-     * @throws ReflectionException
1742
-     */
1743
-    public function get_nearest_descendant_of_type($type)
1744
-    {
1745
-        EE_Error::doing_it_wrong(
1746
-            'EE_Line_Item::get_nearest_descendant_of_type()',
1747
-            sprintf(
1748
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
1749
-                'EEH_Line_Item::get_nearest_descendant_of_type()'
1750
-            ),
1751
-            '4.6.0'
1752
-        );
1753
-        return EEH_Line_Item::get_nearest_descendant_of_type($this, $type);
1754
-    }
17
+	/**
18
+	 * for children line items (currently not a normal relation)
19
+	 *
20
+	 * @type EE_Line_Item[]
21
+	 */
22
+	protected $_children = array();
23
+
24
+	/**
25
+	 * for the parent line item
26
+	 *
27
+	 * @var EE_Line_Item
28
+	 */
29
+	protected $_parent;
30
+
31
+
32
+	/**
33
+	 * @param array  $props_n_values          incoming values
34
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
35
+	 *                                        used.)
36
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
37
+	 *                                        date_format and the second value is the time format
38
+	 * @return EE_Line_Item
39
+	 * @throws EE_Error
40
+	 * @throws InvalidArgumentException
41
+	 * @throws InvalidDataTypeException
42
+	 * @throws InvalidInterfaceException
43
+	 * @throws ReflectionException
44
+	 */
45
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
46
+	{
47
+		$has_object = parent::_check_for_object(
48
+			$props_n_values,
49
+			__CLASS__,
50
+			$timezone,
51
+			$date_formats
52
+		);
53
+		return $has_object
54
+			? $has_object
55
+			: new self($props_n_values, false, $timezone);
56
+	}
57
+
58
+
59
+	/**
60
+	 * @param array  $props_n_values  incoming values from the database
61
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
62
+	 *                                the website will be used.
63
+	 * @return EE_Line_Item
64
+	 * @throws EE_Error
65
+	 * @throws InvalidArgumentException
66
+	 * @throws InvalidDataTypeException
67
+	 * @throws InvalidInterfaceException
68
+	 * @throws ReflectionException
69
+	 */
70
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
71
+	{
72
+		return new self($props_n_values, true, $timezone);
73
+	}
74
+
75
+
76
+	/**
77
+	 * Adds some defaults if they're not specified
78
+	 *
79
+	 * @param array  $fieldValues
80
+	 * @param bool   $bydb
81
+	 * @param string $timezone
82
+	 * @throws EE_Error
83
+	 * @throws InvalidArgumentException
84
+	 * @throws InvalidDataTypeException
85
+	 * @throws InvalidInterfaceException
86
+	 * @throws ReflectionException
87
+	 */
88
+	protected function __construct($fieldValues = array(), $bydb = false, $timezone = '')
89
+	{
90
+		parent::__construct($fieldValues, $bydb, $timezone);
91
+		if (! $this->get('LIN_code')) {
92
+			$this->set_code($this->generate_code());
93
+		}
94
+	}
95
+
96
+
97
+	/**
98
+	 * Gets ID
99
+	 *
100
+	 * @return int
101
+	 * @throws EE_Error
102
+	 * @throws InvalidArgumentException
103
+	 * @throws InvalidDataTypeException
104
+	 * @throws InvalidInterfaceException
105
+	 * @throws ReflectionException
106
+	 */
107
+	public function ID()
108
+	{
109
+		return $this->get('LIN_ID');
110
+	}
111
+
112
+
113
+	/**
114
+	 * Gets TXN_ID
115
+	 *
116
+	 * @return int
117
+	 * @throws EE_Error
118
+	 * @throws InvalidArgumentException
119
+	 * @throws InvalidDataTypeException
120
+	 * @throws InvalidInterfaceException
121
+	 * @throws ReflectionException
122
+	 */
123
+	public function TXN_ID()
124
+	{
125
+		return $this->get('TXN_ID');
126
+	}
127
+
128
+
129
+	/**
130
+	 * Sets TXN_ID
131
+	 *
132
+	 * @param int $TXN_ID
133
+	 * @throws EE_Error
134
+	 * @throws InvalidArgumentException
135
+	 * @throws InvalidDataTypeException
136
+	 * @throws InvalidInterfaceException
137
+	 * @throws ReflectionException
138
+	 */
139
+	public function set_TXN_ID($TXN_ID)
140
+	{
141
+		$this->set('TXN_ID', $TXN_ID);
142
+	}
143
+
144
+
145
+	/**
146
+	 * Gets name
147
+	 *
148
+	 * @return string
149
+	 * @throws EE_Error
150
+	 * @throws InvalidArgumentException
151
+	 * @throws InvalidDataTypeException
152
+	 * @throws InvalidInterfaceException
153
+	 * @throws ReflectionException
154
+	 */
155
+	public function name()
156
+	{
157
+		$name = $this->get('LIN_name');
158
+		if (! $name) {
159
+			$name = ucwords(str_replace('-', ' ', $this->type()));
160
+		}
161
+		return $name;
162
+	}
163
+
164
+
165
+	/**
166
+	 * Sets name
167
+	 *
168
+	 * @param string $name
169
+	 * @throws EE_Error
170
+	 * @throws InvalidArgumentException
171
+	 * @throws InvalidDataTypeException
172
+	 * @throws InvalidInterfaceException
173
+	 * @throws ReflectionException
174
+	 */
175
+	public function set_name($name)
176
+	{
177
+		$this->set('LIN_name', $name);
178
+	}
179
+
180
+
181
+	/**
182
+	 * Gets desc
183
+	 *
184
+	 * @return string
185
+	 * @throws EE_Error
186
+	 * @throws InvalidArgumentException
187
+	 * @throws InvalidDataTypeException
188
+	 * @throws InvalidInterfaceException
189
+	 * @throws ReflectionException
190
+	 */
191
+	public function desc()
192
+	{
193
+		return $this->get('LIN_desc');
194
+	}
195
+
196
+
197
+	/**
198
+	 * Sets desc
199
+	 *
200
+	 * @param string $desc
201
+	 * @throws EE_Error
202
+	 * @throws InvalidArgumentException
203
+	 * @throws InvalidDataTypeException
204
+	 * @throws InvalidInterfaceException
205
+	 * @throws ReflectionException
206
+	 */
207
+	public function set_desc($desc)
208
+	{
209
+		$this->set('LIN_desc', $desc);
210
+	}
211
+
212
+
213
+	/**
214
+	 * Gets quantity
215
+	 *
216
+	 * @return int
217
+	 * @throws EE_Error
218
+	 * @throws InvalidArgumentException
219
+	 * @throws InvalidDataTypeException
220
+	 * @throws InvalidInterfaceException
221
+	 * @throws ReflectionException
222
+	 */
223
+	public function quantity()
224
+	{
225
+		return $this->get('LIN_quantity');
226
+	}
227
+
228
+
229
+	/**
230
+	 * Sets quantity
231
+	 *
232
+	 * @param int $quantity
233
+	 * @throws EE_Error
234
+	 * @throws InvalidArgumentException
235
+	 * @throws InvalidDataTypeException
236
+	 * @throws InvalidInterfaceException
237
+	 * @throws ReflectionException
238
+	 */
239
+	public function set_quantity($quantity)
240
+	{
241
+		$this->set('LIN_quantity', max($quantity, 0));
242
+	}
243
+
244
+
245
+	/**
246
+	 * Gets item_id
247
+	 *
248
+	 * @return string
249
+	 * @throws EE_Error
250
+	 * @throws InvalidArgumentException
251
+	 * @throws InvalidDataTypeException
252
+	 * @throws InvalidInterfaceException
253
+	 * @throws ReflectionException
254
+	 */
255
+	public function OBJ_ID()
256
+	{
257
+		return $this->get('OBJ_ID');
258
+	}
259
+
260
+
261
+	/**
262
+	 * Sets item_id
263
+	 *
264
+	 * @param string $item_id
265
+	 * @throws EE_Error
266
+	 * @throws InvalidArgumentException
267
+	 * @throws InvalidDataTypeException
268
+	 * @throws InvalidInterfaceException
269
+	 * @throws ReflectionException
270
+	 */
271
+	public function set_OBJ_ID($item_id)
272
+	{
273
+		$this->set('OBJ_ID', $item_id);
274
+	}
275
+
276
+
277
+	/**
278
+	 * Gets item_type
279
+	 *
280
+	 * @return string
281
+	 * @throws EE_Error
282
+	 * @throws InvalidArgumentException
283
+	 * @throws InvalidDataTypeException
284
+	 * @throws InvalidInterfaceException
285
+	 * @throws ReflectionException
286
+	 */
287
+	public function OBJ_type()
288
+	{
289
+		return $this->get('OBJ_type');
290
+	}
291
+
292
+
293
+	/**
294
+	 * Gets item_type
295
+	 *
296
+	 * @return string
297
+	 * @throws EE_Error
298
+	 * @throws InvalidArgumentException
299
+	 * @throws InvalidDataTypeException
300
+	 * @throws InvalidInterfaceException
301
+	 * @throws ReflectionException
302
+	 */
303
+	public function OBJ_type_i18n()
304
+	{
305
+		$obj_type = $this->OBJ_type();
306
+		switch ($obj_type) {
307
+			case EEM_Line_Item::OBJ_TYPE_EVENT:
308
+				$obj_type = esc_html__('Event', 'event_espresso');
309
+				break;
310
+			case EEM_Line_Item::OBJ_TYPE_PRICE:
311
+				$obj_type = esc_html__('Price', 'event_espresso');
312
+				break;
313
+			case EEM_Line_Item::OBJ_TYPE_PROMOTION:
314
+				$obj_type = esc_html__('Promotion', 'event_espresso');
315
+				break;
316
+			case EEM_Line_Item::OBJ_TYPE_TICKET:
317
+				$obj_type = esc_html__('Ticket', 'event_espresso');
318
+				break;
319
+			case EEM_Line_Item::OBJ_TYPE_TRANSACTION:
320
+				$obj_type = esc_html__('Transaction', 'event_espresso');
321
+				break;
322
+		}
323
+		return apply_filters('FHEE__EE_Line_Item__OBJ_type_i18n', $obj_type, $this);
324
+	}
325
+
326
+
327
+	/**
328
+	 * Sets item_type
329
+	 *
330
+	 * @param string $OBJ_type
331
+	 * @throws EE_Error
332
+	 * @throws InvalidArgumentException
333
+	 * @throws InvalidDataTypeException
334
+	 * @throws InvalidInterfaceException
335
+	 * @throws ReflectionException
336
+	 */
337
+	public function set_OBJ_type($OBJ_type)
338
+	{
339
+		$this->set('OBJ_type', $OBJ_type);
340
+	}
341
+
342
+
343
+	/**
344
+	 * Gets unit_price
345
+	 *
346
+	 * @return float
347
+	 * @throws EE_Error
348
+	 * @throws InvalidArgumentException
349
+	 * @throws InvalidDataTypeException
350
+	 * @throws InvalidInterfaceException
351
+	 * @throws ReflectionException
352
+	 */
353
+	public function unit_price()
354
+	{
355
+		return $this->get('LIN_unit_price');
356
+	}
357
+
358
+
359
+	/**
360
+	 * Sets unit_price
361
+	 *
362
+	 * @param float $unit_price
363
+	 * @throws EE_Error
364
+	 * @throws InvalidArgumentException
365
+	 * @throws InvalidDataTypeException
366
+	 * @throws InvalidInterfaceException
367
+	 * @throws ReflectionException
368
+	 */
369
+	public function set_unit_price($unit_price)
370
+	{
371
+		$this->set('LIN_unit_price', $unit_price);
372
+	}
373
+
374
+
375
+	/**
376
+	 * Checks if this item is a percentage modifier or not
377
+	 *
378
+	 * @return boolean
379
+	 * @throws EE_Error
380
+	 * @throws InvalidArgumentException
381
+	 * @throws InvalidDataTypeException
382
+	 * @throws InvalidInterfaceException
383
+	 * @throws ReflectionException
384
+	 */
385
+	public function is_percent()
386
+	{
387
+		if ($this->is_tax_sub_total()) {
388
+			// tax subtotals HAVE a percent on them, that percentage only applies
389
+			// to taxable items, so its' an exception. Treat it like a flat line item
390
+			return false;
391
+		}
392
+		$unit_price = abs($this->get('LIN_unit_price'));
393
+		$percent = abs($this->get('LIN_percent'));
394
+		if ($unit_price < .001 && $percent) {
395
+			return true;
396
+		}
397
+		if ($unit_price >= .001 && ! $percent) {
398
+			return false;
399
+		}
400
+		if ($unit_price >= .001 && $percent) {
401
+			throw new EE_Error(
402
+				sprintf(
403
+					esc_html__(
404
+						'A Line Item can not have a unit price of (%s) AND a percent (%s)!',
405
+						'event_espresso'
406
+					),
407
+					$unit_price,
408
+					$percent
409
+				)
410
+			);
411
+		}
412
+		// if they're both 0, assume its not a percent item
413
+		return false;
414
+	}
415
+
416
+
417
+	/**
418
+	 * Gets percent (between 100-.001)
419
+	 *
420
+	 * @return float
421
+	 * @throws EE_Error
422
+	 * @throws InvalidArgumentException
423
+	 * @throws InvalidDataTypeException
424
+	 * @throws InvalidInterfaceException
425
+	 * @throws ReflectionException
426
+	 */
427
+	public function percent()
428
+	{
429
+		return $this->get('LIN_percent');
430
+	}
431
+
432
+
433
+	/**
434
+	 * Sets percent (between 100-0.01)
435
+	 *
436
+	 * @param float $percent
437
+	 * @throws EE_Error
438
+	 * @throws InvalidArgumentException
439
+	 * @throws InvalidDataTypeException
440
+	 * @throws InvalidInterfaceException
441
+	 * @throws ReflectionException
442
+	 */
443
+	public function set_percent($percent)
444
+	{
445
+		$this->set('LIN_percent', $percent);
446
+	}
447
+
448
+
449
+	/**
450
+	 * Gets total
451
+	 *
452
+	 * @return float
453
+	 * @throws EE_Error
454
+	 * @throws InvalidArgumentException
455
+	 * @throws InvalidDataTypeException
456
+	 * @throws InvalidInterfaceException
457
+	 * @throws ReflectionException
458
+	 */
459
+	public function total()
460
+	{
461
+		return $this->get('LIN_total');
462
+	}
463
+
464
+
465
+	/**
466
+	 * Sets total
467
+	 *
468
+	 * @param float $total
469
+	 * @throws EE_Error
470
+	 * @throws InvalidArgumentException
471
+	 * @throws InvalidDataTypeException
472
+	 * @throws InvalidInterfaceException
473
+	 * @throws ReflectionException
474
+	 */
475
+	public function set_total($total)
476
+	{
477
+		$this->set('LIN_total', $total);
478
+	}
479
+
480
+
481
+	/**
482
+	 * Gets order
483
+	 *
484
+	 * @return int
485
+	 * @throws EE_Error
486
+	 * @throws InvalidArgumentException
487
+	 * @throws InvalidDataTypeException
488
+	 * @throws InvalidInterfaceException
489
+	 * @throws ReflectionException
490
+	 */
491
+	public function order()
492
+	{
493
+		return $this->get('LIN_order');
494
+	}
495
+
496
+
497
+	/**
498
+	 * Sets order
499
+	 *
500
+	 * @param int $order
501
+	 * @throws EE_Error
502
+	 * @throws InvalidArgumentException
503
+	 * @throws InvalidDataTypeException
504
+	 * @throws InvalidInterfaceException
505
+	 * @throws ReflectionException
506
+	 */
507
+	public function set_order($order)
508
+	{
509
+		$this->set('LIN_order', $order);
510
+	}
511
+
512
+
513
+	/**
514
+	 * Gets parent
515
+	 *
516
+	 * @return int
517
+	 * @throws EE_Error
518
+	 * @throws InvalidArgumentException
519
+	 * @throws InvalidDataTypeException
520
+	 * @throws InvalidInterfaceException
521
+	 * @throws ReflectionException
522
+	 */
523
+	public function parent_ID()
524
+	{
525
+		return $this->get('LIN_parent');
526
+	}
527
+
528
+
529
+	/**
530
+	 * Sets parent
531
+	 *
532
+	 * @param int $parent
533
+	 * @throws EE_Error
534
+	 * @throws InvalidArgumentException
535
+	 * @throws InvalidDataTypeException
536
+	 * @throws InvalidInterfaceException
537
+	 * @throws ReflectionException
538
+	 */
539
+	public function set_parent_ID($parent)
540
+	{
541
+		$this->set('LIN_parent', $parent);
542
+	}
543
+
544
+
545
+	/**
546
+	 * Gets type
547
+	 *
548
+	 * @return string
549
+	 * @throws EE_Error
550
+	 * @throws InvalidArgumentException
551
+	 * @throws InvalidDataTypeException
552
+	 * @throws InvalidInterfaceException
553
+	 * @throws ReflectionException
554
+	 */
555
+	public function type()
556
+	{
557
+		return $this->get('LIN_type');
558
+	}
559
+
560
+
561
+	/**
562
+	 * Sets type
563
+	 *
564
+	 * @param string $type
565
+	 * @throws EE_Error
566
+	 * @throws InvalidArgumentException
567
+	 * @throws InvalidDataTypeException
568
+	 * @throws InvalidInterfaceException
569
+	 * @throws ReflectionException
570
+	 */
571
+	public function set_type($type)
572
+	{
573
+		$this->set('LIN_type', $type);
574
+	}
575
+
576
+
577
+	/**
578
+	 * Gets the line item of which this item is a composite. Eg, if this is a subtotal, the parent might be a total\
579
+	 * If this line item is saved to the DB, fetches the parent from the DB. However, if this line item isn't in the DB
580
+	 * it uses its cached reference to its parent line item (which would have been set by `EE_Line_Item::set_parent()`
581
+	 * or indirectly by `EE_Line_item::add_child_line_item()`)
582
+	 *
583
+	 * @return EE_Base_Class|EE_Line_Item
584
+	 * @throws EE_Error
585
+	 * @throws InvalidArgumentException
586
+	 * @throws InvalidDataTypeException
587
+	 * @throws InvalidInterfaceException
588
+	 * @throws ReflectionException
589
+	 */
590
+	public function parent()
591
+	{
592
+		return $this->ID()
593
+			? $this->get_model()->get_one_by_ID($this->parent_ID())
594
+			: $this->_parent;
595
+	}
596
+
597
+
598
+	/**
599
+	 * Gets ALL the children of this line item (ie, all the parts that contribute towards this total).
600
+	 *
601
+	 * @return EE_Base_Class[]|EE_Line_Item[]
602
+	 * @throws EE_Error
603
+	 * @throws InvalidArgumentException
604
+	 * @throws InvalidDataTypeException
605
+	 * @throws InvalidInterfaceException
606
+	 * @throws ReflectionException
607
+	 */
608
+	public function children()
609
+	{
610
+		if ($this->ID()) {
611
+			return $this->get_model()->get_all(
612
+				array(
613
+					array('LIN_parent' => $this->ID()),
614
+					'order_by' => array('LIN_order' => 'ASC'),
615
+				)
616
+			);
617
+		}
618
+		if (! is_array($this->_children)) {
619
+			$this->_children = array();
620
+		}
621
+		return $this->_children;
622
+	}
623
+
624
+
625
+	/**
626
+	 * Gets code
627
+	 *
628
+	 * @return string
629
+	 * @throws EE_Error
630
+	 * @throws InvalidArgumentException
631
+	 * @throws InvalidDataTypeException
632
+	 * @throws InvalidInterfaceException
633
+	 * @throws ReflectionException
634
+	 */
635
+	public function code()
636
+	{
637
+		return $this->get('LIN_code');
638
+	}
639
+
640
+
641
+	/**
642
+	 * Sets code
643
+	 *
644
+	 * @param string $code
645
+	 * @throws EE_Error
646
+	 * @throws InvalidArgumentException
647
+	 * @throws InvalidDataTypeException
648
+	 * @throws InvalidInterfaceException
649
+	 * @throws ReflectionException
650
+	 */
651
+	public function set_code($code)
652
+	{
653
+		$this->set('LIN_code', $code);
654
+	}
655
+
656
+
657
+	/**
658
+	 * Gets is_taxable
659
+	 *
660
+	 * @return boolean
661
+	 * @throws EE_Error
662
+	 * @throws InvalidArgumentException
663
+	 * @throws InvalidDataTypeException
664
+	 * @throws InvalidInterfaceException
665
+	 * @throws ReflectionException
666
+	 */
667
+	public function is_taxable()
668
+	{
669
+		return $this->get('LIN_is_taxable');
670
+	}
671
+
672
+
673
+	/**
674
+	 * Sets is_taxable
675
+	 *
676
+	 * @param boolean $is_taxable
677
+	 * @throws EE_Error
678
+	 * @throws InvalidArgumentException
679
+	 * @throws InvalidDataTypeException
680
+	 * @throws InvalidInterfaceException
681
+	 * @throws ReflectionException
682
+	 */
683
+	public function set_is_taxable($is_taxable)
684
+	{
685
+		$this->set('LIN_is_taxable', $is_taxable);
686
+	}
687
+
688
+
689
+	/**
690
+	 * Gets the object that this model-joins-to.
691
+	 * returns one of the model objects that the field OBJ_ID can point to... see the 'OBJ_ID' field on
692
+	 * EEM_Promotion_Object
693
+	 *        Eg, if this line item join model object is for a ticket, this will return the EE_Ticket object
694
+	 *
695
+	 * @return EE_Base_Class | NULL
696
+	 * @throws EE_Error
697
+	 * @throws InvalidArgumentException
698
+	 * @throws InvalidDataTypeException
699
+	 * @throws InvalidInterfaceException
700
+	 * @throws ReflectionException
701
+	 */
702
+	public function get_object()
703
+	{
704
+		$model_name_of_related_obj = $this->OBJ_type();
705
+		return $this->get_model()->has_relation($model_name_of_related_obj)
706
+			? $this->get_first_related($model_name_of_related_obj)
707
+			: null;
708
+	}
709
+
710
+
711
+	/**
712
+	 * Like EE_Line_Item::get_object(), but can only ever actually return an EE_Ticket.
713
+	 * (IE, if this line item is for a price or something else, will return NULL)
714
+	 *
715
+	 * @param array $query_params
716
+	 * @return EE_Base_Class|EE_Ticket
717
+	 * @throws EE_Error
718
+	 * @throws InvalidArgumentException
719
+	 * @throws InvalidDataTypeException
720
+	 * @throws InvalidInterfaceException
721
+	 * @throws ReflectionException
722
+	 */
723
+	public function ticket($query_params = array())
724
+	{
725
+		// we're going to assume that when this method is called
726
+		// we always want to receive the attached ticket EVEN if that ticket is archived.
727
+		// This can be overridden via the incoming $query_params argument
728
+		$remove_defaults = array('default_where_conditions' => 'none');
729
+		$query_params = array_merge($remove_defaults, $query_params);
730
+		return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TICKET, $query_params);
731
+	}
732
+
733
+
734
+	/**
735
+	 * Gets the EE_Datetime that's related to the ticket, IF this is for a ticket
736
+	 *
737
+	 * @return EE_Datetime | NULL
738
+	 * @throws EE_Error
739
+	 * @throws InvalidArgumentException
740
+	 * @throws InvalidDataTypeException
741
+	 * @throws InvalidInterfaceException
742
+	 * @throws ReflectionException
743
+	 */
744
+	public function get_ticket_datetime()
745
+	{
746
+		if ($this->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) {
747
+			$ticket = $this->ticket();
748
+			if ($ticket instanceof EE_Ticket) {
749
+				$datetime = $ticket->first_datetime();
750
+				if ($datetime instanceof EE_Datetime) {
751
+					return $datetime;
752
+				}
753
+			}
754
+		}
755
+		return null;
756
+	}
757
+
758
+
759
+	/**
760
+	 * Gets the event's name that's related to the ticket, if this is for
761
+	 * a ticket
762
+	 *
763
+	 * @return string
764
+	 * @throws EE_Error
765
+	 * @throws InvalidArgumentException
766
+	 * @throws InvalidDataTypeException
767
+	 * @throws InvalidInterfaceException
768
+	 * @throws ReflectionException
769
+	 */
770
+	public function ticket_event_name()
771
+	{
772
+		$event_name = esc_html__('Unknown', 'event_espresso');
773
+		$event = $this->ticket_event();
774
+		if ($event instanceof EE_Event) {
775
+			$event_name = $event->name();
776
+		}
777
+		return $event_name;
778
+	}
779
+
780
+
781
+	/**
782
+	 * Gets the event that's related to the ticket, if this line item represents a ticket.
783
+	 *
784
+	 * @return EE_Event|null
785
+	 * @throws EE_Error
786
+	 * @throws InvalidArgumentException
787
+	 * @throws InvalidDataTypeException
788
+	 * @throws InvalidInterfaceException
789
+	 * @throws ReflectionException
790
+	 */
791
+	public function ticket_event()
792
+	{
793
+		$event = null;
794
+		$ticket = $this->ticket();
795
+		if ($ticket instanceof EE_Ticket) {
796
+			$datetime = $ticket->first_datetime();
797
+			if ($datetime instanceof EE_Datetime) {
798
+				$event = $datetime->event();
799
+			}
800
+		}
801
+		return $event;
802
+	}
803
+
804
+
805
+	/**
806
+	 * Gets the first datetime for this lien item, assuming it's for a ticket
807
+	 *
808
+	 * @param string $date_format
809
+	 * @param string $time_format
810
+	 * @return string
811
+	 * @throws EE_Error
812
+	 * @throws InvalidArgumentException
813
+	 * @throws InvalidDataTypeException
814
+	 * @throws InvalidInterfaceException
815
+	 * @throws ReflectionException
816
+	 */
817
+	public function ticket_datetime_start($date_format = '', $time_format = '')
818
+	{
819
+		$first_datetime_string = esc_html__('Unknown', 'event_espresso');
820
+		$datetime = $this->get_ticket_datetime();
821
+		if ($datetime) {
822
+			$first_datetime_string = $datetime->start_date_and_time($date_format, $time_format);
823
+		}
824
+		return $first_datetime_string;
825
+	}
826
+
827
+
828
+	/**
829
+	 * Adds the line item as a child to this line item. If there is another child line
830
+	 * item with the same LIN_code, it is overwritten by this new one
831
+	 *
832
+	 * @param EEI_Line_Item $line_item
833
+	 * @param bool          $set_order
834
+	 * @return bool success
835
+	 * @throws EE_Error
836
+	 * @throws InvalidArgumentException
837
+	 * @throws InvalidDataTypeException
838
+	 * @throws InvalidInterfaceException
839
+	 * @throws ReflectionException
840
+	 */
841
+	public function add_child_line_item(EEI_Line_Item $line_item, $set_order = true)
842
+	{
843
+		// should we calculate the LIN_order for this line item ?
844
+		if ($set_order || $line_item->order() === null) {
845
+			$line_item->set_order(count($this->children()));
846
+		}
847
+		if ($this->ID()) {
848
+			// check for any duplicate line items (with the same code), if so, this replaces it
849
+			$line_item_with_same_code = $this->get_child_line_item($line_item->code());
850
+			if ($line_item_with_same_code instanceof EE_Line_Item && $line_item_with_same_code !== $line_item) {
851
+				$this->delete_child_line_item($line_item_with_same_code->code());
852
+			}
853
+			$line_item->set_parent_ID($this->ID());
854
+			if ($this->TXN_ID()) {
855
+				$line_item->set_TXN_ID($this->TXN_ID());
856
+			}
857
+			return $line_item->save();
858
+		}
859
+		$this->_children[ $line_item->code() ] = $line_item;
860
+		if ($line_item->parent() !== $this) {
861
+			$line_item->set_parent($this);
862
+		}
863
+		return true;
864
+	}
865
+
866
+
867
+	/**
868
+	 * Similar to EE_Base_Class::_add_relation_to, except this isn't a normal relation.
869
+	 * If this line item is saved to the DB, this is just a wrapper for set_parent_ID() and save()
870
+	 * However, if this line item is NOT saved to the DB, this just caches the parent on
871
+	 * the EE_Line_Item::_parent property.
872
+	 *
873
+	 * @param EE_Line_Item $line_item
874
+	 * @throws EE_Error
875
+	 * @throws InvalidArgumentException
876
+	 * @throws InvalidDataTypeException
877
+	 * @throws InvalidInterfaceException
878
+	 * @throws ReflectionException
879
+	 */
880
+	public function set_parent($line_item)
881
+	{
882
+		if ($this->ID()) {
883
+			if (! $line_item->ID()) {
884
+				$line_item->save();
885
+			}
886
+			$this->set_parent_ID($line_item->ID());
887
+			$this->save();
888
+		} else {
889
+			$this->_parent = $line_item;
890
+			$this->set_parent_ID($line_item->ID());
891
+		}
892
+	}
893
+
894
+
895
+	/**
896
+	 * Gets the child line item as specified by its code. Because this returns an object (by reference)
897
+	 * you can modify this child line item and the parent (this object) can know about them
898
+	 * because it also has a reference to that line item
899
+	 *
900
+	 * @param string $code
901
+	 * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL
902
+	 * @throws EE_Error
903
+	 * @throws InvalidArgumentException
904
+	 * @throws InvalidDataTypeException
905
+	 * @throws InvalidInterfaceException
906
+	 * @throws ReflectionException
907
+	 */
908
+	public function get_child_line_item($code)
909
+	{
910
+		if ($this->ID()) {
911
+			return $this->get_model()->get_one(
912
+				array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code))
913
+			);
914
+		}
915
+		return isset($this->_children[ $code ])
916
+			? $this->_children[ $code ]
917
+			: null;
918
+	}
919
+
920
+
921
+	/**
922
+	 * Returns how many items are deleted (or, if this item has not been saved ot the DB yet, just how many it HAD
923
+	 * cached on it)
924
+	 *
925
+	 * @return int
926
+	 * @throws EE_Error
927
+	 * @throws InvalidArgumentException
928
+	 * @throws InvalidDataTypeException
929
+	 * @throws InvalidInterfaceException
930
+	 * @throws ReflectionException
931
+	 */
932
+	public function delete_children_line_items()
933
+	{
934
+		if ($this->ID()) {
935
+			return $this->get_model()->delete(array(array('LIN_parent' => $this->ID())));
936
+		}
937
+		$count = count($this->_children);
938
+		$this->_children = array();
939
+		return $count;
940
+	}
941
+
942
+
943
+	/**
944
+	 * If this line item has been saved to the DB, deletes its child with LIN_code == $code. If this line
945
+	 * HAS NOT been saved to the DB, removes the child line item with index $code.
946
+	 * Also searches through the child's children for a matching line item. However, once a line item has been found
947
+	 * and deleted, stops searching (so if there are line items with duplicate codes, only the first one found will be
948
+	 * deleted)
949
+	 *
950
+	 * @param string $code
951
+	 * @param bool   $stop_search_once_found
952
+	 * @return int count of items deleted (or simply removed from the line item's cache, if not has not been saved to
953
+	 *             the DB yet)
954
+	 * @throws EE_Error
955
+	 * @throws InvalidArgumentException
956
+	 * @throws InvalidDataTypeException
957
+	 * @throws InvalidInterfaceException
958
+	 * @throws ReflectionException
959
+	 */
960
+	public function delete_child_line_item($code, $stop_search_once_found = true)
961
+	{
962
+		if ($this->ID()) {
963
+			$items_deleted = 0;
964
+			if ($this->code() === $code) {
965
+				$items_deleted += EEH_Line_Item::delete_all_child_items($this);
966
+				$items_deleted += (int) $this->delete();
967
+				if ($stop_search_once_found) {
968
+					return $items_deleted;
969
+				}
970
+			}
971
+			foreach ($this->children() as $child_line_item) {
972
+				$items_deleted += $child_line_item->delete_child_line_item($code, $stop_search_once_found);
973
+			}
974
+			return $items_deleted;
975
+		}
976
+		if (isset($this->_children[ $code ])) {
977
+			unset($this->_children[ $code ]);
978
+			return 1;
979
+		}
980
+		return 0;
981
+	}
982
+
983
+
984
+	/**
985
+	 * If this line item is in the database, is of the type subtotal, and
986
+	 * has no children, why do we have it? It should be deleted so this function
987
+	 * does that
988
+	 *
989
+	 * @return boolean
990
+	 * @throws EE_Error
991
+	 * @throws InvalidArgumentException
992
+	 * @throws InvalidDataTypeException
993
+	 * @throws InvalidInterfaceException
994
+	 * @throws ReflectionException
995
+	 */
996
+	public function delete_if_childless_subtotal()
997
+	{
998
+		if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && ! $this->children()) {
999
+			return $this->delete();
1000
+		}
1001
+		return false;
1002
+	}
1003
+
1004
+
1005
+	/**
1006
+	 * Creates a code and returns a string. doesn't assign the code to this model object
1007
+	 *
1008
+	 * @return string
1009
+	 * @throws EE_Error
1010
+	 * @throws InvalidArgumentException
1011
+	 * @throws InvalidDataTypeException
1012
+	 * @throws InvalidInterfaceException
1013
+	 * @throws ReflectionException
1014
+	 */
1015
+	public function generate_code()
1016
+	{
1017
+		// each line item in the cart requires a unique identifier
1018
+		return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime());
1019
+	}
1020
+
1021
+
1022
+	/**
1023
+	 * @return bool
1024
+	 * @throws EE_Error
1025
+	 * @throws InvalidArgumentException
1026
+	 * @throws InvalidDataTypeException
1027
+	 * @throws InvalidInterfaceException
1028
+	 * @throws ReflectionException
1029
+	 */
1030
+	public function is_tax()
1031
+	{
1032
+		return $this->type() === EEM_Line_Item::type_tax;
1033
+	}
1034
+
1035
+
1036
+	/**
1037
+	 * @return bool
1038
+	 * @throws EE_Error
1039
+	 * @throws InvalidArgumentException
1040
+	 * @throws InvalidDataTypeException
1041
+	 * @throws InvalidInterfaceException
1042
+	 * @throws ReflectionException
1043
+	 */
1044
+	public function is_tax_sub_total()
1045
+	{
1046
+		return $this->type() === EEM_Line_Item::type_tax_sub_total;
1047
+	}
1048
+
1049
+
1050
+	/**
1051
+	 * @return bool
1052
+	 * @throws EE_Error
1053
+	 * @throws InvalidArgumentException
1054
+	 * @throws InvalidDataTypeException
1055
+	 * @throws InvalidInterfaceException
1056
+	 * @throws ReflectionException
1057
+	 */
1058
+	public function is_line_item()
1059
+	{
1060
+		return $this->type() === EEM_Line_Item::type_line_item;
1061
+	}
1062
+
1063
+
1064
+	/**
1065
+	 * @return bool
1066
+	 * @throws EE_Error
1067
+	 * @throws InvalidArgumentException
1068
+	 * @throws InvalidDataTypeException
1069
+	 * @throws InvalidInterfaceException
1070
+	 * @throws ReflectionException
1071
+	 */
1072
+	public function is_sub_line_item()
1073
+	{
1074
+		return $this->type() === EEM_Line_Item::type_sub_line_item;
1075
+	}
1076
+
1077
+
1078
+	/**
1079
+	 * @return bool
1080
+	 * @throws EE_Error
1081
+	 * @throws InvalidArgumentException
1082
+	 * @throws InvalidDataTypeException
1083
+	 * @throws InvalidInterfaceException
1084
+	 * @throws ReflectionException
1085
+	 */
1086
+	public function is_sub_total()
1087
+	{
1088
+		return $this->type() === EEM_Line_Item::type_sub_total;
1089
+	}
1090
+
1091
+
1092
+	/**
1093
+	 * Whether or not this line item is a cancellation line item
1094
+	 *
1095
+	 * @return boolean
1096
+	 * @throws EE_Error
1097
+	 * @throws InvalidArgumentException
1098
+	 * @throws InvalidDataTypeException
1099
+	 * @throws InvalidInterfaceException
1100
+	 * @throws ReflectionException
1101
+	 */
1102
+	public function is_cancellation()
1103
+	{
1104
+		return EEM_Line_Item::type_cancellation === $this->type();
1105
+	}
1106
+
1107
+
1108
+	/**
1109
+	 * @return bool
1110
+	 * @throws EE_Error
1111
+	 * @throws InvalidArgumentException
1112
+	 * @throws InvalidDataTypeException
1113
+	 * @throws InvalidInterfaceException
1114
+	 * @throws ReflectionException
1115
+	 */
1116
+	public function is_total()
1117
+	{
1118
+		return $this->type() === EEM_Line_Item::type_total;
1119
+	}
1120
+
1121
+
1122
+	/**
1123
+	 * @return bool
1124
+	 * @throws EE_Error
1125
+	 * @throws InvalidArgumentException
1126
+	 * @throws InvalidDataTypeException
1127
+	 * @throws InvalidInterfaceException
1128
+	 * @throws ReflectionException
1129
+	 */
1130
+	public function is_cancelled()
1131
+	{
1132
+		return $this->type() === EEM_Line_Item::type_cancellation;
1133
+	}
1134
+
1135
+
1136
+	/**
1137
+	 * @return string like '2, 004.00', formatted according to the localized currency
1138
+	 * @throws EE_Error
1139
+	 * @throws InvalidArgumentException
1140
+	 * @throws InvalidDataTypeException
1141
+	 * @throws InvalidInterfaceException
1142
+	 * @throws ReflectionException
1143
+	 */
1144
+	public function unit_price_no_code()
1145
+	{
1146
+		return $this->get_pretty('LIN_unit_price', 'no_currency_code');
1147
+	}
1148
+
1149
+
1150
+	/**
1151
+	 * @return string like '2, 004.00', formatted according to the localized currency
1152
+	 * @throws EE_Error
1153
+	 * @throws InvalidArgumentException
1154
+	 * @throws InvalidDataTypeException
1155
+	 * @throws InvalidInterfaceException
1156
+	 * @throws ReflectionException
1157
+	 */
1158
+	public function total_no_code()
1159
+	{
1160
+		return $this->get_pretty('LIN_total', 'no_currency_code');
1161
+	}
1162
+
1163
+
1164
+	/**
1165
+	 * Gets the final total on this item, taking taxes into account.
1166
+	 * Has the side-effect of setting the sub-total as it was just calculated.
1167
+	 * If this is used on a grand-total line item, also updates the transaction's
1168
+	 * TXN_total (provided this line item is allowed to persist, otherwise we don't
1169
+	 * want to change a persistable transaction with info from a non-persistent line item)
1170
+	 *
1171
+	 * @param bool $update_txn_status
1172
+	 * @return float
1173
+	 * @throws EE_Error
1174
+	 * @throws InvalidArgumentException
1175
+	 * @throws InvalidDataTypeException
1176
+	 * @throws InvalidInterfaceException
1177
+	 * @throws ReflectionException
1178
+	 * @throws RuntimeException
1179
+	 */
1180
+	public function recalculate_total_including_taxes($update_txn_status = false)
1181
+	{
1182
+		$pre_tax_total = $this->recalculate_pre_tax_total();
1183
+		$tax_total = $this->recalculate_taxes_and_tax_total();
1184
+		$total = $pre_tax_total + $tax_total;
1185
+		// no negative totals plz
1186
+		$total = max($total, 0);
1187
+		$this->set_total($total);
1188
+		// only update the related transaction's total
1189
+		// if we intend to save this line item and its a grand total
1190
+		if (
1191
+			$this->allow_persist() && $this->type() === EEM_Line_Item::type_total
1192
+			&& $this->transaction()
1193
+			   instanceof
1194
+			   EE_Transaction
1195
+		) {
1196
+			$this->transaction()->set_total($total);
1197
+			if ($update_txn_status) {
1198
+				// don't save the TXN because that will be done below
1199
+				// and the following method only saves if the status changes
1200
+				$this->transaction()->update_status_based_on_total_paid(false);
1201
+			}
1202
+			if ($this->transaction()->ID()) {
1203
+				$this->transaction()->save();
1204
+			}
1205
+		}
1206
+		$this->maybe_save();
1207
+		return $total;
1208
+	}
1209
+
1210
+
1211
+	/**
1212
+	 * Recursively goes through all the children and recalculates sub-totals EXCEPT for
1213
+	 * tax-sub-totals (they're a an odd beast). Updates the 'total' on each line item according to either its
1214
+	 * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and
1215
+	 * when this is called on the grand total
1216
+	 *
1217
+	 * @return float
1218
+	 * @throws EE_Error
1219
+	 * @throws InvalidArgumentException
1220
+	 * @throws InvalidDataTypeException
1221
+	 * @throws InvalidInterfaceException
1222
+	 * @throws ReflectionException
1223
+	 */
1224
+	public function recalculate_pre_tax_total()
1225
+	{
1226
+		$total = 0;
1227
+		$my_children = $this->children();
1228
+		$has_children = ! empty($my_children);
1229
+		if ($has_children && $this->is_line_item()) {
1230
+			$total = $this->_recalculate_pretax_total_for_line_item($total, $my_children);
1231
+		} elseif (! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) {
1232
+			$total = $this->unit_price() * $this->quantity();
1233
+		} elseif ($this->is_sub_total() || $this->is_total()) {
1234
+			$total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children);
1235
+		} elseif ($this->is_tax_sub_total() || $this->is_tax() || $this->is_cancelled()) {
1236
+			// completely ignore tax totals, tax sub-totals, and cancelled line items, when calculating the pre-tax-total
1237
+			return 0;
1238
+		}
1239
+		// ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events)
1240
+		if (
1241
+			! $this->is_line_item() && ! $this->is_sub_line_item() && ! $this->is_cancellation()
1242
+		) {
1243
+			if ($this->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_EVENT) {
1244
+				$this->set_quantity(1);
1245
+			}
1246
+			if (! $this->is_percent()) {
1247
+				$this->set_unit_price($total);
1248
+			}
1249
+		}
1250
+		// we don't want to bother saving grand totals, because that needs to factor in taxes anyways
1251
+		// so it ought to be
1252
+		if (! $this->is_total()) {
1253
+			$this->set_total($total);
1254
+			// if not a percent line item, make sure we keep the unit price in sync
1255
+			if (
1256
+				$has_children
1257
+				&& $this->is_line_item()
1258
+				&& ! $this->is_percent()
1259
+			) {
1260
+				if ($this->quantity() === 0) {
1261
+					$new_unit_price = 0;
1262
+				} else {
1263
+					$new_unit_price = $this->total() / $this->quantity();
1264
+				}
1265
+				$this->set_unit_price($new_unit_price);
1266
+			}
1267
+			$this->maybe_save();
1268
+		}
1269
+		return $total;
1270
+	}
1271
+
1272
+
1273
+	/**
1274
+	 * Calculates the pretax total when this line item is a subtotal or total line item.
1275
+	 * Basically does a sum-then-round approach (ie, any percent line item that are children
1276
+	 * will calculate their total based on the un-rounded total we're working with so far, and
1277
+	 * THEN round the result; instead of rounding as we go like with sub-line-items)
1278
+	 *
1279
+	 * @param float          $calculated_total_so_far
1280
+	 * @param EE_Line_Item[] $my_children
1281
+	 * @return float
1282
+	 * @throws EE_Error
1283
+	 * @throws InvalidArgumentException
1284
+	 * @throws InvalidDataTypeException
1285
+	 * @throws InvalidInterfaceException
1286
+	 * @throws ReflectionException
1287
+	 */
1288
+	protected function _recalculate_pretax_total_for_subtotal($calculated_total_so_far, $my_children = null)
1289
+	{
1290
+		if ($my_children === null) {
1291
+			$my_children = $this->children();
1292
+		}
1293
+		$subtotal_quantity = 0;
1294
+		// get the total of all its children
1295
+		foreach ($my_children as $child_line_item) {
1296
+			if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) {
1297
+				// percentage line items are based on total so far
1298
+				if ($child_line_item->is_percent()) {
1299
+					// round as we go so that the line items add up ok
1300
+					$percent_total = round(
1301
+						$calculated_total_so_far * $child_line_item->percent() / 100,
1302
+						EE_Registry::instance()->CFG->currency->dec_plc
1303
+					);
1304
+					$child_line_item->set_total($percent_total);
1305
+					// so far all percent line items should have a quantity of 1
1306
+					// (ie, no double percent discounts. Although that might be requested someday)
1307
+					$child_line_item->set_quantity(1);
1308
+					$child_line_item->maybe_save();
1309
+					$calculated_total_so_far += $percent_total;
1310
+				} else {
1311
+					// verify flat sub-line-item quantities match their parent
1312
+					if ($child_line_item->is_sub_line_item()) {
1313
+						$child_line_item->set_quantity($this->quantity());
1314
+					}
1315
+					$calculated_total_so_far += $child_line_item->recalculate_pre_tax_total();
1316
+					$subtotal_quantity += $child_line_item->quantity();
1317
+				}
1318
+			}
1319
+		}
1320
+		if ($this->is_sub_total()) {
1321
+			// no negative totals plz
1322
+			$calculated_total_so_far = max($calculated_total_so_far, 0);
1323
+			$subtotal_quantity = $subtotal_quantity > 0 ? 1 : 0;
1324
+			$this->set_quantity($subtotal_quantity);
1325
+			$this->maybe_save();
1326
+		}
1327
+		return $calculated_total_so_far;
1328
+	}
1329
+
1330
+
1331
+	/**
1332
+	 * Calculates the pretax total for a normal line item, in a round-then-sum approach
1333
+	 * (where each sub-line-item is applied to the base price for the line item
1334
+	 * and the result is immediately rounded, rather than summing all the sub-line-items
1335
+	 * then rounding, like we do when recalculating pretax totals on totals and subtotals).
1336
+	 *
1337
+	 * @param float          $calculated_total_so_far
1338
+	 * @param EE_Line_Item[] $my_children
1339
+	 * @return float
1340
+	 * @throws EE_Error
1341
+	 * @throws InvalidArgumentException
1342
+	 * @throws InvalidDataTypeException
1343
+	 * @throws InvalidInterfaceException
1344
+	 * @throws ReflectionException
1345
+	 */
1346
+	protected function _recalculate_pretax_total_for_line_item($calculated_total_so_far, $my_children = null)
1347
+	{
1348
+		if ($my_children === null) {
1349
+			$my_children = $this->children();
1350
+		}
1351
+		// we need to keep track of the running total for a single item,
1352
+		// because we need to round as we go
1353
+		$unit_price_for_total = 0;
1354
+		$quantity_for_total = 1;
1355
+		// get the total of all its children
1356
+		foreach ($my_children as $child_line_item) {
1357
+			if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) {
1358
+				if ($child_line_item->is_percent()) {
1359
+					// it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity
1360
+					// not total multiplied by percent, because that ignores rounding along-the-way
1361
+					$percent_unit_price = round(
1362
+						$unit_price_for_total * $child_line_item->percent() / 100,
1363
+						EE_Registry::instance()->CFG->currency->dec_plc
1364
+					);
1365
+					$percent_total = $percent_unit_price * $quantity_for_total;
1366
+					$child_line_item->set_total($percent_total);
1367
+					// so far all percent line items should have a quantity of 1
1368
+					// (ie, no double percent discounts. Although that might be requested someday)
1369
+					$child_line_item->set_quantity(1);
1370
+					$child_line_item->maybe_save();
1371
+					$calculated_total_so_far += $percent_total;
1372
+					$unit_price_for_total += $percent_unit_price;
1373
+				} else {
1374
+					// verify flat sub-line-item quantities match their parent
1375
+					if ($child_line_item->is_sub_line_item()) {
1376
+						$child_line_item->set_quantity($this->quantity());
1377
+					}
1378
+					$quantity_for_total = $child_line_item->quantity();
1379
+					$calculated_total_so_far += $child_line_item->recalculate_pre_tax_total();
1380
+					$unit_price_for_total += $child_line_item->unit_price();
1381
+				}
1382
+			}
1383
+		}
1384
+		return $calculated_total_so_far;
1385
+	}
1386
+
1387
+
1388
+	/**
1389
+	 * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets
1390
+	 * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items
1391
+	 * and tax sub-total if already in the DB
1392
+	 *
1393
+	 * @return float
1394
+	 * @throws EE_Error
1395
+	 * @throws InvalidArgumentException
1396
+	 * @throws InvalidDataTypeException
1397
+	 * @throws InvalidInterfaceException
1398
+	 * @throws ReflectionException
1399
+	 */
1400
+	public function recalculate_taxes_and_tax_total()
1401
+	{
1402
+		// get all taxes
1403
+		$taxes = $this->tax_descendants();
1404
+		// calculate the pretax total
1405
+		$taxable_total = $this->taxable_total();
1406
+		$tax_total = 0;
1407
+		foreach ($taxes as $tax) {
1408
+			$total_on_this_tax = $taxable_total * $tax->percent() / 100;
1409
+			// remember the total on this line item
1410
+			$tax->set_total($total_on_this_tax);
1411
+			$tax->maybe_save();
1412
+			$tax_total += $tax->total();
1413
+		}
1414
+		$this->_recalculate_tax_sub_total();
1415
+		return $tax_total;
1416
+	}
1417
+
1418
+
1419
+	/**
1420
+	 * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated
1421
+	 *
1422
+	 * @return void
1423
+	 * @throws EE_Error
1424
+	 * @throws InvalidArgumentException
1425
+	 * @throws InvalidDataTypeException
1426
+	 * @throws InvalidInterfaceException
1427
+	 * @throws ReflectionException
1428
+	 */
1429
+	private function _recalculate_tax_sub_total()
1430
+	{
1431
+		if ($this->is_tax_sub_total()) {
1432
+			$total = 0;
1433
+			$total_percent = 0;
1434
+			// simply loop through all its children (which should be taxes) and sum their total
1435
+			foreach ($this->children() as $child_tax) {
1436
+				if ($child_tax instanceof EE_Line_Item) {
1437
+					$total += $child_tax->total();
1438
+					$total_percent += $child_tax->percent();
1439
+				}
1440
+			}
1441
+			$this->set_total($total);
1442
+			$this->set_percent($total_percent);
1443
+			$this->maybe_save();
1444
+		} elseif ($this->is_total()) {
1445
+			foreach ($this->children() as $maybe_tax_subtotal) {
1446
+				if ($maybe_tax_subtotal instanceof EE_Line_Item) {
1447
+					$maybe_tax_subtotal->_recalculate_tax_sub_total();
1448
+				}
1449
+			}
1450
+		}
1451
+	}
1452
+
1453
+
1454
+	/**
1455
+	 * Gets the total tax on this line item. Assumes taxes have already been calculated using
1456
+	 * recalculate_taxes_and_total
1457
+	 *
1458
+	 * @return float
1459
+	 * @throws EE_Error
1460
+	 * @throws InvalidArgumentException
1461
+	 * @throws InvalidDataTypeException
1462
+	 * @throws InvalidInterfaceException
1463
+	 * @throws ReflectionException
1464
+	 */
1465
+	public function get_total_tax()
1466
+	{
1467
+		$this->_recalculate_tax_sub_total();
1468
+		$total = 0;
1469
+		foreach ($this->tax_descendants() as $tax_line_item) {
1470
+			if ($tax_line_item instanceof EE_Line_Item) {
1471
+				$total += $tax_line_item->total();
1472
+			}
1473
+		}
1474
+		return $total;
1475
+	}
1476
+
1477
+
1478
+	/**
1479
+	 * Gets the total for all the items purchased only
1480
+	 *
1481
+	 * @return float
1482
+	 * @throws EE_Error
1483
+	 * @throws InvalidArgumentException
1484
+	 * @throws InvalidDataTypeException
1485
+	 * @throws InvalidInterfaceException
1486
+	 * @throws ReflectionException
1487
+	 */
1488
+	public function get_items_total()
1489
+	{
1490
+		// by default, let's make sure we're consistent with the existing line item
1491
+		if ($this->is_total()) {
1492
+			$pretax_subtotal_li = EEH_Line_Item::get_pre_tax_subtotal($this);
1493
+			if ($pretax_subtotal_li instanceof EE_Line_Item) {
1494
+				return $pretax_subtotal_li->total();
1495
+			}
1496
+		}
1497
+		$total = 0;
1498
+		foreach ($this->get_items() as $item) {
1499
+			if ($item instanceof EE_Line_Item) {
1500
+				$total += $item->total();
1501
+			}
1502
+		}
1503
+		return $total;
1504
+	}
1505
+
1506
+
1507
+	/**
1508
+	 * Gets all the descendants (ie, children or children of children etc) that
1509
+	 * are of the type 'tax'
1510
+	 *
1511
+	 * @return EE_Line_Item[]
1512
+	 * @throws EE_Error
1513
+	 */
1514
+	public function tax_descendants()
1515
+	{
1516
+		return EEH_Line_Item::get_tax_descendants($this);
1517
+	}
1518
+
1519
+
1520
+	/**
1521
+	 * Gets all the real items purchased which are children of this item
1522
+	 *
1523
+	 * @return EE_Line_Item[]
1524
+	 * @throws EE_Error
1525
+	 */
1526
+	public function get_items()
1527
+	{
1528
+		return EEH_Line_Item::get_line_item_descendants($this);
1529
+	}
1530
+
1531
+
1532
+	/**
1533
+	 * Returns the amount taxable among this line item's children (or if it has no children,
1534
+	 * how much of it is taxable). Does not recalculate totals or subtotals.
1535
+	 * If the taxable total is negative, (eg, if none of the tickets were taxable,
1536
+	 * but there is a "Taxable" discount), returns 0.
1537
+	 *
1538
+	 * @return float
1539
+	 * @throws EE_Error
1540
+	 * @throws InvalidArgumentException
1541
+	 * @throws InvalidDataTypeException
1542
+	 * @throws InvalidInterfaceException
1543
+	 * @throws ReflectionException
1544
+	 */
1545
+	public function taxable_total()
1546
+	{
1547
+		$total = 0;
1548
+		if ($this->children()) {
1549
+			foreach ($this->children() as $child_line_item) {
1550
+				if ($child_line_item->type() === EEM_Line_Item::type_line_item && $child_line_item->is_taxable()) {
1551
+					// if it's a percent item, only take into account the percent
1552
+					// that's taxable too (the taxable total so far)
1553
+					if ($child_line_item->is_percent()) {
1554
+						$total += ($total * $child_line_item->percent() / 100);
1555
+					} else {
1556
+						$total += $child_line_item->total();
1557
+					}
1558
+				} elseif ($child_line_item->type() === EEM_Line_Item::type_sub_total) {
1559
+					$total += $child_line_item->taxable_total();
1560
+				}
1561
+			}
1562
+		}
1563
+		return max($total, 0);
1564
+	}
1565
+
1566
+
1567
+	/**
1568
+	 * Gets the transaction for this line item
1569
+	 *
1570
+	 * @return EE_Base_Class|EE_Transaction
1571
+	 * @throws EE_Error
1572
+	 * @throws InvalidArgumentException
1573
+	 * @throws InvalidDataTypeException
1574
+	 * @throws InvalidInterfaceException
1575
+	 * @throws ReflectionException
1576
+	 */
1577
+	public function transaction()
1578
+	{
1579
+		return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TRANSACTION);
1580
+	}
1581
+
1582
+
1583
+	/**
1584
+	 * Saves this line item to the DB, and recursively saves its descendants.
1585
+	 * Because there currently is no proper parent-child relation on the model,
1586
+	 * save_this_and_cached() will NOT save the descendants.
1587
+	 * Also sets the transaction on this line item and all its descendants before saving
1588
+	 *
1589
+	 * @param int $txn_id if none is provided, assumes $this->TXN_ID()
1590
+	 * @return int count of items saved
1591
+	 * @throws EE_Error
1592
+	 * @throws InvalidArgumentException
1593
+	 * @throws InvalidDataTypeException
1594
+	 * @throws InvalidInterfaceException
1595
+	 * @throws ReflectionException
1596
+	 */
1597
+	public function save_this_and_descendants_to_txn($txn_id = null)
1598
+	{
1599
+		$count = 0;
1600
+		if (! $txn_id) {
1601
+			$txn_id = $this->TXN_ID();
1602
+		}
1603
+		$this->set_TXN_ID($txn_id);
1604
+		$children = $this->children();
1605
+		$count += $this->save()
1606
+			? 1
1607
+			: 0;
1608
+		foreach ($children as $child_line_item) {
1609
+			if ($child_line_item instanceof EE_Line_Item) {
1610
+				$child_line_item->set_parent_ID($this->ID());
1611
+				$count += $child_line_item->save_this_and_descendants_to_txn($txn_id);
1612
+			}
1613
+		}
1614
+		return $count;
1615
+	}
1616
+
1617
+
1618
+	/**
1619
+	 * Saves this line item to the DB, and recursively saves its descendants.
1620
+	 *
1621
+	 * @return int count of items saved
1622
+	 * @throws EE_Error
1623
+	 * @throws InvalidArgumentException
1624
+	 * @throws InvalidDataTypeException
1625
+	 * @throws InvalidInterfaceException
1626
+	 * @throws ReflectionException
1627
+	 */
1628
+	public function save_this_and_descendants()
1629
+	{
1630
+		$count = 0;
1631
+		$children = $this->children();
1632
+		$count += $this->save()
1633
+			? 1
1634
+			: 0;
1635
+		foreach ($children as $child_line_item) {
1636
+			if ($child_line_item instanceof EE_Line_Item) {
1637
+				$child_line_item->set_parent_ID($this->ID());
1638
+				$count += $child_line_item->save_this_and_descendants();
1639
+			}
1640
+		}
1641
+		return $count;
1642
+	}
1643
+
1644
+
1645
+	/**
1646
+	 * returns the cancellation line item if this item was cancelled
1647
+	 *
1648
+	 * @return EE_Line_Item[]
1649
+	 * @throws InvalidArgumentException
1650
+	 * @throws InvalidInterfaceException
1651
+	 * @throws InvalidDataTypeException
1652
+	 * @throws ReflectionException
1653
+	 * @throws EE_Error
1654
+	 */
1655
+	public function get_cancellations()
1656
+	{
1657
+		EE_Registry::instance()->load_helper('Line_Item');
1658
+		return EEH_Line_Item::get_descendants_of_type($this, EEM_Line_Item::type_cancellation);
1659
+	}
1660
+
1661
+
1662
+	/**
1663
+	 * If this item has an ID, then this saves it again to update the db
1664
+	 *
1665
+	 * @return int count of items saved
1666
+	 * @throws EE_Error
1667
+	 * @throws InvalidArgumentException
1668
+	 * @throws InvalidDataTypeException
1669
+	 * @throws InvalidInterfaceException
1670
+	 * @throws ReflectionException
1671
+	 */
1672
+	public function maybe_save()
1673
+	{
1674
+		if ($this->ID()) {
1675
+			return $this->save();
1676
+		}
1677
+		return false;
1678
+	}
1679
+
1680
+
1681
+	/**
1682
+	 * clears the cached children and parent from the line item
1683
+	 *
1684
+	 * @return void
1685
+	 */
1686
+	public function clear_related_line_item_cache()
1687
+	{
1688
+		$this->_children = array();
1689
+		$this->_parent = null;
1690
+	}
1691
+
1692
+
1693
+	/**
1694
+	 * @param bool $raw
1695
+	 * @return int
1696
+	 * @throws EE_Error
1697
+	 * @throws InvalidArgumentException
1698
+	 * @throws InvalidDataTypeException
1699
+	 * @throws InvalidInterfaceException
1700
+	 * @throws ReflectionException
1701
+	 */
1702
+	public function timestamp($raw = false)
1703
+	{
1704
+		return $raw
1705
+			? $this->get_raw('LIN_timestamp')
1706
+			: $this->get('LIN_timestamp');
1707
+	}
1708
+
1709
+
1710
+
1711
+
1712
+	/************************* DEPRECATED *************************/
1713
+	/**
1714
+	 * @deprecated 4.6.0
1715
+	 * @param string $type one of the constants on EEM_Line_Item
1716
+	 * @return EE_Line_Item[]
1717
+	 * @throws EE_Error
1718
+	 */
1719
+	protected function _get_descendants_of_type($type)
1720
+	{
1721
+		EE_Error::doing_it_wrong(
1722
+			'EE_Line_Item::_get_descendants_of_type()',
1723
+			sprintf(
1724
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
1725
+				'EEH_Line_Item::get_descendants_of_type()'
1726
+			),
1727
+			'4.6.0'
1728
+		);
1729
+		return EEH_Line_Item::get_descendants_of_type($this, $type);
1730
+	}
1731
+
1732
+
1733
+	/**
1734
+	 * @deprecated 4.6.0
1735
+	 * @param string $type like one of the EEM_Line_Item::type_*
1736
+	 * @return EE_Line_Item
1737
+	 * @throws EE_Error
1738
+	 * @throws InvalidArgumentException
1739
+	 * @throws InvalidDataTypeException
1740
+	 * @throws InvalidInterfaceException
1741
+	 * @throws ReflectionException
1742
+	 */
1743
+	public function get_nearest_descendant_of_type($type)
1744
+	{
1745
+		EE_Error::doing_it_wrong(
1746
+			'EE_Line_Item::get_nearest_descendant_of_type()',
1747
+			sprintf(
1748
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
1749
+				'EEH_Line_Item::get_nearest_descendant_of_type()'
1750
+			),
1751
+			'4.6.0'
1752
+		);
1753
+		return EEH_Line_Item::get_nearest_descendant_of_type($this, $type);
1754
+	}
1755 1755
 }
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -88,7 +88,7 @@  discard block
 block discarded – undo
88 88
     protected function __construct($fieldValues = array(), $bydb = false, $timezone = '')
89 89
     {
90 90
         parent::__construct($fieldValues, $bydb, $timezone);
91
-        if (! $this->get('LIN_code')) {
91
+        if ( ! $this->get('LIN_code')) {
92 92
             $this->set_code($this->generate_code());
93 93
         }
94 94
     }
@@ -155,7 +155,7 @@  discard block
 block discarded – undo
155 155
     public function name()
156 156
     {
157 157
         $name = $this->get('LIN_name');
158
-        if (! $name) {
158
+        if ( ! $name) {
159 159
             $name = ucwords(str_replace('-', ' ', $this->type()));
160 160
         }
161 161
         return $name;
@@ -615,7 +615,7 @@  discard block
 block discarded – undo
615 615
                 )
616 616
             );
617 617
         }
618
-        if (! is_array($this->_children)) {
618
+        if ( ! is_array($this->_children)) {
619 619
             $this->_children = array();
620 620
         }
621 621
         return $this->_children;
@@ -856,7 +856,7 @@  discard block
 block discarded – undo
856 856
             }
857 857
             return $line_item->save();
858 858
         }
859
-        $this->_children[ $line_item->code() ] = $line_item;
859
+        $this->_children[$line_item->code()] = $line_item;
860 860
         if ($line_item->parent() !== $this) {
861 861
             $line_item->set_parent($this);
862 862
         }
@@ -880,7 +880,7 @@  discard block
 block discarded – undo
880 880
     public function set_parent($line_item)
881 881
     {
882 882
         if ($this->ID()) {
883
-            if (! $line_item->ID()) {
883
+            if ( ! $line_item->ID()) {
884 884
                 $line_item->save();
885 885
             }
886 886
             $this->set_parent_ID($line_item->ID());
@@ -912,8 +912,8 @@  discard block
 block discarded – undo
912 912
                 array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code))
913 913
             );
914 914
         }
915
-        return isset($this->_children[ $code ])
916
-            ? $this->_children[ $code ]
915
+        return isset($this->_children[$code])
916
+            ? $this->_children[$code]
917 917
             : null;
918 918
     }
919 919
 
@@ -973,8 +973,8 @@  discard block
 block discarded – undo
973 973
             }
974 974
             return $items_deleted;
975 975
         }
976
-        if (isset($this->_children[ $code ])) {
977
-            unset($this->_children[ $code ]);
976
+        if (isset($this->_children[$code])) {
977
+            unset($this->_children[$code]);
978 978
             return 1;
979 979
         }
980 980
         return 0;
@@ -1015,7 +1015,7 @@  discard block
 block discarded – undo
1015 1015
     public function generate_code()
1016 1016
     {
1017 1017
         // each line item in the cart requires a unique identifier
1018
-        return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime());
1018
+        return md5($this->get('OBJ_type').$this->get('OBJ_ID').microtime());
1019 1019
     }
1020 1020
 
1021 1021
 
@@ -1228,7 +1228,7 @@  discard block
 block discarded – undo
1228 1228
         $has_children = ! empty($my_children);
1229 1229
         if ($has_children && $this->is_line_item()) {
1230 1230
             $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children);
1231
-        } elseif (! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) {
1231
+        } elseif ( ! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) {
1232 1232
             $total = $this->unit_price() * $this->quantity();
1233 1233
         } elseif ($this->is_sub_total() || $this->is_total()) {
1234 1234
             $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children);
@@ -1243,13 +1243,13 @@  discard block
 block discarded – undo
1243 1243
             if ($this->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_EVENT) {
1244 1244
                 $this->set_quantity(1);
1245 1245
             }
1246
-            if (! $this->is_percent()) {
1246
+            if ( ! $this->is_percent()) {
1247 1247
                 $this->set_unit_price($total);
1248 1248
             }
1249 1249
         }
1250 1250
         // we don't want to bother saving grand totals, because that needs to factor in taxes anyways
1251 1251
         // so it ought to be
1252
-        if (! $this->is_total()) {
1252
+        if ( ! $this->is_total()) {
1253 1253
             $this->set_total($total);
1254 1254
             // if not a percent line item, make sure we keep the unit price in sync
1255 1255
             if (
@@ -1597,7 +1597,7 @@  discard block
 block discarded – undo
1597 1597
     public function save_this_and_descendants_to_txn($txn_id = null)
1598 1598
     {
1599 1599
         $count = 0;
1600
-        if (! $txn_id) {
1600
+        if ( ! $txn_id) {
1601 1601
             $txn_id = $this->TXN_ID();
1602 1602
         }
1603 1603
         $this->set_TXN_ID($txn_id);
Please login to merge, or discard this patch.
core/domain/entities/editor/blocks/EventAttendees.php 2 patches
Indentation   +157 added lines, -157 removed lines patch added patch discarded remove patch
@@ -21,172 +21,172 @@
 block discarded – undo
21 21
 class EventAttendees extends Block
22 22
 {
23 23
 
24
-    const BLOCK_TYPE = 'event-attendees';
24
+	const BLOCK_TYPE = 'event-attendees';
25 25
 
26
-    /**
27
-     * @var EventAttendeesBlockRenderer $renderer
28
-     */
29
-    protected $renderer;
26
+	/**
27
+	 * @var EventAttendeesBlockRenderer $renderer
28
+	 */
29
+	protected $renderer;
30 30
 
31 31
 
32
-    /**
33
-     * EventAttendees constructor.
34
-     *
35
-     * @param CoreBlocksAssetManager      $block_asset_manager
36
-     * @param RequestInterface            $request
37
-     * @param EventAttendeesBlockRenderer $renderer
38
-     */
39
-    public function __construct(
40
-        CoreBlocksAssetManager $block_asset_manager,
41
-        RequestInterface $request,
42
-        EventAttendeesBlockRenderer $renderer
43
-    ) {
44
-        parent::__construct($block_asset_manager, $request);
45
-        $this->renderer = $renderer;
46
-    }
32
+	/**
33
+	 * EventAttendees constructor.
34
+	 *
35
+	 * @param CoreBlocksAssetManager      $block_asset_manager
36
+	 * @param RequestInterface            $request
37
+	 * @param EventAttendeesBlockRenderer $renderer
38
+	 */
39
+	public function __construct(
40
+		CoreBlocksAssetManager $block_asset_manager,
41
+		RequestInterface $request,
42
+		EventAttendeesBlockRenderer $renderer
43
+	) {
44
+		parent::__construct($block_asset_manager, $request);
45
+		$this->renderer = $renderer;
46
+	}
47 47
 
48 48
 
49
-    /**
50
-     * Perform any early setup required by the block
51
-     * including setting the block type and supported post types
52
-     *
53
-     * @return void
54
-     */
55
-    public function initialize()
56
-    {
57
-        $this->setBlockType(self::BLOCK_TYPE);
58
-        $this->setSupportedRoutes(
59
-            array(
60
-                'EventEspresso\core\domain\entities\route_match\specifications\admin\EspressoStandardPostTypeEditor',
61
-                'EventEspresso\core\domain\entities\route_match\specifications\admin\WordPressPostTypeEditor',
62
-                'EventEspresso\core\domain\entities\route_match\specifications\frontend\EspressoBlockRenderer',
63
-                'EventEspresso\core\domain\entities\route_match\specifications\frontend\AnyFrontendRequest'
64
-            )
65
-        );
66
-        $EVT_ID = $this->request->getRequestParam('page') === 'espresso_events'
67
-            ? $this->request->getRequestParam('post', 0, 'int')
68
-            : 0;
69
-        $this->setAttributes(
70
-            array(
71
-                'eventId'           => array(
72
-                    'type'    => 'number',
73
-                    'default' => $EVT_ID,
74
-                ),
75
-                'datetimeId'        => array(
76
-                    'type'    => 'number',
77
-                    'default' => 0,
78
-                ),
79
-                'ticketId'          => array(
80
-                    'type'    => 'number',
81
-                    'default' => 0,
82
-                ),
83
-                'status'            => array(
84
-                    'type'    => 'string',
85
-                    'default' => EEM_Registration::status_id_approved,
86
-                ),
87
-                'limit'             => array(
88
-                    'type'    => 'number',
89
-                    'default' => 100,
90
-                ),
91
-                'order' => array(
92
-                    'type' => 'string',
93
-                    'default' => 'ASC'
94
-                ),
95
-                'orderBy' => array(
96
-                    'type' => 'string',
97
-                    'default' => 'lastThenFirstName',
98
-                ),
99
-                'showGravatar'      => array(
100
-                    'type'    => 'boolean',
101
-                    'default' => false,
102
-                ),
103
-                'avatarClass' => array(
104
-                    'type' => 'string',
105
-                    'default' => 'contact',
106
-                ),
107
-                'avatarSize' => array(
108
-                    'type' => 'number',
109
-                    'default' => 24,
110
-                ),
111
-                'displayOnArchives' => array(
112
-                    'type'    => 'boolean',
113
-                    'default' => false,
114
-                ),
115
-            )
116
-        );
117
-        $this->setDynamic();
118
-    }
49
+	/**
50
+	 * Perform any early setup required by the block
51
+	 * including setting the block type and supported post types
52
+	 *
53
+	 * @return void
54
+	 */
55
+	public function initialize()
56
+	{
57
+		$this->setBlockType(self::BLOCK_TYPE);
58
+		$this->setSupportedRoutes(
59
+			array(
60
+				'EventEspresso\core\domain\entities\route_match\specifications\admin\EspressoStandardPostTypeEditor',
61
+				'EventEspresso\core\domain\entities\route_match\specifications\admin\WordPressPostTypeEditor',
62
+				'EventEspresso\core\domain\entities\route_match\specifications\frontend\EspressoBlockRenderer',
63
+				'EventEspresso\core\domain\entities\route_match\specifications\frontend\AnyFrontendRequest'
64
+			)
65
+		);
66
+		$EVT_ID = $this->request->getRequestParam('page') === 'espresso_events'
67
+			? $this->request->getRequestParam('post', 0, 'int')
68
+			: 0;
69
+		$this->setAttributes(
70
+			array(
71
+				'eventId'           => array(
72
+					'type'    => 'number',
73
+					'default' => $EVT_ID,
74
+				),
75
+				'datetimeId'        => array(
76
+					'type'    => 'number',
77
+					'default' => 0,
78
+				),
79
+				'ticketId'          => array(
80
+					'type'    => 'number',
81
+					'default' => 0,
82
+				),
83
+				'status'            => array(
84
+					'type'    => 'string',
85
+					'default' => EEM_Registration::status_id_approved,
86
+				),
87
+				'limit'             => array(
88
+					'type'    => 'number',
89
+					'default' => 100,
90
+				),
91
+				'order' => array(
92
+					'type' => 'string',
93
+					'default' => 'ASC'
94
+				),
95
+				'orderBy' => array(
96
+					'type' => 'string',
97
+					'default' => 'lastThenFirstName',
98
+				),
99
+				'showGravatar'      => array(
100
+					'type'    => 'boolean',
101
+					'default' => false,
102
+				),
103
+				'avatarClass' => array(
104
+					'type' => 'string',
105
+					'default' => 'contact',
106
+				),
107
+				'avatarSize' => array(
108
+					'type' => 'number',
109
+					'default' => 24,
110
+				),
111
+				'displayOnArchives' => array(
112
+					'type'    => 'boolean',
113
+					'default' => false,
114
+				),
115
+			)
116
+		);
117
+		$this->setDynamic();
118
+	}
119 119
 
120 120
 
121
-    /**
122
-     * Returns an array where the key corresponds to the incoming attribute name from the WP block
123
-     * and the value corresponds to the attribute name for the existing EspressoEventAttendees shortcode
124
-     *
125
-     * @since 4.9.71.p
126
-     * @return array
127
-     */
128
-    private function getAttributesMap()
129
-    {
130
-        return array(
131
-            'eventId'           => 'absint',
132
-            'datetimeId'        => 'absint',
133
-            'ticketId'          => 'absint',
134
-            'status'            => 'sanitize_text_field',
135
-            'limit'             => 'intval',
136
-            'showGravatar'      => 'bool',
137
-            'avatarClass'       => 'sanitize_text_field',
138
-            'avatarSize'        => 'absint',
139
-            'displayOnArchives' => 'bool',
140
-            'order' => 'sanitize_text_field',
141
-            'orderBy' => 'sanitize_text_field',
142
-        );
143
-    }
121
+	/**
122
+	 * Returns an array where the key corresponds to the incoming attribute name from the WP block
123
+	 * and the value corresponds to the attribute name for the existing EspressoEventAttendees shortcode
124
+	 *
125
+	 * @since 4.9.71.p
126
+	 * @return array
127
+	 */
128
+	private function getAttributesMap()
129
+	{
130
+		return array(
131
+			'eventId'           => 'absint',
132
+			'datetimeId'        => 'absint',
133
+			'ticketId'          => 'absint',
134
+			'status'            => 'sanitize_text_field',
135
+			'limit'             => 'intval',
136
+			'showGravatar'      => 'bool',
137
+			'avatarClass'       => 'sanitize_text_field',
138
+			'avatarSize'        => 'absint',
139
+			'displayOnArchives' => 'bool',
140
+			'order' => 'sanitize_text_field',
141
+			'orderBy' => 'sanitize_text_field',
142
+		);
143
+	}
144 144
 
145 145
 
146
-    /**
147
-     * Sanitizes attributes.
148
-     *
149
-     * @param array $attributes
150
-     * @return array
151
-     */
152
-    private function sanitizeAttributes(array $attributes)
153
-    {
154
-        $sanitized_attributes = array();
155
-        foreach ($attributes as $attribute => $value) {
156
-            $convert = $this->getAttributesMap();
157
-            if (isset($convert[ $attribute ])) {
158
-                $sanitize = $convert[ $attribute ];
159
-                if ($sanitize === 'bool') {
160
-                    $sanitized_attributes[ $attribute ] = filter_var(
161
-                        $value,
162
-                        FILTER_VALIDATE_BOOLEAN
163
-                    );
164
-                } else {
165
-                    $sanitized_attributes[ $attribute ] = $sanitize($value);
166
-                }
167
-                // don't pass along attributes with a 0 value
168
-                if ($sanitized_attributes[ $attribute ] === 0) {
169
-                    unset($sanitized_attributes[ $attribute ]);
170
-                }
171
-            }
172
-        }
173
-        return $attributes;
174
-    }
146
+	/**
147
+	 * Sanitizes attributes.
148
+	 *
149
+	 * @param array $attributes
150
+	 * @return array
151
+	 */
152
+	private function sanitizeAttributes(array $attributes)
153
+	{
154
+		$sanitized_attributes = array();
155
+		foreach ($attributes as $attribute => $value) {
156
+			$convert = $this->getAttributesMap();
157
+			if (isset($convert[ $attribute ])) {
158
+				$sanitize = $convert[ $attribute ];
159
+				if ($sanitize === 'bool') {
160
+					$sanitized_attributes[ $attribute ] = filter_var(
161
+						$value,
162
+						FILTER_VALIDATE_BOOLEAN
163
+					);
164
+				} else {
165
+					$sanitized_attributes[ $attribute ] = $sanitize($value);
166
+				}
167
+				// don't pass along attributes with a 0 value
168
+				if ($sanitized_attributes[ $attribute ] === 0) {
169
+					unset($sanitized_attributes[ $attribute ]);
170
+				}
171
+			}
172
+		}
173
+		return $attributes;
174
+	}
175 175
 
176 176
 
177
-    /**
178
-     * Returns the rendered HTML for the block
179
-     *
180
-     * @param array $attributes
181
-     * @return string
182
-     * @throws DomainException
183
-     * @throws EE_Error
184
-     */
185
-    public function renderBlock(array $attributes = array())
186
-    {
187
-        $attributes = $this->sanitizeAttributes($attributes);
188
-        return (is_archive() || is_front_page() || is_home()) && ! $attributes['displayOnArchives']
189
-            ? ''
190
-            : $this->renderer->render($attributes);
191
-    }
177
+	/**
178
+	 * Returns the rendered HTML for the block
179
+	 *
180
+	 * @param array $attributes
181
+	 * @return string
182
+	 * @throws DomainException
183
+	 * @throws EE_Error
184
+	 */
185
+	public function renderBlock(array $attributes = array())
186
+	{
187
+		$attributes = $this->sanitizeAttributes($attributes);
188
+		return (is_archive() || is_front_page() || is_home()) && ! $attributes['displayOnArchives']
189
+			? ''
190
+			: $this->renderer->render($attributes);
191
+	}
192 192
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -154,19 +154,19 @@
 block discarded – undo
154 154
         $sanitized_attributes = array();
155 155
         foreach ($attributes as $attribute => $value) {
156 156
             $convert = $this->getAttributesMap();
157
-            if (isset($convert[ $attribute ])) {
158
-                $sanitize = $convert[ $attribute ];
157
+            if (isset($convert[$attribute])) {
158
+                $sanitize = $convert[$attribute];
159 159
                 if ($sanitize === 'bool') {
160
-                    $sanitized_attributes[ $attribute ] = filter_var(
160
+                    $sanitized_attributes[$attribute] = filter_var(
161 161
                         $value,
162 162
                         FILTER_VALIDATE_BOOLEAN
163 163
                     );
164 164
                 } else {
165
-                    $sanitized_attributes[ $attribute ] = $sanitize($value);
165
+                    $sanitized_attributes[$attribute] = $sanitize($value);
166 166
                 }
167 167
                 // don't pass along attributes with a 0 value
168
-                if ($sanitized_attributes[ $attribute ] === 0) {
169
-                    unset($sanitized_attributes[ $attribute ]);
168
+                if ($sanitized_attributes[$attribute] === 0) {
169
+                    unset($sanitized_attributes[$attribute]);
170 170
                 }
171 171
             }
172 172
         }
Please login to merge, or discard this patch.
core/domain/entities/shortcodes/EspressoTxnPage.php 1 patch
Indentation   +82 added lines, -82 removed lines patch added patch discarded remove patch
@@ -26,92 +26,92 @@
 block discarded – undo
26 26
 {
27 27
 
28 28
 
29
-    /**
30
-     * the actual shortcode tag that gets registered with WordPress
31
-     *
32
-     * @return string
33
-     */
34
-    public function getTag()
35
-    {
36
-        return 'ESPRESSO_TXN_PAGE';
37
-    }
29
+	/**
30
+	 * the actual shortcode tag that gets registered with WordPress
31
+	 *
32
+	 * @return string
33
+	 */
34
+	public function getTag()
35
+	{
36
+		return 'ESPRESSO_TXN_PAGE';
37
+	}
38 38
 
39 39
 
40
-    /**
41
-     * the time in seconds to cache the results of the processShortcode() method
42
-     * 0 means the processShortcode() results will NOT be cached at all
43
-     *
44
-     * @return int
45
-     */
46
-    public function cacheExpiration()
47
-    {
48
-        return 0;
49
-    }
40
+	/**
41
+	 * the time in seconds to cache the results of the processShortcode() method
42
+	 * 0 means the processShortcode() results will NOT be cached at all
43
+	 *
44
+	 * @return int
45
+	 */
46
+	public function cacheExpiration()
47
+	{
48
+		return 0;
49
+	}
50 50
 
51 51
 
52
-    /**
53
-     * a place for adding any initialization code that needs to run prior to wp_header().
54
-     * this may be required for shortcodes that utilize a corresponding module,
55
-     * and need to enqueue assets for that module
56
-     *
57
-     * @return void
58
-     * @throws Exception
59
-     * @throws EE_Error
60
-     */
61
-    public function initializeShortcode()
62
-    {
63
-        $transaction  = null;
64
-        $request      = LoaderFactory::getLoader()->getShared(RequestInterface::class);
65
-        $reg_url_link = $request->getRequestParam('e_reg_url_link');
66
-        if ($reg_url_link) {
67
-            /** @var EEM_Transaction $EEM_Transaction */
68
-            $EEM_Transaction = EE_Registry::instance()->load_model('Transaction');
69
-            $transaction = $EEM_Transaction->get_transaction_from_reg_url_link($reg_url_link);
70
-        }
71
-        if ($transaction instanceof EE_Transaction) {
72
-            $payment_method = null;
73
-            $payment_method_slug = $request->getRequestParam('ee_payment_method');
74
-            if ($payment_method_slug) {
75
-                $payment_method = EEM_Payment_Method::instance()->get_one_by_slug($payment_method_slug);
76
-            }
77
-            if ($payment_method instanceof EE_Payment_Method && $payment_method->is_off_site()) {
78
-                $gateway = $payment_method->type_obj()->get_gateway();
79
-                if (
80
-                    $gateway instanceof EE_Offsite_Gateway
81
-                    && $gateway->handle_IPN_in_this_request(
82
-                        $request->requestParams(),
83
-                        true
84
-                    )
85
-                ) {
86
-                    /** @type EE_Payment_Processor $payment_processor */
87
-                    $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
88
-                    /** @var RequestInterface $request */
89
-                    $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
90
-                    $payment_processor->process_ipn($request->requestParams(), $transaction, $payment_method);
91
-                }
92
-            }
93
-            // allow gateways to add a filter to stop rendering the page
94
-            if (apply_filters('FHEE__EES_Espresso_Txn_Page__run__exit', false)) {
95
-                exit;
96
-            }
97
-        }
98
-        $this->shortcodeHasBeenInitialized();
99
-    }
52
+	/**
53
+	 * a place for adding any initialization code that needs to run prior to wp_header().
54
+	 * this may be required for shortcodes that utilize a corresponding module,
55
+	 * and need to enqueue assets for that module
56
+	 *
57
+	 * @return void
58
+	 * @throws Exception
59
+	 * @throws EE_Error
60
+	 */
61
+	public function initializeShortcode()
62
+	{
63
+		$transaction  = null;
64
+		$request      = LoaderFactory::getLoader()->getShared(RequestInterface::class);
65
+		$reg_url_link = $request->getRequestParam('e_reg_url_link');
66
+		if ($reg_url_link) {
67
+			/** @var EEM_Transaction $EEM_Transaction */
68
+			$EEM_Transaction = EE_Registry::instance()->load_model('Transaction');
69
+			$transaction = $EEM_Transaction->get_transaction_from_reg_url_link($reg_url_link);
70
+		}
71
+		if ($transaction instanceof EE_Transaction) {
72
+			$payment_method = null;
73
+			$payment_method_slug = $request->getRequestParam('ee_payment_method');
74
+			if ($payment_method_slug) {
75
+				$payment_method = EEM_Payment_Method::instance()->get_one_by_slug($payment_method_slug);
76
+			}
77
+			if ($payment_method instanceof EE_Payment_Method && $payment_method->is_off_site()) {
78
+				$gateway = $payment_method->type_obj()->get_gateway();
79
+				if (
80
+					$gateway instanceof EE_Offsite_Gateway
81
+					&& $gateway->handle_IPN_in_this_request(
82
+						$request->requestParams(),
83
+						true
84
+					)
85
+				) {
86
+					/** @type EE_Payment_Processor $payment_processor */
87
+					$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
88
+					/** @var RequestInterface $request */
89
+					$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
90
+					$payment_processor->process_ipn($request->requestParams(), $transaction, $payment_method);
91
+				}
92
+			}
93
+			// allow gateways to add a filter to stop rendering the page
94
+			if (apply_filters('FHEE__EES_Espresso_Txn_Page__run__exit', false)) {
95
+				exit;
96
+			}
97
+		}
98
+		$this->shortcodeHasBeenInitialized();
99
+	}
100 100
 
101 101
 
102
-    /**
103
-     * callback that runs when the shortcode is encountered in post content.
104
-     * IMPORTANT !!!
105
-     * remember that shortcode content should be RETURNED and NOT echoed out
106
-     *
107
-     * @param array $attributes
108
-     * @return string
109
-     */
110
-    public function processShortcode($attributes = array())
111
-    {
112
-        return esc_html__(
113
-            'This is the Event Espresso Transactions page. This page receives instant payment notification (IPN) requests and should have a status of published, but should not be easily accessible by site visitors. Do not add it to your website\'s navigation menu or link to it from another page. Also, do not delete it or change its status to private.',
114
-            'event_espresso'
115
-        );
116
-    }
102
+	/**
103
+	 * callback that runs when the shortcode is encountered in post content.
104
+	 * IMPORTANT !!!
105
+	 * remember that shortcode content should be RETURNED and NOT echoed out
106
+	 *
107
+	 * @param array $attributes
108
+	 * @return string
109
+	 */
110
+	public function processShortcode($attributes = array())
111
+	{
112
+		return esc_html__(
113
+			'This is the Event Espresso Transactions page. This page receives instant payment notification (IPN) requests and should have a status of published, but should not be easily accessible by site visitors. Do not add it to your website\'s navigation menu or link to it from another page. Also, do not delete it or change its status to private.',
114
+			'event_espresso'
115
+		);
116
+	}
117 117
 }
Please login to merge, or discard this patch.
core/domain/entities/custom_post_types/CustomPostTypeDefinitions.php 2 patches
Indentation   +264 added lines, -264 removed lines patch added patch discarded remove patch
@@ -17,288 +17,288 @@
 block discarded – undo
17 17
 class CustomPostTypeDefinitions
18 18
 {
19 19
 
20
-    /**
21
-     * @var EE_Core_Config
22
-     */
23
-    public $core_config;
20
+	/**
21
+	 * @var EE_Core_Config
22
+	 */
23
+	public $core_config;
24 24
 
25
-    /**
26
-     * @var array $custom_post_types
27
-     */
28
-    private $custom_post_types;
25
+	/**
26
+	 * @var array $custom_post_types
27
+	 */
28
+	private $custom_post_types;
29 29
 
30
-    /**
31
-     * @var LoaderInterface $loader
32
-     */
33
-    private $loader;
30
+	/**
31
+	 * @var LoaderInterface $loader
32
+	 */
33
+	private $loader;
34 34
 
35 35
 
36
-    /**
37
-     * EspressoCustomPostTypeDefinitions constructor.
38
-     *
39
-     * @param EE_Core_Config  $core_config
40
-     * @param LoaderInterface $loader
41
-     */
42
-    public function __construct(EE_Core_Config $core_config, LoaderInterface $loader)
43
-    {
44
-        $this->core_config = $core_config;
45
-        $this->loader = $loader;
46
-        $this->setDefinitions();
47
-    }
36
+	/**
37
+	 * EspressoCustomPostTypeDefinitions constructor.
38
+	 *
39
+	 * @param EE_Core_Config  $core_config
40
+	 * @param LoaderInterface $loader
41
+	 */
42
+	public function __construct(EE_Core_Config $core_config, LoaderInterface $loader)
43
+	{
44
+		$this->core_config = $core_config;
45
+		$this->loader = $loader;
46
+		$this->setDefinitions();
47
+	}
48 48
 
49 49
 
50
-    /**
51
-     * defines Espresso Custom Post Types
52
-     * NOTE the ['args']['page_templates'] array index is something specific to our CPTs
53
-     * and not part of the WP custom post type api.
54
-     *
55
-     * @return void
56
-     */
57
-    private function setDefinitions()
58
-    {
59
-        $this->custom_post_types = array(
60
-            'espresso_events'    => array(
61
-                'singular_name' => esc_html__('Event', 'event_espresso'),
62
-                'plural_name'   => esc_html__('Events', 'event_espresso'),
63
-                'singular_slug' => esc_html__('event', 'event_espresso'),
64
-                'plural_slug'   => $this->core_config->event_cpt_slug,
65
-                'class_name'    => 'EE_Event',
66
-                'model_name'    => 'EEM_Event',
67
-                'args'          => array(
68
-                    'public'            => true,
69
-                    'show_in_nav_menus' => true,
70
-                    'capability_type'   => 'event',
71
-                    'capabilities'      => array(
72
-                        'edit_post'              => 'ee_edit_event',
73
-                        'read_post'              => 'ee_read_event',
74
-                        'delete_post'            => 'ee_delete_event',
75
-                        'edit_posts'             => 'ee_edit_events',
76
-                        'edit_others_posts'      => 'ee_edit_others_events',
77
-                        'publish_posts'          => 'ee_publish_events',
78
-                        'read_private_posts'     => 'ee_read_private_events',
79
-                        'delete_posts'           => 'ee_delete_events',
80
-                        'delete_private_posts'   => 'ee_delete_private_events',
81
-                        'delete_published_posts' => 'ee_delete_published_events',
82
-                        'delete_others_posts'    => 'ee_delete_others_events',
83
-                        'edit_private_posts'     => 'ee_edit_private_events',
84
-                        'edit_published_posts'   => 'ee_edit_published_events',
85
-                    ),
86
-                    'taxonomies'        => array(
87
-                        'espresso_event_categories',
88
-                        'espresso_event_type',
89
-                        'post_tag',
90
-                    ),
91
-                    'page_templates'    => true,
92
-                ),
93
-            ),
94
-            'espresso_venues'    => array(
95
-                'singular_name' => esc_html__('Venue', 'event_espresso'),
96
-                'plural_name'   => esc_html__('Venues', 'event_espresso'),
97
-                'singular_slug' => esc_html__('venue', 'event_espresso'),
98
-                'plural_slug'   => esc_html__('venues', 'event_espresso'),
99
-                'class_name'    => 'EE_Venue',
100
-                'model_name'    => 'EEM_Venue',
101
-                'args'          => array(
102
-                    'public'            => true,
103
-                    'show_in_nav_menus' => false, // by default this doesn't show for decaf,
104
-                    'capability_type'   => 'venue',
105
-                    'capabilities'      => array(
106
-                        'edit_post'              => 'ee_edit_venue',
107
-                        'read_post'              => 'ee_read_venue',
108
-                        'delete_post'            => 'ee_delete_venue',
109
-                        'edit_posts'             => 'ee_edit_venues',
110
-                        'edit_others_posts'      => 'ee_edit_others_venues',
111
-                        'publish_posts'          => 'ee_publish_venues',
112
-                        'read_private_posts'     => 'ee_read_private_venues',
113
-                        'delete_posts'           => 'ee_delete_venues',
114
-                        'delete_private_posts'   => 'ee_delete_private_venues',
115
-                        'delete_published_posts' => 'ee_delete_published_venues',
116
-                        'delete_others_posts'    => 'ee_edit_others_venues',
117
-                        'edit_private_posts'     => 'ee_edit_private_venues',
118
-                        'edit_published_posts'   => 'ee_edit_published_venues',
119
-                    ),
120
-                    'taxonomies'        => array(
121
-                        'espresso_venue_categories',
122
-                        'post_tag',
123
-                    ),
124
-                    'page_templates'    => true,
125
-                ),
126
-            ),
127
-            'espresso_attendees' => array(
128
-                'singular_name' => esc_html__('Contact', 'event_espresso'),
129
-                'plural_name'   => esc_html__('Contacts', 'event_espresso'),
130
-                'singular_slug' => esc_html__('contact', 'event_espresso'),
131
-                'plural_slug'   => esc_html__('contacts', 'event_espresso'),
132
-                'class_name'    => 'EE_Attendee',
133
-                'model_name'    => 'EEM_Attendee',
134
-                'args'          => array(
135
-                    'public'             => false,
136
-                    'publicly_queryable' => false,
137
-                    'hierarchical'       => false,
138
-                    'has_archive'        => false,
139
-                    'supports'           => array(
140
-                        'editor',
141
-                        'thumbnail',
142
-                        'excerpt',
143
-                        'custom-fields',
144
-                        'comments',
145
-                    ),
146
-                    'taxonomies'         => array('post_tag'),
147
-                    'capability_type'    => 'contact',
148
-                    'capabilities'       => array(
149
-                        'edit_post'              => 'ee_edit_contact',
150
-                        'read_post'              => 'ee_read_contact',
151
-                        'delete_post'            => 'ee_delete_contact',
152
-                        'edit_posts'             => 'ee_edit_contacts',
153
-                        'edit_others_posts'      => 'ee_edit_contacts',
154
-                        'publish_posts'          => 'ee_edit_contacts',
155
-                        'read_private_posts'     => 'ee_edit_contacts',
156
-                        'delete_posts'           => 'ee_delete_contacts',
157
-                        'delete_private_posts'   => 'ee_delete_contacts',
158
-                        'delete_published_posts' => 'ee_delete_contacts',
159
-                        'delete_others_posts'    => 'ee_delete_contacts',
160
-                        'edit_private_posts'     => 'ee_edit_contacts',
161
-                        'edit_published_posts'   => 'ee_edit_contacts',
162
-                    ),
163
-                ),
164
-            ),
165
-        );
166
-    }
50
+	/**
51
+	 * defines Espresso Custom Post Types
52
+	 * NOTE the ['args']['page_templates'] array index is something specific to our CPTs
53
+	 * and not part of the WP custom post type api.
54
+	 *
55
+	 * @return void
56
+	 */
57
+	private function setDefinitions()
58
+	{
59
+		$this->custom_post_types = array(
60
+			'espresso_events'    => array(
61
+				'singular_name' => esc_html__('Event', 'event_espresso'),
62
+				'plural_name'   => esc_html__('Events', 'event_espresso'),
63
+				'singular_slug' => esc_html__('event', 'event_espresso'),
64
+				'plural_slug'   => $this->core_config->event_cpt_slug,
65
+				'class_name'    => 'EE_Event',
66
+				'model_name'    => 'EEM_Event',
67
+				'args'          => array(
68
+					'public'            => true,
69
+					'show_in_nav_menus' => true,
70
+					'capability_type'   => 'event',
71
+					'capabilities'      => array(
72
+						'edit_post'              => 'ee_edit_event',
73
+						'read_post'              => 'ee_read_event',
74
+						'delete_post'            => 'ee_delete_event',
75
+						'edit_posts'             => 'ee_edit_events',
76
+						'edit_others_posts'      => 'ee_edit_others_events',
77
+						'publish_posts'          => 'ee_publish_events',
78
+						'read_private_posts'     => 'ee_read_private_events',
79
+						'delete_posts'           => 'ee_delete_events',
80
+						'delete_private_posts'   => 'ee_delete_private_events',
81
+						'delete_published_posts' => 'ee_delete_published_events',
82
+						'delete_others_posts'    => 'ee_delete_others_events',
83
+						'edit_private_posts'     => 'ee_edit_private_events',
84
+						'edit_published_posts'   => 'ee_edit_published_events',
85
+					),
86
+					'taxonomies'        => array(
87
+						'espresso_event_categories',
88
+						'espresso_event_type',
89
+						'post_tag',
90
+					),
91
+					'page_templates'    => true,
92
+				),
93
+			),
94
+			'espresso_venues'    => array(
95
+				'singular_name' => esc_html__('Venue', 'event_espresso'),
96
+				'plural_name'   => esc_html__('Venues', 'event_espresso'),
97
+				'singular_slug' => esc_html__('venue', 'event_espresso'),
98
+				'plural_slug'   => esc_html__('venues', 'event_espresso'),
99
+				'class_name'    => 'EE_Venue',
100
+				'model_name'    => 'EEM_Venue',
101
+				'args'          => array(
102
+					'public'            => true,
103
+					'show_in_nav_menus' => false, // by default this doesn't show for decaf,
104
+					'capability_type'   => 'venue',
105
+					'capabilities'      => array(
106
+						'edit_post'              => 'ee_edit_venue',
107
+						'read_post'              => 'ee_read_venue',
108
+						'delete_post'            => 'ee_delete_venue',
109
+						'edit_posts'             => 'ee_edit_venues',
110
+						'edit_others_posts'      => 'ee_edit_others_venues',
111
+						'publish_posts'          => 'ee_publish_venues',
112
+						'read_private_posts'     => 'ee_read_private_venues',
113
+						'delete_posts'           => 'ee_delete_venues',
114
+						'delete_private_posts'   => 'ee_delete_private_venues',
115
+						'delete_published_posts' => 'ee_delete_published_venues',
116
+						'delete_others_posts'    => 'ee_edit_others_venues',
117
+						'edit_private_posts'     => 'ee_edit_private_venues',
118
+						'edit_published_posts'   => 'ee_edit_published_venues',
119
+					),
120
+					'taxonomies'        => array(
121
+						'espresso_venue_categories',
122
+						'post_tag',
123
+					),
124
+					'page_templates'    => true,
125
+				),
126
+			),
127
+			'espresso_attendees' => array(
128
+				'singular_name' => esc_html__('Contact', 'event_espresso'),
129
+				'plural_name'   => esc_html__('Contacts', 'event_espresso'),
130
+				'singular_slug' => esc_html__('contact', 'event_espresso'),
131
+				'plural_slug'   => esc_html__('contacts', 'event_espresso'),
132
+				'class_name'    => 'EE_Attendee',
133
+				'model_name'    => 'EEM_Attendee',
134
+				'args'          => array(
135
+					'public'             => false,
136
+					'publicly_queryable' => false,
137
+					'hierarchical'       => false,
138
+					'has_archive'        => false,
139
+					'supports'           => array(
140
+						'editor',
141
+						'thumbnail',
142
+						'excerpt',
143
+						'custom-fields',
144
+						'comments',
145
+					),
146
+					'taxonomies'         => array('post_tag'),
147
+					'capability_type'    => 'contact',
148
+					'capabilities'       => array(
149
+						'edit_post'              => 'ee_edit_contact',
150
+						'read_post'              => 'ee_read_contact',
151
+						'delete_post'            => 'ee_delete_contact',
152
+						'edit_posts'             => 'ee_edit_contacts',
153
+						'edit_others_posts'      => 'ee_edit_contacts',
154
+						'publish_posts'          => 'ee_edit_contacts',
155
+						'read_private_posts'     => 'ee_edit_contacts',
156
+						'delete_posts'           => 'ee_delete_contacts',
157
+						'delete_private_posts'   => 'ee_delete_contacts',
158
+						'delete_published_posts' => 'ee_delete_contacts',
159
+						'delete_others_posts'    => 'ee_delete_contacts',
160
+						'edit_private_posts'     => 'ee_edit_contacts',
161
+						'edit_published_posts'   => 'ee_edit_contacts',
162
+					),
163
+				),
164
+			),
165
+		);
166
+	}
167 167
 
168 168
 
169
-    /**
170
-     * @return array
171
-     */
172
-    public function getDefinitions()
173
-    {
174
-        return (array) apply_filters(
175
-            'FHEE__EventEspresso_core_domain_entities_custom_post_types_CustomPostTypeDefinitions__getCustomPostTypes',
176
-            // legacy filter applied for now,
177
-            // later on we'll run a has_filter($tag) check and throw a doing_it_wrong() notice
178
-            apply_filters(
179
-                'FHEE__EE_Register_CPTs__get_CPTs__cpts',
180
-                $this->custom_post_types
181
-            )
182
-        );
183
-    }
169
+	/**
170
+	 * @return array
171
+	 */
172
+	public function getDefinitions()
173
+	{
174
+		return (array) apply_filters(
175
+			'FHEE__EventEspresso_core_domain_entities_custom_post_types_CustomPostTypeDefinitions__getCustomPostTypes',
176
+			// legacy filter applied for now,
177
+			// later on we'll run a has_filter($tag) check and throw a doing_it_wrong() notice
178
+			apply_filters(
179
+				'FHEE__EE_Register_CPTs__get_CPTs__cpts',
180
+				$this->custom_post_types
181
+			)
182
+		);
183
+	}
184 184
 
185 185
 
186
-    /**
187
-     * @return array
188
-     */
189
-    public function getCustomPostTypeSlugs()
190
-    {
191
-        return array_keys($this->getDefinitions());
192
-    }
186
+	/**
187
+	 * @return array
188
+	 */
189
+	public function getCustomPostTypeSlugs()
190
+	{
191
+		return array_keys($this->getDefinitions());
192
+	}
193 193
 
194 194
 
195
-    /**
196
-     * This basically goes through the CPT array and returns only CPT's
197
-     * that have the ['args']['public'] option set as false
198
-     *
199
-     * @return array
200
-     */
201
-    public function getPrivateCustomPostTypes()
202
-    {
203
-        $private_CPTs = array();
204
-        foreach ($this->getDefinitions() as $CPT => $details) {
205
-            if (empty($details['args']['public'])) {
206
-                $private_CPTs[ $CPT ] = $details;
207
-            }
208
-        }
209
-        return $private_CPTs;
210
-    }
195
+	/**
196
+	 * This basically goes through the CPT array and returns only CPT's
197
+	 * that have the ['args']['public'] option set as false
198
+	 *
199
+	 * @return array
200
+	 */
201
+	public function getPrivateCustomPostTypes()
202
+	{
203
+		$private_CPTs = array();
204
+		foreach ($this->getDefinitions() as $CPT => $details) {
205
+			if (empty($details['args']['public'])) {
206
+				$private_CPTs[ $CPT ] = $details;
207
+			}
208
+		}
209
+		return $private_CPTs;
210
+	}
211 211
 
212 212
 
213
-    /**
214
-     * This returns the corresponding model name for cpts registered by EE.
215
-     *
216
-     * @param string $post_type_slug    If a slug is included, then attempt to retrieve
217
-     *                                  the model name for the given cpt slug.
218
-     *                                  Otherwise if empty, then we'll return
219
-     *                                  all cpt model names for cpts registered in EE.
220
-     * @return array                    Empty array if no matching model names for the given slug
221
-     *                                  or an array of model names indexed by post type slug.
222
-     */
223
-    public function getCustomPostTypeModelNames($post_type_slug = '')
224
-    {
225
-        $cpts = $this->getDefinitions();
226
-        // first if slug passed in...
227
-        if (! empty($post_type_slug)) {
228
-            // check that slug and cpt match
229
-            if (! isset($cpts[ $post_type_slug ])) {
230
-                return array();
231
-            }
232
-            if (
233
-                empty($cpts[ $post_type_slug ]['class_name'])
234
-                && empty($cpts[ $post_type_slug ]['model_name'])
235
-            ) {
236
-                return array();
237
-            }
238
-            // k let's get the model name for this cpt.
239
-            return $this->getCustomPostTypeModelName($post_type_slug, $cpts[ $post_type_slug ]);
240
-        }
241
-        // if we made it here then we're returning an array of cpt model names indexed by post_type_slug.
242
-        $cpt_models = array();
243
-        foreach ($cpts as $slug => $args) {
244
-            $model = $this->getCustomPostTypeModelName($post_type_slug, $cpts[ $post_type_slug ]);
245
-            if (! empty($model)) {
246
-                $cpt_models[ $slug ] = $model;
247
-            }
248
-        }
249
-        return $cpt_models;
250
-    }
213
+	/**
214
+	 * This returns the corresponding model name for cpts registered by EE.
215
+	 *
216
+	 * @param string $post_type_slug    If a slug is included, then attempt to retrieve
217
+	 *                                  the model name for the given cpt slug.
218
+	 *                                  Otherwise if empty, then we'll return
219
+	 *                                  all cpt model names for cpts registered in EE.
220
+	 * @return array                    Empty array if no matching model names for the given slug
221
+	 *                                  or an array of model names indexed by post type slug.
222
+	 */
223
+	public function getCustomPostTypeModelNames($post_type_slug = '')
224
+	{
225
+		$cpts = $this->getDefinitions();
226
+		// first if slug passed in...
227
+		if (! empty($post_type_slug)) {
228
+			// check that slug and cpt match
229
+			if (! isset($cpts[ $post_type_slug ])) {
230
+				return array();
231
+			}
232
+			if (
233
+				empty($cpts[ $post_type_slug ]['class_name'])
234
+				&& empty($cpts[ $post_type_slug ]['model_name'])
235
+			) {
236
+				return array();
237
+			}
238
+			// k let's get the model name for this cpt.
239
+			return $this->getCustomPostTypeModelName($post_type_slug, $cpts[ $post_type_slug ]);
240
+		}
241
+		// if we made it here then we're returning an array of cpt model names indexed by post_type_slug.
242
+		$cpt_models = array();
243
+		foreach ($cpts as $slug => $args) {
244
+			$model = $this->getCustomPostTypeModelName($post_type_slug, $cpts[ $post_type_slug ]);
245
+			if (! empty($model)) {
246
+				$cpt_models[ $slug ] = $model;
247
+			}
248
+		}
249
+		return $cpt_models;
250
+	}
251 251
 
252 252
 
253
-    /**
254
-     * @param       $post_type_slug
255
-     * @param array $cpt
256
-     * @return array
257
-     */
258
-    private function getCustomPostTypeModelName($post_type_slug, array $cpt)
259
-    {
260
-        if (! empty($cpt['model_name'])) {
261
-            return array($post_type_slug => $cpt['model_name']);
262
-        }
263
-        if (! empty($cpt['class_name'])) {
264
-            return array(
265
-                $post_type_slug => $this->deriveCptModelNameFromClassName($cpt['class_name']),
266
-            );
267
-        }
268
-        return array();
269
-    }
253
+	/**
254
+	 * @param       $post_type_slug
255
+	 * @param array $cpt
256
+	 * @return array
257
+	 */
258
+	private function getCustomPostTypeModelName($post_type_slug, array $cpt)
259
+	{
260
+		if (! empty($cpt['model_name'])) {
261
+			return array($post_type_slug => $cpt['model_name']);
262
+		}
263
+		if (! empty($cpt['class_name'])) {
264
+			return array(
265
+				$post_type_slug => $this->deriveCptModelNameFromClassName($cpt['class_name']),
266
+			);
267
+		}
268
+		return array();
269
+	}
270 270
 
271 271
 
272
-    /**
273
-     * @param string $class_name
274
-     * @return string
275
-     */
276
-    private function deriveCptModelNameFromClassName($class_name)
277
-    {
278
-        return str_replace('EE', 'EEM', $class_name);
279
-    }
272
+	/**
273
+	 * @param string $class_name
274
+	 * @return string
275
+	 */
276
+	private function deriveCptModelNameFromClassName($class_name)
277
+	{
278
+		return str_replace('EE', 'EEM', $class_name);
279
+	}
280 280
 
281 281
 
282
-    /**
283
-     * This instantiates cpt models related to the cpts registered via EE.
284
-     *
285
-     * @since 4.6.16.rc.000
286
-     * @param string $post_type_slug If valid slug is provided, then will instantiate the model only for
287
-     *                               the cpt matching the given slug.  Otherwise all cpt models will be
288
-     *                               instantiated (if possible).
289
-     * @return EEM_CPT_Base[]        successful instantiation will return an array of successfully instantiated
290
-     *                               EEM models indexed by post slug.
291
-     */
292
-    public function getCustomPostTypeModels($post_type_slug = '')
293
-    {
294
-        $cpt_model_names = $this->getCustomPostTypeModelNames($post_type_slug);
295
-        $instantiated = array();
296
-        foreach ($cpt_model_names as $slug => $model_name) {
297
-            $model = $this->loader->getShared($model_name);
298
-            if ($model instanceof EEM_CPT_Base) {
299
-                $instantiated[ $slug ] = $model;
300
-            }
301
-        }
302
-        return $instantiated;
303
-    }
282
+	/**
283
+	 * This instantiates cpt models related to the cpts registered via EE.
284
+	 *
285
+	 * @since 4.6.16.rc.000
286
+	 * @param string $post_type_slug If valid slug is provided, then will instantiate the model only for
287
+	 *                               the cpt matching the given slug.  Otherwise all cpt models will be
288
+	 *                               instantiated (if possible).
289
+	 * @return EEM_CPT_Base[]        successful instantiation will return an array of successfully instantiated
290
+	 *                               EEM models indexed by post slug.
291
+	 */
292
+	public function getCustomPostTypeModels($post_type_slug = '')
293
+	{
294
+		$cpt_model_names = $this->getCustomPostTypeModelNames($post_type_slug);
295
+		$instantiated = array();
296
+		foreach ($cpt_model_names as $slug => $model_name) {
297
+			$model = $this->loader->getShared($model_name);
298
+			if ($model instanceof EEM_CPT_Base) {
299
+				$instantiated[ $slug ] = $model;
300
+			}
301
+		}
302
+		return $instantiated;
303
+	}
304 304
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -203,7 +203,7 @@  discard block
 block discarded – undo
203 203
         $private_CPTs = array();
204 204
         foreach ($this->getDefinitions() as $CPT => $details) {
205 205
             if (empty($details['args']['public'])) {
206
-                $private_CPTs[ $CPT ] = $details;
206
+                $private_CPTs[$CPT] = $details;
207 207
             }
208 208
         }
209 209
         return $private_CPTs;
@@ -224,26 +224,26 @@  discard block
 block discarded – undo
224 224
     {
225 225
         $cpts = $this->getDefinitions();
226 226
         // first if slug passed in...
227
-        if (! empty($post_type_slug)) {
227
+        if ( ! empty($post_type_slug)) {
228 228
             // check that slug and cpt match
229
-            if (! isset($cpts[ $post_type_slug ])) {
229
+            if ( ! isset($cpts[$post_type_slug])) {
230 230
                 return array();
231 231
             }
232 232
             if (
233
-                empty($cpts[ $post_type_slug ]['class_name'])
234
-                && empty($cpts[ $post_type_slug ]['model_name'])
233
+                empty($cpts[$post_type_slug]['class_name'])
234
+                && empty($cpts[$post_type_slug]['model_name'])
235 235
             ) {
236 236
                 return array();
237 237
             }
238 238
             // k let's get the model name for this cpt.
239
-            return $this->getCustomPostTypeModelName($post_type_slug, $cpts[ $post_type_slug ]);
239
+            return $this->getCustomPostTypeModelName($post_type_slug, $cpts[$post_type_slug]);
240 240
         }
241 241
         // if we made it here then we're returning an array of cpt model names indexed by post_type_slug.
242 242
         $cpt_models = array();
243 243
         foreach ($cpts as $slug => $args) {
244
-            $model = $this->getCustomPostTypeModelName($post_type_slug, $cpts[ $post_type_slug ]);
245
-            if (! empty($model)) {
246
-                $cpt_models[ $slug ] = $model;
244
+            $model = $this->getCustomPostTypeModelName($post_type_slug, $cpts[$post_type_slug]);
245
+            if ( ! empty($model)) {
246
+                $cpt_models[$slug] = $model;
247 247
             }
248 248
         }
249 249
         return $cpt_models;
@@ -257,10 +257,10 @@  discard block
 block discarded – undo
257 257
      */
258 258
     private function getCustomPostTypeModelName($post_type_slug, array $cpt)
259 259
     {
260
-        if (! empty($cpt['model_name'])) {
260
+        if ( ! empty($cpt['model_name'])) {
261 261
             return array($post_type_slug => $cpt['model_name']);
262 262
         }
263
-        if (! empty($cpt['class_name'])) {
263
+        if ( ! empty($cpt['class_name'])) {
264 264
             return array(
265 265
                 $post_type_slug => $this->deriveCptModelNameFromClassName($cpt['class_name']),
266 266
             );
@@ -296,7 +296,7 @@  discard block
 block discarded – undo
296 296
         foreach ($cpt_model_names as $slug => $model_name) {
297 297
             $model = $this->loader->getShared($model_name);
298 298
             if ($model instanceof EEM_CPT_Base) {
299
-                $instantiated[ $slug ] = $model;
299
+                $instantiated[$slug] = $model;
300 300
             }
301 301
         }
302 302
         return $instantiated;
Please login to merge, or discard this patch.
strategies/EE_Restriction_Generator_Default_Protected.strategy.php 2 patches
Indentation   +75 added lines, -75 removed lines patch added patch discarded remove patch
@@ -17,85 +17,85 @@
 block discarded – undo
17 17
  */
18 18
 class EE_Restriction_Generator_Default_Protected extends EE_Restriction_Generator_Base
19 19
 {
20
-    /**
21
-     * Name of the field on this model (or a related model, including the model chain to it)
22
-     * that is a boolean indicating whether or not a model object is considered "Default" or not
23
-     * @var string
24
-     */
25
-    protected $_default_field_name;
20
+	/**
21
+	 * Name of the field on this model (or a related model, including the model chain to it)
22
+	 * that is a boolean indicating whether or not a model object is considered "Default" or not
23
+	 * @var string
24
+	 */
25
+	protected $_default_field_name;
26 26
 
27
-    /**
28
-     * The model chain to follow to get to the event model, including the event model itself.
29
-     * Eg 'Ticket.Datetime.Event'
30
-     * @var string
31
-     */
32
-    protected $_path_to_event_model;
33
-    /**
34
-     *
35
-     * @param string $default_field_name the name of the field Name of the field on this model (or a related model, including the model chain to it)
36
-     * that is a boolean indicating whether or not a model object is considered "Default" or not
37
-     * @param string $path_to_event_model The model chain to follow to get to the event model, including the event model itself.
38
-     * Eg 'Ticket.Datetime.Event'
39
-     */
40
-    public function __construct($default_field_name, $path_to_event_model)
41
-    {
42
-        $this->_default_field_name = $default_field_name;
43
-        if (substr($path_to_event_model, -1, 1) != '.') {
44
-            $path_to_event_model .= '.';
45
-        }
46
-        $this->_path_to_event_model = $path_to_event_model;
47
-    }
27
+	/**
28
+	 * The model chain to follow to get to the event model, including the event model itself.
29
+	 * Eg 'Ticket.Datetime.Event'
30
+	 * @var string
31
+	 */
32
+	protected $_path_to_event_model;
33
+	/**
34
+	 *
35
+	 * @param string $default_field_name the name of the field Name of the field on this model (or a related model, including the model chain to it)
36
+	 * that is a boolean indicating whether or not a model object is considered "Default" or not
37
+	 * @param string $path_to_event_model The model chain to follow to get to the event model, including the event model itself.
38
+	 * Eg 'Ticket.Datetime.Event'
39
+	 */
40
+	public function __construct($default_field_name, $path_to_event_model)
41
+	{
42
+		$this->_default_field_name = $default_field_name;
43
+		if (substr($path_to_event_model, -1, 1) != '.') {
44
+			$path_to_event_model .= '.';
45
+		}
46
+		$this->_path_to_event_model = $path_to_event_model;
47
+	}
48 48
 
49 49
 
50 50
 
51
-    /**
52
-     *
53
-     * @return \EE_Default_Where_Conditions
54
-     */
55
-    protected function _generate_restrictions()
56
-    {
57
-        // if there are no standard caps for this model, then for now all we know is
58
-        // if they need the default cap to access this
59
-        if (! $this->model()->cap_slug()) {
60
-            return array(
61
-                self::get_default_restrictions_cap() => new EE_Return_None_Where_Conditions()
62
-            );
63
-        }
51
+	/**
52
+	 *
53
+	 * @return \EE_Default_Where_Conditions
54
+	 */
55
+	protected function _generate_restrictions()
56
+	{
57
+		// if there are no standard caps for this model, then for now all we know is
58
+		// if they need the default cap to access this
59
+		if (! $this->model()->cap_slug()) {
60
+			return array(
61
+				self::get_default_restrictions_cap() => new EE_Return_None_Where_Conditions()
62
+			);
63
+		}
64 64
 
65
-        $event_model = EEM_Event::instance();
65
+		$event_model = EEM_Event::instance();
66 66
 
67
-        $restrictions =  array(
68
-            // first: basically access to non-defaults is essentially controlled by which events are accessible
69
-            // if they don't have the basic event cap, they can't access ANY non-default items
70
-            EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action()) => new EE_Default_Where_Conditions(array( $this->_default_field_name => true )),
71
-            // if they don't have the others event cap, they can't access others' non-default items
72
-            EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_others') => new EE_Default_Where_Conditions(array(
73
-                'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_others') => array(
74
-                    $this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder ),
75
-                    $this->_default_field_name => true )),
76
-            // if they have basic and others, but not private, they can't access others' private non-default items
77
-            EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_private') => new EE_Default_Where_Conditions(array(
78
-                'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_private') => array(
79
-                $this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder,
80
-                $this->_path_to_event_model . 'status' => array( '!=', 'private' ),
81
-                $this->_default_field_name => true ) )),
82
-            // second: access to defaults is controlled by the defaulty capabilities
83
-            // if they don't have the default capability, restrict access to only non-default items
84
-            EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_default') => new EE_Default_Where_Conditions(array( $this->_default_field_name => false )),
85
-            // if they don't have the "others" default capability, restrict access to only their default ones, and non-default ones
86
-             );
87
-        if (EE_Restriction_Generator_Base::is_cap($this->model(), $this->action() . '_others_default')) {
88
-            $restrictions[ EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_others_default') ] = new EE_Default_Where_Conditions(array(
89
-                    // if they don't have the others default cap, they can't access others default items (but they can access
90
-                    // their own default items, and non-default items)
91
-                    'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_others_default') => array(
92
-                        'AND' => array(
93
-                            $this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder,
94
-                            $this->_default_field_name => true
95
-                            ),
96
-                        $this->_default_field_name => false
97
-                    ) ));
98
-        }
99
-        return $restrictions;
100
-    }
67
+		$restrictions =  array(
68
+			// first: basically access to non-defaults is essentially controlled by which events are accessible
69
+			// if they don't have the basic event cap, they can't access ANY non-default items
70
+			EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action()) => new EE_Default_Where_Conditions(array( $this->_default_field_name => true )),
71
+			// if they don't have the others event cap, they can't access others' non-default items
72
+			EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_others') => new EE_Default_Where_Conditions(array(
73
+				'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_others') => array(
74
+					$this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder ),
75
+					$this->_default_field_name => true )),
76
+			// if they have basic and others, but not private, they can't access others' private non-default items
77
+			EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_private') => new EE_Default_Where_Conditions(array(
78
+				'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_private') => array(
79
+				$this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder,
80
+				$this->_path_to_event_model . 'status' => array( '!=', 'private' ),
81
+				$this->_default_field_name => true ) )),
82
+			// second: access to defaults is controlled by the defaulty capabilities
83
+			// if they don't have the default capability, restrict access to only non-default items
84
+			EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_default') => new EE_Default_Where_Conditions(array( $this->_default_field_name => false )),
85
+			// if they don't have the "others" default capability, restrict access to only their default ones, and non-default ones
86
+			 );
87
+		if (EE_Restriction_Generator_Base::is_cap($this->model(), $this->action() . '_others_default')) {
88
+			$restrictions[ EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_others_default') ] = new EE_Default_Where_Conditions(array(
89
+					// if they don't have the others default cap, they can't access others default items (but they can access
90
+					// their own default items, and non-default items)
91
+					'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_others_default') => array(
92
+						'AND' => array(
93
+							$this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder,
94
+							$this->_default_field_name => true
95
+							),
96
+						$this->_default_field_name => false
97
+					) ));
98
+		}
99
+		return $restrictions;
100
+	}
101 101
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -56,7 +56,7 @@  discard block
 block discarded – undo
56 56
     {
57 57
         // if there are no standard caps for this model, then for now all we know is
58 58
         // if they need the default cap to access this
59
-        if (! $this->model()->cap_slug()) {
59
+        if ( ! $this->model()->cap_slug()) {
60 60
             return array(
61 61
                 self::get_default_restrictions_cap() => new EE_Return_None_Where_Conditions()
62 62
             );
@@ -64,33 +64,33 @@  discard block
 block discarded – undo
64 64
 
65 65
         $event_model = EEM_Event::instance();
66 66
 
67
-        $restrictions =  array(
67
+        $restrictions = array(
68 68
             // first: basically access to non-defaults is essentially controlled by which events are accessible
69 69
             // if they don't have the basic event cap, they can't access ANY non-default items
70
-            EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action()) => new EE_Default_Where_Conditions(array( $this->_default_field_name => true )),
70
+            EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action()) => new EE_Default_Where_Conditions(array($this->_default_field_name => true)),
71 71
             // if they don't have the others event cap, they can't access others' non-default items
72
-            EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_others') => new EE_Default_Where_Conditions(array(
73
-                'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_others') => array(
74
-                    $this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder ),
72
+            EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action().'_others') => new EE_Default_Where_Conditions(array(
73
+                'OR*no_'.EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action().'_others') => array(
74
+                    $this->_path_to_event_model.'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder ),
75 75
                     $this->_default_field_name => true )),
76 76
             // if they have basic and others, but not private, they can't access others' private non-default items
77
-            EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_private') => new EE_Default_Where_Conditions(array(
78
-                'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_private') => array(
79
-                $this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder,
80
-                $this->_path_to_event_model . 'status' => array( '!=', 'private' ),
77
+            EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action().'_private') => new EE_Default_Where_Conditions(array(
78
+                'OR*no_'.EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action().'_private') => array(
79
+                $this->_path_to_event_model.'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder,
80
+                $this->_path_to_event_model.'status' => array('!=', 'private'),
81 81
                 $this->_default_field_name => true ) )),
82 82
             // second: access to defaults is controlled by the defaulty capabilities
83 83
             // if they don't have the default capability, restrict access to only non-default items
84
-            EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_default') => new EE_Default_Where_Conditions(array( $this->_default_field_name => false )),
84
+            EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action().'_default') => new EE_Default_Where_Conditions(array($this->_default_field_name => false)),
85 85
             // if they don't have the "others" default capability, restrict access to only their default ones, and non-default ones
86 86
              );
87
-        if (EE_Restriction_Generator_Base::is_cap($this->model(), $this->action() . '_others_default')) {
88
-            $restrictions[ EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_others_default') ] = new EE_Default_Where_Conditions(array(
87
+        if (EE_Restriction_Generator_Base::is_cap($this->model(), $this->action().'_others_default')) {
88
+            $restrictions[EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action().'_others_default')] = new EE_Default_Where_Conditions(array(
89 89
                     // if they don't have the others default cap, they can't access others default items (but they can access
90 90
                     // their own default items, and non-default items)
91
-                    'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_others_default') => array(
91
+                    'OR*no_'.EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action().'_others_default') => array(
92 92
                         'AND' => array(
93
-                            $this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder,
93
+                            $this->_path_to_event_model.'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder,
94 94
                             $this->_default_field_name => true
95 95
                             ),
96 96
                         $this->_default_field_name => false
Please login to merge, or discard this patch.
core/helpers/EEH_Event_Query.helper.php 2 patches
Spacing   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -216,7 +216,7 @@  discard block
 block discarded – undo
216 216
     {
217 217
         if (EEH_Event_Query::apply_query_filters($wp_query)) {
218 218
             global $wpdb;
219
-            $clauses['groupby'] = $wpdb->posts . '.ID ';
219
+            $clauses['groupby'] = $wpdb->posts.'.ID ';
220 220
         }
221 221
         return $clauses;
222 222
     }
@@ -251,23 +251,23 @@  discard block
 block discarded – undo
251 251
      */
252 252
     public static function posts_fields_sql_for_orderby(array $orderby_params = [])
253 253
     {
254
-        $SQL = ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date ';
254
+        $SQL = ', MIN( '.EEM_Datetime::instance()->table().'.DTT_EVT_start ) as event_start_date ';
255 255
         foreach ($orderby_params as $orderby) {
256 256
             switch ($orderby) {
257 257
                 case 'ticket_start':
258
-                    $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_start_date';
258
+                    $SQL .= ', '.EEM_Ticket::instance()->table().'.TKT_start_date';
259 259
                     break;
260 260
                 case 'ticket_end':
261
-                    $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_end_date';
261
+                    $SQL .= ', '.EEM_Ticket::instance()->table().'.TKT_end_date';
262 262
                     break;
263 263
                 case 'venue_title':
264 264
                     $SQL .= ', Venue.post_title AS venue_title';
265 265
                     break;
266 266
                 case 'city':
267
-                    $SQL .= ', ' . EEM_Venue::instance()->second_table() . '.VNU_city';
267
+                    $SQL .= ', '.EEM_Venue::instance()->second_table().'.VNU_city';
268 268
                     break;
269 269
                 case 'state':
270
-                    $SQL .= ', ' . EEM_State::instance()->table() . '.STA_name';
270
+                    $SQL .= ', '.EEM_State::instance()->table().'.STA_name';
271 271
                     break;
272 272
             }
273 273
         }
@@ -307,12 +307,12 @@  discard block
 block discarded – undo
307 307
      */
308 308
     public static function posts_join_sql_for_show_expired($SQL = '', $show_expired = false)
309 309
     {
310
-        if (! $show_expired) {
311
-            $join = EEM_Event::instance()->table() . '.ID = ';
312
-            $join .= EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
310
+        if ( ! $show_expired) {
311
+            $join = EEM_Event::instance()->table().'.ID = ';
312
+            $join .= EEM_Datetime::instance()->table().'.'.EEM_Event::instance()->primary_key_name();
313 313
             // don't add if this is already in the SQL
314 314
             if (strpos($SQL, $join) === false) {
315
-                $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' ) ';
315
+                $SQL .= ' INNER JOIN '.EEM_Datetime::instance()->table().' ON ( '.$join.' ) ';
316 316
             }
317 317
         }
318 318
         return $SQL;
@@ -327,7 +327,7 @@  discard block
 block discarded – undo
327 327
      */
328 328
     public static function posts_join_sql_for_terms($SQL = '', $join_terms = '')
329 329
     {
330
-        if (! empty($join_terms)) {
330
+        if ( ! empty($join_terms)) {
331 331
             global $wpdb;
332 332
             $SQL .= " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)";
333 333
             $SQL .= " LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)";
@@ -356,13 +356,13 @@  discard block
 block discarded – undo
356 356
                 case 'ticket_end':
357 357
                     $SQL .= EEH_Event_Query::_posts_join_for_datetime(
358 358
                         $SQL,
359
-                        EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Datetime::instance()->primary_key_name()
359
+                        EEM_Datetime_Ticket::instance()->table().'.'.EEM_Datetime::instance()->primary_key_name()
360 360
                     );
361
-                    $SQL .= ' LEFT JOIN ' . EEM_Ticket::instance()->table();
361
+                    $SQL .= ' LEFT JOIN '.EEM_Ticket::instance()->table();
362 362
                     $SQL .= ' ON (';
363
-                    $SQL .= EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
363
+                    $SQL .= EEM_Datetime_Ticket::instance()->table().'.'.EEM_Ticket::instance()->primary_key_name();
364 364
                     $SQL .= ' = ';
365
-                    $SQL .= EEM_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
365
+                    $SQL .= EEM_Ticket::instance()->table().'.'.EEM_Ticket::instance()->primary_key_name();
366 366
                     $SQL .= ' )';
367 367
                     break;
368 368
                 case 'venue_title':
@@ -375,7 +375,7 @@  discard block
 block discarded – undo
375 375
                     break;
376 376
                 case 'start_date':
377 377
                 default:
378
-                    $SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table() . '.ID');
378
+                    $SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table().'.ID');
379 379
                     break;
380 380
             }
381 381
         }
@@ -394,10 +394,10 @@  discard block
 block discarded – undo
394 394
      */
395 395
     protected static function _posts_join_for_datetime($SQL = '', $join = '')
396 396
     {
397
-        if (! empty($join)) {
398
-            $join .= ' = ' . EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
397
+        if ( ! empty($join)) {
398
+            $join .= ' = '.EEM_Datetime::instance()->table().'.'.EEM_Event::instance()->primary_key_name();
399 399
             if (strpos($SQL, $join) === false) {
400
-                return ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' )';
400
+                return ' INNER JOIN '.EEM_Datetime::instance()->table().' ON ( '.$join.' )';
401 401
             }
402 402
         }
403 403
         return '';
@@ -417,8 +417,8 @@  discard block
 block discarded – undo
417 417
         // Event Venue table name
418 418
         $event_venue_table = EEM_Event_Venue::instance()->table();
419 419
         // generate conditions for:  Event <=> Event Venue  JOIN clause
420
-        $event_to_event_venue_join = EEM_Event::instance()->table() . '.ID = ';
421
-        $event_to_event_venue_join .= $event_venue_table . '.' . EEM_Event::instance()->primary_key_name();
420
+        $event_to_event_venue_join = EEM_Event::instance()->table().'.ID = ';
421
+        $event_to_event_venue_join .= $event_venue_table.'.'.EEM_Event::instance()->primary_key_name();
422 422
         // don't add joins if they have already been added
423 423
         if (strpos($SQL, $event_to_event_venue_join) === false) {
424 424
             // Venue table name
@@ -506,7 +506,7 @@  discard block
 block discarded – undo
506 506
     public static function posts_where_sql_for_show_expired($show_expired = false)
507 507
     {
508 508
         return ! $show_expired
509
-            ? ' AND ' . EEM_Datetime::instance()->table() . '.DTT_EVT_end > \'' . current_time('mysql', true) . '\' '
509
+            ? ' AND '.EEM_Datetime::instance()->table().'.DTT_EVT_end > \''.current_time('mysql', true).'\' '
510 510
             : '';
511 511
     }
512 512
 
@@ -518,7 +518,7 @@  discard block
 block discarded – undo
518 518
     public static function posts_where_sql_for_event_category_slug($event_category_slug = null)
519 519
     {
520 520
         global $wpdb;
521
-        if (! empty($event_category_slug)) {
521
+        if ( ! empty($event_category_slug)) {
522 522
             $event_category_slugs_array   = array_map('trim', explode(',', $event_category_slug));
523 523
             $event_category_slugs_prepare = implode(', ', array_fill(0, count($event_category_slugs_array), '%s'));
524 524
             return $wpdb->prepare(
@@ -541,14 +541,14 @@  discard block
 block discarded – undo
541 541
     public static function posts_where_sql_for_event_list_month($month = null)
542 542
     {
543 543
         $SQL = '';
544
-        if (! empty($month)) {
544
+        if ( ! empty($month)) {
545 545
             $datetime_table = EEM_Datetime::instance()->table();
546 546
             // event start date is LESS than the end of the month ( so nothing that doesn't start until next month )
547 547
             $SQL = " AND {$datetime_table}.DTT_EVT_start <= '";
548
-            $SQL .= date('Y-m-t 23:59:59', EEH_DTT_Helper::first_of_month_timestamp($month)) . "'";
548
+            $SQL .= date('Y-m-t 23:59:59', EEH_DTT_Helper::first_of_month_timestamp($month))."'";
549 549
             // event end date is GREATER than the start of the month ( so nothing that ended before this month )
550 550
             $SQL .= " AND {$datetime_table}.DTT_EVT_end >= '";
551
-            $SQL .= date('Y-m-01 0:0:00', EEH_DTT_Helper::first_of_month_timestamp($month)) . "' ";
551
+            $SQL .= date('Y-m-01 0:0:00', EEH_DTT_Helper::first_of_month_timestamp($month))."' ";
552 552
         }
553 553
         return $SQL;
554 554
     }
@@ -609,15 +609,15 @@  discard block
 block discarded – undo
609 609
             ? strtoupper($sort)
610 610
             : 'ASC';
611 611
         // make sure 'orderby' is set in query params
612
-        if (! isset(self::$_query_params['orderby'])) {
612
+        if ( ! isset(self::$_query_params['orderby'])) {
613 613
             self::$_query_params['orderby'] = [];
614 614
         }
615 615
         // loop thru $orderby_params (type cast as array)
616 616
         foreach ($orderby_params as $orderby) {
617 617
             // check if we have already added this param
618
-            if (isset(self::$_query_params['orderby'][ $orderby ])) {
618
+            if (isset(self::$_query_params['orderby'][$orderby])) {
619 619
                 // if so then remove from the $orderby_params so that the count() method below is accurate
620
-                unset($orderby_params[ $orderby ]);
620
+                unset($orderby_params[$orderby]);
621 621
                 // then bump ahead to the next param
622 622
                 continue;
623 623
             }
@@ -627,39 +627,39 @@  discard block
 block discarded – undo
627 627
             switch ($orderby) {
628 628
                 case 'id':
629 629
                 case 'ID':
630
-                    $SQL .= $glue . $wpdb->posts . '.ID ' . $sort;
630
+                    $SQL .= $glue.$wpdb->posts.'.ID '.$sort;
631 631
                     break;
632 632
                 case 'end_date':
633
-                    $SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_end ' . $sort;
633
+                    $SQL .= $glue.EEM_Datetime::instance()->table().'.DTT_EVT_end '.$sort;
634 634
                     break;
635 635
                 case 'event_name':
636
-                    $SQL .= $glue . $wpdb->posts . '.post_title ' . $sort;
636
+                    $SQL .= $glue.$wpdb->posts.'.post_title '.$sort;
637 637
                     break;
638 638
                 case 'category_slug':
639
-                    $SQL .= $glue . $wpdb->terms . '.slug ' . $sort;
639
+                    $SQL .= $glue.$wpdb->terms.'.slug '.$sort;
640 640
                     break;
641 641
                 case 'ticket_start':
642
-                    $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_start_date ' . $sort;
642
+                    $SQL .= $glue.EEM_Ticket::instance()->table().'.TKT_start_date '.$sort;
643 643
                     break;
644 644
                 case 'ticket_end':
645
-                    $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_end_date ' . $sort;
645
+                    $SQL .= $glue.EEM_Ticket::instance()->table().'.TKT_end_date '.$sort;
646 646
                     break;
647 647
                 case 'venue_title':
648
-                    $SQL .= $glue . 'venue_title ' . $sort;
648
+                    $SQL .= $glue.'venue_title '.$sort;
649 649
                     break;
650 650
                 case 'city':
651
-                    $SQL .= $glue . EEM_Venue::instance()->second_table() . '.VNU_city ' . $sort;
651
+                    $SQL .= $glue.EEM_Venue::instance()->second_table().'.VNU_city '.$sort;
652 652
                     break;
653 653
                 case 'state':
654
-                    $SQL .= $glue . EEM_State::instance()->table() . '.STA_name ' . $sort;
654
+                    $SQL .= $glue.EEM_State::instance()->table().'.STA_name '.$sort;
655 655
                     break;
656 656
                 case 'start_date':
657 657
                 default:
658
-                    $SQL .= $glue . ' event_start_date ' . $sort;
658
+                    $SQL .= $glue.' event_start_date '.$sort;
659 659
                     break;
660 660
             }
661 661
             // add to array of orderby params that have been added
662
-            self::$_query_params['orderby'][ $orderby ] = true;
662
+            self::$_query_params['orderby'][$orderby] = true;
663 663
             $counter++;
664 664
         }
665 665
         return $SQL;
Please login to merge, or discard this patch.
Indentation   +657 added lines, -657 removed lines patch added patch discarded remove patch
@@ -17,661 +17,661 @@
 block discarded – undo
17 17
 class EEH_Event_Query
18 18
 {
19 19
 
20
-    /**
21
-     * Start Date
22
-     *
23
-     * @var $_event_query_month
24
-     */
25
-    protected static $_event_query_month;
26
-
27
-    /**
28
-     * Category
29
-     *
30
-     * @var $_event_query_category
31
-     */
32
-    protected static $_event_query_category;
33
-
34
-    /**
35
-     * whether to display expired events in the event list
36
-     *
37
-     * @var bool $_show_expired
38
-     */
39
-    protected static $_event_query_show_expired = false;
40
-
41
-    /**
42
-     * list of params for controlling how the query results are ordered
43
-     *
44
-     * @var array $_event_query_orderby
45
-     */
46
-    protected static $_event_query_orderby = [];
47
-
48
-    /**
49
-     * direction list is sorted
50
-     *
51
-     * @var string $_event_query_sort
52
-     */
53
-    protected static $_event_query_sort;
54
-
55
-    /**
56
-     * list of params used to build the query's various clauses
57
-     *
58
-     * @var $_query_params
59
-     */
60
-    protected static $_query_params = [];
61
-
62
-
63
-    /**
64
-     * @return void
65
-     */
66
-    public static function add_query_filters()
67
-    {
68
-        // add query filters
69
-        add_action('pre_get_posts', ['EEH_Event_Query', 'filter_query_parts'], 10, 1);
70
-    }
71
-
72
-
73
-    /**
74
-     * @param WP_Query $WP_Query
75
-     * @return bool
76
-     */
77
-    public static function apply_query_filters(WP_Query $WP_Query)
78
-    {
79
-        return (
80
-                   isset($WP_Query->query['post_type'])
81
-                   && $WP_Query->query['post_type'] === 'espresso_events'
82
-               )
83
-               || apply_filters('FHEE__EEH_Event_Query__apply_query_filters', false);
84
-    }
85
-
86
-
87
-    /**
88
-     * @param WP_Query $WP_Query
89
-     */
90
-    public static function filter_query_parts(WP_Query $WP_Query)
91
-    {
92
-        // ONLY add our filters if this isn't the main wp_query,
93
-        // because if this is the main wp_query we already have
94
-        // our cpt strategies take care of adding things in.
95
-        if ($WP_Query instanceof WP_Query && ! $WP_Query->is_main_query()) {
96
-            // build event list query
97
-            add_filter('posts_fields', ['EEH_Event_Query', 'posts_fields'], 10, 2);
98
-            add_filter('posts_join', ['EEH_Event_Query', 'posts_join'], 10, 2);
99
-            add_filter('posts_where', ['EEH_Event_Query', 'posts_where'], 10, 2);
100
-            add_filter('posts_orderby', ['EEH_Event_Query', 'posts_orderby'], 10, 2);
101
-            add_filter('posts_clauses_request', ['EEH_Event_Query', 'posts_clauses'], 10, 2);
102
-        }
103
-    }
104
-
105
-
106
-    /**
107
-     * @param string $month
108
-     * @param string $category
109
-     * @param bool   $show_expired
110
-     * @param string $orderby
111
-     * @param string $sort
112
-     * @throws InvalidArgumentException
113
-     * @throws InvalidDataTypeException
114
-     * @throws InvalidInterfaceException
115
-     */
116
-    public static function set_query_params(
117
-        $month = '',
118
-        $category = '',
119
-        $show_expired = false,
120
-        $orderby = 'start_date',
121
-        $sort = 'ASC'
122
-    ) {
123
-        self::$_query_params                        = [];
124
-        EEH_Event_Query::$_event_query_month        = EEH_Event_Query::_display_month($month);
125
-        EEH_Event_Query::$_event_query_category     = EEH_Event_Query::_event_category_slug($category);
126
-        EEH_Event_Query::$_event_query_show_expired = EEH_Event_Query::_show_expired($show_expired);
127
-        EEH_Event_Query::$_event_query_orderby      = EEH_Event_Query::_orderby($orderby);
128
-        EEH_Event_Query::$_event_query_sort         = EEH_Event_Query::_sort($sort);
129
-    }
130
-
131
-
132
-    /**
133
-     * what month should the event list display events for?
134
-     *
135
-     * @param string $month
136
-     * @return string
137
-     * @throws InvalidArgumentException
138
-     * @throws InvalidDataTypeException
139
-     * @throws InvalidInterfaceException
140
-     */
141
-    private static function _display_month($month = '')
142
-    {
143
-        return self::getRequest()->getRequestParam('event_query_month', $month);
144
-    }
145
-
146
-
147
-    /**
148
-     * @param string $category
149
-     * @return string
150
-     * @throws InvalidArgumentException
151
-     * @throws InvalidDataTypeException
152
-     * @throws InvalidInterfaceException
153
-     */
154
-    private static function _event_category_slug($category = '')
155
-    {
156
-        return self::getRequest()->getRequestParam('event_query_category', $category);
157
-    }
158
-
159
-
160
-    /**
161
-     * @param bool $show_expired
162
-     * @return bool
163
-     * @throws InvalidArgumentException
164
-     * @throws InvalidDataTypeException
165
-     * @throws InvalidInterfaceException
166
-     */
167
-    private static function _show_expired($show_expired = false)
168
-    {
169
-        // override default expired option if set via filter
170
-        return self::getRequest()->getRequestParam('event_query_show_expired', $show_expired, 'bool');
171
-    }
172
-
173
-
174
-    /**
175
-     * @param string $orderby
176
-     * @return array
177
-     * @throws InvalidArgumentException
178
-     * @throws InvalidDataTypeException
179
-     * @throws InvalidInterfaceException
180
-     */
181
-    private static function _orderby($orderby = 'start_date')
182
-    {
183
-        $event_query_orderby = self::getRequest()->getRequestParam('event_query_orderby', $orderby);
184
-        $event_query_orderby = is_array($event_query_orderby)
185
-            ? $event_query_orderby
186
-            : explode(',', $event_query_orderby);
187
-        $event_query_orderby = array_map('trim', $event_query_orderby);
188
-        return array_map('sanitize_text_field', $event_query_orderby);
189
-    }
190
-
191
-
192
-    /**
193
-     * @param string $sort
194
-     * @return string
195
-     * @throws InvalidArgumentException
196
-     * @throws InvalidDataTypeException
197
-     * @throws InvalidInterfaceException
198
-     */
199
-    private static function _sort($sort = 'ASC')
200
-    {
201
-        $sort = self::getRequest()->getRequestParam('event_query_sort', $sort);
202
-        return in_array($sort, ['ASC', 'asc', 'DESC', 'desc'], true)
203
-            ? strtoupper($sort)
204
-            : 'ASC';
205
-    }
206
-
207
-
208
-    /**
209
-     * Filters the clauses for the WP_Query object
210
-     *
211
-     * @param array    $clauses array of clauses
212
-     * @param WP_Query $wp_query
213
-     * @return array   array of clauses
214
-     */
215
-    public static function posts_clauses($clauses, WP_Query $wp_query)
216
-    {
217
-        if (EEH_Event_Query::apply_query_filters($wp_query)) {
218
-            global $wpdb;
219
-            $clauses['groupby'] = $wpdb->posts . '.ID ';
220
-        }
221
-        return $clauses;
222
-    }
223
-
224
-
225
-    /**
226
-     * @param string   $SQL
227
-     * @param WP_Query $wp_query
228
-     * @return string
229
-     * @throws EE_Error
230
-     * @throws InvalidArgumentException
231
-     * @throws InvalidDataTypeException
232
-     * @throws InvalidInterfaceException
233
-     */
234
-    public static function posts_fields($SQL, WP_Query $wp_query)
235
-    {
236
-        if (EEH_Event_Query::apply_query_filters($wp_query)) {
237
-            // adds something like ", wp_esp_datetime.* " to WP Query SELECT statement
238
-            $SQL .= EEH_Event_Query::posts_fields_sql_for_orderby(EEH_Event_Query::$_event_query_orderby);
239
-        }
240
-        return $SQL;
241
-    }
242
-
243
-
244
-    /**
245
-     * @param array $orderby_params
246
-     * @return string
247
-     * @throws EE_Error
248
-     * @throws InvalidArgumentException
249
-     * @throws InvalidDataTypeException
250
-     * @throws InvalidInterfaceException
251
-     */
252
-    public static function posts_fields_sql_for_orderby(array $orderby_params = [])
253
-    {
254
-        $SQL = ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date ';
255
-        foreach ($orderby_params as $orderby) {
256
-            switch ($orderby) {
257
-                case 'ticket_start':
258
-                    $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_start_date';
259
-                    break;
260
-                case 'ticket_end':
261
-                    $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_end_date';
262
-                    break;
263
-                case 'venue_title':
264
-                    $SQL .= ', Venue.post_title AS venue_title';
265
-                    break;
266
-                case 'city':
267
-                    $SQL .= ', ' . EEM_Venue::instance()->second_table() . '.VNU_city';
268
-                    break;
269
-                case 'state':
270
-                    $SQL .= ', ' . EEM_State::instance()->table() . '.STA_name';
271
-                    break;
272
-            }
273
-        }
274
-        return $SQL;
275
-    }
276
-
277
-
278
-    /**
279
-     * @param string   $SQL
280
-     * @param WP_Query $wp_query
281
-     * @return string
282
-     * @throws EE_Error
283
-     * @throws InvalidArgumentException
284
-     * @throws InvalidDataTypeException
285
-     * @throws InvalidInterfaceException
286
-     */
287
-    public static function posts_join($SQL, WP_Query $wp_query)
288
-    {
289
-        if (EEH_Event_Query::apply_query_filters($wp_query)) {
290
-            // Category
291
-            $SQL = EEH_Event_Query::posts_join_sql_for_show_expired($SQL, EEH_Event_Query::$_event_query_show_expired);
292
-            $SQL = EEH_Event_Query::posts_join_sql_for_terms($SQL, EEH_Event_Query::$_event_query_category);
293
-            $SQL = EEH_Event_Query::posts_join_for_orderby($SQL, EEH_Event_Query::$_event_query_orderby);
294
-        }
295
-        return $SQL;
296
-    }
297
-
298
-
299
-    /**
300
-     * @param string  $SQL
301
-     * @param boolean $show_expired if TRUE, then displayed past events
302
-     * @return string
303
-     * @throws EE_Error
304
-     * @throws InvalidArgumentException
305
-     * @throws InvalidDataTypeException
306
-     * @throws InvalidInterfaceException
307
-     */
308
-    public static function posts_join_sql_for_show_expired($SQL = '', $show_expired = false)
309
-    {
310
-        if (! $show_expired) {
311
-            $join = EEM_Event::instance()->table() . '.ID = ';
312
-            $join .= EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
313
-            // don't add if this is already in the SQL
314
-            if (strpos($SQL, $join) === false) {
315
-                $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' ) ';
316
-            }
317
-        }
318
-        return $SQL;
319
-    }
320
-
321
-
322
-    /**
323
-     * @param string $SQL
324
-     * @param string $join_terms    pass TRUE or term string, doesn't really matter since this value doesn't really get
325
-     *                              used for anything yet
326
-     * @return string
327
-     */
328
-    public static function posts_join_sql_for_terms($SQL = '', $join_terms = '')
329
-    {
330
-        if (! empty($join_terms)) {
331
-            global $wpdb;
332
-            $SQL .= " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)";
333
-            $SQL .= " LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)";
334
-            $SQL .= " LEFT JOIN $wpdb->terms ON ($wpdb->terms.term_id = $wpdb->term_taxonomy.term_id) ";
335
-        }
336
-        return $SQL;
337
-    }
338
-
339
-
340
-    /**
341
-     * usage:  $SQL .= EEH_Event_Query::posts_join_for_orderby( $orderby_params );
342
-     *
343
-     * @param string $SQL
344
-     * @param array  $orderby_params
345
-     * @return string
346
-     * @throws EE_Error
347
-     * @throws InvalidArgumentException
348
-     * @throws InvalidDataTypeException
349
-     * @throws InvalidInterfaceException
350
-     */
351
-    public static function posts_join_for_orderby($SQL = '', array $orderby_params = [])
352
-    {
353
-        foreach ($orderby_params as $orderby) {
354
-            switch ($orderby) {
355
-                case 'ticket_start':
356
-                case 'ticket_end':
357
-                    $SQL .= EEH_Event_Query::_posts_join_for_datetime(
358
-                        $SQL,
359
-                        EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Datetime::instance()->primary_key_name()
360
-                    );
361
-                    $SQL .= ' LEFT JOIN ' . EEM_Ticket::instance()->table();
362
-                    $SQL .= ' ON (';
363
-                    $SQL .= EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
364
-                    $SQL .= ' = ';
365
-                    $SQL .= EEM_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
366
-                    $SQL .= ' )';
367
-                    break;
368
-                case 'venue_title':
369
-                case 'city':
370
-                    $SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL);
371
-                    break;
372
-                case 'state':
373
-                    $SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL);
374
-                    $SQL .= EEH_Event_Query::_posts_join_for_venue_state($SQL);
375
-                    break;
376
-                case 'start_date':
377
-                default:
378
-                    $SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table() . '.ID');
379
-                    break;
380
-            }
381
-        }
382
-        return $SQL;
383
-    }
384
-
385
-
386
-    /**
387
-     * @param string $SQL
388
-     * @param string $join
389
-     * @return string
390
-     * @throws EE_Error
391
-     * @throws InvalidArgumentException
392
-     * @throws InvalidDataTypeException
393
-     * @throws InvalidInterfaceException
394
-     */
395
-    protected static function _posts_join_for_datetime($SQL = '', $join = '')
396
-    {
397
-        if (! empty($join)) {
398
-            $join .= ' = ' . EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
399
-            if (strpos($SQL, $join) === false) {
400
-                return ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' )';
401
-            }
402
-        }
403
-        return '';
404
-    }
405
-
406
-
407
-    /**
408
-     * @param string $SQL
409
-     * @return string
410
-     * @throws EE_Error
411
-     * @throws InvalidArgumentException
412
-     * @throws InvalidDataTypeException
413
-     * @throws InvalidInterfaceException
414
-     */
415
-    protected static function _posts_join_for_event_venue($SQL = '')
416
-    {
417
-        // Event Venue table name
418
-        $event_venue_table = EEM_Event_Venue::instance()->table();
419
-        // generate conditions for:  Event <=> Event Venue  JOIN clause
420
-        $event_to_event_venue_join = EEM_Event::instance()->table() . '.ID = ';
421
-        $event_to_event_venue_join .= $event_venue_table . '.' . EEM_Event::instance()->primary_key_name();
422
-        // don't add joins if they have already been added
423
-        if (strpos($SQL, $event_to_event_venue_join) === false) {
424
-            // Venue table name
425
-            $venue_table = EEM_Venue::instance()->table();
426
-            // Venue table pk
427
-            $venue_table_pk = EEM_Venue::instance()->primary_key_name();
428
-            // Venue Meta table name
429
-            $venue_meta_table = EEM_Venue::instance()->second_table();
430
-            // generate JOIN clause for: Event <=> Event Venue
431
-            $venue_SQL = " LEFT JOIN $event_venue_table ON ( $event_to_event_venue_join )";
432
-            // generate JOIN clause for: Event Venue <=> Venue
433
-            $venue_SQL .= " LEFT JOIN $venue_table as Venue ON ( $event_venue_table.$venue_table_pk = Venue.ID )";
434
-            // generate JOIN clause for: Venue <=> Venue Meta
435
-            $venue_SQL .= " LEFT JOIN $venue_meta_table ON ( Venue.ID = $venue_meta_table.$venue_table_pk )";
436
-            unset($event_venue_table, $event_to_event_venue_join, $venue_table, $venue_table_pk, $venue_meta_table);
437
-            return $venue_SQL;
438
-        }
439
-        unset($event_venue_table, $event_to_event_venue_join);
440
-        return '';
441
-    }
442
-
443
-
444
-    /**
445
-     * @param string $SQL
446
-     * @return string
447
-     * @throws EE_Error
448
-     * @throws InvalidArgumentException
449
-     * @throws InvalidDataTypeException
450
-     * @throws InvalidInterfaceException
451
-     */
452
-    protected static function _posts_join_for_venue_state($SQL = '')
453
-    {
454
-        // Venue Meta table name
455
-        $venue_meta_table = EEM_Venue::instance()->second_table();
456
-        // State table name
457
-        $state_table = EEM_State::instance()->table();
458
-        // State table pk
459
-        $state_table_pk = EEM_State::instance()->primary_key_name();
460
-        // verify vars
461
-        if ($venue_meta_table && $state_table && $state_table_pk) {
462
-            // like: wp_esp_venue_meta.STA_ID = wp_esp_state.STA_ID
463
-            $join = "$venue_meta_table.$state_table_pk = $state_table.$state_table_pk";
464
-            // don't add join if it has already been added
465
-            if (strpos($SQL, $join) === false) {
466
-                unset($state_table_pk, $venue_meta_table, $venue_table_pk);
467
-                return " LEFT JOIN $state_table ON ( $join )";
468
-            }
469
-        }
470
-        unset($join, $state_table, $state_table_pk, $venue_meta_table, $venue_table_pk);
471
-        return '';
472
-    }
473
-
474
-
475
-    /**
476
-     * @param string   $SQL
477
-     * @param WP_Query $wp_query
478
-     * @return string
479
-     * @throws EE_Error
480
-     * @throws InvalidArgumentException
481
-     * @throws InvalidDataTypeException
482
-     * @throws InvalidInterfaceException
483
-     */
484
-    public static function posts_where($SQL, WP_Query $wp_query)
485
-    {
486
-        if (EEH_Event_Query::apply_query_filters($wp_query)) {
487
-            // Show Expired ?
488
-            $SQL .= EEH_Event_Query::posts_where_sql_for_show_expired(EEH_Event_Query::$_event_query_show_expired);
489
-            // Category
490
-            $SQL .= EEH_Event_Query::posts_where_sql_for_event_category_slug(EEH_Event_Query::$_event_query_category);
491
-            // Start Date
492
-            $SQL .= EEH_Event_Query::posts_where_sql_for_event_list_month(EEH_Event_Query::$_event_query_month);
493
-        }
494
-        return $SQL;
495
-    }
496
-
497
-
498
-    /**
499
-     * @param boolean $show_expired if TRUE, then displayed past events
500
-     * @return string
501
-     * @throws EE_Error
502
-     * @throws InvalidArgumentException
503
-     * @throws InvalidDataTypeException
504
-     * @throws InvalidInterfaceException
505
-     */
506
-    public static function posts_where_sql_for_show_expired($show_expired = false)
507
-    {
508
-        return ! $show_expired
509
-            ? ' AND ' . EEM_Datetime::instance()->table() . '.DTT_EVT_end > \'' . current_time('mysql', true) . '\' '
510
-            : '';
511
-    }
512
-
513
-
514
-    /**
515
-     * @param boolean $event_category_slug
516
-     * @return string
517
-     */
518
-    public static function posts_where_sql_for_event_category_slug($event_category_slug = null)
519
-    {
520
-        global $wpdb;
521
-        if (! empty($event_category_slug)) {
522
-            $event_category_slugs_array   = array_map('trim', explode(',', $event_category_slug));
523
-            $event_category_slugs_prepare = implode(', ', array_fill(0, count($event_category_slugs_array), '%s'));
524
-            return $wpdb->prepare(
525
-                " AND {$wpdb->terms}.slug IN ({$event_category_slugs_prepare}) ",
526
-                $event_category_slugs_array
527
-            );
528
-        }
529
-        return '';
530
-    }
531
-
532
-
533
-    /**
534
-     * @param boolean $month
535
-     * @return string
536
-     * @throws EE_Error
537
-     * @throws InvalidArgumentException
538
-     * @throws InvalidDataTypeException
539
-     * @throws InvalidInterfaceException
540
-     */
541
-    public static function posts_where_sql_for_event_list_month($month = null)
542
-    {
543
-        $SQL = '';
544
-        if (! empty($month)) {
545
-            $datetime_table = EEM_Datetime::instance()->table();
546
-            // event start date is LESS than the end of the month ( so nothing that doesn't start until next month )
547
-            $SQL = " AND {$datetime_table}.DTT_EVT_start <= '";
548
-            $SQL .= date('Y-m-t 23:59:59', EEH_DTT_Helper::first_of_month_timestamp($month)) . "'";
549
-            // event end date is GREATER than the start of the month ( so nothing that ended before this month )
550
-            $SQL .= " AND {$datetime_table}.DTT_EVT_end >= '";
551
-            $SQL .= date('Y-m-01 0:0:00', EEH_DTT_Helper::first_of_month_timestamp($month)) . "' ";
552
-        }
553
-        return $SQL;
554
-    }
555
-
556
-
557
-    /**
558
-     * @param string   $SQL
559
-     * @param WP_Query $wp_query
560
-     * @return string
561
-     * @throws EE_Error
562
-     * @throws InvalidArgumentException
563
-     * @throws InvalidDataTypeException
564
-     * @throws InvalidInterfaceException
565
-     */
566
-    public static function posts_orderby($SQL, WP_Query $wp_query)
567
-    {
568
-        if (EEH_Event_Query::apply_query_filters($wp_query)) {
569
-            $SQL = EEH_Event_Query::posts_orderby_sql(
570
-                EEH_Event_Query::$_event_query_orderby,
571
-                EEH_Event_Query::$_event_query_sort
572
-            );
573
-        }
574
-        return $SQL;
575
-    }
576
-
577
-
578
-    /**
579
-     *    posts_orderby_sql
580
-     *    possible parameters:
581
-     *    ID
582
-     *    start_date
583
-     *    end_date
584
-     *    event_name
585
-     *    category_slug
586
-     *    ticket_start
587
-     *    ticket_end
588
-     *    venue_title
589
-     *    city
590
-     *    state
591
-     *    **IMPORTANT**
592
-     *    make sure to also send the $orderby_params array to the posts_join_for_orderby() method
593
-     *    or else some of the table references below will result in MySQL errors
594
-     *
595
-     * @param array  $orderby_params
596
-     * @param string $sort
597
-     * @return string
598
-     * @throws EE_Error
599
-     * @throws InvalidArgumentException
600
-     * @throws InvalidDataTypeException
601
-     * @throws InvalidInterfaceException
602
-     */
603
-    public static function posts_orderby_sql(array $orderby_params = [], $sort = 'ASC')
604
-    {
605
-        global $wpdb;
606
-        $SQL     = '';
607
-        $counter = 0;
608
-        $sort    = in_array($sort, ['ASC', 'asc', 'DESC', 'desc'], true)
609
-            ? strtoupper($sort)
610
-            : 'ASC';
611
-        // make sure 'orderby' is set in query params
612
-        if (! isset(self::$_query_params['orderby'])) {
613
-            self::$_query_params['orderby'] = [];
614
-        }
615
-        // loop thru $orderby_params (type cast as array)
616
-        foreach ($orderby_params as $orderby) {
617
-            // check if we have already added this param
618
-            if (isset(self::$_query_params['orderby'][ $orderby ])) {
619
-                // if so then remove from the $orderby_params so that the count() method below is accurate
620
-                unset($orderby_params[ $orderby ]);
621
-                // then bump ahead to the next param
622
-                continue;
623
-            }
624
-            // this will ad a comma depending on whether this is the first or last param
625
-            $glue = $counter === 0 || $counter === count($orderby_params) ? ' ' : ', ';
626
-            // ok what's we dealing with?
627
-            switch ($orderby) {
628
-                case 'id':
629
-                case 'ID':
630
-                    $SQL .= $glue . $wpdb->posts . '.ID ' . $sort;
631
-                    break;
632
-                case 'end_date':
633
-                    $SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_end ' . $sort;
634
-                    break;
635
-                case 'event_name':
636
-                    $SQL .= $glue . $wpdb->posts . '.post_title ' . $sort;
637
-                    break;
638
-                case 'category_slug':
639
-                    $SQL .= $glue . $wpdb->terms . '.slug ' . $sort;
640
-                    break;
641
-                case 'ticket_start':
642
-                    $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_start_date ' . $sort;
643
-                    break;
644
-                case 'ticket_end':
645
-                    $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_end_date ' . $sort;
646
-                    break;
647
-                case 'venue_title':
648
-                    $SQL .= $glue . 'venue_title ' . $sort;
649
-                    break;
650
-                case 'city':
651
-                    $SQL .= $glue . EEM_Venue::instance()->second_table() . '.VNU_city ' . $sort;
652
-                    break;
653
-                case 'state':
654
-                    $SQL .= $glue . EEM_State::instance()->table() . '.STA_name ' . $sort;
655
-                    break;
656
-                case 'start_date':
657
-                default:
658
-                    $SQL .= $glue . ' event_start_date ' . $sort;
659
-                    break;
660
-            }
661
-            // add to array of orderby params that have been added
662
-            self::$_query_params['orderby'][ $orderby ] = true;
663
-            $counter++;
664
-        }
665
-        return $SQL;
666
-    }
667
-
668
-
669
-    /**
670
-     * @return RequestInterface
671
-     * @since   4.10.14.p
672
-     */
673
-    private static function getRequest()
674
-    {
675
-        return LoaderFactory::getLoader()->getShared(RequestInterface::class);
676
-    }
20
+	/**
21
+	 * Start Date
22
+	 *
23
+	 * @var $_event_query_month
24
+	 */
25
+	protected static $_event_query_month;
26
+
27
+	/**
28
+	 * Category
29
+	 *
30
+	 * @var $_event_query_category
31
+	 */
32
+	protected static $_event_query_category;
33
+
34
+	/**
35
+	 * whether to display expired events in the event list
36
+	 *
37
+	 * @var bool $_show_expired
38
+	 */
39
+	protected static $_event_query_show_expired = false;
40
+
41
+	/**
42
+	 * list of params for controlling how the query results are ordered
43
+	 *
44
+	 * @var array $_event_query_orderby
45
+	 */
46
+	protected static $_event_query_orderby = [];
47
+
48
+	/**
49
+	 * direction list is sorted
50
+	 *
51
+	 * @var string $_event_query_sort
52
+	 */
53
+	protected static $_event_query_sort;
54
+
55
+	/**
56
+	 * list of params used to build the query's various clauses
57
+	 *
58
+	 * @var $_query_params
59
+	 */
60
+	protected static $_query_params = [];
61
+
62
+
63
+	/**
64
+	 * @return void
65
+	 */
66
+	public static function add_query_filters()
67
+	{
68
+		// add query filters
69
+		add_action('pre_get_posts', ['EEH_Event_Query', 'filter_query_parts'], 10, 1);
70
+	}
71
+
72
+
73
+	/**
74
+	 * @param WP_Query $WP_Query
75
+	 * @return bool
76
+	 */
77
+	public static function apply_query_filters(WP_Query $WP_Query)
78
+	{
79
+		return (
80
+				   isset($WP_Query->query['post_type'])
81
+				   && $WP_Query->query['post_type'] === 'espresso_events'
82
+			   )
83
+			   || apply_filters('FHEE__EEH_Event_Query__apply_query_filters', false);
84
+	}
85
+
86
+
87
+	/**
88
+	 * @param WP_Query $WP_Query
89
+	 */
90
+	public static function filter_query_parts(WP_Query $WP_Query)
91
+	{
92
+		// ONLY add our filters if this isn't the main wp_query,
93
+		// because if this is the main wp_query we already have
94
+		// our cpt strategies take care of adding things in.
95
+		if ($WP_Query instanceof WP_Query && ! $WP_Query->is_main_query()) {
96
+			// build event list query
97
+			add_filter('posts_fields', ['EEH_Event_Query', 'posts_fields'], 10, 2);
98
+			add_filter('posts_join', ['EEH_Event_Query', 'posts_join'], 10, 2);
99
+			add_filter('posts_where', ['EEH_Event_Query', 'posts_where'], 10, 2);
100
+			add_filter('posts_orderby', ['EEH_Event_Query', 'posts_orderby'], 10, 2);
101
+			add_filter('posts_clauses_request', ['EEH_Event_Query', 'posts_clauses'], 10, 2);
102
+		}
103
+	}
104
+
105
+
106
+	/**
107
+	 * @param string $month
108
+	 * @param string $category
109
+	 * @param bool   $show_expired
110
+	 * @param string $orderby
111
+	 * @param string $sort
112
+	 * @throws InvalidArgumentException
113
+	 * @throws InvalidDataTypeException
114
+	 * @throws InvalidInterfaceException
115
+	 */
116
+	public static function set_query_params(
117
+		$month = '',
118
+		$category = '',
119
+		$show_expired = false,
120
+		$orderby = 'start_date',
121
+		$sort = 'ASC'
122
+	) {
123
+		self::$_query_params                        = [];
124
+		EEH_Event_Query::$_event_query_month        = EEH_Event_Query::_display_month($month);
125
+		EEH_Event_Query::$_event_query_category     = EEH_Event_Query::_event_category_slug($category);
126
+		EEH_Event_Query::$_event_query_show_expired = EEH_Event_Query::_show_expired($show_expired);
127
+		EEH_Event_Query::$_event_query_orderby      = EEH_Event_Query::_orderby($orderby);
128
+		EEH_Event_Query::$_event_query_sort         = EEH_Event_Query::_sort($sort);
129
+	}
130
+
131
+
132
+	/**
133
+	 * what month should the event list display events for?
134
+	 *
135
+	 * @param string $month
136
+	 * @return string
137
+	 * @throws InvalidArgumentException
138
+	 * @throws InvalidDataTypeException
139
+	 * @throws InvalidInterfaceException
140
+	 */
141
+	private static function _display_month($month = '')
142
+	{
143
+		return self::getRequest()->getRequestParam('event_query_month', $month);
144
+	}
145
+
146
+
147
+	/**
148
+	 * @param string $category
149
+	 * @return string
150
+	 * @throws InvalidArgumentException
151
+	 * @throws InvalidDataTypeException
152
+	 * @throws InvalidInterfaceException
153
+	 */
154
+	private static function _event_category_slug($category = '')
155
+	{
156
+		return self::getRequest()->getRequestParam('event_query_category', $category);
157
+	}
158
+
159
+
160
+	/**
161
+	 * @param bool $show_expired
162
+	 * @return bool
163
+	 * @throws InvalidArgumentException
164
+	 * @throws InvalidDataTypeException
165
+	 * @throws InvalidInterfaceException
166
+	 */
167
+	private static function _show_expired($show_expired = false)
168
+	{
169
+		// override default expired option if set via filter
170
+		return self::getRequest()->getRequestParam('event_query_show_expired', $show_expired, 'bool');
171
+	}
172
+
173
+
174
+	/**
175
+	 * @param string $orderby
176
+	 * @return array
177
+	 * @throws InvalidArgumentException
178
+	 * @throws InvalidDataTypeException
179
+	 * @throws InvalidInterfaceException
180
+	 */
181
+	private static function _orderby($orderby = 'start_date')
182
+	{
183
+		$event_query_orderby = self::getRequest()->getRequestParam('event_query_orderby', $orderby);
184
+		$event_query_orderby = is_array($event_query_orderby)
185
+			? $event_query_orderby
186
+			: explode(',', $event_query_orderby);
187
+		$event_query_orderby = array_map('trim', $event_query_orderby);
188
+		return array_map('sanitize_text_field', $event_query_orderby);
189
+	}
190
+
191
+
192
+	/**
193
+	 * @param string $sort
194
+	 * @return string
195
+	 * @throws InvalidArgumentException
196
+	 * @throws InvalidDataTypeException
197
+	 * @throws InvalidInterfaceException
198
+	 */
199
+	private static function _sort($sort = 'ASC')
200
+	{
201
+		$sort = self::getRequest()->getRequestParam('event_query_sort', $sort);
202
+		return in_array($sort, ['ASC', 'asc', 'DESC', 'desc'], true)
203
+			? strtoupper($sort)
204
+			: 'ASC';
205
+	}
206
+
207
+
208
+	/**
209
+	 * Filters the clauses for the WP_Query object
210
+	 *
211
+	 * @param array    $clauses array of clauses
212
+	 * @param WP_Query $wp_query
213
+	 * @return array   array of clauses
214
+	 */
215
+	public static function posts_clauses($clauses, WP_Query $wp_query)
216
+	{
217
+		if (EEH_Event_Query::apply_query_filters($wp_query)) {
218
+			global $wpdb;
219
+			$clauses['groupby'] = $wpdb->posts . '.ID ';
220
+		}
221
+		return $clauses;
222
+	}
223
+
224
+
225
+	/**
226
+	 * @param string   $SQL
227
+	 * @param WP_Query $wp_query
228
+	 * @return string
229
+	 * @throws EE_Error
230
+	 * @throws InvalidArgumentException
231
+	 * @throws InvalidDataTypeException
232
+	 * @throws InvalidInterfaceException
233
+	 */
234
+	public static function posts_fields($SQL, WP_Query $wp_query)
235
+	{
236
+		if (EEH_Event_Query::apply_query_filters($wp_query)) {
237
+			// adds something like ", wp_esp_datetime.* " to WP Query SELECT statement
238
+			$SQL .= EEH_Event_Query::posts_fields_sql_for_orderby(EEH_Event_Query::$_event_query_orderby);
239
+		}
240
+		return $SQL;
241
+	}
242
+
243
+
244
+	/**
245
+	 * @param array $orderby_params
246
+	 * @return string
247
+	 * @throws EE_Error
248
+	 * @throws InvalidArgumentException
249
+	 * @throws InvalidDataTypeException
250
+	 * @throws InvalidInterfaceException
251
+	 */
252
+	public static function posts_fields_sql_for_orderby(array $orderby_params = [])
253
+	{
254
+		$SQL = ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date ';
255
+		foreach ($orderby_params as $orderby) {
256
+			switch ($orderby) {
257
+				case 'ticket_start':
258
+					$SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_start_date';
259
+					break;
260
+				case 'ticket_end':
261
+					$SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_end_date';
262
+					break;
263
+				case 'venue_title':
264
+					$SQL .= ', Venue.post_title AS venue_title';
265
+					break;
266
+				case 'city':
267
+					$SQL .= ', ' . EEM_Venue::instance()->second_table() . '.VNU_city';
268
+					break;
269
+				case 'state':
270
+					$SQL .= ', ' . EEM_State::instance()->table() . '.STA_name';
271
+					break;
272
+			}
273
+		}
274
+		return $SQL;
275
+	}
276
+
277
+
278
+	/**
279
+	 * @param string   $SQL
280
+	 * @param WP_Query $wp_query
281
+	 * @return string
282
+	 * @throws EE_Error
283
+	 * @throws InvalidArgumentException
284
+	 * @throws InvalidDataTypeException
285
+	 * @throws InvalidInterfaceException
286
+	 */
287
+	public static function posts_join($SQL, WP_Query $wp_query)
288
+	{
289
+		if (EEH_Event_Query::apply_query_filters($wp_query)) {
290
+			// Category
291
+			$SQL = EEH_Event_Query::posts_join_sql_for_show_expired($SQL, EEH_Event_Query::$_event_query_show_expired);
292
+			$SQL = EEH_Event_Query::posts_join_sql_for_terms($SQL, EEH_Event_Query::$_event_query_category);
293
+			$SQL = EEH_Event_Query::posts_join_for_orderby($SQL, EEH_Event_Query::$_event_query_orderby);
294
+		}
295
+		return $SQL;
296
+	}
297
+
298
+
299
+	/**
300
+	 * @param string  $SQL
301
+	 * @param boolean $show_expired if TRUE, then displayed past events
302
+	 * @return string
303
+	 * @throws EE_Error
304
+	 * @throws InvalidArgumentException
305
+	 * @throws InvalidDataTypeException
306
+	 * @throws InvalidInterfaceException
307
+	 */
308
+	public static function posts_join_sql_for_show_expired($SQL = '', $show_expired = false)
309
+	{
310
+		if (! $show_expired) {
311
+			$join = EEM_Event::instance()->table() . '.ID = ';
312
+			$join .= EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
313
+			// don't add if this is already in the SQL
314
+			if (strpos($SQL, $join) === false) {
315
+				$SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' ) ';
316
+			}
317
+		}
318
+		return $SQL;
319
+	}
320
+
321
+
322
+	/**
323
+	 * @param string $SQL
324
+	 * @param string $join_terms    pass TRUE or term string, doesn't really matter since this value doesn't really get
325
+	 *                              used for anything yet
326
+	 * @return string
327
+	 */
328
+	public static function posts_join_sql_for_terms($SQL = '', $join_terms = '')
329
+	{
330
+		if (! empty($join_terms)) {
331
+			global $wpdb;
332
+			$SQL .= " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)";
333
+			$SQL .= " LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)";
334
+			$SQL .= " LEFT JOIN $wpdb->terms ON ($wpdb->terms.term_id = $wpdb->term_taxonomy.term_id) ";
335
+		}
336
+		return $SQL;
337
+	}
338
+
339
+
340
+	/**
341
+	 * usage:  $SQL .= EEH_Event_Query::posts_join_for_orderby( $orderby_params );
342
+	 *
343
+	 * @param string $SQL
344
+	 * @param array  $orderby_params
345
+	 * @return string
346
+	 * @throws EE_Error
347
+	 * @throws InvalidArgumentException
348
+	 * @throws InvalidDataTypeException
349
+	 * @throws InvalidInterfaceException
350
+	 */
351
+	public static function posts_join_for_orderby($SQL = '', array $orderby_params = [])
352
+	{
353
+		foreach ($orderby_params as $orderby) {
354
+			switch ($orderby) {
355
+				case 'ticket_start':
356
+				case 'ticket_end':
357
+					$SQL .= EEH_Event_Query::_posts_join_for_datetime(
358
+						$SQL,
359
+						EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Datetime::instance()->primary_key_name()
360
+					);
361
+					$SQL .= ' LEFT JOIN ' . EEM_Ticket::instance()->table();
362
+					$SQL .= ' ON (';
363
+					$SQL .= EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
364
+					$SQL .= ' = ';
365
+					$SQL .= EEM_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name();
366
+					$SQL .= ' )';
367
+					break;
368
+				case 'venue_title':
369
+				case 'city':
370
+					$SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL);
371
+					break;
372
+				case 'state':
373
+					$SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL);
374
+					$SQL .= EEH_Event_Query::_posts_join_for_venue_state($SQL);
375
+					break;
376
+				case 'start_date':
377
+				default:
378
+					$SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table() . '.ID');
379
+					break;
380
+			}
381
+		}
382
+		return $SQL;
383
+	}
384
+
385
+
386
+	/**
387
+	 * @param string $SQL
388
+	 * @param string $join
389
+	 * @return string
390
+	 * @throws EE_Error
391
+	 * @throws InvalidArgumentException
392
+	 * @throws InvalidDataTypeException
393
+	 * @throws InvalidInterfaceException
394
+	 */
395
+	protected static function _posts_join_for_datetime($SQL = '', $join = '')
396
+	{
397
+		if (! empty($join)) {
398
+			$join .= ' = ' . EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name();
399
+			if (strpos($SQL, $join) === false) {
400
+				return ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' )';
401
+			}
402
+		}
403
+		return '';
404
+	}
405
+
406
+
407
+	/**
408
+	 * @param string $SQL
409
+	 * @return string
410
+	 * @throws EE_Error
411
+	 * @throws InvalidArgumentException
412
+	 * @throws InvalidDataTypeException
413
+	 * @throws InvalidInterfaceException
414
+	 */
415
+	protected static function _posts_join_for_event_venue($SQL = '')
416
+	{
417
+		// Event Venue table name
418
+		$event_venue_table = EEM_Event_Venue::instance()->table();
419
+		// generate conditions for:  Event <=> Event Venue  JOIN clause
420
+		$event_to_event_venue_join = EEM_Event::instance()->table() . '.ID = ';
421
+		$event_to_event_venue_join .= $event_venue_table . '.' . EEM_Event::instance()->primary_key_name();
422
+		// don't add joins if they have already been added
423
+		if (strpos($SQL, $event_to_event_venue_join) === false) {
424
+			// Venue table name
425
+			$venue_table = EEM_Venue::instance()->table();
426
+			// Venue table pk
427
+			$venue_table_pk = EEM_Venue::instance()->primary_key_name();
428
+			// Venue Meta table name
429
+			$venue_meta_table = EEM_Venue::instance()->second_table();
430
+			// generate JOIN clause for: Event <=> Event Venue
431
+			$venue_SQL = " LEFT JOIN $event_venue_table ON ( $event_to_event_venue_join )";
432
+			// generate JOIN clause for: Event Venue <=> Venue
433
+			$venue_SQL .= " LEFT JOIN $venue_table as Venue ON ( $event_venue_table.$venue_table_pk = Venue.ID )";
434
+			// generate JOIN clause for: Venue <=> Venue Meta
435
+			$venue_SQL .= " LEFT JOIN $venue_meta_table ON ( Venue.ID = $venue_meta_table.$venue_table_pk )";
436
+			unset($event_venue_table, $event_to_event_venue_join, $venue_table, $venue_table_pk, $venue_meta_table);
437
+			return $venue_SQL;
438
+		}
439
+		unset($event_venue_table, $event_to_event_venue_join);
440
+		return '';
441
+	}
442
+
443
+
444
+	/**
445
+	 * @param string $SQL
446
+	 * @return string
447
+	 * @throws EE_Error
448
+	 * @throws InvalidArgumentException
449
+	 * @throws InvalidDataTypeException
450
+	 * @throws InvalidInterfaceException
451
+	 */
452
+	protected static function _posts_join_for_venue_state($SQL = '')
453
+	{
454
+		// Venue Meta table name
455
+		$venue_meta_table = EEM_Venue::instance()->second_table();
456
+		// State table name
457
+		$state_table = EEM_State::instance()->table();
458
+		// State table pk
459
+		$state_table_pk = EEM_State::instance()->primary_key_name();
460
+		// verify vars
461
+		if ($venue_meta_table && $state_table && $state_table_pk) {
462
+			// like: wp_esp_venue_meta.STA_ID = wp_esp_state.STA_ID
463
+			$join = "$venue_meta_table.$state_table_pk = $state_table.$state_table_pk";
464
+			// don't add join if it has already been added
465
+			if (strpos($SQL, $join) === false) {
466
+				unset($state_table_pk, $venue_meta_table, $venue_table_pk);
467
+				return " LEFT JOIN $state_table ON ( $join )";
468
+			}
469
+		}
470
+		unset($join, $state_table, $state_table_pk, $venue_meta_table, $venue_table_pk);
471
+		return '';
472
+	}
473
+
474
+
475
+	/**
476
+	 * @param string   $SQL
477
+	 * @param WP_Query $wp_query
478
+	 * @return string
479
+	 * @throws EE_Error
480
+	 * @throws InvalidArgumentException
481
+	 * @throws InvalidDataTypeException
482
+	 * @throws InvalidInterfaceException
483
+	 */
484
+	public static function posts_where($SQL, WP_Query $wp_query)
485
+	{
486
+		if (EEH_Event_Query::apply_query_filters($wp_query)) {
487
+			// Show Expired ?
488
+			$SQL .= EEH_Event_Query::posts_where_sql_for_show_expired(EEH_Event_Query::$_event_query_show_expired);
489
+			// Category
490
+			$SQL .= EEH_Event_Query::posts_where_sql_for_event_category_slug(EEH_Event_Query::$_event_query_category);
491
+			// Start Date
492
+			$SQL .= EEH_Event_Query::posts_where_sql_for_event_list_month(EEH_Event_Query::$_event_query_month);
493
+		}
494
+		return $SQL;
495
+	}
496
+
497
+
498
+	/**
499
+	 * @param boolean $show_expired if TRUE, then displayed past events
500
+	 * @return string
501
+	 * @throws EE_Error
502
+	 * @throws InvalidArgumentException
503
+	 * @throws InvalidDataTypeException
504
+	 * @throws InvalidInterfaceException
505
+	 */
506
+	public static function posts_where_sql_for_show_expired($show_expired = false)
507
+	{
508
+		return ! $show_expired
509
+			? ' AND ' . EEM_Datetime::instance()->table() . '.DTT_EVT_end > \'' . current_time('mysql', true) . '\' '
510
+			: '';
511
+	}
512
+
513
+
514
+	/**
515
+	 * @param boolean $event_category_slug
516
+	 * @return string
517
+	 */
518
+	public static function posts_where_sql_for_event_category_slug($event_category_slug = null)
519
+	{
520
+		global $wpdb;
521
+		if (! empty($event_category_slug)) {
522
+			$event_category_slugs_array   = array_map('trim', explode(',', $event_category_slug));
523
+			$event_category_slugs_prepare = implode(', ', array_fill(0, count($event_category_slugs_array), '%s'));
524
+			return $wpdb->prepare(
525
+				" AND {$wpdb->terms}.slug IN ({$event_category_slugs_prepare}) ",
526
+				$event_category_slugs_array
527
+			);
528
+		}
529
+		return '';
530
+	}
531
+
532
+
533
+	/**
534
+	 * @param boolean $month
535
+	 * @return string
536
+	 * @throws EE_Error
537
+	 * @throws InvalidArgumentException
538
+	 * @throws InvalidDataTypeException
539
+	 * @throws InvalidInterfaceException
540
+	 */
541
+	public static function posts_where_sql_for_event_list_month($month = null)
542
+	{
543
+		$SQL = '';
544
+		if (! empty($month)) {
545
+			$datetime_table = EEM_Datetime::instance()->table();
546
+			// event start date is LESS than the end of the month ( so nothing that doesn't start until next month )
547
+			$SQL = " AND {$datetime_table}.DTT_EVT_start <= '";
548
+			$SQL .= date('Y-m-t 23:59:59', EEH_DTT_Helper::first_of_month_timestamp($month)) . "'";
549
+			// event end date is GREATER than the start of the month ( so nothing that ended before this month )
550
+			$SQL .= " AND {$datetime_table}.DTT_EVT_end >= '";
551
+			$SQL .= date('Y-m-01 0:0:00', EEH_DTT_Helper::first_of_month_timestamp($month)) . "' ";
552
+		}
553
+		return $SQL;
554
+	}
555
+
556
+
557
+	/**
558
+	 * @param string   $SQL
559
+	 * @param WP_Query $wp_query
560
+	 * @return string
561
+	 * @throws EE_Error
562
+	 * @throws InvalidArgumentException
563
+	 * @throws InvalidDataTypeException
564
+	 * @throws InvalidInterfaceException
565
+	 */
566
+	public static function posts_orderby($SQL, WP_Query $wp_query)
567
+	{
568
+		if (EEH_Event_Query::apply_query_filters($wp_query)) {
569
+			$SQL = EEH_Event_Query::posts_orderby_sql(
570
+				EEH_Event_Query::$_event_query_orderby,
571
+				EEH_Event_Query::$_event_query_sort
572
+			);
573
+		}
574
+		return $SQL;
575
+	}
576
+
577
+
578
+	/**
579
+	 *    posts_orderby_sql
580
+	 *    possible parameters:
581
+	 *    ID
582
+	 *    start_date
583
+	 *    end_date
584
+	 *    event_name
585
+	 *    category_slug
586
+	 *    ticket_start
587
+	 *    ticket_end
588
+	 *    venue_title
589
+	 *    city
590
+	 *    state
591
+	 *    **IMPORTANT**
592
+	 *    make sure to also send the $orderby_params array to the posts_join_for_orderby() method
593
+	 *    or else some of the table references below will result in MySQL errors
594
+	 *
595
+	 * @param array  $orderby_params
596
+	 * @param string $sort
597
+	 * @return string
598
+	 * @throws EE_Error
599
+	 * @throws InvalidArgumentException
600
+	 * @throws InvalidDataTypeException
601
+	 * @throws InvalidInterfaceException
602
+	 */
603
+	public static function posts_orderby_sql(array $orderby_params = [], $sort = 'ASC')
604
+	{
605
+		global $wpdb;
606
+		$SQL     = '';
607
+		$counter = 0;
608
+		$sort    = in_array($sort, ['ASC', 'asc', 'DESC', 'desc'], true)
609
+			? strtoupper($sort)
610
+			: 'ASC';
611
+		// make sure 'orderby' is set in query params
612
+		if (! isset(self::$_query_params['orderby'])) {
613
+			self::$_query_params['orderby'] = [];
614
+		}
615
+		// loop thru $orderby_params (type cast as array)
616
+		foreach ($orderby_params as $orderby) {
617
+			// check if we have already added this param
618
+			if (isset(self::$_query_params['orderby'][ $orderby ])) {
619
+				// if so then remove from the $orderby_params so that the count() method below is accurate
620
+				unset($orderby_params[ $orderby ]);
621
+				// then bump ahead to the next param
622
+				continue;
623
+			}
624
+			// this will ad a comma depending on whether this is the first or last param
625
+			$glue = $counter === 0 || $counter === count($orderby_params) ? ' ' : ', ';
626
+			// ok what's we dealing with?
627
+			switch ($orderby) {
628
+				case 'id':
629
+				case 'ID':
630
+					$SQL .= $glue . $wpdb->posts . '.ID ' . $sort;
631
+					break;
632
+				case 'end_date':
633
+					$SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_end ' . $sort;
634
+					break;
635
+				case 'event_name':
636
+					$SQL .= $glue . $wpdb->posts . '.post_title ' . $sort;
637
+					break;
638
+				case 'category_slug':
639
+					$SQL .= $glue . $wpdb->terms . '.slug ' . $sort;
640
+					break;
641
+				case 'ticket_start':
642
+					$SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_start_date ' . $sort;
643
+					break;
644
+				case 'ticket_end':
645
+					$SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_end_date ' . $sort;
646
+					break;
647
+				case 'venue_title':
648
+					$SQL .= $glue . 'venue_title ' . $sort;
649
+					break;
650
+				case 'city':
651
+					$SQL .= $glue . EEM_Venue::instance()->second_table() . '.VNU_city ' . $sort;
652
+					break;
653
+				case 'state':
654
+					$SQL .= $glue . EEM_State::instance()->table() . '.STA_name ' . $sort;
655
+					break;
656
+				case 'start_date':
657
+				default:
658
+					$SQL .= $glue . ' event_start_date ' . $sort;
659
+					break;
660
+			}
661
+			// add to array of orderby params that have been added
662
+			self::$_query_params['orderby'][ $orderby ] = true;
663
+			$counter++;
664
+		}
665
+		return $SQL;
666
+	}
667
+
668
+
669
+	/**
670
+	 * @return RequestInterface
671
+	 * @since   4.10.14.p
672
+	 */
673
+	private static function getRequest()
674
+	{
675
+		return LoaderFactory::getLoader()->getShared(RequestInterface::class);
676
+	}
677 677
 }
Please login to merge, or discard this patch.