@@ -228,7 +228,7 @@ discard block |
||
228 | 228 | */ |
229 | 229 | public function set_submit_button_text($submit_button_text = '') |
230 | 230 | { |
231 | - if (! empty($submit_button_text)) { |
|
231 | + if ( ! empty($submit_button_text)) { |
|
232 | 232 | $this->_submit_button_text = $submit_button_text; |
233 | 233 | } elseif ($this->checkout->next_step instanceof EE_SPCO_Reg_Step) { |
234 | 234 | if ($this->checkout->revisit) { |
@@ -388,7 +388,7 @@ discard block |
||
388 | 388 | public function reg_form_name() |
389 | 389 | { |
390 | 390 | if (empty($this->_reg_form_name)) { |
391 | - $this->set_reg_form_name('ee-spco-' . $this->slug() . '-reg-step-form'); |
|
391 | + $this->set_reg_form_name('ee-spco-'.$this->slug().'-reg-step-form'); |
|
392 | 392 | } |
393 | 393 | return $this->_reg_form_name; |
394 | 394 | } |
@@ -412,7 +412,7 @@ discard block |
||
412 | 412 | public function reg_step_url($action = '') |
413 | 413 | { |
414 | 414 | $query_args = ['step' => $this->slug()]; |
415 | - if (! empty($action)) { |
|
415 | + if ( ! empty($action)) { |
|
416 | 416 | $query_args['action'] = $action; |
417 | 417 | } |
418 | 418 | // final step has no display |
@@ -442,12 +442,12 @@ discard block |
||
442 | 442 | return new EE_Form_Section_Proper( |
443 | 443 | [ |
444 | 444 | 'layout_strategy' => new EE_Div_Per_Section_Layout(), |
445 | - 'html_id' => 'ee-' . $this->slug() . '-hidden-inputs', |
|
445 | + 'html_id' => 'ee-'.$this->slug().'-hidden-inputs', |
|
446 | 446 | 'subsections' => [ |
447 | 447 | 'next_step' => new EE_Fixed_Hidden_Input( |
448 | 448 | [ |
449 | 449 | 'html_name' => 'next_step', |
450 | - 'html_id' => 'spco-' . $this->slug() . '-next-step', |
|
450 | + 'html_id' => 'spco-'.$this->slug().'-next-step', |
|
451 | 451 | 'default' => $this->checkout->next_step instanceof EE_SPCO_Reg_Step |
452 | 452 | ? $this->checkout->next_step->slug() |
453 | 453 | : '', |
@@ -461,12 +461,12 @@ discard block |
||
461 | 461 | return new EE_Form_Section_Proper( |
462 | 462 | [ |
463 | 463 | 'layout_strategy' => new EE_Div_Per_Section_Layout(), |
464 | - 'html_id' => 'ee-' . $this->slug() . '-hidden-inputs', |
|
464 | + 'html_id' => 'ee-'.$this->slug().'-hidden-inputs', |
|
465 | 465 | 'subsections' => [ |
466 | 466 | 'action' => new EE_Fixed_Hidden_Input( |
467 | 467 | [ |
468 | 468 | 'html_name' => 'action', |
469 | - 'html_id' => 'spco-' . $this->slug() . '-action', |
|
469 | + 'html_id' => 'spco-'.$this->slug().'-action', |
|
470 | 470 | 'default' => apply_filters( |
471 | 471 | 'FHEE__EE_SPCO_Reg_Step__reg_step_hidden_inputs__default_form_action', |
472 | 472 | empty($this->checkout->reg_url_link) |
@@ -479,7 +479,7 @@ discard block |
||
479 | 479 | 'next_step' => new EE_Fixed_Hidden_Input( |
480 | 480 | [ |
481 | 481 | 'html_name' => 'next_step', |
482 | - 'html_id' => 'spco-' . $this->slug() . '-next-step', |
|
482 | + 'html_id' => 'spco-'.$this->slug().'-next-step', |
|
483 | 483 | 'default' => $this->checkout->next_step instanceof EE_SPCO_Reg_Step |
484 | 484 | ? $this->checkout->next_step->slug() |
485 | 485 | : '', |
@@ -513,7 +513,7 @@ discard block |
||
513 | 513 | */ |
514 | 514 | public function generate_reg_form_for_actions($actions = []) |
515 | 515 | { |
516 | - $actions = array_merge( |
|
516 | + $actions = array_merge( |
|
517 | 517 | [ |
518 | 518 | 'generate_reg_form', |
519 | 519 | 'display_spco_reg_step', |
@@ -556,7 +556,7 @@ discard block |
||
556 | 556 | */ |
557 | 557 | public function reg_step_submit_button() |
558 | 558 | { |
559 | - if (! $this->checkout->next_step instanceof EE_SPCO_Reg_Step) { |
|
559 | + if ( ! $this->checkout->next_step instanceof EE_SPCO_Reg_Step) { |
|
560 | 560 | return ''; |
561 | 561 | } |
562 | 562 | ob_start(); |
@@ -570,18 +570,18 @@ discard block |
||
570 | 570 | // generate submit button |
571 | 571 | $submit_btn = new EE_Submit_Input( |
572 | 572 | [ |
573 | - 'html_name' => 'spco-go-to-step-' . $this->checkout->next_step->slug(), |
|
574 | - 'html_id' => 'spco-go-to-step-' . $this->checkout->next_step->slug(), |
|
573 | + 'html_name' => 'spco-go-to-step-'.$this->checkout->next_step->slug(), |
|
574 | + 'html_id' => 'spco-go-to-step-'.$this->checkout->next_step->slug(), |
|
575 | 575 | 'html_class' => 'spco-next-step-btn', |
576 | - 'other_html_attributes' => ' rel="' . $this->slug() . '"', |
|
576 | + 'other_html_attributes' => ' rel="'.$this->slug().'"', |
|
577 | 577 | 'default' => $this->submit_button_text(), |
578 | 578 | ] |
579 | 579 | ); |
580 | 580 | $submit_btn->set_button_css_attributes(true, 'large'); |
581 | 581 | $submit_btn_html = $submit_btn->get_html_for_input(); |
582 | - $html .= EEH_HTML::div( |
|
582 | + $html .= EEH_HTML::div( |
|
583 | 583 | apply_filters('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', $submit_btn_html, $this), |
584 | - 'spco-' . $this->slug() . '-whats-next-buttons-dv', |
|
584 | + 'spco-'.$this->slug().'-whats-next-buttons-dv', |
|
585 | 585 | 'spco-whats-next-buttons' |
586 | 586 | ); |
587 | 587 | return $html; |
@@ -13,648 +13,648 @@ |
||
13 | 13 | */ |
14 | 14 | abstract class EE_SPCO_Reg_Step |
15 | 15 | { |
16 | - /** |
|
17 | - * $_completed - TRUE if this step has fully completed it's duties |
|
18 | - * |
|
19 | - * @access protected |
|
20 | - * @type bool $_completed |
|
21 | - */ |
|
22 | - protected $_completed = false; |
|
23 | - |
|
24 | - /** |
|
25 | - * $_is_current_step - TRUE if this is the current step |
|
26 | - * |
|
27 | - * @access protected |
|
28 | - * @type bool $_is_current_step |
|
29 | - */ |
|
30 | - protected $_is_current_step = false; |
|
31 | - |
|
32 | - /** |
|
33 | - * $_order - when the reg step should be run relative to other steps |
|
34 | - * |
|
35 | - * @access protected |
|
36 | - * @type int $_template |
|
37 | - */ |
|
38 | - protected $_order = 0; |
|
39 | - |
|
40 | - /** |
|
41 | - * $_slug - URL param for this step |
|
42 | - * |
|
43 | - * @access protected |
|
44 | - * @type string $_slug |
|
45 | - */ |
|
46 | - protected $_slug; |
|
47 | - |
|
48 | - /** |
|
49 | - * $_name - Step Name - translatable string |
|
50 | - * |
|
51 | - * @access protected |
|
52 | - * @type string $_slug |
|
53 | - */ |
|
54 | - protected $_name; |
|
55 | - |
|
56 | - /** |
|
57 | - * $_submit_button_text - translatable string that appears on this step's submit button |
|
58 | - * |
|
59 | - * @access protected |
|
60 | - * @type string $_slug |
|
61 | - */ |
|
62 | - protected $_submit_button_text; |
|
63 | - |
|
64 | - /** |
|
65 | - * $_template - template name |
|
66 | - * |
|
67 | - * @access protected |
|
68 | - * @type string $_template |
|
69 | - */ |
|
70 | - protected $_template; |
|
71 | - |
|
72 | - /** |
|
73 | - * $_reg_form_name - the form input name and id attribute |
|
74 | - * |
|
75 | - * @access protected |
|
76 | - * @var string $_reg_form_name |
|
77 | - */ |
|
78 | - protected $_reg_form_name; |
|
79 | - |
|
80 | - /** |
|
81 | - * $_success_message - text to display upon successful form submission |
|
82 | - * |
|
83 | - * @access private |
|
84 | - * @var string $_success_message |
|
85 | - */ |
|
86 | - protected $_success_message; |
|
87 | - |
|
88 | - /** |
|
89 | - * $_instructions - a brief description of how to complete the reg step. |
|
90 | - * Usually displayed in conjunction with the previous step's success message. |
|
91 | - * |
|
92 | - * @access private |
|
93 | - * @var string $_instructions |
|
94 | - */ |
|
95 | - protected $_instructions; |
|
96 | - |
|
97 | - /** |
|
98 | - * $_valid_data - the normalized and validated data for this step |
|
99 | - * |
|
100 | - * @access public |
|
101 | - * @var array $_valid_data |
|
102 | - */ |
|
103 | - protected $_valid_data = []; |
|
104 | - |
|
105 | - /** |
|
106 | - * $reg_form - the registration form for this step |
|
107 | - * |
|
108 | - * @access public |
|
109 | - * @var EE_Form_Section_Proper $reg_form |
|
110 | - */ |
|
111 | - public $reg_form; |
|
112 | - |
|
113 | - /** |
|
114 | - * $checkout - EE_Checkout object for handling the properties of the current checkout process |
|
115 | - * |
|
116 | - * @access public |
|
117 | - * @var EE_Checkout $checkout |
|
118 | - */ |
|
119 | - public $checkout; |
|
120 | - |
|
121 | - /** |
|
122 | - * @var RequestInterface $request |
|
123 | - */ |
|
124 | - protected $request; |
|
125 | - |
|
126 | - |
|
127 | - /** |
|
128 | - * @return void |
|
129 | - */ |
|
130 | - abstract public function translate_js_strings(); |
|
131 | - |
|
132 | - |
|
133 | - /** |
|
134 | - * @return void |
|
135 | - */ |
|
136 | - abstract public function enqueue_styles_and_scripts(); |
|
137 | - |
|
138 | - |
|
139 | - /** |
|
140 | - * @return boolean |
|
141 | - */ |
|
142 | - abstract public function initialize_reg_step(); |
|
143 | - |
|
144 | - |
|
145 | - /** |
|
146 | - * @return string |
|
147 | - */ |
|
148 | - abstract public function generate_reg_form(); |
|
149 | - |
|
150 | - |
|
151 | - /** |
|
152 | - * @return boolean |
|
153 | - */ |
|
154 | - abstract public function process_reg_step(); |
|
155 | - |
|
156 | - |
|
157 | - /** |
|
158 | - * @return boolean |
|
159 | - */ |
|
160 | - abstract public function update_reg_step(); |
|
161 | - |
|
162 | - |
|
163 | - /** |
|
164 | - * @return boolean |
|
165 | - */ |
|
166 | - public function completed() |
|
167 | - { |
|
168 | - return $this->_completed; |
|
169 | - } |
|
170 | - |
|
171 | - |
|
172 | - /** |
|
173 | - * set_completed - toggles $_completed to TRUE |
|
174 | - */ |
|
175 | - public function set_completed() |
|
176 | - { |
|
177 | - // DEBUG LOG |
|
178 | - // $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ ); |
|
179 | - $this->_completed = apply_filters('FHEE__EE_SPCO_Reg_Step__set_completed___completed', true, $this); |
|
180 | - } |
|
181 | - |
|
182 | - |
|
183 | - /** |
|
184 | - * set_completed - toggles $_completed to FALSE |
|
185 | - */ |
|
186 | - public function set_not_completed() |
|
187 | - { |
|
188 | - $this->_completed = false; |
|
189 | - } |
|
190 | - |
|
191 | - |
|
192 | - /** |
|
193 | - * @return string |
|
194 | - */ |
|
195 | - public function name() |
|
196 | - { |
|
197 | - return $this->_name; |
|
198 | - } |
|
199 | - |
|
200 | - |
|
201 | - /** |
|
202 | - * @return string |
|
203 | - */ |
|
204 | - public function slug() |
|
205 | - { |
|
206 | - return $this->_slug; |
|
207 | - } |
|
208 | - |
|
209 | - |
|
210 | - /** |
|
211 | - * submit_button_text |
|
212 | - * the text that appears on the reg step form submit button |
|
213 | - * |
|
214 | - * @return string |
|
215 | - */ |
|
216 | - public function submit_button_text() |
|
217 | - { |
|
218 | - return $this->_submit_button_text; |
|
219 | - } |
|
220 | - |
|
221 | - |
|
222 | - /** |
|
223 | - * set_submit_button_text |
|
224 | - * sets the text that appears on the reg step form submit button |
|
225 | - * |
|
226 | - * @param string $submit_button_text |
|
227 | - */ |
|
228 | - public function set_submit_button_text($submit_button_text = '') |
|
229 | - { |
|
230 | - if (! empty($submit_button_text)) { |
|
231 | - $this->_submit_button_text = $submit_button_text; |
|
232 | - } elseif ($this->checkout->next_step instanceof EE_SPCO_Reg_Step) { |
|
233 | - if ($this->checkout->revisit) { |
|
234 | - $this->_submit_button_text = sprintf( |
|
235 | - esc_html__('Update %s', 'event_espresso'), |
|
236 | - $this->checkout->current_step->name() |
|
237 | - ); |
|
238 | - } else { |
|
239 | - $this->_submit_button_text = sprintf( |
|
240 | - esc_html__('Proceed to %s', 'event_espresso'), |
|
241 | - $this->checkout->next_step->name() |
|
242 | - ); |
|
243 | - } |
|
244 | - } |
|
245 | - // filters the submit button text |
|
246 | - $this->_submit_button_text = apply_filters( |
|
247 | - 'FHEE__EE_SPCO_Reg_Step__set_submit_button_text___submit_button_text', |
|
248 | - $this->_submit_button_text, |
|
249 | - $this->checkout |
|
250 | - ); |
|
251 | - } |
|
252 | - |
|
253 | - |
|
254 | - /** |
|
255 | - * @param boolean $is_current_step |
|
256 | - */ |
|
257 | - public function set_is_current_step($is_current_step) |
|
258 | - { |
|
259 | - $this->_is_current_step = $is_current_step; |
|
260 | - } |
|
261 | - |
|
262 | - |
|
263 | - /** |
|
264 | - * @return boolean |
|
265 | - */ |
|
266 | - public function is_current_step() |
|
267 | - { |
|
268 | - return $this->_is_current_step; |
|
269 | - } |
|
270 | - |
|
271 | - |
|
272 | - /** |
|
273 | - * @return boolean |
|
274 | - */ |
|
275 | - public function is_final_step() |
|
276 | - { |
|
277 | - return $this instanceof EE_SPCO_Reg_Step_Finalize_Registration; |
|
278 | - } |
|
279 | - |
|
280 | - |
|
281 | - /** |
|
282 | - * @param int $order |
|
283 | - */ |
|
284 | - public function set_order($order) |
|
285 | - { |
|
286 | - $this->_order = $order; |
|
287 | - } |
|
288 | - |
|
289 | - |
|
290 | - /** |
|
291 | - * @return int |
|
292 | - */ |
|
293 | - public function order() |
|
294 | - { |
|
295 | - return $this->_order; |
|
296 | - } |
|
297 | - |
|
298 | - |
|
299 | - /** |
|
300 | - * @return string |
|
301 | - */ |
|
302 | - public function template() |
|
303 | - { |
|
304 | - return $this->_template; |
|
305 | - } |
|
306 | - |
|
307 | - |
|
308 | - /** |
|
309 | - * @return string |
|
310 | - */ |
|
311 | - public function success_message() |
|
312 | - { |
|
313 | - return $this->_success_message; |
|
314 | - } |
|
315 | - |
|
316 | - |
|
317 | - /** |
|
318 | - * _set_success_message |
|
319 | - * |
|
320 | - * @param string $success_message |
|
321 | - */ |
|
322 | - protected function _set_success_message($success_message) |
|
323 | - { |
|
324 | - $this->_success_message = $success_message; |
|
325 | - } |
|
326 | - |
|
327 | - |
|
328 | - /** |
|
329 | - * _reset_success_message |
|
330 | - * |
|
331 | - * @return void |
|
332 | - */ |
|
333 | - protected function _reset_success_message() |
|
334 | - { |
|
335 | - $this->_success_message = ''; |
|
336 | - } |
|
337 | - |
|
338 | - |
|
339 | - /** |
|
340 | - * @return string |
|
341 | - */ |
|
342 | - public function _instructions() |
|
343 | - { |
|
344 | - return $this->_instructions; |
|
345 | - } |
|
346 | - |
|
347 | - |
|
348 | - /** |
|
349 | - * @param string $instructions |
|
350 | - */ |
|
351 | - public function set_instructions($instructions) |
|
352 | - { |
|
353 | - $this->_instructions = apply_filters( |
|
354 | - 'FHEE__EE_SPCO_Reg_Step__set_instructions__instructions', |
|
355 | - $instructions, |
|
356 | - $this |
|
357 | - ); |
|
358 | - } |
|
359 | - |
|
360 | - |
|
361 | - /** |
|
362 | - * @param array $valid_data |
|
363 | - */ |
|
364 | - public function set_valid_data($valid_data) |
|
365 | - { |
|
366 | - $this->_valid_data = $valid_data; |
|
367 | - } |
|
368 | - |
|
369 | - |
|
370 | - /** |
|
371 | - * @return array |
|
372 | - * @throws EE_Error |
|
373 | - * @throws EE_Error |
|
374 | - */ |
|
375 | - public function valid_data() |
|
376 | - { |
|
377 | - if (empty($this->_valid_data)) { |
|
378 | - $this->_valid_data = $this->reg_form->valid_data(); |
|
379 | - } |
|
380 | - return $this->_valid_data; |
|
381 | - } |
|
382 | - |
|
383 | - |
|
384 | - /** |
|
385 | - * @return string |
|
386 | - */ |
|
387 | - public function reg_form_name() |
|
388 | - { |
|
389 | - if (empty($this->_reg_form_name)) { |
|
390 | - $this->set_reg_form_name('ee-spco-' . $this->slug() . '-reg-step-form'); |
|
391 | - } |
|
392 | - return $this->_reg_form_name; |
|
393 | - } |
|
394 | - |
|
395 | - |
|
396 | - /** |
|
397 | - * @param string $reg_form_name |
|
398 | - */ |
|
399 | - protected function set_reg_form_name($reg_form_name) |
|
400 | - { |
|
401 | - $this->_reg_form_name = $reg_form_name; |
|
402 | - } |
|
403 | - |
|
404 | - |
|
405 | - /** |
|
406 | - * reg_step_url |
|
407 | - * |
|
408 | - * @param string $action |
|
409 | - * @return string |
|
410 | - */ |
|
411 | - public function reg_step_url($action = '') |
|
412 | - { |
|
413 | - $query_args = ['step' => $this->slug()]; |
|
414 | - if (! empty($action)) { |
|
415 | - $query_args['action'] = $action; |
|
416 | - } |
|
417 | - // final step has no display |
|
418 | - if ($this instanceof EE_SPCO_Reg_Step_Finalize_Registration && $action === 'display_spco_reg_step') { |
|
419 | - $query_args['action'] = 'process_reg_step'; |
|
420 | - } |
|
421 | - if ($this->checkout->revisit) { |
|
422 | - $query_args['revisit'] = true; |
|
423 | - } |
|
424 | - if ($this->checkout->reg_url_link) { |
|
425 | - $query_args['e_reg_url_link'] = $this->checkout->reg_url_link; |
|
426 | - } |
|
427 | - return add_query_arg($query_args, $this->checkout->reg_page_base_url); |
|
428 | - } |
|
429 | - |
|
430 | - |
|
431 | - /** |
|
432 | - * creates the default hidden inputs section |
|
433 | - * |
|
434 | - * @return EE_Form_Section_Proper |
|
435 | - * @throws EE_Error |
|
436 | - */ |
|
437 | - public function reg_step_hidden_inputs() |
|
438 | - { |
|
439 | - // hidden inputs for admin registrations |
|
440 | - if ($this->checkout->admin_request) { |
|
441 | - return new EE_Form_Section_Proper( |
|
442 | - [ |
|
443 | - 'layout_strategy' => new EE_Div_Per_Section_Layout(), |
|
444 | - 'html_id' => 'ee-' . $this->slug() . '-hidden-inputs', |
|
445 | - 'subsections' => [ |
|
446 | - 'next_step' => new EE_Fixed_Hidden_Input( |
|
447 | - [ |
|
448 | - 'html_name' => 'next_step', |
|
449 | - 'html_id' => 'spco-' . $this->slug() . '-next-step', |
|
450 | - 'default' => $this->checkout->next_step instanceof EE_SPCO_Reg_Step |
|
451 | - ? $this->checkout->next_step->slug() |
|
452 | - : '', |
|
453 | - ] |
|
454 | - ), |
|
455 | - ], |
|
456 | - ] |
|
457 | - ); |
|
458 | - } |
|
459 | - // hidden inputs for frontend registrations |
|
460 | - return new EE_Form_Section_Proper( |
|
461 | - [ |
|
462 | - 'layout_strategy' => new EE_Div_Per_Section_Layout(), |
|
463 | - 'html_id' => 'ee-' . $this->slug() . '-hidden-inputs', |
|
464 | - 'subsections' => [ |
|
465 | - 'action' => new EE_Fixed_Hidden_Input( |
|
466 | - [ |
|
467 | - 'html_name' => 'action', |
|
468 | - 'html_id' => 'spco-' . $this->slug() . '-action', |
|
469 | - 'default' => apply_filters( |
|
470 | - 'FHEE__EE_SPCO_Reg_Step__reg_step_hidden_inputs__default_form_action', |
|
471 | - empty($this->checkout->reg_url_link) |
|
472 | - ? 'process_reg_step' |
|
473 | - : 'update_reg_step', |
|
474 | - $this |
|
475 | - ), |
|
476 | - ] |
|
477 | - ), |
|
478 | - 'next_step' => new EE_Fixed_Hidden_Input( |
|
479 | - [ |
|
480 | - 'html_name' => 'next_step', |
|
481 | - 'html_id' => 'spco-' . $this->slug() . '-next-step', |
|
482 | - 'default' => $this->checkout->next_step instanceof EE_SPCO_Reg_Step |
|
483 | - ? $this->checkout->next_step->slug() |
|
484 | - : '', |
|
485 | - ] |
|
486 | - ), |
|
487 | - 'e_reg_url_link' => new EE_Fixed_Hidden_Input( |
|
488 | - [ |
|
489 | - 'html_name' => 'e_reg_url_link', |
|
490 | - 'html_id' => 'spco-reg_url_link', |
|
491 | - 'default' => $this->checkout->reg_url_link, |
|
492 | - ] |
|
493 | - ), |
|
494 | - 'revisit' => new EE_Fixed_Hidden_Input( |
|
495 | - [ |
|
496 | - 'html_name' => 'revisit', |
|
497 | - 'html_id' => 'spco-revisit', |
|
498 | - 'default' => $this->checkout->revisit, |
|
499 | - ] |
|
500 | - ), |
|
501 | - ], |
|
502 | - ] |
|
503 | - ); |
|
504 | - } |
|
505 | - |
|
506 | - |
|
507 | - /** |
|
508 | - * generate_reg_form_for_actions |
|
509 | - * |
|
510 | - * @param array $actions |
|
511 | - * @return void |
|
512 | - */ |
|
513 | - public function generate_reg_form_for_actions($actions = []) |
|
514 | - { |
|
515 | - $actions = array_merge( |
|
516 | - [ |
|
517 | - 'generate_reg_form', |
|
518 | - 'display_spco_reg_step', |
|
519 | - 'process_reg_step', |
|
520 | - 'update_reg_step', |
|
521 | - ], |
|
522 | - $actions |
|
523 | - ); |
|
524 | - $this->checkout->generate_reg_form = in_array($this->checkout->action, $actions, true); |
|
525 | - } |
|
526 | - |
|
527 | - |
|
528 | - /** |
|
529 | - * @return string |
|
530 | - * @throws EE_Error |
|
531 | - */ |
|
532 | - public function display_reg_form() |
|
533 | - { |
|
534 | - $html = ''; |
|
535 | - if ($this->reg_form instanceof EE_Form_Section_Proper) { |
|
536 | - do_action('AHEE__EE_SPCO_Reg_Step__display_reg_form__reg_form', $this->reg_form, $this); |
|
537 | - $html .= ! $this->checkout->admin_request ? $this->reg_form->form_open($this->reg_step_url()) : ''; |
|
538 | - if ($this->request->isAjax()) { |
|
539 | - $this->reg_form->localize_validation_rules(); |
|
540 | - $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization()); |
|
541 | - } |
|
542 | - $html .= $this->reg_form->get_html(); |
|
543 | - $html .= ! $this->checkout->admin_request ? $this->reg_step_submit_button() : ''; |
|
544 | - $html .= ! $this->checkout->admin_request ? $this->reg_form->form_close() : ''; |
|
545 | - } |
|
546 | - return $html; |
|
547 | - } |
|
548 | - |
|
549 | - |
|
550 | - /** |
|
551 | - * div_class - returns nothing for current step, but a css class of "hidden" for others |
|
552 | - * |
|
553 | - * @return string |
|
554 | - * @throws EE_Error |
|
555 | - */ |
|
556 | - public function reg_step_submit_button() |
|
557 | - { |
|
558 | - if (! $this->checkout->next_step instanceof EE_SPCO_Reg_Step) { |
|
559 | - return ''; |
|
560 | - } |
|
561 | - ob_start(); |
|
562 | - do_action( |
|
563 | - 'AHEE__before_spco_whats_next_buttons', |
|
564 | - $this->slug(), |
|
565 | - $this->checkout->next_step->slug(), |
|
566 | - $this->checkout |
|
567 | - ); |
|
568 | - $html = ob_get_clean(); |
|
569 | - // generate submit button |
|
570 | - $submit_btn = new EE_Submit_Input( |
|
571 | - [ |
|
572 | - 'html_name' => 'spco-go-to-step-' . $this->checkout->next_step->slug(), |
|
573 | - 'html_id' => 'spco-go-to-step-' . $this->checkout->next_step->slug(), |
|
574 | - 'html_class' => 'spco-next-step-btn', |
|
575 | - 'other_html_attributes' => ' rel="' . $this->slug() . '"', |
|
576 | - 'default' => $this->submit_button_text(), |
|
577 | - ] |
|
578 | - ); |
|
579 | - $submit_btn->set_button_css_attributes(true, 'large'); |
|
580 | - $submit_btn_html = $submit_btn->get_html_for_input(); |
|
581 | - $html .= EEH_HTML::div( |
|
582 | - apply_filters('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', $submit_btn_html, $this), |
|
583 | - 'spco-' . $this->slug() . '-whats-next-buttons-dv', |
|
584 | - 'spco-whats-next-buttons' |
|
585 | - ); |
|
586 | - return $html; |
|
587 | - } |
|
588 | - |
|
589 | - |
|
590 | - /** |
|
591 | - * div_class - returns nothing for current step, but a css class of "hidden" for others |
|
592 | - * |
|
593 | - * @return string |
|
594 | - */ |
|
595 | - public function div_class() |
|
596 | - { |
|
597 | - return $this->is_current_step() ? '' : ' hidden'; |
|
598 | - } |
|
599 | - |
|
600 | - |
|
601 | - /** |
|
602 | - * div_class - returns a css class of "hidden" for current step, but nothing for others |
|
603 | - * |
|
604 | - * @return string |
|
605 | - */ |
|
606 | - public function edit_lnk_url() |
|
607 | - { |
|
608 | - return add_query_arg(['step' => $this->slug()], $this->checkout->reg_page_base_url); |
|
609 | - } |
|
610 | - |
|
611 | - |
|
612 | - /** |
|
613 | - * div_class - returns a css class of "hidden" for current step, but nothing for others |
|
614 | - * |
|
615 | - * @return string |
|
616 | - */ |
|
617 | - public function edit_link_class() |
|
618 | - { |
|
619 | - return $this->is_current_step() ? ' hidden' : ''; |
|
620 | - } |
|
621 | - |
|
622 | - |
|
623 | - /** |
|
624 | - * update_checkout with changes that have been made to the cart |
|
625 | - * |
|
626 | - * @return void |
|
627 | - * @throws EE_Error |
|
628 | - * @throws ReflectionException |
|
629 | - */ |
|
630 | - public function update_checkout() |
|
631 | - { |
|
632 | - // grab the cart grand total and reset TXN total |
|
633 | - $this->checkout->transaction->set_total($this->checkout->cart->get_cart_grand_total()); |
|
634 | - $this->checkout->stash_transaction_and_checkout(); |
|
635 | - } |
|
636 | - |
|
637 | - |
|
638 | - /** |
|
639 | - * __sleep |
|
640 | - * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon |
|
641 | - * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the |
|
642 | - * reg form, because if needed, it will be regenerated anyways |
|
643 | - * |
|
644 | - * @return array |
|
645 | - */ |
|
646 | - public function __sleep() |
|
647 | - { |
|
648 | - // remove the reg form and the checkout |
|
649 | - return array_diff(array_keys(get_object_vars($this)), ['reg_form', 'checkout']); |
|
650 | - } |
|
651 | - |
|
652 | - |
|
653 | - /** |
|
654 | - * @param RequestInterface $request |
|
655 | - */ |
|
656 | - public function setRequest(RequestInterface $request) |
|
657 | - { |
|
658 | - $this->request = $request; |
|
659 | - } |
|
16 | + /** |
|
17 | + * $_completed - TRUE if this step has fully completed it's duties |
|
18 | + * |
|
19 | + * @access protected |
|
20 | + * @type bool $_completed |
|
21 | + */ |
|
22 | + protected $_completed = false; |
|
23 | + |
|
24 | + /** |
|
25 | + * $_is_current_step - TRUE if this is the current step |
|
26 | + * |
|
27 | + * @access protected |
|
28 | + * @type bool $_is_current_step |
|
29 | + */ |
|
30 | + protected $_is_current_step = false; |
|
31 | + |
|
32 | + /** |
|
33 | + * $_order - when the reg step should be run relative to other steps |
|
34 | + * |
|
35 | + * @access protected |
|
36 | + * @type int $_template |
|
37 | + */ |
|
38 | + protected $_order = 0; |
|
39 | + |
|
40 | + /** |
|
41 | + * $_slug - URL param for this step |
|
42 | + * |
|
43 | + * @access protected |
|
44 | + * @type string $_slug |
|
45 | + */ |
|
46 | + protected $_slug; |
|
47 | + |
|
48 | + /** |
|
49 | + * $_name - Step Name - translatable string |
|
50 | + * |
|
51 | + * @access protected |
|
52 | + * @type string $_slug |
|
53 | + */ |
|
54 | + protected $_name; |
|
55 | + |
|
56 | + /** |
|
57 | + * $_submit_button_text - translatable string that appears on this step's submit button |
|
58 | + * |
|
59 | + * @access protected |
|
60 | + * @type string $_slug |
|
61 | + */ |
|
62 | + protected $_submit_button_text; |
|
63 | + |
|
64 | + /** |
|
65 | + * $_template - template name |
|
66 | + * |
|
67 | + * @access protected |
|
68 | + * @type string $_template |
|
69 | + */ |
|
70 | + protected $_template; |
|
71 | + |
|
72 | + /** |
|
73 | + * $_reg_form_name - the form input name and id attribute |
|
74 | + * |
|
75 | + * @access protected |
|
76 | + * @var string $_reg_form_name |
|
77 | + */ |
|
78 | + protected $_reg_form_name; |
|
79 | + |
|
80 | + /** |
|
81 | + * $_success_message - text to display upon successful form submission |
|
82 | + * |
|
83 | + * @access private |
|
84 | + * @var string $_success_message |
|
85 | + */ |
|
86 | + protected $_success_message; |
|
87 | + |
|
88 | + /** |
|
89 | + * $_instructions - a brief description of how to complete the reg step. |
|
90 | + * Usually displayed in conjunction with the previous step's success message. |
|
91 | + * |
|
92 | + * @access private |
|
93 | + * @var string $_instructions |
|
94 | + */ |
|
95 | + protected $_instructions; |
|
96 | + |
|
97 | + /** |
|
98 | + * $_valid_data - the normalized and validated data for this step |
|
99 | + * |
|
100 | + * @access public |
|
101 | + * @var array $_valid_data |
|
102 | + */ |
|
103 | + protected $_valid_data = []; |
|
104 | + |
|
105 | + /** |
|
106 | + * $reg_form - the registration form for this step |
|
107 | + * |
|
108 | + * @access public |
|
109 | + * @var EE_Form_Section_Proper $reg_form |
|
110 | + */ |
|
111 | + public $reg_form; |
|
112 | + |
|
113 | + /** |
|
114 | + * $checkout - EE_Checkout object for handling the properties of the current checkout process |
|
115 | + * |
|
116 | + * @access public |
|
117 | + * @var EE_Checkout $checkout |
|
118 | + */ |
|
119 | + public $checkout; |
|
120 | + |
|
121 | + /** |
|
122 | + * @var RequestInterface $request |
|
123 | + */ |
|
124 | + protected $request; |
|
125 | + |
|
126 | + |
|
127 | + /** |
|
128 | + * @return void |
|
129 | + */ |
|
130 | + abstract public function translate_js_strings(); |
|
131 | + |
|
132 | + |
|
133 | + /** |
|
134 | + * @return void |
|
135 | + */ |
|
136 | + abstract public function enqueue_styles_and_scripts(); |
|
137 | + |
|
138 | + |
|
139 | + /** |
|
140 | + * @return boolean |
|
141 | + */ |
|
142 | + abstract public function initialize_reg_step(); |
|
143 | + |
|
144 | + |
|
145 | + /** |
|
146 | + * @return string |
|
147 | + */ |
|
148 | + abstract public function generate_reg_form(); |
|
149 | + |
|
150 | + |
|
151 | + /** |
|
152 | + * @return boolean |
|
153 | + */ |
|
154 | + abstract public function process_reg_step(); |
|
155 | + |
|
156 | + |
|
157 | + /** |
|
158 | + * @return boolean |
|
159 | + */ |
|
160 | + abstract public function update_reg_step(); |
|
161 | + |
|
162 | + |
|
163 | + /** |
|
164 | + * @return boolean |
|
165 | + */ |
|
166 | + public function completed() |
|
167 | + { |
|
168 | + return $this->_completed; |
|
169 | + } |
|
170 | + |
|
171 | + |
|
172 | + /** |
|
173 | + * set_completed - toggles $_completed to TRUE |
|
174 | + */ |
|
175 | + public function set_completed() |
|
176 | + { |
|
177 | + // DEBUG LOG |
|
178 | + // $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ ); |
|
179 | + $this->_completed = apply_filters('FHEE__EE_SPCO_Reg_Step__set_completed___completed', true, $this); |
|
180 | + } |
|
181 | + |
|
182 | + |
|
183 | + /** |
|
184 | + * set_completed - toggles $_completed to FALSE |
|
185 | + */ |
|
186 | + public function set_not_completed() |
|
187 | + { |
|
188 | + $this->_completed = false; |
|
189 | + } |
|
190 | + |
|
191 | + |
|
192 | + /** |
|
193 | + * @return string |
|
194 | + */ |
|
195 | + public function name() |
|
196 | + { |
|
197 | + return $this->_name; |
|
198 | + } |
|
199 | + |
|
200 | + |
|
201 | + /** |
|
202 | + * @return string |
|
203 | + */ |
|
204 | + public function slug() |
|
205 | + { |
|
206 | + return $this->_slug; |
|
207 | + } |
|
208 | + |
|
209 | + |
|
210 | + /** |
|
211 | + * submit_button_text |
|
212 | + * the text that appears on the reg step form submit button |
|
213 | + * |
|
214 | + * @return string |
|
215 | + */ |
|
216 | + public function submit_button_text() |
|
217 | + { |
|
218 | + return $this->_submit_button_text; |
|
219 | + } |
|
220 | + |
|
221 | + |
|
222 | + /** |
|
223 | + * set_submit_button_text |
|
224 | + * sets the text that appears on the reg step form submit button |
|
225 | + * |
|
226 | + * @param string $submit_button_text |
|
227 | + */ |
|
228 | + public function set_submit_button_text($submit_button_text = '') |
|
229 | + { |
|
230 | + if (! empty($submit_button_text)) { |
|
231 | + $this->_submit_button_text = $submit_button_text; |
|
232 | + } elseif ($this->checkout->next_step instanceof EE_SPCO_Reg_Step) { |
|
233 | + if ($this->checkout->revisit) { |
|
234 | + $this->_submit_button_text = sprintf( |
|
235 | + esc_html__('Update %s', 'event_espresso'), |
|
236 | + $this->checkout->current_step->name() |
|
237 | + ); |
|
238 | + } else { |
|
239 | + $this->_submit_button_text = sprintf( |
|
240 | + esc_html__('Proceed to %s', 'event_espresso'), |
|
241 | + $this->checkout->next_step->name() |
|
242 | + ); |
|
243 | + } |
|
244 | + } |
|
245 | + // filters the submit button text |
|
246 | + $this->_submit_button_text = apply_filters( |
|
247 | + 'FHEE__EE_SPCO_Reg_Step__set_submit_button_text___submit_button_text', |
|
248 | + $this->_submit_button_text, |
|
249 | + $this->checkout |
|
250 | + ); |
|
251 | + } |
|
252 | + |
|
253 | + |
|
254 | + /** |
|
255 | + * @param boolean $is_current_step |
|
256 | + */ |
|
257 | + public function set_is_current_step($is_current_step) |
|
258 | + { |
|
259 | + $this->_is_current_step = $is_current_step; |
|
260 | + } |
|
261 | + |
|
262 | + |
|
263 | + /** |
|
264 | + * @return boolean |
|
265 | + */ |
|
266 | + public function is_current_step() |
|
267 | + { |
|
268 | + return $this->_is_current_step; |
|
269 | + } |
|
270 | + |
|
271 | + |
|
272 | + /** |
|
273 | + * @return boolean |
|
274 | + */ |
|
275 | + public function is_final_step() |
|
276 | + { |
|
277 | + return $this instanceof EE_SPCO_Reg_Step_Finalize_Registration; |
|
278 | + } |
|
279 | + |
|
280 | + |
|
281 | + /** |
|
282 | + * @param int $order |
|
283 | + */ |
|
284 | + public function set_order($order) |
|
285 | + { |
|
286 | + $this->_order = $order; |
|
287 | + } |
|
288 | + |
|
289 | + |
|
290 | + /** |
|
291 | + * @return int |
|
292 | + */ |
|
293 | + public function order() |
|
294 | + { |
|
295 | + return $this->_order; |
|
296 | + } |
|
297 | + |
|
298 | + |
|
299 | + /** |
|
300 | + * @return string |
|
301 | + */ |
|
302 | + public function template() |
|
303 | + { |
|
304 | + return $this->_template; |
|
305 | + } |
|
306 | + |
|
307 | + |
|
308 | + /** |
|
309 | + * @return string |
|
310 | + */ |
|
311 | + public function success_message() |
|
312 | + { |
|
313 | + return $this->_success_message; |
|
314 | + } |
|
315 | + |
|
316 | + |
|
317 | + /** |
|
318 | + * _set_success_message |
|
319 | + * |
|
320 | + * @param string $success_message |
|
321 | + */ |
|
322 | + protected function _set_success_message($success_message) |
|
323 | + { |
|
324 | + $this->_success_message = $success_message; |
|
325 | + } |
|
326 | + |
|
327 | + |
|
328 | + /** |
|
329 | + * _reset_success_message |
|
330 | + * |
|
331 | + * @return void |
|
332 | + */ |
|
333 | + protected function _reset_success_message() |
|
334 | + { |
|
335 | + $this->_success_message = ''; |
|
336 | + } |
|
337 | + |
|
338 | + |
|
339 | + /** |
|
340 | + * @return string |
|
341 | + */ |
|
342 | + public function _instructions() |
|
343 | + { |
|
344 | + return $this->_instructions; |
|
345 | + } |
|
346 | + |
|
347 | + |
|
348 | + /** |
|
349 | + * @param string $instructions |
|
350 | + */ |
|
351 | + public function set_instructions($instructions) |
|
352 | + { |
|
353 | + $this->_instructions = apply_filters( |
|
354 | + 'FHEE__EE_SPCO_Reg_Step__set_instructions__instructions', |
|
355 | + $instructions, |
|
356 | + $this |
|
357 | + ); |
|
358 | + } |
|
359 | + |
|
360 | + |
|
361 | + /** |
|
362 | + * @param array $valid_data |
|
363 | + */ |
|
364 | + public function set_valid_data($valid_data) |
|
365 | + { |
|
366 | + $this->_valid_data = $valid_data; |
|
367 | + } |
|
368 | + |
|
369 | + |
|
370 | + /** |
|
371 | + * @return array |
|
372 | + * @throws EE_Error |
|
373 | + * @throws EE_Error |
|
374 | + */ |
|
375 | + public function valid_data() |
|
376 | + { |
|
377 | + if (empty($this->_valid_data)) { |
|
378 | + $this->_valid_data = $this->reg_form->valid_data(); |
|
379 | + } |
|
380 | + return $this->_valid_data; |
|
381 | + } |
|
382 | + |
|
383 | + |
|
384 | + /** |
|
385 | + * @return string |
|
386 | + */ |
|
387 | + public function reg_form_name() |
|
388 | + { |
|
389 | + if (empty($this->_reg_form_name)) { |
|
390 | + $this->set_reg_form_name('ee-spco-' . $this->slug() . '-reg-step-form'); |
|
391 | + } |
|
392 | + return $this->_reg_form_name; |
|
393 | + } |
|
394 | + |
|
395 | + |
|
396 | + /** |
|
397 | + * @param string $reg_form_name |
|
398 | + */ |
|
399 | + protected function set_reg_form_name($reg_form_name) |
|
400 | + { |
|
401 | + $this->_reg_form_name = $reg_form_name; |
|
402 | + } |
|
403 | + |
|
404 | + |
|
405 | + /** |
|
406 | + * reg_step_url |
|
407 | + * |
|
408 | + * @param string $action |
|
409 | + * @return string |
|
410 | + */ |
|
411 | + public function reg_step_url($action = '') |
|
412 | + { |
|
413 | + $query_args = ['step' => $this->slug()]; |
|
414 | + if (! empty($action)) { |
|
415 | + $query_args['action'] = $action; |
|
416 | + } |
|
417 | + // final step has no display |
|
418 | + if ($this instanceof EE_SPCO_Reg_Step_Finalize_Registration && $action === 'display_spco_reg_step') { |
|
419 | + $query_args['action'] = 'process_reg_step'; |
|
420 | + } |
|
421 | + if ($this->checkout->revisit) { |
|
422 | + $query_args['revisit'] = true; |
|
423 | + } |
|
424 | + if ($this->checkout->reg_url_link) { |
|
425 | + $query_args['e_reg_url_link'] = $this->checkout->reg_url_link; |
|
426 | + } |
|
427 | + return add_query_arg($query_args, $this->checkout->reg_page_base_url); |
|
428 | + } |
|
429 | + |
|
430 | + |
|
431 | + /** |
|
432 | + * creates the default hidden inputs section |
|
433 | + * |
|
434 | + * @return EE_Form_Section_Proper |
|
435 | + * @throws EE_Error |
|
436 | + */ |
|
437 | + public function reg_step_hidden_inputs() |
|
438 | + { |
|
439 | + // hidden inputs for admin registrations |
|
440 | + if ($this->checkout->admin_request) { |
|
441 | + return new EE_Form_Section_Proper( |
|
442 | + [ |
|
443 | + 'layout_strategy' => new EE_Div_Per_Section_Layout(), |
|
444 | + 'html_id' => 'ee-' . $this->slug() . '-hidden-inputs', |
|
445 | + 'subsections' => [ |
|
446 | + 'next_step' => new EE_Fixed_Hidden_Input( |
|
447 | + [ |
|
448 | + 'html_name' => 'next_step', |
|
449 | + 'html_id' => 'spco-' . $this->slug() . '-next-step', |
|
450 | + 'default' => $this->checkout->next_step instanceof EE_SPCO_Reg_Step |
|
451 | + ? $this->checkout->next_step->slug() |
|
452 | + : '', |
|
453 | + ] |
|
454 | + ), |
|
455 | + ], |
|
456 | + ] |
|
457 | + ); |
|
458 | + } |
|
459 | + // hidden inputs for frontend registrations |
|
460 | + return new EE_Form_Section_Proper( |
|
461 | + [ |
|
462 | + 'layout_strategy' => new EE_Div_Per_Section_Layout(), |
|
463 | + 'html_id' => 'ee-' . $this->slug() . '-hidden-inputs', |
|
464 | + 'subsections' => [ |
|
465 | + 'action' => new EE_Fixed_Hidden_Input( |
|
466 | + [ |
|
467 | + 'html_name' => 'action', |
|
468 | + 'html_id' => 'spco-' . $this->slug() . '-action', |
|
469 | + 'default' => apply_filters( |
|
470 | + 'FHEE__EE_SPCO_Reg_Step__reg_step_hidden_inputs__default_form_action', |
|
471 | + empty($this->checkout->reg_url_link) |
|
472 | + ? 'process_reg_step' |
|
473 | + : 'update_reg_step', |
|
474 | + $this |
|
475 | + ), |
|
476 | + ] |
|
477 | + ), |
|
478 | + 'next_step' => new EE_Fixed_Hidden_Input( |
|
479 | + [ |
|
480 | + 'html_name' => 'next_step', |
|
481 | + 'html_id' => 'spco-' . $this->slug() . '-next-step', |
|
482 | + 'default' => $this->checkout->next_step instanceof EE_SPCO_Reg_Step |
|
483 | + ? $this->checkout->next_step->slug() |
|
484 | + : '', |
|
485 | + ] |
|
486 | + ), |
|
487 | + 'e_reg_url_link' => new EE_Fixed_Hidden_Input( |
|
488 | + [ |
|
489 | + 'html_name' => 'e_reg_url_link', |
|
490 | + 'html_id' => 'spco-reg_url_link', |
|
491 | + 'default' => $this->checkout->reg_url_link, |
|
492 | + ] |
|
493 | + ), |
|
494 | + 'revisit' => new EE_Fixed_Hidden_Input( |
|
495 | + [ |
|
496 | + 'html_name' => 'revisit', |
|
497 | + 'html_id' => 'spco-revisit', |
|
498 | + 'default' => $this->checkout->revisit, |
|
499 | + ] |
|
500 | + ), |
|
501 | + ], |
|
502 | + ] |
|
503 | + ); |
|
504 | + } |
|
505 | + |
|
506 | + |
|
507 | + /** |
|
508 | + * generate_reg_form_for_actions |
|
509 | + * |
|
510 | + * @param array $actions |
|
511 | + * @return void |
|
512 | + */ |
|
513 | + public function generate_reg_form_for_actions($actions = []) |
|
514 | + { |
|
515 | + $actions = array_merge( |
|
516 | + [ |
|
517 | + 'generate_reg_form', |
|
518 | + 'display_spco_reg_step', |
|
519 | + 'process_reg_step', |
|
520 | + 'update_reg_step', |
|
521 | + ], |
|
522 | + $actions |
|
523 | + ); |
|
524 | + $this->checkout->generate_reg_form = in_array($this->checkout->action, $actions, true); |
|
525 | + } |
|
526 | + |
|
527 | + |
|
528 | + /** |
|
529 | + * @return string |
|
530 | + * @throws EE_Error |
|
531 | + */ |
|
532 | + public function display_reg_form() |
|
533 | + { |
|
534 | + $html = ''; |
|
535 | + if ($this->reg_form instanceof EE_Form_Section_Proper) { |
|
536 | + do_action('AHEE__EE_SPCO_Reg_Step__display_reg_form__reg_form', $this->reg_form, $this); |
|
537 | + $html .= ! $this->checkout->admin_request ? $this->reg_form->form_open($this->reg_step_url()) : ''; |
|
538 | + if ($this->request->isAjax()) { |
|
539 | + $this->reg_form->localize_validation_rules(); |
|
540 | + $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization()); |
|
541 | + } |
|
542 | + $html .= $this->reg_form->get_html(); |
|
543 | + $html .= ! $this->checkout->admin_request ? $this->reg_step_submit_button() : ''; |
|
544 | + $html .= ! $this->checkout->admin_request ? $this->reg_form->form_close() : ''; |
|
545 | + } |
|
546 | + return $html; |
|
547 | + } |
|
548 | + |
|
549 | + |
|
550 | + /** |
|
551 | + * div_class - returns nothing for current step, but a css class of "hidden" for others |
|
552 | + * |
|
553 | + * @return string |
|
554 | + * @throws EE_Error |
|
555 | + */ |
|
556 | + public function reg_step_submit_button() |
|
557 | + { |
|
558 | + if (! $this->checkout->next_step instanceof EE_SPCO_Reg_Step) { |
|
559 | + return ''; |
|
560 | + } |
|
561 | + ob_start(); |
|
562 | + do_action( |
|
563 | + 'AHEE__before_spco_whats_next_buttons', |
|
564 | + $this->slug(), |
|
565 | + $this->checkout->next_step->slug(), |
|
566 | + $this->checkout |
|
567 | + ); |
|
568 | + $html = ob_get_clean(); |
|
569 | + // generate submit button |
|
570 | + $submit_btn = new EE_Submit_Input( |
|
571 | + [ |
|
572 | + 'html_name' => 'spco-go-to-step-' . $this->checkout->next_step->slug(), |
|
573 | + 'html_id' => 'spco-go-to-step-' . $this->checkout->next_step->slug(), |
|
574 | + 'html_class' => 'spco-next-step-btn', |
|
575 | + 'other_html_attributes' => ' rel="' . $this->slug() . '"', |
|
576 | + 'default' => $this->submit_button_text(), |
|
577 | + ] |
|
578 | + ); |
|
579 | + $submit_btn->set_button_css_attributes(true, 'large'); |
|
580 | + $submit_btn_html = $submit_btn->get_html_for_input(); |
|
581 | + $html .= EEH_HTML::div( |
|
582 | + apply_filters('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', $submit_btn_html, $this), |
|
583 | + 'spco-' . $this->slug() . '-whats-next-buttons-dv', |
|
584 | + 'spco-whats-next-buttons' |
|
585 | + ); |
|
586 | + return $html; |
|
587 | + } |
|
588 | + |
|
589 | + |
|
590 | + /** |
|
591 | + * div_class - returns nothing for current step, but a css class of "hidden" for others |
|
592 | + * |
|
593 | + * @return string |
|
594 | + */ |
|
595 | + public function div_class() |
|
596 | + { |
|
597 | + return $this->is_current_step() ? '' : ' hidden'; |
|
598 | + } |
|
599 | + |
|
600 | + |
|
601 | + /** |
|
602 | + * div_class - returns a css class of "hidden" for current step, but nothing for others |
|
603 | + * |
|
604 | + * @return string |
|
605 | + */ |
|
606 | + public function edit_lnk_url() |
|
607 | + { |
|
608 | + return add_query_arg(['step' => $this->slug()], $this->checkout->reg_page_base_url); |
|
609 | + } |
|
610 | + |
|
611 | + |
|
612 | + /** |
|
613 | + * div_class - returns a css class of "hidden" for current step, but nothing for others |
|
614 | + * |
|
615 | + * @return string |
|
616 | + */ |
|
617 | + public function edit_link_class() |
|
618 | + { |
|
619 | + return $this->is_current_step() ? ' hidden' : ''; |
|
620 | + } |
|
621 | + |
|
622 | + |
|
623 | + /** |
|
624 | + * update_checkout with changes that have been made to the cart |
|
625 | + * |
|
626 | + * @return void |
|
627 | + * @throws EE_Error |
|
628 | + * @throws ReflectionException |
|
629 | + */ |
|
630 | + public function update_checkout() |
|
631 | + { |
|
632 | + // grab the cart grand total and reset TXN total |
|
633 | + $this->checkout->transaction->set_total($this->checkout->cart->get_cart_grand_total()); |
|
634 | + $this->checkout->stash_transaction_and_checkout(); |
|
635 | + } |
|
636 | + |
|
637 | + |
|
638 | + /** |
|
639 | + * __sleep |
|
640 | + * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon |
|
641 | + * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the |
|
642 | + * reg form, because if needed, it will be regenerated anyways |
|
643 | + * |
|
644 | + * @return array |
|
645 | + */ |
|
646 | + public function __sleep() |
|
647 | + { |
|
648 | + // remove the reg form and the checkout |
|
649 | + return array_diff(array_keys(get_object_vars($this)), ['reg_form', 'checkout']); |
|
650 | + } |
|
651 | + |
|
652 | + |
|
653 | + /** |
|
654 | + * @param RequestInterface $request |
|
655 | + */ |
|
656 | + public function setRequest(RequestInterface $request) |
|
657 | + { |
|
658 | + $this->request = $request; |
|
659 | + } |
|
660 | 660 | } |
@@ -40,279 +40,279 @@ |
||
40 | 40 | */ |
41 | 41 | class FilesDataHandler |
42 | 42 | { |
43 | - /** |
|
44 | - * @var Request |
|
45 | - */ |
|
46 | - protected $request; |
|
43 | + /** |
|
44 | + * @var Request |
|
45 | + */ |
|
46 | + protected $request; |
|
47 | 47 | |
48 | - /** |
|
49 | - * @var CollectionInterface | FileSubmissionInterface[] |
|
50 | - */ |
|
51 | - protected $file_objects; |
|
48 | + /** |
|
49 | + * @var CollectionInterface | FileSubmissionInterface[] |
|
50 | + */ |
|
51 | + protected $file_objects; |
|
52 | 52 | |
53 | - /** |
|
54 | - * @var bool |
|
55 | - */ |
|
56 | - protected $initialized = false; |
|
53 | + /** |
|
54 | + * @var bool |
|
55 | + */ |
|
56 | + protected $initialized = false; |
|
57 | 57 | |
58 | 58 | |
59 | - /** |
|
60 | - * FilesDataHandler constructor. |
|
61 | - * |
|
62 | - * @param Request $request |
|
63 | - */ |
|
64 | - public function __construct(Request $request) |
|
65 | - { |
|
66 | - $this->request = $request; |
|
67 | - } |
|
59 | + /** |
|
60 | + * FilesDataHandler constructor. |
|
61 | + * |
|
62 | + * @param Request $request |
|
63 | + */ |
|
64 | + public function __construct(Request $request) |
|
65 | + { |
|
66 | + $this->request = $request; |
|
67 | + } |
|
68 | 68 | |
69 | 69 | |
70 | - /** |
|
71 | - * @return CollectionInterface | FileSubmissionInterface[] |
|
72 | - * @throws UnexpectedValueException |
|
73 | - * @throws InvalidArgumentException |
|
74 | - * @since 4.9.80.p |
|
75 | - */ |
|
76 | - protected function getFileObjects() |
|
77 | - { |
|
78 | - $this->initialize(); |
|
79 | - return $this->file_objects; |
|
80 | - } |
|
70 | + /** |
|
71 | + * @return CollectionInterface | FileSubmissionInterface[] |
|
72 | + * @throws UnexpectedValueException |
|
73 | + * @throws InvalidArgumentException |
|
74 | + * @since 4.9.80.p |
|
75 | + */ |
|
76 | + protected function getFileObjects() |
|
77 | + { |
|
78 | + $this->initialize(); |
|
79 | + return $this->file_objects; |
|
80 | + } |
|
81 | 81 | |
82 | 82 | |
83 | - /** |
|
84 | - * Sets up the file objects from the request's $_FILES data. |
|
85 | - * |
|
86 | - * @throws UnexpectedValueException |
|
87 | - * @throws InvalidArgumentException |
|
88 | - * @throws InvalidInterfaceException |
|
89 | - * @since 4.9.80.p |
|
90 | - */ |
|
91 | - protected function initialize() |
|
92 | - { |
|
93 | - if ($this->initialized) { |
|
94 | - return; |
|
95 | - } |
|
96 | - $this->file_objects = new Collection( |
|
97 | - // collection interface |
|
98 | - 'EventEspresso\core\services\request\files\FileSubmissionInterface', |
|
99 | - // collection name |
|
100 | - 'submitted_files' |
|
101 | - ); |
|
102 | - $files_raw_data = $this->request->filesParams(); |
|
103 | - if (empty($files_raw_data)) { |
|
104 | - return; |
|
105 | - } |
|
106 | - if ($this->isStrangeFilesArray($files_raw_data)) { |
|
107 | - $data = $this->fixFilesDataArray($files_raw_data); |
|
108 | - } else { |
|
109 | - $data = $files_raw_data; |
|
110 | - } |
|
111 | - $this->createFileObjects($data); |
|
112 | - $this->initialized = true; |
|
113 | - } |
|
83 | + /** |
|
84 | + * Sets up the file objects from the request's $_FILES data. |
|
85 | + * |
|
86 | + * @throws UnexpectedValueException |
|
87 | + * @throws InvalidArgumentException |
|
88 | + * @throws InvalidInterfaceException |
|
89 | + * @since 4.9.80.p |
|
90 | + */ |
|
91 | + protected function initialize() |
|
92 | + { |
|
93 | + if ($this->initialized) { |
|
94 | + return; |
|
95 | + } |
|
96 | + $this->file_objects = new Collection( |
|
97 | + // collection interface |
|
98 | + 'EventEspresso\core\services\request\files\FileSubmissionInterface', |
|
99 | + // collection name |
|
100 | + 'submitted_files' |
|
101 | + ); |
|
102 | + $files_raw_data = $this->request->filesParams(); |
|
103 | + if (empty($files_raw_data)) { |
|
104 | + return; |
|
105 | + } |
|
106 | + if ($this->isStrangeFilesArray($files_raw_data)) { |
|
107 | + $data = $this->fixFilesDataArray($files_raw_data); |
|
108 | + } else { |
|
109 | + $data = $files_raw_data; |
|
110 | + } |
|
111 | + $this->createFileObjects($data); |
|
112 | + $this->initialized = true; |
|
113 | + } |
|
114 | 114 | |
115 | 115 | |
116 | - /** |
|
117 | - * Detects if $_FILES is a weird multi-dimensional array that needs fixing or not. |
|
118 | - * |
|
119 | - * @param $files_data |
|
120 | - * @return bool |
|
121 | - * @throws UnexpectedValueException |
|
122 | - * @since 4.9.80.p |
|
123 | - */ |
|
124 | - protected function isStrangeFilesArray($files_data) |
|
125 | - { |
|
126 | - if (! is_array($files_data)) { |
|
127 | - throw new UnexpectedValueException( |
|
128 | - sprintf( |
|
129 | - esc_html__( |
|
130 | - 'Unexpected PHP $_FILES data format. "%1$s" was expected to be an array.', |
|
131 | - 'event_espresso' |
|
132 | - ), |
|
133 | - (string) $files_data |
|
134 | - ) |
|
135 | - ); |
|
136 | - } |
|
137 | - $first_value = reset($files_data); |
|
138 | - if (! is_array($first_value)) { |
|
139 | - throw new UnexpectedValueException( |
|
140 | - sprintf( |
|
141 | - esc_html__( |
|
142 | - 'Unexpected PHP $_FILES data format. "%1$s" was expected to be an array.', |
|
143 | - 'event_espresso' |
|
144 | - ), |
|
145 | - (string) $first_value |
|
146 | - ) |
|
147 | - ); |
|
148 | - } |
|
149 | - $first_sub_array_item = reset($first_value); |
|
150 | - if (is_array($first_sub_array_item)) { |
|
151 | - // not just a 2d array |
|
152 | - return true; |
|
153 | - } |
|
154 | - // yep, just 2d array |
|
155 | - return false; |
|
156 | - } |
|
116 | + /** |
|
117 | + * Detects if $_FILES is a weird multi-dimensional array that needs fixing or not. |
|
118 | + * |
|
119 | + * @param $files_data |
|
120 | + * @return bool |
|
121 | + * @throws UnexpectedValueException |
|
122 | + * @since 4.9.80.p |
|
123 | + */ |
|
124 | + protected function isStrangeFilesArray($files_data) |
|
125 | + { |
|
126 | + if (! is_array($files_data)) { |
|
127 | + throw new UnexpectedValueException( |
|
128 | + sprintf( |
|
129 | + esc_html__( |
|
130 | + 'Unexpected PHP $_FILES data format. "%1$s" was expected to be an array.', |
|
131 | + 'event_espresso' |
|
132 | + ), |
|
133 | + (string) $files_data |
|
134 | + ) |
|
135 | + ); |
|
136 | + } |
|
137 | + $first_value = reset($files_data); |
|
138 | + if (! is_array($first_value)) { |
|
139 | + throw new UnexpectedValueException( |
|
140 | + sprintf( |
|
141 | + esc_html__( |
|
142 | + 'Unexpected PHP $_FILES data format. "%1$s" was expected to be an array.', |
|
143 | + 'event_espresso' |
|
144 | + ), |
|
145 | + (string) $first_value |
|
146 | + ) |
|
147 | + ); |
|
148 | + } |
|
149 | + $first_sub_array_item = reset($first_value); |
|
150 | + if (is_array($first_sub_array_item)) { |
|
151 | + // not just a 2d array |
|
152 | + return true; |
|
153 | + } |
|
154 | + // yep, just 2d array |
|
155 | + return false; |
|
156 | + } |
|
157 | 157 | |
158 | 158 | |
159 | - /** |
|
160 | - * Takes into account that $_FILES does a weird thing when you have hierarchical form names (eg `<input type="file" |
|
161 | - * name="my[hierarchical][form]">`): it leaves the top-level form part alone, but replaces the SECOND part with |
|
162 | - * "name", "size", "tmp_name", etc. So that file's data is located at "my[name][hierarchical][form]", |
|
163 | - * "my[size][hierarchical][form]", "my[tmp_name][hierarchical][form]", etc. It's really weird. |
|
164 | - * |
|
165 | - * @param $files_data |
|
166 | - * @return array |
|
167 | - * @since 4.9.80.p |
|
168 | - */ |
|
169 | - protected function fixFilesDataArray($files_data) |
|
170 | - { |
|
171 | - $sane_files_array = []; |
|
172 | - foreach ($files_data as $top_level_name => $top_level_children) { |
|
173 | - $sub_array = []; |
|
174 | - $sane_files_array[ $top_level_name ] = []; |
|
175 | - foreach ($top_level_children as $file_data_part => $second_level_children) { |
|
176 | - foreach ($second_level_children as $next_level_name => $sub_values) { |
|
177 | - $sub_array[ $next_level_name ] = $this->organizeFilesData($sub_values, $file_data_part); |
|
178 | - } |
|
179 | - $sane_files_array[ $top_level_name ] = array_replace_recursive( |
|
180 | - $sub_array, |
|
181 | - $sane_files_array[ $top_level_name ] |
|
182 | - ); |
|
183 | - } |
|
184 | - } |
|
185 | - return $sane_files_array; |
|
186 | - } |
|
159 | + /** |
|
160 | + * Takes into account that $_FILES does a weird thing when you have hierarchical form names (eg `<input type="file" |
|
161 | + * name="my[hierarchical][form]">`): it leaves the top-level form part alone, but replaces the SECOND part with |
|
162 | + * "name", "size", "tmp_name", etc. So that file's data is located at "my[name][hierarchical][form]", |
|
163 | + * "my[size][hierarchical][form]", "my[tmp_name][hierarchical][form]", etc. It's really weird. |
|
164 | + * |
|
165 | + * @param $files_data |
|
166 | + * @return array |
|
167 | + * @since 4.9.80.p |
|
168 | + */ |
|
169 | + protected function fixFilesDataArray($files_data) |
|
170 | + { |
|
171 | + $sane_files_array = []; |
|
172 | + foreach ($files_data as $top_level_name => $top_level_children) { |
|
173 | + $sub_array = []; |
|
174 | + $sane_files_array[ $top_level_name ] = []; |
|
175 | + foreach ($top_level_children as $file_data_part => $second_level_children) { |
|
176 | + foreach ($second_level_children as $next_level_name => $sub_values) { |
|
177 | + $sub_array[ $next_level_name ] = $this->organizeFilesData($sub_values, $file_data_part); |
|
178 | + } |
|
179 | + $sane_files_array[ $top_level_name ] = array_replace_recursive( |
|
180 | + $sub_array, |
|
181 | + $sane_files_array[ $top_level_name ] |
|
182 | + ); |
|
183 | + } |
|
184 | + } |
|
185 | + return $sane_files_array; |
|
186 | + } |
|
187 | 187 | |
188 | 188 | |
189 | - /** |
|
190 | - * Recursively explores the array until it finds a leaf node, and tacks `$type` as a final index in front of it. |
|
191 | - * |
|
192 | - * @param $data array|string |
|
193 | - * @param $type 'name', 'tmp_name', 'size', or 'error' |
|
194 | - * @return array |
|
195 | - * @since 4.9.80.p |
|
196 | - */ |
|
197 | - protected function organizeFilesData($data, $type) |
|
198 | - { |
|
199 | - if (! is_array($data)) { |
|
200 | - return [ |
|
201 | - $type => $data, |
|
202 | - ]; |
|
203 | - } |
|
204 | - $organized_data = []; |
|
205 | - foreach ($data as $input_name_part => $sub_inputs_or_value) { |
|
206 | - if (is_array($sub_inputs_or_value)) { |
|
207 | - $organized_data[ $input_name_part ] = $this->organizeFilesData($sub_inputs_or_value, $type); |
|
208 | - } else { |
|
209 | - $organized_data[ $input_name_part ][ $type ] = $sub_inputs_or_value; |
|
210 | - } |
|
211 | - } |
|
212 | - return $organized_data; |
|
213 | - } |
|
189 | + /** |
|
190 | + * Recursively explores the array until it finds a leaf node, and tacks `$type` as a final index in front of it. |
|
191 | + * |
|
192 | + * @param $data array|string |
|
193 | + * @param $type 'name', 'tmp_name', 'size', or 'error' |
|
194 | + * @return array |
|
195 | + * @since 4.9.80.p |
|
196 | + */ |
|
197 | + protected function organizeFilesData($data, $type) |
|
198 | + { |
|
199 | + if (! is_array($data)) { |
|
200 | + return [ |
|
201 | + $type => $data, |
|
202 | + ]; |
|
203 | + } |
|
204 | + $organized_data = []; |
|
205 | + foreach ($data as $input_name_part => $sub_inputs_or_value) { |
|
206 | + if (is_array($sub_inputs_or_value)) { |
|
207 | + $organized_data[ $input_name_part ] = $this->organizeFilesData($sub_inputs_or_value, $type); |
|
208 | + } else { |
|
209 | + $organized_data[ $input_name_part ][ $type ] = $sub_inputs_or_value; |
|
210 | + } |
|
211 | + } |
|
212 | + return $organized_data; |
|
213 | + } |
|
214 | 214 | |
215 | 215 | |
216 | - /** |
|
217 | - * Takes the organized $_FILES array (where all file info is located at the same spot as you'd expect an input |
|
218 | - * to be in post data, with all the file's data located side-by-side in an array) and creates a |
|
219 | - * multi-dimensional array of FileSubmissionInterface objects. Stores it in `$this->file_objects`. |
|
220 | - * |
|
221 | - * @param array $organized_files $_FILES but organized like $_POST |
|
222 | - * @param array $name_parts_so_far for multidimensional HTML form names, |
|
223 | - * @throws UnexpectedValueException |
|
224 | - * @throws InvalidArgumentException |
|
225 | - * @since 4.9.80.p |
|
226 | - */ |
|
227 | - protected function createFileObjects($organized_files, $name_parts_so_far = []) |
|
228 | - { |
|
229 | - if (! is_array($organized_files)) { |
|
230 | - throw new UnexpectedValueException( |
|
231 | - sprintf( |
|
232 | - esc_html__( |
|
233 | - 'Unexpected PHP $organized_files data format. "%1$s" was expected to be an array.', |
|
234 | - 'event_espresso' |
|
235 | - ), |
|
236 | - (string) $organized_files |
|
237 | - ) |
|
238 | - ); |
|
239 | - } |
|
240 | - foreach ($organized_files as $key => $value) { |
|
241 | - $this_input_name_parts = $name_parts_so_far; |
|
242 | - array_push( |
|
243 | - $this_input_name_parts, |
|
244 | - $key |
|
245 | - ); |
|
246 | - if (isset($value['name'], $value['tmp_name'], $value['size'])) { |
|
247 | - $html_name = $this->inputNameFromParts($this_input_name_parts); |
|
248 | - $this->file_objects->add( |
|
249 | - new FileSubmission( |
|
250 | - $value['name'], |
|
251 | - $value['tmp_name'], |
|
252 | - $value['size'], |
|
253 | - $value['error'] |
|
254 | - ), |
|
255 | - $html_name |
|
256 | - ); |
|
257 | - } else { |
|
258 | - $this->createFileObjects($value, $this_input_name_parts); |
|
259 | - } |
|
260 | - } |
|
261 | - } |
|
216 | + /** |
|
217 | + * Takes the organized $_FILES array (where all file info is located at the same spot as you'd expect an input |
|
218 | + * to be in post data, with all the file's data located side-by-side in an array) and creates a |
|
219 | + * multi-dimensional array of FileSubmissionInterface objects. Stores it in `$this->file_objects`. |
|
220 | + * |
|
221 | + * @param array $organized_files $_FILES but organized like $_POST |
|
222 | + * @param array $name_parts_so_far for multidimensional HTML form names, |
|
223 | + * @throws UnexpectedValueException |
|
224 | + * @throws InvalidArgumentException |
|
225 | + * @since 4.9.80.p |
|
226 | + */ |
|
227 | + protected function createFileObjects($organized_files, $name_parts_so_far = []) |
|
228 | + { |
|
229 | + if (! is_array($organized_files)) { |
|
230 | + throw new UnexpectedValueException( |
|
231 | + sprintf( |
|
232 | + esc_html__( |
|
233 | + 'Unexpected PHP $organized_files data format. "%1$s" was expected to be an array.', |
|
234 | + 'event_espresso' |
|
235 | + ), |
|
236 | + (string) $organized_files |
|
237 | + ) |
|
238 | + ); |
|
239 | + } |
|
240 | + foreach ($organized_files as $key => $value) { |
|
241 | + $this_input_name_parts = $name_parts_so_far; |
|
242 | + array_push( |
|
243 | + $this_input_name_parts, |
|
244 | + $key |
|
245 | + ); |
|
246 | + if (isset($value['name'], $value['tmp_name'], $value['size'])) { |
|
247 | + $html_name = $this->inputNameFromParts($this_input_name_parts); |
|
248 | + $this->file_objects->add( |
|
249 | + new FileSubmission( |
|
250 | + $value['name'], |
|
251 | + $value['tmp_name'], |
|
252 | + $value['size'], |
|
253 | + $value['error'] |
|
254 | + ), |
|
255 | + $html_name |
|
256 | + ); |
|
257 | + } else { |
|
258 | + $this->createFileObjects($value, $this_input_name_parts); |
|
259 | + } |
|
260 | + } |
|
261 | + } |
|
262 | 262 | |
263 | 263 | |
264 | - /** |
|
265 | - * Takes the input name parts, like `['my', 'great', 'file', 'input1']` |
|
266 | - * and returns the HTML name for it, "my[great][file][input1]" |
|
267 | - * |
|
268 | - * @throws UnexpectedValueException |
|
269 | - * @since 4.9.80.p |
|
270 | - */ |
|
271 | - protected function inputNameFromParts($parts) |
|
272 | - { |
|
273 | - if (! is_array($parts)) { |
|
274 | - throw new UnexpectedValueException(esc_html__('Name parts should be an array.', 'event_espresso')); |
|
275 | - } |
|
276 | - $generated_string = ''; |
|
277 | - foreach ($parts as $part) { |
|
278 | - $part = (string) $part; |
|
279 | - // wrap all but the first part in [] |
|
280 | - $generated_string .= $generated_string === '' ? $part : '[' . $part . ']'; |
|
281 | - } |
|
282 | - return $generated_string; |
|
283 | - } |
|
264 | + /** |
|
265 | + * Takes the input name parts, like `['my', 'great', 'file', 'input1']` |
|
266 | + * and returns the HTML name for it, "my[great][file][input1]" |
|
267 | + * |
|
268 | + * @throws UnexpectedValueException |
|
269 | + * @since 4.9.80.p |
|
270 | + */ |
|
271 | + protected function inputNameFromParts($parts) |
|
272 | + { |
|
273 | + if (! is_array($parts)) { |
|
274 | + throw new UnexpectedValueException(esc_html__('Name parts should be an array.', 'event_espresso')); |
|
275 | + } |
|
276 | + $generated_string = ''; |
|
277 | + foreach ($parts as $part) { |
|
278 | + $part = (string) $part; |
|
279 | + // wrap all but the first part in [] |
|
280 | + $generated_string .= $generated_string === '' ? $part : '[' . $part . ']'; |
|
281 | + } |
|
282 | + return $generated_string; |
|
283 | + } |
|
284 | 284 | |
285 | 285 | |
286 | - /** |
|
287 | - * Gets the input by the indicated $name_parts. |
|
288 | - * Eg if you're looking for an input named "my[great][file][input1]", $name_parts |
|
289 | - * should be `['my', 'great', 'file', 'input1']`. |
|
290 | - * Alternatively, you could use `FileDataHandler::getFileObject('my[great][file][input1]');` |
|
291 | - * |
|
292 | - * @param $name_parts |
|
293 | - * @return FileSubmissionInterface |
|
294 | - * @throws UnexpectedValueException |
|
295 | - * @since 4.9.80.p |
|
296 | - */ |
|
297 | - public function getFileObjectFromNameParts($name_parts) |
|
298 | - { |
|
299 | - return $this->getFileObjects()->get($this->inputNameFromParts($name_parts)); |
|
300 | - } |
|
286 | + /** |
|
287 | + * Gets the input by the indicated $name_parts. |
|
288 | + * Eg if you're looking for an input named "my[great][file][input1]", $name_parts |
|
289 | + * should be `['my', 'great', 'file', 'input1']`. |
|
290 | + * Alternatively, you could use `FileDataHandler::getFileObject('my[great][file][input1]');` |
|
291 | + * |
|
292 | + * @param $name_parts |
|
293 | + * @return FileSubmissionInterface |
|
294 | + * @throws UnexpectedValueException |
|
295 | + * @since 4.9.80.p |
|
296 | + */ |
|
297 | + public function getFileObjectFromNameParts($name_parts) |
|
298 | + { |
|
299 | + return $this->getFileObjects()->get($this->inputNameFromParts($name_parts)); |
|
300 | + } |
|
301 | 301 | |
302 | 302 | |
303 | - /** |
|
304 | - * Gets the FileSubmissionInterface corresponding to the HTML name provided. |
|
305 | - * |
|
306 | - * @param $html_name |
|
307 | - * @return mixed |
|
308 | - * @throws InvalidArgumentException |
|
309 | - * @throws UnexpectedValueException |
|
310 | - * @since 4.9.80.p |
|
311 | - */ |
|
312 | - public function getFileObject($html_name) |
|
313 | - { |
|
314 | - return $this->getFileObjects()->get($html_name); |
|
315 | - } |
|
303 | + /** |
|
304 | + * Gets the FileSubmissionInterface corresponding to the HTML name provided. |
|
305 | + * |
|
306 | + * @param $html_name |
|
307 | + * @return mixed |
|
308 | + * @throws InvalidArgumentException |
|
309 | + * @throws UnexpectedValueException |
|
310 | + * @since 4.9.80.p |
|
311 | + */ |
|
312 | + public function getFileObject($html_name) |
|
313 | + { |
|
314 | + return $this->getFileObjects()->get($html_name); |
|
315 | + } |
|
316 | 316 | } |
317 | 317 | // End of file FilesDataHandler.php |
318 | 318 | // Location: EventEspresso\core\services\request\files/FilesDataHandler.php |
@@ -99,7 +99,7 @@ discard block |
||
99 | 99 | // collection name |
100 | 100 | 'submitted_files' |
101 | 101 | ); |
102 | - $files_raw_data = $this->request->filesParams(); |
|
102 | + $files_raw_data = $this->request->filesParams(); |
|
103 | 103 | if (empty($files_raw_data)) { |
104 | 104 | return; |
105 | 105 | } |
@@ -123,7 +123,7 @@ discard block |
||
123 | 123 | */ |
124 | 124 | protected function isStrangeFilesArray($files_data) |
125 | 125 | { |
126 | - if (! is_array($files_data)) { |
|
126 | + if ( ! is_array($files_data)) { |
|
127 | 127 | throw new UnexpectedValueException( |
128 | 128 | sprintf( |
129 | 129 | esc_html__( |
@@ -135,7 +135,7 @@ discard block |
||
135 | 135 | ); |
136 | 136 | } |
137 | 137 | $first_value = reset($files_data); |
138 | - if (! is_array($first_value)) { |
|
138 | + if ( ! is_array($first_value)) { |
|
139 | 139 | throw new UnexpectedValueException( |
140 | 140 | sprintf( |
141 | 141 | esc_html__( |
@@ -171,14 +171,14 @@ discard block |
||
171 | 171 | $sane_files_array = []; |
172 | 172 | foreach ($files_data as $top_level_name => $top_level_children) { |
173 | 173 | $sub_array = []; |
174 | - $sane_files_array[ $top_level_name ] = []; |
|
174 | + $sane_files_array[$top_level_name] = []; |
|
175 | 175 | foreach ($top_level_children as $file_data_part => $second_level_children) { |
176 | 176 | foreach ($second_level_children as $next_level_name => $sub_values) { |
177 | - $sub_array[ $next_level_name ] = $this->organizeFilesData($sub_values, $file_data_part); |
|
177 | + $sub_array[$next_level_name] = $this->organizeFilesData($sub_values, $file_data_part); |
|
178 | 178 | } |
179 | - $sane_files_array[ $top_level_name ] = array_replace_recursive( |
|
179 | + $sane_files_array[$top_level_name] = array_replace_recursive( |
|
180 | 180 | $sub_array, |
181 | - $sane_files_array[ $top_level_name ] |
|
181 | + $sane_files_array[$top_level_name] |
|
182 | 182 | ); |
183 | 183 | } |
184 | 184 | } |
@@ -196,7 +196,7 @@ discard block |
||
196 | 196 | */ |
197 | 197 | protected function organizeFilesData($data, $type) |
198 | 198 | { |
199 | - if (! is_array($data)) { |
|
199 | + if ( ! is_array($data)) { |
|
200 | 200 | return [ |
201 | 201 | $type => $data, |
202 | 202 | ]; |
@@ -204,9 +204,9 @@ discard block |
||
204 | 204 | $organized_data = []; |
205 | 205 | foreach ($data as $input_name_part => $sub_inputs_or_value) { |
206 | 206 | if (is_array($sub_inputs_or_value)) { |
207 | - $organized_data[ $input_name_part ] = $this->organizeFilesData($sub_inputs_or_value, $type); |
|
207 | + $organized_data[$input_name_part] = $this->organizeFilesData($sub_inputs_or_value, $type); |
|
208 | 208 | } else { |
209 | - $organized_data[ $input_name_part ][ $type ] = $sub_inputs_or_value; |
|
209 | + $organized_data[$input_name_part][$type] = $sub_inputs_or_value; |
|
210 | 210 | } |
211 | 211 | } |
212 | 212 | return $organized_data; |
@@ -226,7 +226,7 @@ discard block |
||
226 | 226 | */ |
227 | 227 | protected function createFileObjects($organized_files, $name_parts_so_far = []) |
228 | 228 | { |
229 | - if (! is_array($organized_files)) { |
|
229 | + if ( ! is_array($organized_files)) { |
|
230 | 230 | throw new UnexpectedValueException( |
231 | 231 | sprintf( |
232 | 232 | esc_html__( |
@@ -270,14 +270,14 @@ discard block |
||
270 | 270 | */ |
271 | 271 | protected function inputNameFromParts($parts) |
272 | 272 | { |
273 | - if (! is_array($parts)) { |
|
273 | + if ( ! is_array($parts)) { |
|
274 | 274 | throw new UnexpectedValueException(esc_html__('Name parts should be an array.', 'event_espresso')); |
275 | 275 | } |
276 | 276 | $generated_string = ''; |
277 | 277 | foreach ($parts as $part) { |
278 | 278 | $part = (string) $part; |
279 | 279 | // wrap all but the first part in [] |
280 | - $generated_string .= $generated_string === '' ? $part : '[' . $part . ']'; |
|
280 | + $generated_string .= $generated_string === '' ? $part : '['.$part.']'; |
|
281 | 281 | } |
282 | 282 | return $generated_string; |
283 | 283 | } |
@@ -7,16 +7,16 @@ discard block |
||
7 | 7 | define('EE_SUPPORT_EMAIL', '[email protected]'); |
8 | 8 | // used to be DIRECTORY_SEPARATOR, but that caused issues on windows |
9 | 9 | if (! defined('DS')) { |
10 | - define('DS', '/'); |
|
10 | + define('DS', '/'); |
|
11 | 11 | } |
12 | 12 | if (! defined('PS')) { |
13 | - define('PS', PATH_SEPARATOR); |
|
13 | + define('PS', PATH_SEPARATOR); |
|
14 | 14 | } |
15 | 15 | if (! defined('SP')) { |
16 | - define('SP', ' '); |
|
16 | + define('SP', ' '); |
|
17 | 17 | } |
18 | 18 | if (! defined('EENL')) { |
19 | - define('EENL', "\n"); |
|
19 | + define('EENL', "\n"); |
|
20 | 20 | } |
21 | 21 | // define the plugin directory and URL |
22 | 22 | define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE)); |
@@ -70,7 +70,7 @@ discard block |
||
70 | 70 | define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages/'); |
71 | 71 | // check for DOMPDF fonts in uploads |
72 | 72 | if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts/')) { |
73 | - define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts/'); |
|
73 | + define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts/'); |
|
74 | 74 | } |
75 | 75 | // just a handy constant occasionally needed for finding values representing infinity in the DB |
76 | 76 | // you're better to use this than its straight value (currently -1) in case you ever |
@@ -78,9 +78,9 @@ discard block |
||
78 | 78 | define('EE_INF_IN_DB', -1); |
79 | 79 | define('EE_INF', INF > (float) PHP_INT_MAX ? INF : PHP_INT_MAX); |
80 | 80 | if (! defined('EE_DEBUG')) { |
81 | - define('EE_DEBUG', false); |
|
81 | + define('EE_DEBUG', false); |
|
82 | 82 | } |
83 | 83 | // for older WP versions |
84 | 84 | if (! defined('MONTH_IN_SECONDS')) { |
85 | - define('MONTH_IN_SECONDS', DAY_IN_SECONDS * 30); |
|
85 | + define('MONTH_IN_SECONDS', DAY_IN_SECONDS * 30); |
|
86 | 86 | } |
@@ -6,81 +6,81 @@ |
||
6 | 6 | define('EE_MIN_PHP_VER_RECOMMENDED', '5.6.32'); |
7 | 7 | define('EE_SUPPORT_EMAIL', '[email protected]'); |
8 | 8 | // used to be DIRECTORY_SEPARATOR, but that caused issues on windows |
9 | -if (! defined('DS')) { |
|
9 | +if ( ! defined('DS')) { |
|
10 | 10 | define('DS', '/'); |
11 | 11 | } |
12 | -if (! defined('PS')) { |
|
12 | +if ( ! defined('PS')) { |
|
13 | 13 | define('PS', PATH_SEPARATOR); |
14 | 14 | } |
15 | -if (! defined('SP')) { |
|
15 | +if ( ! defined('SP')) { |
|
16 | 16 | define('SP', ' '); |
17 | 17 | } |
18 | -if (! defined('EENL')) { |
|
18 | +if ( ! defined('EENL')) { |
|
19 | 19 | define('EENL', "\n"); |
20 | 20 | } |
21 | 21 | // define the plugin directory and URL |
22 | 22 | define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE)); |
23 | -define('EE_PLUGIN_DIR_PATH', dirname(EVENT_ESPRESSO_MAIN_FILE) . '/'); |
|
23 | +define('EE_PLUGIN_DIR_PATH', dirname(EVENT_ESPRESSO_MAIN_FILE).'/'); |
|
24 | 24 | define('EE_PLUGIN_DIR_URL', plugin_dir_url(EVENT_ESPRESSO_MAIN_FILE)); |
25 | 25 | // main root folder paths |
26 | -define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH . 'admin_pages/'); |
|
27 | -define('EE_CORE', EE_PLUGIN_DIR_PATH . 'core/'); |
|
28 | -define('EE_MODULES', EE_PLUGIN_DIR_PATH . 'modules/'); |
|
29 | -define('EE_PUBLIC', EE_PLUGIN_DIR_PATH . 'public/'); |
|
30 | -define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH . 'shortcodes/'); |
|
31 | -define('EE_WIDGETS', EE_PLUGIN_DIR_PATH . 'widgets/'); |
|
32 | -define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH . 'payment_methods/'); |
|
33 | -define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH . 'caffeinated/'); |
|
26 | +define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH.'admin_pages/'); |
|
27 | +define('EE_CORE', EE_PLUGIN_DIR_PATH.'core/'); |
|
28 | +define('EE_MODULES', EE_PLUGIN_DIR_PATH.'modules/'); |
|
29 | +define('EE_PUBLIC', EE_PLUGIN_DIR_PATH.'public/'); |
|
30 | +define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH.'shortcodes/'); |
|
31 | +define('EE_WIDGETS', EE_PLUGIN_DIR_PATH.'widgets/'); |
|
32 | +define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH.'payment_methods/'); |
|
33 | +define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH.'caffeinated/'); |
|
34 | 34 | // core system paths |
35 | -define('EE_ADMIN', EE_CORE . 'admin/'); |
|
36 | -define('EE_CPTS', EE_CORE . 'CPTs/'); |
|
37 | -define('EE_CLASSES', EE_CORE . 'db_classes/'); |
|
38 | -define('EE_INTERFACES', EE_CORE . 'interfaces/'); |
|
39 | -define('EE_BUSINESS', EE_CORE . 'business/'); |
|
40 | -define('EE_MODELS', EE_CORE . 'db_models/'); |
|
41 | -define('EE_HELPERS', EE_CORE . 'helpers/'); |
|
42 | -define('EE_LIBRARIES', EE_CORE . 'libraries/'); |
|
43 | -define('EE_TEMPLATES', EE_CORE . 'templates/'); |
|
44 | -define('EE_THIRD_PARTY', EE_CORE . 'third_party_libs/'); |
|
45 | -define('EE_GLOBAL_ASSETS', EE_TEMPLATES . 'global_assets/'); |
|
46 | -define('EE_FORM_SECTIONS', EE_LIBRARIES . 'form_sections/'); |
|
35 | +define('EE_ADMIN', EE_CORE.'admin/'); |
|
36 | +define('EE_CPTS', EE_CORE.'CPTs/'); |
|
37 | +define('EE_CLASSES', EE_CORE.'db_classes/'); |
|
38 | +define('EE_INTERFACES', EE_CORE.'interfaces/'); |
|
39 | +define('EE_BUSINESS', EE_CORE.'business/'); |
|
40 | +define('EE_MODELS', EE_CORE.'db_models/'); |
|
41 | +define('EE_HELPERS', EE_CORE.'helpers/'); |
|
42 | +define('EE_LIBRARIES', EE_CORE.'libraries/'); |
|
43 | +define('EE_TEMPLATES', EE_CORE.'templates/'); |
|
44 | +define('EE_THIRD_PARTY', EE_CORE.'third_party_libs/'); |
|
45 | +define('EE_GLOBAL_ASSETS', EE_TEMPLATES.'global_assets/'); |
|
46 | +define('EE_FORM_SECTIONS', EE_LIBRARIES.'form_sections/'); |
|
47 | 47 | // gateways |
48 | -define('EE_GATEWAYS', EE_MODULES . 'gateways/'); |
|
49 | -define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL . 'modules/gateways/'); |
|
48 | +define('EE_GATEWAYS', EE_MODULES.'gateways/'); |
|
49 | +define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL.'modules/gateways/'); |
|
50 | 50 | // asset URL paths |
51 | -define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL . 'core/templates/'); |
|
52 | -define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL . 'global_assets/'); |
|
53 | -define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL . 'images/'); |
|
54 | -define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL . 'core/third_party_libs/'); |
|
55 | -define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL . 'core/helpers/assets/'); |
|
56 | -define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL . 'core/libraries/'); |
|
51 | +define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL.'core/templates/'); |
|
52 | +define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL.'global_assets/'); |
|
53 | +define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL.'images/'); |
|
54 | +define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL.'core/third_party_libs/'); |
|
55 | +define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL.'core/helpers/assets/'); |
|
56 | +define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL.'core/libraries/'); |
|
57 | 57 | // define upload paths |
58 | 58 | $uploads = wp_upload_dir(); |
59 | 59 | // define the uploads directory and URL |
60 | -define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'] . '/espresso/'); |
|
61 | -define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'] . '/espresso/'); |
|
60 | +define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'].'/espresso/'); |
|
61 | +define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'].'/espresso/'); |
|
62 | 62 | // define the templates directory and URL |
63 | -define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'] . '/espresso/templates/'); |
|
64 | -define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'] . '/espresso/templates/'); |
|
63 | +define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'].'/espresso/templates/'); |
|
64 | +define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'].'/espresso/templates/'); |
|
65 | 65 | // define the gateway directory and URL |
66 | -define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'] . '/espresso/gateways/'); |
|
67 | -define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'] . '/espresso/gateways/'); |
|
66 | +define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'].'/espresso/gateways/'); |
|
67 | +define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'].'/espresso/gateways/'); |
|
68 | 68 | // languages folder/path |
69 | -define('EE_LANGUAGES_SAFE_LOC', '../' . 'uploads/' . 'espresso/languages/'); |
|
70 | -define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages/'); |
|
69 | +define('EE_LANGUAGES_SAFE_LOC', '../'.'uploads/'.'espresso/languages/'); |
|
70 | +define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR.'languages/'); |
|
71 | 71 | // check for DOMPDF fonts in uploads |
72 | -if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts/')) { |
|
73 | - define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts/'); |
|
72 | +if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR.'fonts/')) { |
|
73 | + define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR.'fonts/'); |
|
74 | 74 | } |
75 | 75 | // just a handy constant occasionally needed for finding values representing infinity in the DB |
76 | 76 | // you're better to use this than its straight value (currently -1) in case you ever |
77 | 77 | // want to change its default value! or find when -1 means infinity |
78 | 78 | define('EE_INF_IN_DB', -1); |
79 | 79 | define('EE_INF', INF > (float) PHP_INT_MAX ? INF : PHP_INT_MAX); |
80 | -if (! defined('EE_DEBUG')) { |
|
80 | +if ( ! defined('EE_DEBUG')) { |
|
81 | 81 | define('EE_DEBUG', false); |
82 | 82 | } |
83 | 83 | // for older WP versions |
84 | -if (! defined('MONTH_IN_SECONDS')) { |
|
84 | +if ( ! defined('MONTH_IN_SECONDS')) { |
|
85 | 85 | define('MONTH_IN_SECONDS', DAY_IN_SECONDS * 30); |
86 | 86 | } |
@@ -74,9 +74,9 @@ discard block |
||
74 | 74 | public function statsCallback() |
75 | 75 | { |
76 | 76 | // returns a callback that can is used to retrieve the stats to send along to the pue server. |
77 | - return function () { |
|
77 | + return function() { |
|
78 | 78 | // we only send stats one a week, so let's see if our stat timestamp has expired. |
79 | - if (! $this->sendStats()) { |
|
79 | + if ( ! $this->sendStats()) { |
|
80 | 80 | return array(); |
81 | 81 | } |
82 | 82 | return $this->stats_gatherer->stats(); |
@@ -124,9 +124,9 @@ discard block |
||
124 | 124 | */ |
125 | 125 | public static function optinText($extra = true) |
126 | 126 | { |
127 | - if (! $extra) { |
|
127 | + if ( ! $extra) { |
|
128 | 128 | echo '<h2 class="ee-admin-settings-hdr" ' |
129 | - . (! $extra ? 'id="UXIP_settings"' : '') |
|
129 | + . ( ! $extra ? 'id="UXIP_settings"' : '') |
|
130 | 130 | . '>' |
131 | 131 | . esc_html__('User eXperience Improvement Program (UXIP)', 'event_espresso') |
132 | 132 | . EEH_Template::get_help_tab_link('organization_logo_info') |
@@ -157,7 +157,7 @@ discard block |
||
157 | 157 | ), |
158 | 158 | '<a href="https://eventespresso.com/about/user-experience-improvement-program-uxip/" target="_blank">', |
159 | 159 | '</a>', |
160 | - '<a href="' . $settings_url . '" target="_blank">', |
|
160 | + '<a href="'.$settings_url.'" target="_blank">', |
|
161 | 161 | '</a>' |
162 | 162 | ); |
163 | 163 | } |
@@ -171,14 +171,14 @@ discard block |
||
171 | 171 | { |
172 | 172 | wp_register_script( |
173 | 173 | 'ee-data-optin-js', |
174 | - EE_GLOBAL_ASSETS_URL . 'scripts/ee-data-optin.js', |
|
174 | + EE_GLOBAL_ASSETS_URL.'scripts/ee-data-optin.js', |
|
175 | 175 | array('jquery'), |
176 | 176 | EVENT_ESPRESSO_VERSION, |
177 | 177 | true |
178 | 178 | ); |
179 | 179 | wp_register_style( |
180 | 180 | 'ee-data-optin-css', |
181 | - EE_GLOBAL_ASSETS_URL . 'css/ee-data-optin.css', |
|
181 | + EE_GLOBAL_ASSETS_URL.'css/ee-data-optin.css', |
|
182 | 182 | array(), |
183 | 183 | EVENT_ESPRESSO_VERSION |
184 | 184 | ); |
@@ -197,7 +197,7 @@ discard block |
||
197 | 197 | $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
198 | 198 | $nonce = $request->getRequestParam('nonce'); |
199 | 199 | // verify nonce |
200 | - if (! $nonce || ! wp_verify_nonce($nonce, 'ee-data-optin')) { |
|
200 | + if ( ! $nonce || ! wp_verify_nonce($nonce, 'ee-data-optin')) { |
|
201 | 201 | exit(); |
202 | 202 | } |
203 | 203 |
@@ -21,86 +21,86 @@ discard block |
||
21 | 21 | */ |
22 | 22 | class Stats |
23 | 23 | { |
24 | - const OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS = 'ee_uxip_stats_expiry'; |
|
25 | - |
|
26 | - /** |
|
27 | - * @var Config |
|
28 | - */ |
|
29 | - private $config; |
|
30 | - |
|
31 | - |
|
32 | - /** |
|
33 | - * @var StatsGatherer |
|
34 | - */ |
|
35 | - private $stats_gatherer; |
|
36 | - |
|
37 | - |
|
38 | - /** |
|
39 | - * @var EE_Maintenance_Mode |
|
40 | - */ |
|
41 | - private $maintenance_mode; |
|
42 | - |
|
43 | - public function __construct( |
|
44 | - Config $config, |
|
45 | - EE_Maintenance_Mode $maintenance_mode, |
|
46 | - StatsGatherer $stats_gatherer |
|
47 | - ) { |
|
48 | - $this->config = $config; |
|
49 | - $this->maintenance_mode = $maintenance_mode; |
|
50 | - $this->stats_gatherer = $stats_gatherer; |
|
51 | - $this->setUxipNotices(); |
|
52 | - } |
|
53 | - |
|
54 | - |
|
55 | - /** |
|
56 | - * Displays uxip opt-in notice if necessary. |
|
57 | - */ |
|
58 | - private function setUxipNotices() |
|
59 | - { |
|
60 | - if ($this->canDisplayNotices()) { |
|
61 | - add_action('admin_notices', array($this, 'optinNotice')); |
|
62 | - add_action('admin_enqueue_scripts', array($this, 'enqueueScripts')); |
|
63 | - add_action('wp_ajax_espresso_data_optin', array($this, 'ajaxHandler')); |
|
64 | - } |
|
65 | - } |
|
66 | - |
|
67 | - |
|
68 | - /** |
|
69 | - * This returns the callback that PluginUpdateEngineChecker will use for getting any extra stats to send. |
|
70 | - * |
|
71 | - * @return Closure |
|
72 | - */ |
|
73 | - public function statsCallback() |
|
74 | - { |
|
75 | - // returns a callback that can is used to retrieve the stats to send along to the pue server. |
|
76 | - return function () { |
|
77 | - // we only send stats one a week, so let's see if our stat timestamp has expired. |
|
78 | - if (! $this->sendStats()) { |
|
79 | - return array(); |
|
80 | - } |
|
81 | - return $this->stats_gatherer->stats(); |
|
82 | - }; |
|
83 | - } |
|
84 | - |
|
85 | - |
|
86 | - /** |
|
87 | - * Return whether notices can be displayed or not |
|
88 | - * |
|
89 | - * @return bool |
|
90 | - */ |
|
91 | - private function canDisplayNotices() |
|
92 | - { |
|
93 | - return ! $this->config->hasNotifiedForUxip() |
|
94 | - && $this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance; |
|
95 | - } |
|
96 | - |
|
97 | - |
|
98 | - /** |
|
99 | - * Callback for the admin_notices hook that outputs the UXIP optin-in notice. |
|
100 | - */ |
|
101 | - public function optinNotice() |
|
102 | - { |
|
103 | - ?> |
|
24 | + const OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS = 'ee_uxip_stats_expiry'; |
|
25 | + |
|
26 | + /** |
|
27 | + * @var Config |
|
28 | + */ |
|
29 | + private $config; |
|
30 | + |
|
31 | + |
|
32 | + /** |
|
33 | + * @var StatsGatherer |
|
34 | + */ |
|
35 | + private $stats_gatherer; |
|
36 | + |
|
37 | + |
|
38 | + /** |
|
39 | + * @var EE_Maintenance_Mode |
|
40 | + */ |
|
41 | + private $maintenance_mode; |
|
42 | + |
|
43 | + public function __construct( |
|
44 | + Config $config, |
|
45 | + EE_Maintenance_Mode $maintenance_mode, |
|
46 | + StatsGatherer $stats_gatherer |
|
47 | + ) { |
|
48 | + $this->config = $config; |
|
49 | + $this->maintenance_mode = $maintenance_mode; |
|
50 | + $this->stats_gatherer = $stats_gatherer; |
|
51 | + $this->setUxipNotices(); |
|
52 | + } |
|
53 | + |
|
54 | + |
|
55 | + /** |
|
56 | + * Displays uxip opt-in notice if necessary. |
|
57 | + */ |
|
58 | + private function setUxipNotices() |
|
59 | + { |
|
60 | + if ($this->canDisplayNotices()) { |
|
61 | + add_action('admin_notices', array($this, 'optinNotice')); |
|
62 | + add_action('admin_enqueue_scripts', array($this, 'enqueueScripts')); |
|
63 | + add_action('wp_ajax_espresso_data_optin', array($this, 'ajaxHandler')); |
|
64 | + } |
|
65 | + } |
|
66 | + |
|
67 | + |
|
68 | + /** |
|
69 | + * This returns the callback that PluginUpdateEngineChecker will use for getting any extra stats to send. |
|
70 | + * |
|
71 | + * @return Closure |
|
72 | + */ |
|
73 | + public function statsCallback() |
|
74 | + { |
|
75 | + // returns a callback that can is used to retrieve the stats to send along to the pue server. |
|
76 | + return function () { |
|
77 | + // we only send stats one a week, so let's see if our stat timestamp has expired. |
|
78 | + if (! $this->sendStats()) { |
|
79 | + return array(); |
|
80 | + } |
|
81 | + return $this->stats_gatherer->stats(); |
|
82 | + }; |
|
83 | + } |
|
84 | + |
|
85 | + |
|
86 | + /** |
|
87 | + * Return whether notices can be displayed or not |
|
88 | + * |
|
89 | + * @return bool |
|
90 | + */ |
|
91 | + private function canDisplayNotices() |
|
92 | + { |
|
93 | + return ! $this->config->hasNotifiedForUxip() |
|
94 | + && $this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance; |
|
95 | + } |
|
96 | + |
|
97 | + |
|
98 | + /** |
|
99 | + * Callback for the admin_notices hook that outputs the UXIP optin-in notice. |
|
100 | + */ |
|
101 | + public function optinNotice() |
|
102 | + { |
|
103 | + ?> |
|
104 | 104 | <div class="updated data-collect-optin" id="espresso-data-collect-optin-container"> |
105 | 105 | <div id="data-collect-optin-options-container"> |
106 | 106 | <span class="dashicons dashicons-admin-site"></span> |
@@ -113,128 +113,128 @@ discard block |
||
113 | 113 | </div> |
114 | 114 | </div> |
115 | 115 | <?php |
116 | - } |
|
117 | - |
|
118 | - |
|
119 | - /** |
|
120 | - * Retrieves the optin text (static so it can be used in multiple places as necessary). |
|
121 | - * |
|
122 | - * @param bool $extra |
|
123 | - */ |
|
124 | - public static function optinText($extra = true) |
|
125 | - { |
|
126 | - if (! $extra) { |
|
127 | - echo '<h2 class="ee-admin-settings-hdr" ' |
|
128 | - . (! $extra ? 'id="UXIP_settings"' : '') |
|
129 | - . '>' |
|
130 | - . esc_html__('User eXperience Improvement Program (UXIP)', 'event_espresso') |
|
131 | - . EEH_Template::get_help_tab_link('organization_logo_info') |
|
132 | - . '</h2>'; |
|
133 | - printf( |
|
134 | - esc_html__( |
|
135 | - '%1$sPlease help us make Event Espresso better and vote for your favorite features.%2$s The %3$sUser eXperience Improvement Program (UXIP)%4$s, has been created so when you use Event Espresso you are voting for the features and settings that are important to you. The UXIP helps us understand how you use our products and services, track problems and in what context. If you opt-out of the UXIP you essentially elect for us to disregard how you use Event Espresso as we build new features and make changes. Participation in the program is completely voluntary and it is disabled by default. The end results of the UXIP are software improvements to better meet your needs. The data we collect will never be sold, traded, or misused in any way. %5$sPlease see our %6$sPrivacy Policy%7$s for more information.', |
|
136 | - 'event_espresso' |
|
137 | - ), |
|
138 | - '<p><em>', |
|
139 | - '</em></p>', |
|
140 | - '<a href="https://eventespresso.com/about/user-experience-improvement-program-uxip/" target="_blank">', |
|
141 | - '</a>', |
|
142 | - '<br><br>', |
|
143 | - '<a href="https://eventespresso.com/about/privacy-policy/" target="_blank">', |
|
144 | - '</a>' |
|
145 | - ); |
|
146 | - } else { |
|
147 | - $settings_url = EEH_URL::add_query_args_and_nonce( |
|
148 | - array('action' => 'default'), |
|
149 | - admin_url('admin.php?page=espresso_general_settings') |
|
150 | - ); |
|
151 | - $settings_url .= '#UXIP_settings'; |
|
152 | - printf( |
|
153 | - esc_html__( |
|
154 | - 'The Event Espresso UXIP feature is not yet active on your site. For %1$smore info%2$s and to opt-in %3$sclick here%4$s.', |
|
155 | - 'event_espresso' |
|
156 | - ), |
|
157 | - '<a href="https://eventespresso.com/about/user-experience-improvement-program-uxip/" target="_blank">', |
|
158 | - '</a>', |
|
159 | - '<a href="' . $settings_url . '" target="_blank">', |
|
160 | - '</a>' |
|
161 | - ); |
|
162 | - } |
|
163 | - } |
|
164 | - |
|
165 | - |
|
166 | - /** |
|
167 | - * Callback for admin_enqueue_scripts that sets up the scripts and styles for the uxip notice |
|
168 | - */ |
|
169 | - public function enqueueScripts() |
|
170 | - { |
|
171 | - wp_register_script( |
|
172 | - 'ee-data-optin-js', |
|
173 | - EE_GLOBAL_ASSETS_URL . 'scripts/ee-data-optin.js', |
|
174 | - array('jquery'), |
|
175 | - EVENT_ESPRESSO_VERSION, |
|
176 | - true |
|
177 | - ); |
|
178 | - wp_register_style( |
|
179 | - 'ee-data-optin-css', |
|
180 | - EE_GLOBAL_ASSETS_URL . 'css/ee-data-optin.css', |
|
181 | - array(), |
|
182 | - EVENT_ESPRESSO_VERSION |
|
183 | - ); |
|
184 | - |
|
185 | - wp_enqueue_script('ee-data-optin-js'); |
|
186 | - wp_enqueue_style('ee-data-optin-css'); |
|
187 | - } |
|
188 | - |
|
189 | - |
|
190 | - /** |
|
191 | - * Callback for wp_ajax_espresso_data_optin that handles the ajax request |
|
192 | - */ |
|
193 | - public function ajaxHandler() |
|
194 | - { |
|
195 | - /** @var RequestInterface $request */ |
|
196 | - $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
197 | - $nonce = $request->getRequestParam('nonce'); |
|
198 | - // verify nonce |
|
199 | - if (! $nonce || ! wp_verify_nonce($nonce, 'ee-data-optin')) { |
|
200 | - exit(); |
|
201 | - } |
|
202 | - |
|
203 | - // update has notified option |
|
204 | - $this->config->setHasNotifiedAboutUxip(); |
|
205 | - exit(); |
|
206 | - } |
|
207 | - |
|
208 | - |
|
209 | - /** |
|
210 | - * Used to determine whether additional stats are sent. |
|
211 | - */ |
|
212 | - private function sendStats() |
|
213 | - { |
|
214 | - return $this->config->isOptedInForUxip() |
|
215 | - && $this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance |
|
216 | - && $this->statSendTimestampExpired(); |
|
217 | - } |
|
218 | - |
|
219 | - |
|
220 | - /** |
|
221 | - * Returns true when the timestamp used to track whether stats get sent (currently a weekly interval) is expired. |
|
222 | - * Returns false otherwise. |
|
223 | - * |
|
224 | - * @return bool |
|
225 | - */ |
|
226 | - private function statSendTimestampExpired() |
|
227 | - { |
|
228 | - $current_expiry = get_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, null); |
|
229 | - if ($current_expiry === null) { |
|
230 | - add_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, time() + WEEK_IN_SECONDS, '', 'no'); |
|
231 | - return true; |
|
232 | - } |
|
233 | - |
|
234 | - if (time() > (int) $current_expiry) { |
|
235 | - update_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, time() + WEEK_IN_SECONDS); |
|
236 | - return true; |
|
237 | - } |
|
238 | - return false; |
|
239 | - } |
|
116 | + } |
|
117 | + |
|
118 | + |
|
119 | + /** |
|
120 | + * Retrieves the optin text (static so it can be used in multiple places as necessary). |
|
121 | + * |
|
122 | + * @param bool $extra |
|
123 | + */ |
|
124 | + public static function optinText($extra = true) |
|
125 | + { |
|
126 | + if (! $extra) { |
|
127 | + echo '<h2 class="ee-admin-settings-hdr" ' |
|
128 | + . (! $extra ? 'id="UXIP_settings"' : '') |
|
129 | + . '>' |
|
130 | + . esc_html__('User eXperience Improvement Program (UXIP)', 'event_espresso') |
|
131 | + . EEH_Template::get_help_tab_link('organization_logo_info') |
|
132 | + . '</h2>'; |
|
133 | + printf( |
|
134 | + esc_html__( |
|
135 | + '%1$sPlease help us make Event Espresso better and vote for your favorite features.%2$s The %3$sUser eXperience Improvement Program (UXIP)%4$s, has been created so when you use Event Espresso you are voting for the features and settings that are important to you. The UXIP helps us understand how you use our products and services, track problems and in what context. If you opt-out of the UXIP you essentially elect for us to disregard how you use Event Espresso as we build new features and make changes. Participation in the program is completely voluntary and it is disabled by default. The end results of the UXIP are software improvements to better meet your needs. The data we collect will never be sold, traded, or misused in any way. %5$sPlease see our %6$sPrivacy Policy%7$s for more information.', |
|
136 | + 'event_espresso' |
|
137 | + ), |
|
138 | + '<p><em>', |
|
139 | + '</em></p>', |
|
140 | + '<a href="https://eventespresso.com/about/user-experience-improvement-program-uxip/" target="_blank">', |
|
141 | + '</a>', |
|
142 | + '<br><br>', |
|
143 | + '<a href="https://eventespresso.com/about/privacy-policy/" target="_blank">', |
|
144 | + '</a>' |
|
145 | + ); |
|
146 | + } else { |
|
147 | + $settings_url = EEH_URL::add_query_args_and_nonce( |
|
148 | + array('action' => 'default'), |
|
149 | + admin_url('admin.php?page=espresso_general_settings') |
|
150 | + ); |
|
151 | + $settings_url .= '#UXIP_settings'; |
|
152 | + printf( |
|
153 | + esc_html__( |
|
154 | + 'The Event Espresso UXIP feature is not yet active on your site. For %1$smore info%2$s and to opt-in %3$sclick here%4$s.', |
|
155 | + 'event_espresso' |
|
156 | + ), |
|
157 | + '<a href="https://eventespresso.com/about/user-experience-improvement-program-uxip/" target="_blank">', |
|
158 | + '</a>', |
|
159 | + '<a href="' . $settings_url . '" target="_blank">', |
|
160 | + '</a>' |
|
161 | + ); |
|
162 | + } |
|
163 | + } |
|
164 | + |
|
165 | + |
|
166 | + /** |
|
167 | + * Callback for admin_enqueue_scripts that sets up the scripts and styles for the uxip notice |
|
168 | + */ |
|
169 | + public function enqueueScripts() |
|
170 | + { |
|
171 | + wp_register_script( |
|
172 | + 'ee-data-optin-js', |
|
173 | + EE_GLOBAL_ASSETS_URL . 'scripts/ee-data-optin.js', |
|
174 | + array('jquery'), |
|
175 | + EVENT_ESPRESSO_VERSION, |
|
176 | + true |
|
177 | + ); |
|
178 | + wp_register_style( |
|
179 | + 'ee-data-optin-css', |
|
180 | + EE_GLOBAL_ASSETS_URL . 'css/ee-data-optin.css', |
|
181 | + array(), |
|
182 | + EVENT_ESPRESSO_VERSION |
|
183 | + ); |
|
184 | + |
|
185 | + wp_enqueue_script('ee-data-optin-js'); |
|
186 | + wp_enqueue_style('ee-data-optin-css'); |
|
187 | + } |
|
188 | + |
|
189 | + |
|
190 | + /** |
|
191 | + * Callback for wp_ajax_espresso_data_optin that handles the ajax request |
|
192 | + */ |
|
193 | + public function ajaxHandler() |
|
194 | + { |
|
195 | + /** @var RequestInterface $request */ |
|
196 | + $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
197 | + $nonce = $request->getRequestParam('nonce'); |
|
198 | + // verify nonce |
|
199 | + if (! $nonce || ! wp_verify_nonce($nonce, 'ee-data-optin')) { |
|
200 | + exit(); |
|
201 | + } |
|
202 | + |
|
203 | + // update has notified option |
|
204 | + $this->config->setHasNotifiedAboutUxip(); |
|
205 | + exit(); |
|
206 | + } |
|
207 | + |
|
208 | + |
|
209 | + /** |
|
210 | + * Used to determine whether additional stats are sent. |
|
211 | + */ |
|
212 | + private function sendStats() |
|
213 | + { |
|
214 | + return $this->config->isOptedInForUxip() |
|
215 | + && $this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance |
|
216 | + && $this->statSendTimestampExpired(); |
|
217 | + } |
|
218 | + |
|
219 | + |
|
220 | + /** |
|
221 | + * Returns true when the timestamp used to track whether stats get sent (currently a weekly interval) is expired. |
|
222 | + * Returns false otherwise. |
|
223 | + * |
|
224 | + * @return bool |
|
225 | + */ |
|
226 | + private function statSendTimestampExpired() |
|
227 | + { |
|
228 | + $current_expiry = get_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, null); |
|
229 | + if ($current_expiry === null) { |
|
230 | + add_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, time() + WEEK_IN_SECONDS, '', 'no'); |
|
231 | + return true; |
|
232 | + } |
|
233 | + |
|
234 | + if (time() > (int) $current_expiry) { |
|
235 | + update_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, time() + WEEK_IN_SECONDS); |
|
236 | + return true; |
|
237 | + } |
|
238 | + return false; |
|
239 | + } |
|
240 | 240 | } |
@@ -48,7 +48,7 @@ discard block |
||
48 | 48 | */ |
49 | 49 | public static function instance() |
50 | 50 | { |
51 | - if (! self::$_instance instanceof EE_Log) { |
|
51 | + if ( ! self::$_instance instanceof EE_Log) { |
|
52 | 52 | self::$_instance = new self(); |
53 | 53 | } |
54 | 54 | return self::$_instance; |
@@ -61,7 +61,7 @@ discard block |
||
61 | 61 | private function __construct() |
62 | 62 | { |
63 | 63 | |
64 | - if (! EE_Registry::instance()->CFG->admin->use_remote_logging) { |
|
64 | + if ( ! EE_Registry::instance()->CFG->admin->use_remote_logging) { |
|
65 | 65 | return; |
66 | 66 | } |
67 | 67 | |
@@ -105,14 +105,14 @@ discard block |
||
105 | 105 | */ |
106 | 106 | private function _format_message($file = '', $function = '', $message = '', $type = '') |
107 | 107 | { |
108 | - $msg = '----------------------------------------------------------------------------------------' . PHP_EOL; |
|
109 | - $msg .= '[' . current_time('mysql') . '] '; |
|
108 | + $msg = '----------------------------------------------------------------------------------------'.PHP_EOL; |
|
109 | + $msg .= '['.current_time('mysql').'] '; |
|
110 | 110 | $msg .= ! empty($file) ? basename($file) : ''; |
111 | 111 | $msg .= ! empty($file) && ! empty($function) ? ' -> ' : ''; |
112 | - $msg .= ! empty($function) ? $function . '()' : ''; |
|
112 | + $msg .= ! empty($function) ? $function.'()' : ''; |
|
113 | 113 | $msg .= PHP_EOL; |
114 | 114 | $type = ! empty($type) ? $type : 'log message'; |
115 | - $msg .= ! empty($message) ? "\t" . '[' . $type . '] ' . $message . PHP_EOL : ''; |
|
115 | + $msg .= ! empty($message) ? "\t".'['.$type.'] '.$message.PHP_EOL : ''; |
|
116 | 116 | return $msg; |
117 | 117 | } |
118 | 118 | |
@@ -164,18 +164,18 @@ discard block |
||
164 | 164 | |
165 | 165 | /** @var RequestInterface $request */ |
166 | 166 | $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
167 | - $data = 'domain=' . $request->getServerParam('HTTP_HOST'); |
|
168 | - $data .= '&ip=' . $request->getServerParam('SERVER_ADDR'); |
|
169 | - $data .= '&server_type=' . $request->getServerParam('SERVER_SOFTWARE'); |
|
170 | - $data .= '&time=' . time(); |
|
171 | - $data .= '&remote_log=' . $this->_log; |
|
167 | + $data = 'domain='.$request->getServerParam('HTTP_HOST'); |
|
168 | + $data .= '&ip='.$request->getServerParam('SERVER_ADDR'); |
|
169 | + $data .= '&server_type='.$request->getServerParam('SERVER_SOFTWARE'); |
|
170 | + $data .= '&time='.time(); |
|
171 | + $data .= '&remote_log='.$this->_log; |
|
172 | 172 | $data .= '&action=save'; |
173 | 173 | |
174 | 174 | if (defined('EELOGGING_PASS')) { |
175 | - $data .= '&pass=' . EELOGGING_PASS; |
|
175 | + $data .= '&pass='.EELOGGING_PASS; |
|
176 | 176 | } |
177 | 177 | if (defined('EELOGGING_KEY')) { |
178 | - $data .= '&key=' . EELOGGING_KEY; |
|
178 | + $data .= '&key='.EELOGGING_KEY; |
|
179 | 179 | } |
180 | 180 | |
181 | 181 | $c = curl_init($this->_remote_logging_url); |
@@ -19,197 +19,197 @@ |
||
19 | 19 | */ |
20 | 20 | class EE_Log |
21 | 21 | { |
22 | - /** |
|
23 | - * @var string |
|
24 | - */ |
|
25 | - private $_log = ''; |
|
26 | - |
|
27 | - /** |
|
28 | - * Used for remote logging |
|
29 | - * |
|
30 | - * @var string |
|
31 | - */ |
|
32 | - private $_remote_logging_url = ''; |
|
33 | - |
|
34 | - /** |
|
35 | - * @var string |
|
36 | - */ |
|
37 | - private $_remote_log = ''; |
|
38 | - |
|
39 | - /** |
|
40 | - * @var EE_Log |
|
41 | - */ |
|
42 | - private static $_instance; |
|
43 | - |
|
44 | - |
|
45 | - /** |
|
46 | - * @return EE_Log |
|
47 | - */ |
|
48 | - public static function instance() |
|
49 | - { |
|
50 | - if (! self::$_instance instanceof EE_Log) { |
|
51 | - self::$_instance = new self(); |
|
52 | - } |
|
53 | - return self::$_instance; |
|
54 | - } |
|
55 | - |
|
56 | - /** |
|
57 | - * @access private |
|
58 | - * @return EE_Log |
|
59 | - */ |
|
60 | - private function __construct() |
|
61 | - { |
|
62 | - |
|
63 | - if (! EE_Registry::instance()->CFG->admin->use_remote_logging) { |
|
64 | - return; |
|
65 | - } |
|
66 | - |
|
67 | - $this->_remote_logging_url = EE_Registry::instance()->CFG->admin->remote_logging_url; |
|
68 | - $this->_remote_log = ''; |
|
69 | - |
|
70 | - if (EE_Registry::instance()->CFG->admin->use_remote_logging) { |
|
71 | - add_action('shutdown', array($this, 'send_log'), 9999); |
|
72 | - } |
|
73 | - } |
|
74 | - |
|
75 | - |
|
76 | - /** |
|
77 | - * verify_filesystem |
|
78 | - * tests that the required files and folders exist and are writable |
|
79 | - * |
|
80 | - */ |
|
81 | - public function verify_filesystem() |
|
82 | - { |
|
83 | - $msg = esc_html__( |
|
84 | - 'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.', |
|
85 | - 'event_espresso' |
|
86 | - ); |
|
87 | - EE_Error::doing_it_wrong( |
|
88 | - __METHOD__, |
|
89 | - $msg, |
|
90 | - '4.10.1.p' |
|
91 | - ); |
|
92 | - } |
|
93 | - |
|
94 | - |
|
95 | - /** |
|
96 | - * _format_message |
|
97 | - * makes yer log entries look all purdy |
|
98 | - * |
|
99 | - * @param string $file |
|
100 | - * @param string $function |
|
101 | - * @param string $message |
|
102 | - * @param string $type |
|
103 | - * @return string |
|
104 | - */ |
|
105 | - private function _format_message($file = '', $function = '', $message = '', $type = '') |
|
106 | - { |
|
107 | - $msg = '----------------------------------------------------------------------------------------' . PHP_EOL; |
|
108 | - $msg .= '[' . current_time('mysql') . '] '; |
|
109 | - $msg .= ! empty($file) ? basename($file) : ''; |
|
110 | - $msg .= ! empty($file) && ! empty($function) ? ' -> ' : ''; |
|
111 | - $msg .= ! empty($function) ? $function . '()' : ''; |
|
112 | - $msg .= PHP_EOL; |
|
113 | - $type = ! empty($type) ? $type : 'log message'; |
|
114 | - $msg .= ! empty($message) ? "\t" . '[' . $type . '] ' . $message . PHP_EOL : ''; |
|
115 | - return $msg; |
|
116 | - } |
|
117 | - |
|
118 | - |
|
119 | - /** |
|
120 | - * log |
|
121 | - * adds content to the EE_Log->_log property which gets written to file during the WP 'shutdown' hookpoint via the |
|
122 | - * EE_Log::write_log() callback |
|
123 | - * |
|
124 | - * @param string $file |
|
125 | - * @param string $function |
|
126 | - * @param string $message |
|
127 | - * @param string $type |
|
128 | - */ |
|
129 | - public function log($file = '', $function = '', $message = '', $type = '') |
|
130 | - { |
|
131 | - $this->_log .= $this->_format_message($file, $function, $message, $type); |
|
132 | - } |
|
133 | - |
|
134 | - |
|
135 | - /** |
|
136 | - * write_log |
|
137 | - * appends the results of the 'AHEE_log' filter to the espresso log file |
|
138 | - */ |
|
139 | - public function write_log() |
|
140 | - { |
|
141 | - $msg = esc_html__( |
|
142 | - 'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.', |
|
143 | - 'event_espresso' |
|
144 | - ); |
|
145 | - EE_Error::doing_it_wrong( |
|
146 | - __METHOD__, |
|
147 | - $msg, |
|
148 | - '4.10.1.p' |
|
149 | - ); |
|
150 | - } |
|
151 | - |
|
152 | - |
|
153 | - /** |
|
154 | - * send_log |
|
155 | - * sends the espresso log to a remote URL via a PHP cURL request |
|
156 | - */ |
|
157 | - public function send_log() |
|
158 | - { |
|
159 | - |
|
160 | - if (empty($this->_remote_logging_url)) { |
|
161 | - return; |
|
162 | - } |
|
163 | - |
|
164 | - /** @var RequestInterface $request */ |
|
165 | - $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
166 | - $data = 'domain=' . $request->getServerParam('HTTP_HOST'); |
|
167 | - $data .= '&ip=' . $request->getServerParam('SERVER_ADDR'); |
|
168 | - $data .= '&server_type=' . $request->getServerParam('SERVER_SOFTWARE'); |
|
169 | - $data .= '&time=' . time(); |
|
170 | - $data .= '&remote_log=' . $this->_log; |
|
171 | - $data .= '&action=save'; |
|
172 | - |
|
173 | - if (defined('EELOGGING_PASS')) { |
|
174 | - $data .= '&pass=' . EELOGGING_PASS; |
|
175 | - } |
|
176 | - if (defined('EELOGGING_KEY')) { |
|
177 | - $data .= '&key=' . EELOGGING_KEY; |
|
178 | - } |
|
179 | - |
|
180 | - $c = curl_init($this->_remote_logging_url); |
|
181 | - curl_setopt($c, CURLOPT_POST, true); |
|
182 | - curl_setopt($c, CURLOPT_POSTFIELDS, $data); |
|
183 | - curl_setopt($c, CURLOPT_RETURNTRANSFER, true); |
|
184 | - curl_exec($c); |
|
185 | - curl_close($c); |
|
186 | - } |
|
187 | - |
|
188 | - |
|
189 | - /** |
|
190 | - * write_debug |
|
191 | - * writes the contents of the current request's data to a log file. |
|
192 | - * previous entries are overwritten |
|
193 | - */ |
|
194 | - public function write_debug() |
|
195 | - { |
|
196 | - $msg = esc_html__( |
|
197 | - 'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.', |
|
198 | - 'event_espresso' |
|
199 | - ); |
|
200 | - EE_Error::doing_it_wrong( |
|
201 | - __METHOD__, |
|
202 | - $msg, |
|
203 | - '4.10.1.p' |
|
204 | - ); |
|
205 | - } |
|
206 | - |
|
207 | - |
|
208 | - /** |
|
209 | - * __clone |
|
210 | - */ |
|
211 | - public function __clone() |
|
212 | - { |
|
213 | - trigger_error(esc_html__('Clone is not allowed.', 'event_espresso'), E_USER_ERROR); |
|
214 | - } |
|
22 | + /** |
|
23 | + * @var string |
|
24 | + */ |
|
25 | + private $_log = ''; |
|
26 | + |
|
27 | + /** |
|
28 | + * Used for remote logging |
|
29 | + * |
|
30 | + * @var string |
|
31 | + */ |
|
32 | + private $_remote_logging_url = ''; |
|
33 | + |
|
34 | + /** |
|
35 | + * @var string |
|
36 | + */ |
|
37 | + private $_remote_log = ''; |
|
38 | + |
|
39 | + /** |
|
40 | + * @var EE_Log |
|
41 | + */ |
|
42 | + private static $_instance; |
|
43 | + |
|
44 | + |
|
45 | + /** |
|
46 | + * @return EE_Log |
|
47 | + */ |
|
48 | + public static function instance() |
|
49 | + { |
|
50 | + if (! self::$_instance instanceof EE_Log) { |
|
51 | + self::$_instance = new self(); |
|
52 | + } |
|
53 | + return self::$_instance; |
|
54 | + } |
|
55 | + |
|
56 | + /** |
|
57 | + * @access private |
|
58 | + * @return EE_Log |
|
59 | + */ |
|
60 | + private function __construct() |
|
61 | + { |
|
62 | + |
|
63 | + if (! EE_Registry::instance()->CFG->admin->use_remote_logging) { |
|
64 | + return; |
|
65 | + } |
|
66 | + |
|
67 | + $this->_remote_logging_url = EE_Registry::instance()->CFG->admin->remote_logging_url; |
|
68 | + $this->_remote_log = ''; |
|
69 | + |
|
70 | + if (EE_Registry::instance()->CFG->admin->use_remote_logging) { |
|
71 | + add_action('shutdown', array($this, 'send_log'), 9999); |
|
72 | + } |
|
73 | + } |
|
74 | + |
|
75 | + |
|
76 | + /** |
|
77 | + * verify_filesystem |
|
78 | + * tests that the required files and folders exist and are writable |
|
79 | + * |
|
80 | + */ |
|
81 | + public function verify_filesystem() |
|
82 | + { |
|
83 | + $msg = esc_html__( |
|
84 | + 'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.', |
|
85 | + 'event_espresso' |
|
86 | + ); |
|
87 | + EE_Error::doing_it_wrong( |
|
88 | + __METHOD__, |
|
89 | + $msg, |
|
90 | + '4.10.1.p' |
|
91 | + ); |
|
92 | + } |
|
93 | + |
|
94 | + |
|
95 | + /** |
|
96 | + * _format_message |
|
97 | + * makes yer log entries look all purdy |
|
98 | + * |
|
99 | + * @param string $file |
|
100 | + * @param string $function |
|
101 | + * @param string $message |
|
102 | + * @param string $type |
|
103 | + * @return string |
|
104 | + */ |
|
105 | + private function _format_message($file = '', $function = '', $message = '', $type = '') |
|
106 | + { |
|
107 | + $msg = '----------------------------------------------------------------------------------------' . PHP_EOL; |
|
108 | + $msg .= '[' . current_time('mysql') . '] '; |
|
109 | + $msg .= ! empty($file) ? basename($file) : ''; |
|
110 | + $msg .= ! empty($file) && ! empty($function) ? ' -> ' : ''; |
|
111 | + $msg .= ! empty($function) ? $function . '()' : ''; |
|
112 | + $msg .= PHP_EOL; |
|
113 | + $type = ! empty($type) ? $type : 'log message'; |
|
114 | + $msg .= ! empty($message) ? "\t" . '[' . $type . '] ' . $message . PHP_EOL : ''; |
|
115 | + return $msg; |
|
116 | + } |
|
117 | + |
|
118 | + |
|
119 | + /** |
|
120 | + * log |
|
121 | + * adds content to the EE_Log->_log property which gets written to file during the WP 'shutdown' hookpoint via the |
|
122 | + * EE_Log::write_log() callback |
|
123 | + * |
|
124 | + * @param string $file |
|
125 | + * @param string $function |
|
126 | + * @param string $message |
|
127 | + * @param string $type |
|
128 | + */ |
|
129 | + public function log($file = '', $function = '', $message = '', $type = '') |
|
130 | + { |
|
131 | + $this->_log .= $this->_format_message($file, $function, $message, $type); |
|
132 | + } |
|
133 | + |
|
134 | + |
|
135 | + /** |
|
136 | + * write_log |
|
137 | + * appends the results of the 'AHEE_log' filter to the espresso log file |
|
138 | + */ |
|
139 | + public function write_log() |
|
140 | + { |
|
141 | + $msg = esc_html__( |
|
142 | + 'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.', |
|
143 | + 'event_espresso' |
|
144 | + ); |
|
145 | + EE_Error::doing_it_wrong( |
|
146 | + __METHOD__, |
|
147 | + $msg, |
|
148 | + '4.10.1.p' |
|
149 | + ); |
|
150 | + } |
|
151 | + |
|
152 | + |
|
153 | + /** |
|
154 | + * send_log |
|
155 | + * sends the espresso log to a remote URL via a PHP cURL request |
|
156 | + */ |
|
157 | + public function send_log() |
|
158 | + { |
|
159 | + |
|
160 | + if (empty($this->_remote_logging_url)) { |
|
161 | + return; |
|
162 | + } |
|
163 | + |
|
164 | + /** @var RequestInterface $request */ |
|
165 | + $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
166 | + $data = 'domain=' . $request->getServerParam('HTTP_HOST'); |
|
167 | + $data .= '&ip=' . $request->getServerParam('SERVER_ADDR'); |
|
168 | + $data .= '&server_type=' . $request->getServerParam('SERVER_SOFTWARE'); |
|
169 | + $data .= '&time=' . time(); |
|
170 | + $data .= '&remote_log=' . $this->_log; |
|
171 | + $data .= '&action=save'; |
|
172 | + |
|
173 | + if (defined('EELOGGING_PASS')) { |
|
174 | + $data .= '&pass=' . EELOGGING_PASS; |
|
175 | + } |
|
176 | + if (defined('EELOGGING_KEY')) { |
|
177 | + $data .= '&key=' . EELOGGING_KEY; |
|
178 | + } |
|
179 | + |
|
180 | + $c = curl_init($this->_remote_logging_url); |
|
181 | + curl_setopt($c, CURLOPT_POST, true); |
|
182 | + curl_setopt($c, CURLOPT_POSTFIELDS, $data); |
|
183 | + curl_setopt($c, CURLOPT_RETURNTRANSFER, true); |
|
184 | + curl_exec($c); |
|
185 | + curl_close($c); |
|
186 | + } |
|
187 | + |
|
188 | + |
|
189 | + /** |
|
190 | + * write_debug |
|
191 | + * writes the contents of the current request's data to a log file. |
|
192 | + * previous entries are overwritten |
|
193 | + */ |
|
194 | + public function write_debug() |
|
195 | + { |
|
196 | + $msg = esc_html__( |
|
197 | + 'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.', |
|
198 | + 'event_espresso' |
|
199 | + ); |
|
200 | + EE_Error::doing_it_wrong( |
|
201 | + __METHOD__, |
|
202 | + $msg, |
|
203 | + '4.10.1.p' |
|
204 | + ); |
|
205 | + } |
|
206 | + |
|
207 | + |
|
208 | + /** |
|
209 | + * __clone |
|
210 | + */ |
|
211 | + public function __clone() |
|
212 | + { |
|
213 | + trigger_error(esc_html__('Clone is not allowed.', 'event_espresso'), E_USER_ERROR); |
|
214 | + } |
|
215 | 215 | } |
@@ -141,7 +141,7 @@ discard block |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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; |
@@ -13,97 +13,97 @@ discard block |
||
13 | 13 | */ |
14 | 14 | class EE_Import implements ResettableInterface |
15 | 15 | { |
16 | - const do_insert = 'insert'; |
|
17 | - const do_update = 'update'; |
|
18 | - const do_nothing = 'nothing'; |
|
19 | - |
|
20 | - |
|
21 | - // instance of the EE_Import object |
|
22 | - private static $_instance; |
|
23 | - |
|
24 | - private static $_csv_array = array(); |
|
25 | - |
|
26 | - /** |
|
27 | - * |
|
28 | - * @var array of model names |
|
29 | - */ |
|
30 | - private static $_model_list = array(); |
|
31 | - |
|
32 | - private static $_columns_to_save = array(); |
|
33 | - |
|
34 | - protected $_total_inserts = 0; |
|
35 | - protected $_total_updates = 0; |
|
36 | - protected $_total_insert_errors = 0; |
|
37 | - protected $_total_update_errors = 0; |
|
38 | - |
|
39 | - /** |
|
40 | - * @var EE_CSV |
|
41 | - * @since 4.10.14.p |
|
42 | - */ |
|
43 | - private $EE_CSV; |
|
44 | - |
|
45 | - |
|
46 | - /** |
|
47 | - * private constructor to prevent direct creation |
|
48 | - * |
|
49 | - * @Constructor |
|
50 | - * @access private |
|
51 | - * @return void |
|
52 | - */ |
|
53 | - private function __construct() |
|
54 | - { |
|
55 | - $this->_total_inserts = 0; |
|
56 | - $this->_total_updates = 0; |
|
57 | - $this->_total_insert_errors = 0; |
|
58 | - $this->_total_update_errors = 0; |
|
59 | - } |
|
60 | - |
|
61 | - |
|
62 | - /** |
|
63 | - * @ singleton method used to instantiate class object |
|
64 | - * @ access public |
|
65 | - * |
|
66 | - * @return EE_Import |
|
67 | - */ |
|
68 | - public static function instance() |
|
69 | - { |
|
70 | - // check if class object is instantiated |
|
71 | - if (self::$_instance === null or ! is_object(self::$_instance) or ! (self::$_instance instanceof EE_Import)) { |
|
72 | - self::$_instance = new self(); |
|
73 | - } |
|
74 | - return self::$_instance; |
|
75 | - } |
|
76 | - |
|
77 | - /** |
|
78 | - * Resets the importer |
|
79 | - * |
|
80 | - * @return EE_Import |
|
81 | - */ |
|
82 | - public static function reset() |
|
83 | - { |
|
84 | - self::$_instance = null; |
|
85 | - return self::instance(); |
|
86 | - } |
|
87 | - |
|
88 | - |
|
89 | - /** |
|
90 | - * @ generates HTML for a file upload input and form |
|
91 | - * @ access public |
|
92 | - * |
|
93 | - * @param string $title - heading for the form |
|
94 | - * @param string $intro - additional text explaing what to do |
|
95 | - * @param string $page - EE Admin page to direct form to - in the form "espresso_{pageslug}" |
|
96 | - * @param string $action - EE Admin page route array "action" that form will direct to |
|
97 | - * @param string $type - type of file to import |
|
98 | - * @ return string |
|
99 | - */ |
|
100 | - public function upload_form($title, $intro, $form_url, $action, $type) |
|
101 | - { |
|
102 | - |
|
103 | - $form_url = EE_Admin_Page::add_query_args_and_nonce(array('action' => $action), $form_url); |
|
104 | - |
|
105 | - ob_start(); |
|
106 | - ?> |
|
16 | + const do_insert = 'insert'; |
|
17 | + const do_update = 'update'; |
|
18 | + const do_nothing = 'nothing'; |
|
19 | + |
|
20 | + |
|
21 | + // instance of the EE_Import object |
|
22 | + private static $_instance; |
|
23 | + |
|
24 | + private static $_csv_array = array(); |
|
25 | + |
|
26 | + /** |
|
27 | + * |
|
28 | + * @var array of model names |
|
29 | + */ |
|
30 | + private static $_model_list = array(); |
|
31 | + |
|
32 | + private static $_columns_to_save = array(); |
|
33 | + |
|
34 | + protected $_total_inserts = 0; |
|
35 | + protected $_total_updates = 0; |
|
36 | + protected $_total_insert_errors = 0; |
|
37 | + protected $_total_update_errors = 0; |
|
38 | + |
|
39 | + /** |
|
40 | + * @var EE_CSV |
|
41 | + * @since 4.10.14.p |
|
42 | + */ |
|
43 | + private $EE_CSV; |
|
44 | + |
|
45 | + |
|
46 | + /** |
|
47 | + * private constructor to prevent direct creation |
|
48 | + * |
|
49 | + * @Constructor |
|
50 | + * @access private |
|
51 | + * @return void |
|
52 | + */ |
|
53 | + private function __construct() |
|
54 | + { |
|
55 | + $this->_total_inserts = 0; |
|
56 | + $this->_total_updates = 0; |
|
57 | + $this->_total_insert_errors = 0; |
|
58 | + $this->_total_update_errors = 0; |
|
59 | + } |
|
60 | + |
|
61 | + |
|
62 | + /** |
|
63 | + * @ singleton method used to instantiate class object |
|
64 | + * @ access public |
|
65 | + * |
|
66 | + * @return EE_Import |
|
67 | + */ |
|
68 | + public static function instance() |
|
69 | + { |
|
70 | + // check if class object is instantiated |
|
71 | + if (self::$_instance === null or ! is_object(self::$_instance) or ! (self::$_instance instanceof EE_Import)) { |
|
72 | + self::$_instance = new self(); |
|
73 | + } |
|
74 | + return self::$_instance; |
|
75 | + } |
|
76 | + |
|
77 | + /** |
|
78 | + * Resets the importer |
|
79 | + * |
|
80 | + * @return EE_Import |
|
81 | + */ |
|
82 | + public static function reset() |
|
83 | + { |
|
84 | + self::$_instance = null; |
|
85 | + return self::instance(); |
|
86 | + } |
|
87 | + |
|
88 | + |
|
89 | + /** |
|
90 | + * @ generates HTML for a file upload input and form |
|
91 | + * @ access public |
|
92 | + * |
|
93 | + * @param string $title - heading for the form |
|
94 | + * @param string $intro - additional text explaing what to do |
|
95 | + * @param string $page - EE Admin page to direct form to - in the form "espresso_{pageslug}" |
|
96 | + * @param string $action - EE Admin page route array "action" that form will direct to |
|
97 | + * @param string $type - type of file to import |
|
98 | + * @ return string |
|
99 | + */ |
|
100 | + public function upload_form($title, $intro, $form_url, $action, $type) |
|
101 | + { |
|
102 | + |
|
103 | + $form_url = EE_Admin_Page::add_query_args_and_nonce(array('action' => $action), $form_url); |
|
104 | + |
|
105 | + ob_start(); |
|
106 | + ?> |
|
107 | 107 | <div class="ee-upload-form-dv"> |
108 | 108 | <h3><?php echo esc_html($title); ?></h3> |
109 | 109 | <p><?php echo esc_html($intro); ?></p> |
@@ -119,882 +119,882 @@ discard block |
||
119 | 119 | <b><?php esc_html_e('Attention', 'event_espresso'); ?></b><br/> |
120 | 120 | <?php echo sprintf(esc_html__('Accepts .%s file types only.', 'event_espresso'), $type); ?> |
121 | 121 | <?php echo esc_html__( |
122 | - 'Please only import CSV files exported from Event Espresso, or compatible 3rd-party software.', |
|
123 | - 'event_espresso' |
|
124 | - ); ?> |
|
122 | + 'Please only import CSV files exported from Event Espresso, or compatible 3rd-party software.', |
|
123 | + 'event_espresso' |
|
124 | + ); ?> |
|
125 | 125 | </p> |
126 | 126 | |
127 | 127 | </div> |
128 | 128 | |
129 | 129 | <?php |
130 | - $uploader = ob_get_clean(); |
|
131 | - return $uploader; |
|
132 | - } |
|
133 | - |
|
134 | - |
|
135 | - /** |
|
136 | - * @Import Event Espresso data - some code "borrowed" from event espresso csv_import.php |
|
137 | - * @access public |
|
138 | - * @return boolean success |
|
139 | - */ |
|
140 | - public function import() |
|
141 | - { |
|
142 | - |
|
143 | - require_once(EE_CLASSES . 'EE_CSV.class.php'); |
|
144 | - $this->EE_CSV = EE_CSV::instance(); |
|
145 | - |
|
146 | - /** @var RequestInterface $request */ |
|
147 | - $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
148 | - |
|
149 | - if ($request->requestParamIsSet('import') && $request->requestParamIsSet('csv_submitted')) { |
|
150 | - $files = $request->filesParams(); |
|
151 | - switch ($files['file']['error'][0]) { |
|
152 | - case UPLOAD_ERR_OK: |
|
153 | - $error_msg = false; |
|
154 | - break; |
|
155 | - case UPLOAD_ERR_INI_SIZE: |
|
156 | - $error_msg = esc_html__( |
|
157 | - "'The uploaded file exceeds the upload_max_filesize directive in php.ini.'", |
|
158 | - "event_espresso" |
|
159 | - ); |
|
160 | - break; |
|
161 | - case UPLOAD_ERR_FORM_SIZE: |
|
162 | - $error_msg = esc_html__( |
|
163 | - 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', |
|
164 | - "event_espresso" |
|
165 | - ); |
|
166 | - break; |
|
167 | - case UPLOAD_ERR_PARTIAL: |
|
168 | - $error_msg = esc_html__('The uploaded file was only partially uploaded.', "event_espresso"); |
|
169 | - break; |
|
170 | - case UPLOAD_ERR_NO_FILE: |
|
171 | - $error_msg = esc_html__('No file was uploaded.', "event_espresso"); |
|
172 | - break; |
|
173 | - case UPLOAD_ERR_NO_TMP_DIR: |
|
174 | - $error_msg = esc_html__('Missing a temporary folder.', "event_espresso"); |
|
175 | - break; |
|
176 | - case UPLOAD_ERR_CANT_WRITE: |
|
177 | - $error_msg = esc_html__('Failed to write file to disk.', "event_espresso"); |
|
178 | - break; |
|
179 | - case UPLOAD_ERR_EXTENSION: |
|
180 | - $error_msg = esc_html__('File upload stopped by extension.', "event_espresso"); |
|
181 | - break; |
|
182 | - default: |
|
183 | - $error_msg = esc_html__( |
|
184 | - 'An unknown error occurred and the file could not be uploaded', |
|
185 | - "event_espresso" |
|
186 | - ); |
|
187 | - break; |
|
188 | - } |
|
189 | - |
|
190 | - if (! $error_msg) { |
|
191 | - $filename = $files['file']['name'][0]; |
|
192 | - $file_ext = substr(strrchr($filename, '.'), 1); |
|
193 | - $file_type = $files['file']['type'][0]; |
|
194 | - $temp_file = $files['file']['tmp_name'][0]; |
|
195 | - $filesize = $files['file']['size'][0] / 1024;// convert from bytes to KB |
|
196 | - |
|
197 | - if ($file_ext == 'csv') { |
|
198 | - $max_upload = $this->EE_CSV->get_max_upload_size();// max upload size in KB |
|
199 | - if ($filesize < $max_upload || true) { |
|
200 | - $wp_upload_dir = str_replace(array('\\', '/'), '/', wp_upload_dir()); |
|
201 | - $path_to_file = $wp_upload_dir['basedir'] . '/espresso/' . $filename; |
|
202 | - |
|
203 | - if (move_uploaded_file($temp_file, $path_to_file)) { |
|
204 | - // convert csv to array |
|
205 | - $this->csv_array = $this->EE_CSV->import_csv_to_model_data_array($path_to_file); |
|
206 | - |
|
207 | - $action = $request->getRequestParam('action'); |
|
208 | - |
|
209 | - // was data successfully stored in an array? |
|
210 | - if (is_array($this->csv_array)) { |
|
211 | - $import_what = str_replace('csv_import_', '', $action); |
|
212 | - $import_what = str_replace('_', ' ', ucwords($import_what)); |
|
213 | - $processed_data = $this->csv_array; |
|
214 | - $this->columns_to_save = false; |
|
215 | - |
|
216 | - // if any imports require funky processing, we'll catch them in the switch |
|
217 | - switch ($action) { |
|
218 | - case "import_events": |
|
219 | - case "event_list": |
|
220 | - $import_what = 'Event Details'; |
|
221 | - break; |
|
222 | - |
|
223 | - case 'groupon_import_csv': |
|
224 | - $import_what = 'Groupon Codes'; |
|
225 | - $processed_data = $this->process_groupon_codes(); |
|
226 | - break; |
|
227 | - } |
|
228 | - // save processed codes to db |
|
229 | - if ($this->save_csv_data_array_to_db($processed_data, $this->columns_to_save)) { |
|
230 | - return true; |
|
231 | - } |
|
232 | - } else { |
|
233 | - // no array? must be an error |
|
234 | - EE_Error::add_error( |
|
235 | - sprintf(esc_html__("No file seems to have been uploaded", "event_espresso")), |
|
236 | - __FILE__, |
|
237 | - __FUNCTION__, |
|
238 | - __LINE__ |
|
239 | - ); |
|
240 | - return false; |
|
241 | - } |
|
242 | - } else { |
|
243 | - EE_Error::add_error( |
|
244 | - sprintf(esc_html__("%s was not successfully uploaded", "event_espresso"), $filename), |
|
245 | - __FILE__, |
|
246 | - __FUNCTION__, |
|
247 | - __LINE__ |
|
248 | - ); |
|
249 | - return false; |
|
250 | - } |
|
251 | - } else { |
|
252 | - EE_Error::add_error( |
|
253 | - sprintf( |
|
254 | - esc_html__( |
|
255 | - "%s was too large of a file and could not be uploaded. The max filesize is %s' KB.", |
|
256 | - "event_espresso" |
|
257 | - ), |
|
258 | - $filename, |
|
259 | - $max_upload |
|
260 | - ), |
|
261 | - __FILE__, |
|
262 | - __FUNCTION__, |
|
263 | - __LINE__ |
|
264 | - ); |
|
265 | - return false; |
|
266 | - } |
|
267 | - } else { |
|
268 | - EE_Error::add_error( |
|
269 | - sprintf(esc_html__("%s had an invalid file extension, not uploaded", "event_espresso"), $filename), |
|
270 | - __FILE__, |
|
271 | - __FUNCTION__, |
|
272 | - __LINE__ |
|
273 | - ); |
|
274 | - return false; |
|
275 | - } |
|
276 | - } else { |
|
277 | - EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
278 | - return false; |
|
279 | - } |
|
280 | - } |
|
281 | - return false; |
|
282 | - } |
|
283 | - |
|
284 | - |
|
285 | - /** |
|
286 | - * Given an array of data (usually from a CSV import) attempts to save that data to the db. |
|
287 | - * If $model_name ISN'T provided, assumes that this is a 3d array, with toplevel keys being model names, |
|
288 | - * next level being numeric indexes adn each value representing a model object, and the last layer down |
|
289 | - * being keys of model fields and their proposed values. |
|
290 | - * If $model_name IS provided, assumes a 2d array of the bottom two layers previously mentioned. |
|
291 | - * If the CSV data says (in the metadata row) that it's from the SAME database, |
|
292 | - * we treat the IDs in the CSV as the normal IDs, and try to update those records. However, if those |
|
293 | - * IDs DON'T exist in the database, they're treated as temporary IDs, |
|
294 | - * which can used elsewhere to refer to the same object. Once an item |
|
295 | - * with a temporary ID gets inserted, we record its mapping from temporary |
|
296 | - * ID to real ID, and use the real ID in place of the temporary ID |
|
297 | - * when that temporary ID was used as a foreign key. |
|
298 | - * If the CSV data says (in the metadata again) that it's from a DIFFERENT database, |
|
299 | - * we treat all the IDs in the CSV as temporary ID- eg, if the CSV specifies an event with |
|
300 | - * ID 1, and the database already has an event with ID 1, we assume that's just a coincidence, |
|
301 | - * and insert a new event, and map it's temporary ID of 1 over to its new real ID. |
|
302 | - * An important exception are non-auto-increment primary keys. If one entry in the |
|
303 | - * CSV file has the same ID as one in the DB, we assume they are meant to be |
|
304 | - * the same item, and instead update the item in the DB with that same ID. |
|
305 | - * Also note, we remember the mappings permanently. So the 2nd, 3rd, and 10000th |
|
306 | - * time you import a CSV from a different site, we remember their mappings, and |
|
307 | - * will try to update the item in the DB instead of inserting another item (eg |
|
308 | - * if we previously imported an event with temporary ID 1, and then it got a |
|
309 | - * real ID of 123, we remember that. So the next time we import an event with |
|
310 | - * temporary ID, from the same site, we know that it's real ID is 123, and will |
|
311 | - * update that event, instead of adding a new event). |
|
312 | - * |
|
313 | - * @access public |
|
314 | - * @param array $csv_data_array - the array containing the csv data produced from |
|
315 | - * EE_CSV::import_csv_to_model_data_array() |
|
316 | - * @param array $fields_to_save - an array containing the csv column names as keys with the corresponding db table |
|
317 | - * fields they will be saved to |
|
318 | - * @return TRUE on success, FALSE on fail |
|
319 | - * @throws \EE_Error |
|
320 | - */ |
|
321 | - public function save_csv_data_array_to_db($csv_data_array, $model_name = false) |
|
322 | - { |
|
323 | - $success = false; |
|
324 | - $error = false; |
|
325 | - // whther to treat this import as if it's data froma different database or not |
|
326 | - // ie, if it IS from a different database, ignore foreign keys whihf |
|
327 | - $export_from_site_a_to_b = true; |
|
328 | - // first level of array is not table information but a table name was passed to the function |
|
329 | - // array is only two levels deep, so let's fix that by adding a level, else the next steps will fail |
|
330 | - if ($model_name) { |
|
331 | - $csv_data_array = array($csv_data_array); |
|
332 | - } |
|
333 | - // begin looking through the $csv_data_array, expecting the toplevel key to be the model's name... |
|
334 | - $old_site_url = 'none-specified'; |
|
335 | - // hanlde metadata |
|
336 | - if (isset($csv_data_array[ EE_CSV::metadata_header ])) { |
|
337 | - $csv_metadata = array_shift($csv_data_array[ EE_CSV::metadata_header ]); |
|
338 | - // ok so its metadata, dont try to save it to ehte db obviously... |
|
339 | - if (isset($csv_metadata['site_url']) && $csv_metadata['site_url'] == site_url()) { |
|
340 | - EE_Error::add_attention( |
|
341 | - sprintf( |
|
342 | - esc_html__( |
|
343 | - "CSV Data appears to be from the same database, so attempting to update data", |
|
344 | - "event_espresso" |
|
345 | - ) |
|
346 | - ) |
|
347 | - ); |
|
348 | - $export_from_site_a_to_b = false; |
|
349 | - } else { |
|
350 | - $old_site_url = isset($csv_metadata['site_url']) ? $csv_metadata['site_url'] : $old_site_url; |
|
351 | - EE_Error::add_attention( |
|
352 | - sprintf( |
|
353 | - esc_html__( |
|
354 | - "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", |
|
355 | - "event_espresso" |
|
356 | - ), |
|
357 | - $old_site_url, |
|
358 | - site_url() |
|
359 | - ) |
|
360 | - ); |
|
361 | - }; |
|
362 | - unset($csv_data_array[ EE_CSV::metadata_header ]); |
|
363 | - } |
|
364 | - /** |
|
365 | - * @var $old_db_to_new_db_mapping 2d array: toplevel keys being model names, bottom-level keys being the original key, and |
|
366 | - * the value will be the newly-inserted ID. |
|
367 | - * If we have already imported data from the same website via CSV, it shoudl be kept in this wp option |
|
368 | - */ |
|
369 | - $old_db_to_new_db_mapping = get_option('ee_id_mapping_from' . sanitize_title($old_site_url), array()); |
|
370 | - if ($old_db_to_new_db_mapping) { |
|
371 | - EE_Error::add_attention( |
|
372 | - sprintf( |
|
373 | - esc_html__( |
|
374 | - "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", |
|
375 | - "event_espresso" |
|
376 | - ), |
|
377 | - $old_site_url, |
|
378 | - site_url() |
|
379 | - ) |
|
380 | - ); |
|
381 | - } |
|
382 | - $old_db_to_new_db_mapping = $this->save_data_rows_to_db( |
|
383 | - $csv_data_array, |
|
384 | - $export_from_site_a_to_b, |
|
385 | - $old_db_to_new_db_mapping |
|
386 | - ); |
|
387 | - |
|
388 | - // save the mapping from old db to new db in case they try re-importing the same data from the same website again |
|
389 | - update_option('ee_id_mapping_from' . sanitize_title($old_site_url), $old_db_to_new_db_mapping); |
|
390 | - |
|
391 | - if ($this->_total_updates > 0) { |
|
392 | - EE_Error::add_success( |
|
393 | - sprintf( |
|
394 | - esc_html__("%s existing records in the database were updated.", "event_espresso"), |
|
395 | - $this->_total_updates |
|
396 | - ) |
|
397 | - ); |
|
398 | - $success = true; |
|
399 | - } |
|
400 | - if ($this->_total_inserts > 0) { |
|
401 | - EE_Error::add_success( |
|
402 | - sprintf(esc_html__("%s new records were added to the database.", "event_espresso"), $this->_total_inserts) |
|
403 | - ); |
|
404 | - $success = true; |
|
405 | - } |
|
406 | - |
|
407 | - if ($this->_total_update_errors > 0) { |
|
408 | - EE_Error::add_error( |
|
409 | - sprintf( |
|
410 | - esc_html__( |
|
411 | - "'One or more errors occurred, and a total of %s existing records in the database were <strong>not</strong> updated.'", |
|
412 | - "event_espresso" |
|
413 | - ), |
|
414 | - $this->_total_update_errors |
|
415 | - ), |
|
416 | - __FILE__, |
|
417 | - __FUNCTION__, |
|
418 | - __LINE__ |
|
419 | - ); |
|
420 | - $error = true; |
|
421 | - } |
|
422 | - if ($this->_total_insert_errors > 0) { |
|
423 | - EE_Error::add_error( |
|
424 | - sprintf( |
|
425 | - esc_html__( |
|
426 | - "One or more errors occurred, and a total of %s new records were <strong>not</strong> added to the database.'", |
|
427 | - "event_espresso" |
|
428 | - ), |
|
429 | - $this->_total_insert_errors |
|
430 | - ), |
|
431 | - __FILE__, |
|
432 | - __FUNCTION__, |
|
433 | - __LINE__ |
|
434 | - ); |
|
435 | - $error = true; |
|
436 | - } |
|
437 | - |
|
438 | - // lastly, we need to update the datetime and ticket sold amounts |
|
439 | - // as those may have been affected by this |
|
440 | - EEM_Ticket::instance()->update_tickets_sold(EEM_Ticket::instance()->get_all()); |
|
441 | - |
|
442 | - // if there was at least one success and absolutely no errors |
|
443 | - if ($success && ! $error) { |
|
444 | - return true; |
|
445 | - } else { |
|
446 | - return false; |
|
447 | - } |
|
448 | - } |
|
449 | - |
|
450 | - |
|
451 | - /** |
|
452 | - * Processes the array of data, given the knowledge that it's from the same database or a different one, |
|
453 | - * and the mapping from temporary IDs to real IDs. |
|
454 | - * If the data is from a different database, we treat the primary keys and their corresponding |
|
455 | - * foreign keys as "temp Ids", basically identifiers that get mapped to real primary keys |
|
456 | - * in the real target database. As items are inserted, their temporary primary keys |
|
457 | - * are mapped to the real IDs in the target database. Also, before doing any update or |
|
458 | - * insert, we replace all the temp ID which are foreign keys with their mapped real IDs. |
|
459 | - * An exception: string primary keys are treated as real IDs, or else we'd need to |
|
460 | - * dynamically generate new string primary keys which would be very awkard for the country table etc. |
|
461 | - * Also, models with no primary key are strange too. We combine use their primar key INDEX (a |
|
462 | - * combination of fields) to create a unique string identifying the row and store |
|
463 | - * those in the mapping. |
|
464 | - * |
|
465 | - * If the data is from the same database, we usually treat primary keys as real IDs. |
|
466 | - * An exception is if there is nothing in the database for that ID. If that's the case, |
|
467 | - * we need to insert a new row for that ID, and then map from the non-existent ID |
|
468 | - * to the newly-inserted real ID. |
|
469 | - * |
|
470 | - * @param type $csv_data_array |
|
471 | - * @param type $export_from_site_a_to_b |
|
472 | - * @param type $old_db_to_new_db_mapping |
|
473 | - * @return array updated $old_db_to_new_db_mapping |
|
474 | - */ |
|
475 | - public function save_data_rows_to_db($csv_data_array, $export_from_site_a_to_b, $old_db_to_new_db_mapping) |
|
476 | - { |
|
477 | - foreach ($csv_data_array as $model_name_in_csv_data => $model_data_from_import) { |
|
478 | - // now check that assumption was correct. If |
|
479 | - if (EE_Registry::instance()->is_model_name($model_name_in_csv_data)) { |
|
480 | - $model_name = $model_name_in_csv_data; |
|
481 | - } else { |
|
482 | - // no table info in the array and no table name passed to the function?? FAIL |
|
483 | - EE_Error::add_error( |
|
484 | - esc_html__( |
|
485 | - 'No table information was specified and/or found, therefore the import could not be completed', |
|
486 | - 'event_espresso' |
|
487 | - ), |
|
488 | - __FILE__, |
|
489 | - __FUNCTION__, |
|
490 | - __LINE__ |
|
491 | - ); |
|
492 | - return false; |
|
493 | - } |
|
494 | - /* @var $model EEM_Base */ |
|
495 | - $model = EE_Registry::instance()->load_model($model_name); |
|
496 | - |
|
497 | - // so without further ado, scanning all the data provided for primary keys and their inital values |
|
498 | - foreach ($model_data_from_import as $model_object_data) { |
|
499 | - // before we do ANYTHING, make sure the csv row wasn't just completely blank |
|
500 | - $row_is_completely_empty = true; |
|
501 | - foreach ($model_object_data as $field) { |
|
502 | - if ($field) { |
|
503 | - $row_is_completely_empty = false; |
|
504 | - } |
|
505 | - } |
|
506 | - if ($row_is_completely_empty) { |
|
507 | - continue; |
|
508 | - } |
|
509 | - // find the PK in the row of data (or a combined key if |
|
510 | - // there is no primary key) |
|
511 | - if ($model->has_primary_key_field()) { |
|
512 | - $id_in_csv = $model_object_data[ $model->primary_key_name() ]; |
|
513 | - } else { |
|
514 | - $id_in_csv = $model->get_index_primary_key_string($model_object_data); |
|
515 | - } |
|
516 | - |
|
517 | - |
|
518 | - $model_object_data = $this->_replace_temp_ids_with_mappings( |
|
519 | - $model_object_data, |
|
520 | - $model, |
|
521 | - $old_db_to_new_db_mapping, |
|
522 | - $export_from_site_a_to_b |
|
523 | - ); |
|
524 | - // now we need to decide if we're going to add a new model object given the $model_object_data, |
|
525 | - // or just update. |
|
526 | - if ($export_from_site_a_to_b) { |
|
527 | - $what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_other_db( |
|
528 | - $id_in_csv, |
|
529 | - $model_object_data, |
|
530 | - $model, |
|
531 | - $old_db_to_new_db_mapping |
|
532 | - ); |
|
533 | - } else {// this is just a re-import |
|
534 | - $what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_same_db( |
|
535 | - $id_in_csv, |
|
536 | - $model_object_data, |
|
537 | - $model, |
|
538 | - $old_db_to_new_db_mapping |
|
539 | - ); |
|
540 | - } |
|
541 | - if ($what_to_do == self::do_nothing) { |
|
542 | - continue; |
|
543 | - } |
|
544 | - |
|
545 | - // double-check we actually want to insert, if that's what we're planning |
|
546 | - // based on whether this item would be unique in the DB or not |
|
547 | - if ($what_to_do == self::do_insert) { |
|
548 | - // we're supposed to be inserting. But wait, will this thing |
|
549 | - // be acceptable if inserted? |
|
550 | - $conflicting = $model->get_one_conflicting($model_object_data, false); |
|
551 | - if ($conflicting) { |
|
552 | - // ok, this item would conflict if inserted. Just update the item that it conflicts with. |
|
553 | - $what_to_do = self::do_update; |
|
554 | - // and if this model has a primary key, remember its mapping |
|
555 | - if ($model->has_primary_key_field()) { |
|
556 | - $old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ] = $conflicting->ID(); |
|
557 | - $model_object_data[ $model->primary_key_name() ] = $conflicting->ID(); |
|
558 | - } else { |
|
559 | - // we want to update this conflicting item, instead of inserting a conflicting item |
|
560 | - // 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 |
|
561 | - // for the WHERE conditions in the update). At the time of this comment, there were no models like this |
|
562 | - foreach ($model->get_combined_primary_key_fields() as $key_field) { |
|
563 | - $model_object_data[ $key_field->get_name() ] = $conflicting->get( |
|
564 | - $key_field->get_name() |
|
565 | - ); |
|
566 | - } |
|
567 | - } |
|
568 | - } |
|
569 | - } |
|
570 | - if ($what_to_do == self::do_insert) { |
|
571 | - $old_db_to_new_db_mapping = $this->_insert_from_data_array( |
|
572 | - $id_in_csv, |
|
573 | - $model_object_data, |
|
574 | - $model, |
|
575 | - $old_db_to_new_db_mapping |
|
576 | - ); |
|
577 | - } elseif ($what_to_do == self::do_update) { |
|
578 | - $old_db_to_new_db_mapping = $this->_update_from_data_array( |
|
579 | - $id_in_csv, |
|
580 | - $model_object_data, |
|
581 | - $model, |
|
582 | - $old_db_to_new_db_mapping |
|
583 | - ); |
|
584 | - } else { |
|
585 | - throw new EE_Error( |
|
586 | - sprintf( |
|
587 | - esc_html__( |
|
588 | - 'Programming error. We shoudl be inserting or updating, but instead we are being told to "%s", whifh is invalid', |
|
589 | - 'event_espresso' |
|
590 | - ), |
|
591 | - $what_to_do |
|
592 | - ) |
|
593 | - ); |
|
594 | - } |
|
595 | - } |
|
596 | - } |
|
597 | - return $old_db_to_new_db_mapping; |
|
598 | - } |
|
599 | - |
|
600 | - |
|
601 | - /** |
|
602 | - * Decides whether or not to insert, given that this data is from another database. |
|
603 | - * So, if the primary key of this $model_object_data already exists in the database, |
|
604 | - * it's just a coincidence and we should still insert. The only time we should |
|
605 | - * update is when we know what it maps to, or there's something that would |
|
606 | - * conflict (and we should instead just update that conflicting thing) |
|
607 | - * |
|
608 | - * @param string $id_in_csv |
|
609 | - * @param array $model_object_data by reference so it can be modified |
|
610 | - * @param EEM_Base $model |
|
611 | - * @param array $old_db_to_new_db_mapping by reference so it can be modified |
|
612 | - * @return string one of the consts on this class that starts with do_* |
|
613 | - */ |
|
614 | - protected function _decide_whether_to_insert_or_update_given_data_from_other_db( |
|
615 | - $id_in_csv, |
|
616 | - $model_object_data, |
|
617 | - $model, |
|
618 | - $old_db_to_new_db_mapping |
|
619 | - ) { |
|
620 | - $model_name = $model->get_this_model_name(); |
|
621 | - // if it's a site-to-site export-and-import, see if this modelobject's id |
|
622 | - // in the old data that we know of |
|
623 | - if (isset($old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ])) { |
|
624 | - return self::do_update; |
|
625 | - } else { |
|
626 | - return self::do_insert; |
|
627 | - } |
|
628 | - } |
|
629 | - |
|
630 | - /** |
|
631 | - * If this thing basically already exists in the database, we want to update it; |
|
632 | - * otherwise insert it (ie, someone tweaked the CSV file, or the item was |
|
633 | - * deleted in the database so it should be re-inserted) |
|
634 | - * |
|
635 | - * @param type $id_in_csv |
|
636 | - * @param type $model_object_data |
|
637 | - * @param EEM_Base $model |
|
638 | - * @param type $old_db_to_new_db_mapping |
|
639 | - * @return |
|
640 | - */ |
|
641 | - protected function _decide_whether_to_insert_or_update_given_data_from_same_db( |
|
642 | - $id_in_csv, |
|
643 | - $model_object_data, |
|
644 | - $model |
|
645 | - ) { |
|
646 | - // in this case, check if this thing ACTUALLY exists in the database |
|
647 | - if ($model->get_one_conflicting($model_object_data)) { |
|
648 | - return self::do_update; |
|
649 | - } else { |
|
650 | - return self::do_insert; |
|
651 | - } |
|
652 | - } |
|
653 | - |
|
654 | - /** |
|
655 | - * Using the $old_db_to_new_db_mapping array, replaces all the temporary IDs |
|
656 | - * with their mapped real IDs. Eg, if importing from site A to B, the mapping |
|
657 | - * file may indicate that the ID "my_event_id" maps to an actual event ID of 123. |
|
658 | - * So this function searches for any event temp Ids called "my_event_id" and |
|
659 | - * replaces them with 123. |
|
660 | - * Also, if there is no temp ID for the INT foreign keys from another database, |
|
661 | - * replaces them with 0 or the field's default. |
|
662 | - * |
|
663 | - * @param type $model_object_data |
|
664 | - * @param EEM_Base $model |
|
665 | - * @param type $old_db_to_new_db_mapping |
|
666 | - * @param boolean $export_from_site_a_to_b |
|
667 | - * @return array updated model object data with temp IDs removed |
|
668 | - */ |
|
669 | - protected function _replace_temp_ids_with_mappings( |
|
670 | - $model_object_data, |
|
671 | - $model, |
|
672 | - $old_db_to_new_db_mapping, |
|
673 | - $export_from_site_a_to_b |
|
674 | - ) { |
|
675 | - // if this model object's primary key is in the mapping, replace it |
|
676 | - if ( |
|
677 | - $model->has_primary_key_field() && |
|
678 | - $model->get_primary_key_field()->is_auto_increment() && |
|
679 | - isset($old_db_to_new_db_mapping[ $model->get_this_model_name() ]) && |
|
680 | - isset( |
|
681 | - $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $model_object_data[ $model->primary_key_name() ] ] |
|
682 | - ) |
|
683 | - ) { |
|
684 | - $model_object_data[ $model->primary_key_name() ] = $old_db_to_new_db_mapping[ $model->get_this_model_name( |
|
685 | - ) ][ $model_object_data[ $model->primary_key_name() ] ]; |
|
686 | - } |
|
687 | - |
|
688 | - try { |
|
689 | - $model_name_field = $model->get_field_containing_related_model_name(); |
|
690 | - $models_pointed_to_by_model_name_field = $model_name_field->get_model_names_pointed_to(); |
|
691 | - } catch (EE_Error $e) { |
|
692 | - $model_name_field = null; |
|
693 | - $models_pointed_to_by_model_name_field = array(); |
|
694 | - } |
|
695 | - foreach ($model->field_settings(true) as $field_obj) { |
|
696 | - if ($field_obj instanceof EE_Foreign_Key_Int_Field) { |
|
697 | - $models_pointed_to = $field_obj->get_model_names_pointed_to(); |
|
698 | - $found_a_mapping = false; |
|
699 | - foreach ($models_pointed_to as $model_pointed_to_by_fk) { |
|
700 | - if ($model_name_field) { |
|
701 | - $value_of_model_name_field = $model_object_data[ $model_name_field->get_name() ]; |
|
702 | - if ($value_of_model_name_field == $model_pointed_to_by_fk) { |
|
703 | - $model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in( |
|
704 | - $model_object_data[ $field_obj->get_name() ], |
|
705 | - $model_pointed_to_by_fk, |
|
706 | - $old_db_to_new_db_mapping, |
|
707 | - $export_from_site_a_to_b |
|
708 | - ); |
|
709 | - $found_a_mapping = true; |
|
710 | - break; |
|
711 | - } |
|
712 | - } else { |
|
713 | - $model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in( |
|
714 | - $model_object_data[ $field_obj->get_name() ], |
|
715 | - $model_pointed_to_by_fk, |
|
716 | - $old_db_to_new_db_mapping, |
|
717 | - $export_from_site_a_to_b |
|
718 | - ); |
|
719 | - $found_a_mapping = true; |
|
720 | - } |
|
721 | - // once we've found a mapping for this field no need to continue |
|
722 | - if ($found_a_mapping) { |
|
723 | - break; |
|
724 | - } |
|
725 | - } |
|
726 | - } else { |
|
727 | - // it's a string foreign key (which we leave alone, because those are things |
|
728 | - // like country names, which we'd really rather not make 2 USAs etc (we'd actually |
|
729 | - // prefer to just update one) |
|
730 | - // or it's just a regular value that ought to be replaced |
|
731 | - } |
|
732 | - } |
|
733 | - // |
|
734 | - if ($model instanceof EEM_Term_Taxonomy) { |
|
735 | - $model_object_data = $this->_handle_split_term_ids($model_object_data); |
|
736 | - } |
|
737 | - return $model_object_data; |
|
738 | - } |
|
739 | - |
|
740 | - /** |
|
741 | - * If the data was exported PRE-4.2, but then imported POST-4.2, then the term_id |
|
742 | - * this term-taxonomy refers to may be out-of-date so we need to update it. |
|
743 | - * see https://make.wordpress.org/core/2015/02/16/taxonomy-term-splitting-in-4-2-a-developer-guide/ |
|
744 | - * |
|
745 | - * @param type $model_object_data |
|
746 | - * @return array new model object data |
|
747 | - */ |
|
748 | - protected function _handle_split_term_ids($model_object_data) |
|
749 | - { |
|
750 | - if ( |
|
751 | - isset($model_object_data['term_id']) |
|
752 | - && isset($model_object_data['taxonomy']) |
|
753 | - && apply_filters( |
|
754 | - 'FHEE__EE_Import__handle_split_term_ids__function_exists', |
|
755 | - function_exists('wp_get_split_term'), |
|
756 | - $model_object_data |
|
757 | - ) |
|
758 | - ) { |
|
759 | - $new_term_id = wp_get_split_term($model_object_data['term_id'], $model_object_data['taxonomy']); |
|
760 | - if ($new_term_id) { |
|
761 | - $model_object_data['term_id'] = $new_term_id; |
|
762 | - } |
|
763 | - } |
|
764 | - return $model_object_data; |
|
765 | - } |
|
766 | - |
|
767 | - /** |
|
768 | - * Given the object's ID and its model's name, find it int he mapping data, |
|
769 | - * bearing in mind where it came from |
|
770 | - * |
|
771 | - * @param type $object_id |
|
772 | - * @param string $model_name |
|
773 | - * @param array $old_db_to_new_db_mapping |
|
774 | - * @param type $export_from_site_a_to_b |
|
775 | - * @return int |
|
776 | - */ |
|
777 | - protected function _find_mapping_in($object_id, $model_name, $old_db_to_new_db_mapping, $export_from_site_a_to_b) |
|
778 | - { |
|
779 | - if (isset($old_db_to_new_db_mapping[ $model_name ][ $object_id ])) { |
|
780 | - return $old_db_to_new_db_mapping[ $model_name ][ $object_id ]; |
|
781 | - } elseif ($object_id == '0' || $object_id == '') { |
|
782 | - // leave as-is |
|
783 | - return $object_id; |
|
784 | - } elseif ($export_from_site_a_to_b) { |
|
785 | - // we couldn't find a mapping for this, and it's from a different site, |
|
786 | - // so blank it out |
|
787 | - return null; |
|
788 | - } elseif (! $export_from_site_a_to_b) { |
|
789 | - // we coudln't find a mapping for this, but it's from thsi DB anyway |
|
790 | - // so let's just leave it as-is |
|
791 | - return $object_id; |
|
792 | - } |
|
793 | - } |
|
794 | - |
|
795 | - /** |
|
796 | - * |
|
797 | - * @param type $id_in_csv |
|
798 | - * @param type $model_object_data |
|
799 | - * @param EEM_Base $model |
|
800 | - * @param type $old_db_to_new_db_mapping |
|
801 | - * @return array updated $old_db_to_new_db_mapping |
|
802 | - */ |
|
803 | - protected function _insert_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping) |
|
804 | - { |
|
805 | - // remove the primary key, if there is one (we don't want it for inserts OR updates) |
|
806 | - // we'll put it back in if we need it |
|
807 | - if ($model->has_primary_key_field() && $model->get_primary_key_field()->is_auto_increment()) { |
|
808 | - $effective_id = $model_object_data[ $model->primary_key_name() ]; |
|
809 | - unset($model_object_data[ $model->primary_key_name() ]); |
|
810 | - } else { |
|
811 | - $effective_id = $model->get_index_primary_key_string($model_object_data); |
|
812 | - } |
|
813 | - // the model takes care of validating the CSV's input |
|
814 | - try { |
|
815 | - $new_id = $model->insert($model_object_data); |
|
816 | - if ($new_id) { |
|
817 | - $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_id; |
|
818 | - $this->_total_inserts++; |
|
819 | - EE_Error::add_success( |
|
820 | - sprintf( |
|
821 | - esc_html__("Successfully added new %s (with id %s) with csv data %s", "event_espresso"), |
|
822 | - $model->get_this_model_name(), |
|
823 | - $new_id, |
|
824 | - implode(",", $model_object_data) |
|
825 | - ) |
|
826 | - ); |
|
827 | - } else { |
|
828 | - $this->_total_insert_errors++; |
|
829 | - // put the ID used back in there for the error message |
|
830 | - if ($model->has_primary_key_field()) { |
|
831 | - $model_object_data[ $model->primary_key_name() ] = $effective_id; |
|
832 | - } |
|
833 | - EE_Error::add_error( |
|
834 | - sprintf( |
|
835 | - esc_html__("Could not insert new %s with the csv data: %s", "event_espresso"), |
|
836 | - $model->get_this_model_name(), |
|
837 | - http_build_query($model_object_data) |
|
838 | - ), |
|
839 | - __FILE__, |
|
840 | - __FUNCTION__, |
|
841 | - __LINE__ |
|
842 | - ); |
|
843 | - } |
|
844 | - } catch (EE_Error $e) { |
|
845 | - $this->_total_insert_errors++; |
|
846 | - if ($model->has_primary_key_field()) { |
|
847 | - $model_object_data[ $model->primary_key_name() ] = $effective_id; |
|
848 | - } |
|
849 | - EE_Error::add_error( |
|
850 | - sprintf( |
|
851 | - esc_html__("Could not insert new %s with the csv data: %s because %s", "event_espresso"), |
|
852 | - $model->get_this_model_name(), |
|
853 | - implode(",", $model_object_data), |
|
854 | - $e->getMessage() |
|
855 | - ), |
|
856 | - __FILE__, |
|
857 | - __FUNCTION__, |
|
858 | - __LINE__ |
|
859 | - ); |
|
860 | - } |
|
861 | - return $old_db_to_new_db_mapping; |
|
862 | - } |
|
863 | - |
|
864 | - /** |
|
865 | - * Given the model object data, finds the row to update and updates it |
|
866 | - * |
|
867 | - * @param string|int $id_in_csv |
|
868 | - * @param array $model_object_data |
|
869 | - * @param EEM_Base $model |
|
870 | - * @param array $old_db_to_new_db_mapping |
|
871 | - * @return array updated $old_db_to_new_db_mapping |
|
872 | - */ |
|
873 | - protected function _update_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping) |
|
874 | - { |
|
875 | - try { |
|
876 | - // let's keep two copies of the model object data: |
|
877 | - // one for performing an update, one for everthing else |
|
878 | - $model_object_data_for_update = $model_object_data; |
|
879 | - if ($model->has_primary_key_field()) { |
|
880 | - $conditions = array($model->primary_key_name() => $model_object_data[ $model->primary_key_name() ]); |
|
881 | - // remove the primary key because we shouldn't use it for updating |
|
882 | - unset($model_object_data_for_update[ $model->primary_key_name() ]); |
|
883 | - } elseif ($model->get_combined_primary_key_fields() > 1) { |
|
884 | - $conditions = array(); |
|
885 | - foreach ($model->get_combined_primary_key_fields() as $key_field) { |
|
886 | - $conditions[ $key_field->get_name() ] = $model_object_data[ $key_field->get_name() ]; |
|
887 | - } |
|
888 | - } else { |
|
889 | - $model->primary_key_name( |
|
890 | - );// this shoudl just throw an exception, explaining that we dont have a primary key (or a combine dkey) |
|
891 | - } |
|
892 | - |
|
893 | - $success = $model->update($model_object_data_for_update, array($conditions)); |
|
894 | - if ($success) { |
|
895 | - $this->_total_updates++; |
|
896 | - EE_Error::add_success( |
|
897 | - sprintf( |
|
898 | - esc_html__("Successfully updated %s with csv data %s", "event_espresso"), |
|
899 | - $model->get_this_model_name(), |
|
900 | - implode(",", $model_object_data_for_update) |
|
901 | - ) |
|
902 | - ); |
|
903 | - // we should still record the mapping even though it was an update |
|
904 | - // because if we were going to insert somethign but it was going to conflict |
|
905 | - // we would have last-minute decided to update. So we'd like to know what we updated |
|
906 | - // and so we record what record ended up being updated using the mapping |
|
907 | - if ($model->has_primary_key_field()) { |
|
908 | - $new_key_for_mapping = $model_object_data[ $model->primary_key_name() ]; |
|
909 | - } else { |
|
910 | - // no primary key just a combined key |
|
911 | - $new_key_for_mapping = $model->get_index_primary_key_string($model_object_data); |
|
912 | - } |
|
913 | - $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_key_for_mapping; |
|
914 | - } else { |
|
915 | - $matched_items = $model->get_all(array($conditions)); |
|
916 | - if (! $matched_items) { |
|
917 | - // no items were matched (so we shouldn't have updated)... but then we should have inserted? what the heck? |
|
918 | - $this->_total_update_errors++; |
|
919 | - EE_Error::add_error( |
|
920 | - sprintf( |
|
921 | - esc_html__( |
|
922 | - "Could not update %s with the csv data: '%s' for an unknown reason (using WHERE conditions %s)", |
|
923 | - "event_espresso" |
|
924 | - ), |
|
925 | - $model->get_this_model_name(), |
|
926 | - http_build_query($model_object_data), |
|
927 | - http_build_query($conditions) |
|
928 | - ), |
|
929 | - __FILE__, |
|
930 | - __FUNCTION__, |
|
931 | - __LINE__ |
|
932 | - ); |
|
933 | - } else { |
|
934 | - $this->_total_updates++; |
|
935 | - EE_Error::add_success( |
|
936 | - sprintf( |
|
937 | - esc_html__( |
|
938 | - "%s with csv data '%s' was found in the database and didn't need updating because all the data is identical.", |
|
939 | - "event_espresso" |
|
940 | - ), |
|
941 | - $model->get_this_model_name(), |
|
942 | - implode(",", $model_object_data) |
|
943 | - ) |
|
944 | - ); |
|
945 | - } |
|
946 | - } |
|
947 | - } catch (EE_Error $e) { |
|
948 | - $this->_total_update_errors++; |
|
949 | - $basic_message = sprintf( |
|
950 | - esc_html__("Could not update %s with the csv data: %s because %s", "event_espresso"), |
|
951 | - $model->get_this_model_name(), |
|
952 | - implode(",", $model_object_data), |
|
953 | - $e->getMessage() |
|
954 | - ); |
|
955 | - $debug_message = $basic_message . ' Stack trace: ' . $e->getTraceAsString(); |
|
956 | - EE_Error::add_error("$basic_message | $debug_message", __FILE__, __FUNCTION__, __LINE__); |
|
957 | - } |
|
958 | - return $old_db_to_new_db_mapping; |
|
959 | - } |
|
960 | - |
|
961 | - /** |
|
962 | - * Gets the number of inserts performed since importer was instantiated or reset |
|
963 | - * |
|
964 | - * @return int |
|
965 | - */ |
|
966 | - public function get_total_inserts() |
|
967 | - { |
|
968 | - return $this->_total_inserts; |
|
969 | - } |
|
970 | - |
|
971 | - /** |
|
972 | - * Gets the number of insert errors since importer was instantiated or reset |
|
973 | - * |
|
974 | - * @return int |
|
975 | - */ |
|
976 | - public function get_total_insert_errors() |
|
977 | - { |
|
978 | - return $this->_total_insert_errors; |
|
979 | - } |
|
980 | - |
|
981 | - /** |
|
982 | - * Gets the number of updates performed since importer was instantiated or reset |
|
983 | - * |
|
984 | - * @return int |
|
985 | - */ |
|
986 | - public function get_total_updates() |
|
987 | - { |
|
988 | - return $this->_total_updates; |
|
989 | - } |
|
990 | - |
|
991 | - /** |
|
992 | - * Gets the number of update errors since importer was instantiated or reset |
|
993 | - * |
|
994 | - * @return int |
|
995 | - */ |
|
996 | - public function get_total_update_errors() |
|
997 | - { |
|
998 | - return $this->_total_update_errors; |
|
999 | - } |
|
130 | + $uploader = ob_get_clean(); |
|
131 | + return $uploader; |
|
132 | + } |
|
133 | + |
|
134 | + |
|
135 | + /** |
|
136 | + * @Import Event Espresso data - some code "borrowed" from event espresso csv_import.php |
|
137 | + * @access public |
|
138 | + * @return boolean success |
|
139 | + */ |
|
140 | + public function import() |
|
141 | + { |
|
142 | + |
|
143 | + require_once(EE_CLASSES . 'EE_CSV.class.php'); |
|
144 | + $this->EE_CSV = EE_CSV::instance(); |
|
145 | + |
|
146 | + /** @var RequestInterface $request */ |
|
147 | + $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
148 | + |
|
149 | + if ($request->requestParamIsSet('import') && $request->requestParamIsSet('csv_submitted')) { |
|
150 | + $files = $request->filesParams(); |
|
151 | + switch ($files['file']['error'][0]) { |
|
152 | + case UPLOAD_ERR_OK: |
|
153 | + $error_msg = false; |
|
154 | + break; |
|
155 | + case UPLOAD_ERR_INI_SIZE: |
|
156 | + $error_msg = esc_html__( |
|
157 | + "'The uploaded file exceeds the upload_max_filesize directive in php.ini.'", |
|
158 | + "event_espresso" |
|
159 | + ); |
|
160 | + break; |
|
161 | + case UPLOAD_ERR_FORM_SIZE: |
|
162 | + $error_msg = esc_html__( |
|
163 | + 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', |
|
164 | + "event_espresso" |
|
165 | + ); |
|
166 | + break; |
|
167 | + case UPLOAD_ERR_PARTIAL: |
|
168 | + $error_msg = esc_html__('The uploaded file was only partially uploaded.', "event_espresso"); |
|
169 | + break; |
|
170 | + case UPLOAD_ERR_NO_FILE: |
|
171 | + $error_msg = esc_html__('No file was uploaded.', "event_espresso"); |
|
172 | + break; |
|
173 | + case UPLOAD_ERR_NO_TMP_DIR: |
|
174 | + $error_msg = esc_html__('Missing a temporary folder.', "event_espresso"); |
|
175 | + break; |
|
176 | + case UPLOAD_ERR_CANT_WRITE: |
|
177 | + $error_msg = esc_html__('Failed to write file to disk.', "event_espresso"); |
|
178 | + break; |
|
179 | + case UPLOAD_ERR_EXTENSION: |
|
180 | + $error_msg = esc_html__('File upload stopped by extension.', "event_espresso"); |
|
181 | + break; |
|
182 | + default: |
|
183 | + $error_msg = esc_html__( |
|
184 | + 'An unknown error occurred and the file could not be uploaded', |
|
185 | + "event_espresso" |
|
186 | + ); |
|
187 | + break; |
|
188 | + } |
|
189 | + |
|
190 | + if (! $error_msg) { |
|
191 | + $filename = $files['file']['name'][0]; |
|
192 | + $file_ext = substr(strrchr($filename, '.'), 1); |
|
193 | + $file_type = $files['file']['type'][0]; |
|
194 | + $temp_file = $files['file']['tmp_name'][0]; |
|
195 | + $filesize = $files['file']['size'][0] / 1024;// convert from bytes to KB |
|
196 | + |
|
197 | + if ($file_ext == 'csv') { |
|
198 | + $max_upload = $this->EE_CSV->get_max_upload_size();// max upload size in KB |
|
199 | + if ($filesize < $max_upload || true) { |
|
200 | + $wp_upload_dir = str_replace(array('\\', '/'), '/', wp_upload_dir()); |
|
201 | + $path_to_file = $wp_upload_dir['basedir'] . '/espresso/' . $filename; |
|
202 | + |
|
203 | + if (move_uploaded_file($temp_file, $path_to_file)) { |
|
204 | + // convert csv to array |
|
205 | + $this->csv_array = $this->EE_CSV->import_csv_to_model_data_array($path_to_file); |
|
206 | + |
|
207 | + $action = $request->getRequestParam('action'); |
|
208 | + |
|
209 | + // was data successfully stored in an array? |
|
210 | + if (is_array($this->csv_array)) { |
|
211 | + $import_what = str_replace('csv_import_', '', $action); |
|
212 | + $import_what = str_replace('_', ' ', ucwords($import_what)); |
|
213 | + $processed_data = $this->csv_array; |
|
214 | + $this->columns_to_save = false; |
|
215 | + |
|
216 | + // if any imports require funky processing, we'll catch them in the switch |
|
217 | + switch ($action) { |
|
218 | + case "import_events": |
|
219 | + case "event_list": |
|
220 | + $import_what = 'Event Details'; |
|
221 | + break; |
|
222 | + |
|
223 | + case 'groupon_import_csv': |
|
224 | + $import_what = 'Groupon Codes'; |
|
225 | + $processed_data = $this->process_groupon_codes(); |
|
226 | + break; |
|
227 | + } |
|
228 | + // save processed codes to db |
|
229 | + if ($this->save_csv_data_array_to_db($processed_data, $this->columns_to_save)) { |
|
230 | + return true; |
|
231 | + } |
|
232 | + } else { |
|
233 | + // no array? must be an error |
|
234 | + EE_Error::add_error( |
|
235 | + sprintf(esc_html__("No file seems to have been uploaded", "event_espresso")), |
|
236 | + __FILE__, |
|
237 | + __FUNCTION__, |
|
238 | + __LINE__ |
|
239 | + ); |
|
240 | + return false; |
|
241 | + } |
|
242 | + } else { |
|
243 | + EE_Error::add_error( |
|
244 | + sprintf(esc_html__("%s was not successfully uploaded", "event_espresso"), $filename), |
|
245 | + __FILE__, |
|
246 | + __FUNCTION__, |
|
247 | + __LINE__ |
|
248 | + ); |
|
249 | + return false; |
|
250 | + } |
|
251 | + } else { |
|
252 | + EE_Error::add_error( |
|
253 | + sprintf( |
|
254 | + esc_html__( |
|
255 | + "%s was too large of a file and could not be uploaded. The max filesize is %s' KB.", |
|
256 | + "event_espresso" |
|
257 | + ), |
|
258 | + $filename, |
|
259 | + $max_upload |
|
260 | + ), |
|
261 | + __FILE__, |
|
262 | + __FUNCTION__, |
|
263 | + __LINE__ |
|
264 | + ); |
|
265 | + return false; |
|
266 | + } |
|
267 | + } else { |
|
268 | + EE_Error::add_error( |
|
269 | + sprintf(esc_html__("%s had an invalid file extension, not uploaded", "event_espresso"), $filename), |
|
270 | + __FILE__, |
|
271 | + __FUNCTION__, |
|
272 | + __LINE__ |
|
273 | + ); |
|
274 | + return false; |
|
275 | + } |
|
276 | + } else { |
|
277 | + EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
278 | + return false; |
|
279 | + } |
|
280 | + } |
|
281 | + return false; |
|
282 | + } |
|
283 | + |
|
284 | + |
|
285 | + /** |
|
286 | + * Given an array of data (usually from a CSV import) attempts to save that data to the db. |
|
287 | + * If $model_name ISN'T provided, assumes that this is a 3d array, with toplevel keys being model names, |
|
288 | + * next level being numeric indexes adn each value representing a model object, and the last layer down |
|
289 | + * being keys of model fields and their proposed values. |
|
290 | + * If $model_name IS provided, assumes a 2d array of the bottom two layers previously mentioned. |
|
291 | + * If the CSV data says (in the metadata row) that it's from the SAME database, |
|
292 | + * we treat the IDs in the CSV as the normal IDs, and try to update those records. However, if those |
|
293 | + * IDs DON'T exist in the database, they're treated as temporary IDs, |
|
294 | + * which can used elsewhere to refer to the same object. Once an item |
|
295 | + * with a temporary ID gets inserted, we record its mapping from temporary |
|
296 | + * ID to real ID, and use the real ID in place of the temporary ID |
|
297 | + * when that temporary ID was used as a foreign key. |
|
298 | + * If the CSV data says (in the metadata again) that it's from a DIFFERENT database, |
|
299 | + * we treat all the IDs in the CSV as temporary ID- eg, if the CSV specifies an event with |
|
300 | + * ID 1, and the database already has an event with ID 1, we assume that's just a coincidence, |
|
301 | + * and insert a new event, and map it's temporary ID of 1 over to its new real ID. |
|
302 | + * An important exception are non-auto-increment primary keys. If one entry in the |
|
303 | + * CSV file has the same ID as one in the DB, we assume they are meant to be |
|
304 | + * the same item, and instead update the item in the DB with that same ID. |
|
305 | + * Also note, we remember the mappings permanently. So the 2nd, 3rd, and 10000th |
|
306 | + * time you import a CSV from a different site, we remember their mappings, and |
|
307 | + * will try to update the item in the DB instead of inserting another item (eg |
|
308 | + * if we previously imported an event with temporary ID 1, and then it got a |
|
309 | + * real ID of 123, we remember that. So the next time we import an event with |
|
310 | + * temporary ID, from the same site, we know that it's real ID is 123, and will |
|
311 | + * update that event, instead of adding a new event). |
|
312 | + * |
|
313 | + * @access public |
|
314 | + * @param array $csv_data_array - the array containing the csv data produced from |
|
315 | + * EE_CSV::import_csv_to_model_data_array() |
|
316 | + * @param array $fields_to_save - an array containing the csv column names as keys with the corresponding db table |
|
317 | + * fields they will be saved to |
|
318 | + * @return TRUE on success, FALSE on fail |
|
319 | + * @throws \EE_Error |
|
320 | + */ |
|
321 | + public function save_csv_data_array_to_db($csv_data_array, $model_name = false) |
|
322 | + { |
|
323 | + $success = false; |
|
324 | + $error = false; |
|
325 | + // whther to treat this import as if it's data froma different database or not |
|
326 | + // ie, if it IS from a different database, ignore foreign keys whihf |
|
327 | + $export_from_site_a_to_b = true; |
|
328 | + // first level of array is not table information but a table name was passed to the function |
|
329 | + // array is only two levels deep, so let's fix that by adding a level, else the next steps will fail |
|
330 | + if ($model_name) { |
|
331 | + $csv_data_array = array($csv_data_array); |
|
332 | + } |
|
333 | + // begin looking through the $csv_data_array, expecting the toplevel key to be the model's name... |
|
334 | + $old_site_url = 'none-specified'; |
|
335 | + // hanlde metadata |
|
336 | + if (isset($csv_data_array[ EE_CSV::metadata_header ])) { |
|
337 | + $csv_metadata = array_shift($csv_data_array[ EE_CSV::metadata_header ]); |
|
338 | + // ok so its metadata, dont try to save it to ehte db obviously... |
|
339 | + if (isset($csv_metadata['site_url']) && $csv_metadata['site_url'] == site_url()) { |
|
340 | + EE_Error::add_attention( |
|
341 | + sprintf( |
|
342 | + esc_html__( |
|
343 | + "CSV Data appears to be from the same database, so attempting to update data", |
|
344 | + "event_espresso" |
|
345 | + ) |
|
346 | + ) |
|
347 | + ); |
|
348 | + $export_from_site_a_to_b = false; |
|
349 | + } else { |
|
350 | + $old_site_url = isset($csv_metadata['site_url']) ? $csv_metadata['site_url'] : $old_site_url; |
|
351 | + EE_Error::add_attention( |
|
352 | + sprintf( |
|
353 | + esc_html__( |
|
354 | + "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", |
|
355 | + "event_espresso" |
|
356 | + ), |
|
357 | + $old_site_url, |
|
358 | + site_url() |
|
359 | + ) |
|
360 | + ); |
|
361 | + }; |
|
362 | + unset($csv_data_array[ EE_CSV::metadata_header ]); |
|
363 | + } |
|
364 | + /** |
|
365 | + * @var $old_db_to_new_db_mapping 2d array: toplevel keys being model names, bottom-level keys being the original key, and |
|
366 | + * the value will be the newly-inserted ID. |
|
367 | + * If we have already imported data from the same website via CSV, it shoudl be kept in this wp option |
|
368 | + */ |
|
369 | + $old_db_to_new_db_mapping = get_option('ee_id_mapping_from' . sanitize_title($old_site_url), array()); |
|
370 | + if ($old_db_to_new_db_mapping) { |
|
371 | + EE_Error::add_attention( |
|
372 | + sprintf( |
|
373 | + esc_html__( |
|
374 | + "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", |
|
375 | + "event_espresso" |
|
376 | + ), |
|
377 | + $old_site_url, |
|
378 | + site_url() |
|
379 | + ) |
|
380 | + ); |
|
381 | + } |
|
382 | + $old_db_to_new_db_mapping = $this->save_data_rows_to_db( |
|
383 | + $csv_data_array, |
|
384 | + $export_from_site_a_to_b, |
|
385 | + $old_db_to_new_db_mapping |
|
386 | + ); |
|
387 | + |
|
388 | + // save the mapping from old db to new db in case they try re-importing the same data from the same website again |
|
389 | + update_option('ee_id_mapping_from' . sanitize_title($old_site_url), $old_db_to_new_db_mapping); |
|
390 | + |
|
391 | + if ($this->_total_updates > 0) { |
|
392 | + EE_Error::add_success( |
|
393 | + sprintf( |
|
394 | + esc_html__("%s existing records in the database were updated.", "event_espresso"), |
|
395 | + $this->_total_updates |
|
396 | + ) |
|
397 | + ); |
|
398 | + $success = true; |
|
399 | + } |
|
400 | + if ($this->_total_inserts > 0) { |
|
401 | + EE_Error::add_success( |
|
402 | + sprintf(esc_html__("%s new records were added to the database.", "event_espresso"), $this->_total_inserts) |
|
403 | + ); |
|
404 | + $success = true; |
|
405 | + } |
|
406 | + |
|
407 | + if ($this->_total_update_errors > 0) { |
|
408 | + EE_Error::add_error( |
|
409 | + sprintf( |
|
410 | + esc_html__( |
|
411 | + "'One or more errors occurred, and a total of %s existing records in the database were <strong>not</strong> updated.'", |
|
412 | + "event_espresso" |
|
413 | + ), |
|
414 | + $this->_total_update_errors |
|
415 | + ), |
|
416 | + __FILE__, |
|
417 | + __FUNCTION__, |
|
418 | + __LINE__ |
|
419 | + ); |
|
420 | + $error = true; |
|
421 | + } |
|
422 | + if ($this->_total_insert_errors > 0) { |
|
423 | + EE_Error::add_error( |
|
424 | + sprintf( |
|
425 | + esc_html__( |
|
426 | + "One or more errors occurred, and a total of %s new records were <strong>not</strong> added to the database.'", |
|
427 | + "event_espresso" |
|
428 | + ), |
|
429 | + $this->_total_insert_errors |
|
430 | + ), |
|
431 | + __FILE__, |
|
432 | + __FUNCTION__, |
|
433 | + __LINE__ |
|
434 | + ); |
|
435 | + $error = true; |
|
436 | + } |
|
437 | + |
|
438 | + // lastly, we need to update the datetime and ticket sold amounts |
|
439 | + // as those may have been affected by this |
|
440 | + EEM_Ticket::instance()->update_tickets_sold(EEM_Ticket::instance()->get_all()); |
|
441 | + |
|
442 | + // if there was at least one success and absolutely no errors |
|
443 | + if ($success && ! $error) { |
|
444 | + return true; |
|
445 | + } else { |
|
446 | + return false; |
|
447 | + } |
|
448 | + } |
|
449 | + |
|
450 | + |
|
451 | + /** |
|
452 | + * Processes the array of data, given the knowledge that it's from the same database or a different one, |
|
453 | + * and the mapping from temporary IDs to real IDs. |
|
454 | + * If the data is from a different database, we treat the primary keys and their corresponding |
|
455 | + * foreign keys as "temp Ids", basically identifiers that get mapped to real primary keys |
|
456 | + * in the real target database. As items are inserted, their temporary primary keys |
|
457 | + * are mapped to the real IDs in the target database. Also, before doing any update or |
|
458 | + * insert, we replace all the temp ID which are foreign keys with their mapped real IDs. |
|
459 | + * An exception: string primary keys are treated as real IDs, or else we'd need to |
|
460 | + * dynamically generate new string primary keys which would be very awkard for the country table etc. |
|
461 | + * Also, models with no primary key are strange too. We combine use their primar key INDEX (a |
|
462 | + * combination of fields) to create a unique string identifying the row and store |
|
463 | + * those in the mapping. |
|
464 | + * |
|
465 | + * If the data is from the same database, we usually treat primary keys as real IDs. |
|
466 | + * An exception is if there is nothing in the database for that ID. If that's the case, |
|
467 | + * we need to insert a new row for that ID, and then map from the non-existent ID |
|
468 | + * to the newly-inserted real ID. |
|
469 | + * |
|
470 | + * @param type $csv_data_array |
|
471 | + * @param type $export_from_site_a_to_b |
|
472 | + * @param type $old_db_to_new_db_mapping |
|
473 | + * @return array updated $old_db_to_new_db_mapping |
|
474 | + */ |
|
475 | + public function save_data_rows_to_db($csv_data_array, $export_from_site_a_to_b, $old_db_to_new_db_mapping) |
|
476 | + { |
|
477 | + foreach ($csv_data_array as $model_name_in_csv_data => $model_data_from_import) { |
|
478 | + // now check that assumption was correct. If |
|
479 | + if (EE_Registry::instance()->is_model_name($model_name_in_csv_data)) { |
|
480 | + $model_name = $model_name_in_csv_data; |
|
481 | + } else { |
|
482 | + // no table info in the array and no table name passed to the function?? FAIL |
|
483 | + EE_Error::add_error( |
|
484 | + esc_html__( |
|
485 | + 'No table information was specified and/or found, therefore the import could not be completed', |
|
486 | + 'event_espresso' |
|
487 | + ), |
|
488 | + __FILE__, |
|
489 | + __FUNCTION__, |
|
490 | + __LINE__ |
|
491 | + ); |
|
492 | + return false; |
|
493 | + } |
|
494 | + /* @var $model EEM_Base */ |
|
495 | + $model = EE_Registry::instance()->load_model($model_name); |
|
496 | + |
|
497 | + // so without further ado, scanning all the data provided for primary keys and their inital values |
|
498 | + foreach ($model_data_from_import as $model_object_data) { |
|
499 | + // before we do ANYTHING, make sure the csv row wasn't just completely blank |
|
500 | + $row_is_completely_empty = true; |
|
501 | + foreach ($model_object_data as $field) { |
|
502 | + if ($field) { |
|
503 | + $row_is_completely_empty = false; |
|
504 | + } |
|
505 | + } |
|
506 | + if ($row_is_completely_empty) { |
|
507 | + continue; |
|
508 | + } |
|
509 | + // find the PK in the row of data (or a combined key if |
|
510 | + // there is no primary key) |
|
511 | + if ($model->has_primary_key_field()) { |
|
512 | + $id_in_csv = $model_object_data[ $model->primary_key_name() ]; |
|
513 | + } else { |
|
514 | + $id_in_csv = $model->get_index_primary_key_string($model_object_data); |
|
515 | + } |
|
516 | + |
|
517 | + |
|
518 | + $model_object_data = $this->_replace_temp_ids_with_mappings( |
|
519 | + $model_object_data, |
|
520 | + $model, |
|
521 | + $old_db_to_new_db_mapping, |
|
522 | + $export_from_site_a_to_b |
|
523 | + ); |
|
524 | + // now we need to decide if we're going to add a new model object given the $model_object_data, |
|
525 | + // or just update. |
|
526 | + if ($export_from_site_a_to_b) { |
|
527 | + $what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_other_db( |
|
528 | + $id_in_csv, |
|
529 | + $model_object_data, |
|
530 | + $model, |
|
531 | + $old_db_to_new_db_mapping |
|
532 | + ); |
|
533 | + } else {// this is just a re-import |
|
534 | + $what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_same_db( |
|
535 | + $id_in_csv, |
|
536 | + $model_object_data, |
|
537 | + $model, |
|
538 | + $old_db_to_new_db_mapping |
|
539 | + ); |
|
540 | + } |
|
541 | + if ($what_to_do == self::do_nothing) { |
|
542 | + continue; |
|
543 | + } |
|
544 | + |
|
545 | + // double-check we actually want to insert, if that's what we're planning |
|
546 | + // based on whether this item would be unique in the DB or not |
|
547 | + if ($what_to_do == self::do_insert) { |
|
548 | + // we're supposed to be inserting. But wait, will this thing |
|
549 | + // be acceptable if inserted? |
|
550 | + $conflicting = $model->get_one_conflicting($model_object_data, false); |
|
551 | + if ($conflicting) { |
|
552 | + // ok, this item would conflict if inserted. Just update the item that it conflicts with. |
|
553 | + $what_to_do = self::do_update; |
|
554 | + // and if this model has a primary key, remember its mapping |
|
555 | + if ($model->has_primary_key_field()) { |
|
556 | + $old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ] = $conflicting->ID(); |
|
557 | + $model_object_data[ $model->primary_key_name() ] = $conflicting->ID(); |
|
558 | + } else { |
|
559 | + // we want to update this conflicting item, instead of inserting a conflicting item |
|
560 | + // 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 |
|
561 | + // for the WHERE conditions in the update). At the time of this comment, there were no models like this |
|
562 | + foreach ($model->get_combined_primary_key_fields() as $key_field) { |
|
563 | + $model_object_data[ $key_field->get_name() ] = $conflicting->get( |
|
564 | + $key_field->get_name() |
|
565 | + ); |
|
566 | + } |
|
567 | + } |
|
568 | + } |
|
569 | + } |
|
570 | + if ($what_to_do == self::do_insert) { |
|
571 | + $old_db_to_new_db_mapping = $this->_insert_from_data_array( |
|
572 | + $id_in_csv, |
|
573 | + $model_object_data, |
|
574 | + $model, |
|
575 | + $old_db_to_new_db_mapping |
|
576 | + ); |
|
577 | + } elseif ($what_to_do == self::do_update) { |
|
578 | + $old_db_to_new_db_mapping = $this->_update_from_data_array( |
|
579 | + $id_in_csv, |
|
580 | + $model_object_data, |
|
581 | + $model, |
|
582 | + $old_db_to_new_db_mapping |
|
583 | + ); |
|
584 | + } else { |
|
585 | + throw new EE_Error( |
|
586 | + sprintf( |
|
587 | + esc_html__( |
|
588 | + 'Programming error. We shoudl be inserting or updating, but instead we are being told to "%s", whifh is invalid', |
|
589 | + 'event_espresso' |
|
590 | + ), |
|
591 | + $what_to_do |
|
592 | + ) |
|
593 | + ); |
|
594 | + } |
|
595 | + } |
|
596 | + } |
|
597 | + return $old_db_to_new_db_mapping; |
|
598 | + } |
|
599 | + |
|
600 | + |
|
601 | + /** |
|
602 | + * Decides whether or not to insert, given that this data is from another database. |
|
603 | + * So, if the primary key of this $model_object_data already exists in the database, |
|
604 | + * it's just a coincidence and we should still insert. The only time we should |
|
605 | + * update is when we know what it maps to, or there's something that would |
|
606 | + * conflict (and we should instead just update that conflicting thing) |
|
607 | + * |
|
608 | + * @param string $id_in_csv |
|
609 | + * @param array $model_object_data by reference so it can be modified |
|
610 | + * @param EEM_Base $model |
|
611 | + * @param array $old_db_to_new_db_mapping by reference so it can be modified |
|
612 | + * @return string one of the consts on this class that starts with do_* |
|
613 | + */ |
|
614 | + protected function _decide_whether_to_insert_or_update_given_data_from_other_db( |
|
615 | + $id_in_csv, |
|
616 | + $model_object_data, |
|
617 | + $model, |
|
618 | + $old_db_to_new_db_mapping |
|
619 | + ) { |
|
620 | + $model_name = $model->get_this_model_name(); |
|
621 | + // if it's a site-to-site export-and-import, see if this modelobject's id |
|
622 | + // in the old data that we know of |
|
623 | + if (isset($old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ])) { |
|
624 | + return self::do_update; |
|
625 | + } else { |
|
626 | + return self::do_insert; |
|
627 | + } |
|
628 | + } |
|
629 | + |
|
630 | + /** |
|
631 | + * If this thing basically already exists in the database, we want to update it; |
|
632 | + * otherwise insert it (ie, someone tweaked the CSV file, or the item was |
|
633 | + * deleted in the database so it should be re-inserted) |
|
634 | + * |
|
635 | + * @param type $id_in_csv |
|
636 | + * @param type $model_object_data |
|
637 | + * @param EEM_Base $model |
|
638 | + * @param type $old_db_to_new_db_mapping |
|
639 | + * @return |
|
640 | + */ |
|
641 | + protected function _decide_whether_to_insert_or_update_given_data_from_same_db( |
|
642 | + $id_in_csv, |
|
643 | + $model_object_data, |
|
644 | + $model |
|
645 | + ) { |
|
646 | + // in this case, check if this thing ACTUALLY exists in the database |
|
647 | + if ($model->get_one_conflicting($model_object_data)) { |
|
648 | + return self::do_update; |
|
649 | + } else { |
|
650 | + return self::do_insert; |
|
651 | + } |
|
652 | + } |
|
653 | + |
|
654 | + /** |
|
655 | + * Using the $old_db_to_new_db_mapping array, replaces all the temporary IDs |
|
656 | + * with their mapped real IDs. Eg, if importing from site A to B, the mapping |
|
657 | + * file may indicate that the ID "my_event_id" maps to an actual event ID of 123. |
|
658 | + * So this function searches for any event temp Ids called "my_event_id" and |
|
659 | + * replaces them with 123. |
|
660 | + * Also, if there is no temp ID for the INT foreign keys from another database, |
|
661 | + * replaces them with 0 or the field's default. |
|
662 | + * |
|
663 | + * @param type $model_object_data |
|
664 | + * @param EEM_Base $model |
|
665 | + * @param type $old_db_to_new_db_mapping |
|
666 | + * @param boolean $export_from_site_a_to_b |
|
667 | + * @return array updated model object data with temp IDs removed |
|
668 | + */ |
|
669 | + protected function _replace_temp_ids_with_mappings( |
|
670 | + $model_object_data, |
|
671 | + $model, |
|
672 | + $old_db_to_new_db_mapping, |
|
673 | + $export_from_site_a_to_b |
|
674 | + ) { |
|
675 | + // if this model object's primary key is in the mapping, replace it |
|
676 | + if ( |
|
677 | + $model->has_primary_key_field() && |
|
678 | + $model->get_primary_key_field()->is_auto_increment() && |
|
679 | + isset($old_db_to_new_db_mapping[ $model->get_this_model_name() ]) && |
|
680 | + isset( |
|
681 | + $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $model_object_data[ $model->primary_key_name() ] ] |
|
682 | + ) |
|
683 | + ) { |
|
684 | + $model_object_data[ $model->primary_key_name() ] = $old_db_to_new_db_mapping[ $model->get_this_model_name( |
|
685 | + ) ][ $model_object_data[ $model->primary_key_name() ] ]; |
|
686 | + } |
|
687 | + |
|
688 | + try { |
|
689 | + $model_name_field = $model->get_field_containing_related_model_name(); |
|
690 | + $models_pointed_to_by_model_name_field = $model_name_field->get_model_names_pointed_to(); |
|
691 | + } catch (EE_Error $e) { |
|
692 | + $model_name_field = null; |
|
693 | + $models_pointed_to_by_model_name_field = array(); |
|
694 | + } |
|
695 | + foreach ($model->field_settings(true) as $field_obj) { |
|
696 | + if ($field_obj instanceof EE_Foreign_Key_Int_Field) { |
|
697 | + $models_pointed_to = $field_obj->get_model_names_pointed_to(); |
|
698 | + $found_a_mapping = false; |
|
699 | + foreach ($models_pointed_to as $model_pointed_to_by_fk) { |
|
700 | + if ($model_name_field) { |
|
701 | + $value_of_model_name_field = $model_object_data[ $model_name_field->get_name() ]; |
|
702 | + if ($value_of_model_name_field == $model_pointed_to_by_fk) { |
|
703 | + $model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in( |
|
704 | + $model_object_data[ $field_obj->get_name() ], |
|
705 | + $model_pointed_to_by_fk, |
|
706 | + $old_db_to_new_db_mapping, |
|
707 | + $export_from_site_a_to_b |
|
708 | + ); |
|
709 | + $found_a_mapping = true; |
|
710 | + break; |
|
711 | + } |
|
712 | + } else { |
|
713 | + $model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in( |
|
714 | + $model_object_data[ $field_obj->get_name() ], |
|
715 | + $model_pointed_to_by_fk, |
|
716 | + $old_db_to_new_db_mapping, |
|
717 | + $export_from_site_a_to_b |
|
718 | + ); |
|
719 | + $found_a_mapping = true; |
|
720 | + } |
|
721 | + // once we've found a mapping for this field no need to continue |
|
722 | + if ($found_a_mapping) { |
|
723 | + break; |
|
724 | + } |
|
725 | + } |
|
726 | + } else { |
|
727 | + // it's a string foreign key (which we leave alone, because those are things |
|
728 | + // like country names, which we'd really rather not make 2 USAs etc (we'd actually |
|
729 | + // prefer to just update one) |
|
730 | + // or it's just a regular value that ought to be replaced |
|
731 | + } |
|
732 | + } |
|
733 | + // |
|
734 | + if ($model instanceof EEM_Term_Taxonomy) { |
|
735 | + $model_object_data = $this->_handle_split_term_ids($model_object_data); |
|
736 | + } |
|
737 | + return $model_object_data; |
|
738 | + } |
|
739 | + |
|
740 | + /** |
|
741 | + * If the data was exported PRE-4.2, but then imported POST-4.2, then the term_id |
|
742 | + * this term-taxonomy refers to may be out-of-date so we need to update it. |
|
743 | + * see https://make.wordpress.org/core/2015/02/16/taxonomy-term-splitting-in-4-2-a-developer-guide/ |
|
744 | + * |
|
745 | + * @param type $model_object_data |
|
746 | + * @return array new model object data |
|
747 | + */ |
|
748 | + protected function _handle_split_term_ids($model_object_data) |
|
749 | + { |
|
750 | + if ( |
|
751 | + isset($model_object_data['term_id']) |
|
752 | + && isset($model_object_data['taxonomy']) |
|
753 | + && apply_filters( |
|
754 | + 'FHEE__EE_Import__handle_split_term_ids__function_exists', |
|
755 | + function_exists('wp_get_split_term'), |
|
756 | + $model_object_data |
|
757 | + ) |
|
758 | + ) { |
|
759 | + $new_term_id = wp_get_split_term($model_object_data['term_id'], $model_object_data['taxonomy']); |
|
760 | + if ($new_term_id) { |
|
761 | + $model_object_data['term_id'] = $new_term_id; |
|
762 | + } |
|
763 | + } |
|
764 | + return $model_object_data; |
|
765 | + } |
|
766 | + |
|
767 | + /** |
|
768 | + * Given the object's ID and its model's name, find it int he mapping data, |
|
769 | + * bearing in mind where it came from |
|
770 | + * |
|
771 | + * @param type $object_id |
|
772 | + * @param string $model_name |
|
773 | + * @param array $old_db_to_new_db_mapping |
|
774 | + * @param type $export_from_site_a_to_b |
|
775 | + * @return int |
|
776 | + */ |
|
777 | + protected function _find_mapping_in($object_id, $model_name, $old_db_to_new_db_mapping, $export_from_site_a_to_b) |
|
778 | + { |
|
779 | + if (isset($old_db_to_new_db_mapping[ $model_name ][ $object_id ])) { |
|
780 | + return $old_db_to_new_db_mapping[ $model_name ][ $object_id ]; |
|
781 | + } elseif ($object_id == '0' || $object_id == '') { |
|
782 | + // leave as-is |
|
783 | + return $object_id; |
|
784 | + } elseif ($export_from_site_a_to_b) { |
|
785 | + // we couldn't find a mapping for this, and it's from a different site, |
|
786 | + // so blank it out |
|
787 | + return null; |
|
788 | + } elseif (! $export_from_site_a_to_b) { |
|
789 | + // we coudln't find a mapping for this, but it's from thsi DB anyway |
|
790 | + // so let's just leave it as-is |
|
791 | + return $object_id; |
|
792 | + } |
|
793 | + } |
|
794 | + |
|
795 | + /** |
|
796 | + * |
|
797 | + * @param type $id_in_csv |
|
798 | + * @param type $model_object_data |
|
799 | + * @param EEM_Base $model |
|
800 | + * @param type $old_db_to_new_db_mapping |
|
801 | + * @return array updated $old_db_to_new_db_mapping |
|
802 | + */ |
|
803 | + protected function _insert_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping) |
|
804 | + { |
|
805 | + // remove the primary key, if there is one (we don't want it for inserts OR updates) |
|
806 | + // we'll put it back in if we need it |
|
807 | + if ($model->has_primary_key_field() && $model->get_primary_key_field()->is_auto_increment()) { |
|
808 | + $effective_id = $model_object_data[ $model->primary_key_name() ]; |
|
809 | + unset($model_object_data[ $model->primary_key_name() ]); |
|
810 | + } else { |
|
811 | + $effective_id = $model->get_index_primary_key_string($model_object_data); |
|
812 | + } |
|
813 | + // the model takes care of validating the CSV's input |
|
814 | + try { |
|
815 | + $new_id = $model->insert($model_object_data); |
|
816 | + if ($new_id) { |
|
817 | + $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_id; |
|
818 | + $this->_total_inserts++; |
|
819 | + EE_Error::add_success( |
|
820 | + sprintf( |
|
821 | + esc_html__("Successfully added new %s (with id %s) with csv data %s", "event_espresso"), |
|
822 | + $model->get_this_model_name(), |
|
823 | + $new_id, |
|
824 | + implode(",", $model_object_data) |
|
825 | + ) |
|
826 | + ); |
|
827 | + } else { |
|
828 | + $this->_total_insert_errors++; |
|
829 | + // put the ID used back in there for the error message |
|
830 | + if ($model->has_primary_key_field()) { |
|
831 | + $model_object_data[ $model->primary_key_name() ] = $effective_id; |
|
832 | + } |
|
833 | + EE_Error::add_error( |
|
834 | + sprintf( |
|
835 | + esc_html__("Could not insert new %s with the csv data: %s", "event_espresso"), |
|
836 | + $model->get_this_model_name(), |
|
837 | + http_build_query($model_object_data) |
|
838 | + ), |
|
839 | + __FILE__, |
|
840 | + __FUNCTION__, |
|
841 | + __LINE__ |
|
842 | + ); |
|
843 | + } |
|
844 | + } catch (EE_Error $e) { |
|
845 | + $this->_total_insert_errors++; |
|
846 | + if ($model->has_primary_key_field()) { |
|
847 | + $model_object_data[ $model->primary_key_name() ] = $effective_id; |
|
848 | + } |
|
849 | + EE_Error::add_error( |
|
850 | + sprintf( |
|
851 | + esc_html__("Could not insert new %s with the csv data: %s because %s", "event_espresso"), |
|
852 | + $model->get_this_model_name(), |
|
853 | + implode(",", $model_object_data), |
|
854 | + $e->getMessage() |
|
855 | + ), |
|
856 | + __FILE__, |
|
857 | + __FUNCTION__, |
|
858 | + __LINE__ |
|
859 | + ); |
|
860 | + } |
|
861 | + return $old_db_to_new_db_mapping; |
|
862 | + } |
|
863 | + |
|
864 | + /** |
|
865 | + * Given the model object data, finds the row to update and updates it |
|
866 | + * |
|
867 | + * @param string|int $id_in_csv |
|
868 | + * @param array $model_object_data |
|
869 | + * @param EEM_Base $model |
|
870 | + * @param array $old_db_to_new_db_mapping |
|
871 | + * @return array updated $old_db_to_new_db_mapping |
|
872 | + */ |
|
873 | + protected function _update_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping) |
|
874 | + { |
|
875 | + try { |
|
876 | + // let's keep two copies of the model object data: |
|
877 | + // one for performing an update, one for everthing else |
|
878 | + $model_object_data_for_update = $model_object_data; |
|
879 | + if ($model->has_primary_key_field()) { |
|
880 | + $conditions = array($model->primary_key_name() => $model_object_data[ $model->primary_key_name() ]); |
|
881 | + // remove the primary key because we shouldn't use it for updating |
|
882 | + unset($model_object_data_for_update[ $model->primary_key_name() ]); |
|
883 | + } elseif ($model->get_combined_primary_key_fields() > 1) { |
|
884 | + $conditions = array(); |
|
885 | + foreach ($model->get_combined_primary_key_fields() as $key_field) { |
|
886 | + $conditions[ $key_field->get_name() ] = $model_object_data[ $key_field->get_name() ]; |
|
887 | + } |
|
888 | + } else { |
|
889 | + $model->primary_key_name( |
|
890 | + );// this shoudl just throw an exception, explaining that we dont have a primary key (or a combine dkey) |
|
891 | + } |
|
892 | + |
|
893 | + $success = $model->update($model_object_data_for_update, array($conditions)); |
|
894 | + if ($success) { |
|
895 | + $this->_total_updates++; |
|
896 | + EE_Error::add_success( |
|
897 | + sprintf( |
|
898 | + esc_html__("Successfully updated %s with csv data %s", "event_espresso"), |
|
899 | + $model->get_this_model_name(), |
|
900 | + implode(",", $model_object_data_for_update) |
|
901 | + ) |
|
902 | + ); |
|
903 | + // we should still record the mapping even though it was an update |
|
904 | + // because if we were going to insert somethign but it was going to conflict |
|
905 | + // we would have last-minute decided to update. So we'd like to know what we updated |
|
906 | + // and so we record what record ended up being updated using the mapping |
|
907 | + if ($model->has_primary_key_field()) { |
|
908 | + $new_key_for_mapping = $model_object_data[ $model->primary_key_name() ]; |
|
909 | + } else { |
|
910 | + // no primary key just a combined key |
|
911 | + $new_key_for_mapping = $model->get_index_primary_key_string($model_object_data); |
|
912 | + } |
|
913 | + $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_key_for_mapping; |
|
914 | + } else { |
|
915 | + $matched_items = $model->get_all(array($conditions)); |
|
916 | + if (! $matched_items) { |
|
917 | + // no items were matched (so we shouldn't have updated)... but then we should have inserted? what the heck? |
|
918 | + $this->_total_update_errors++; |
|
919 | + EE_Error::add_error( |
|
920 | + sprintf( |
|
921 | + esc_html__( |
|
922 | + "Could not update %s with the csv data: '%s' for an unknown reason (using WHERE conditions %s)", |
|
923 | + "event_espresso" |
|
924 | + ), |
|
925 | + $model->get_this_model_name(), |
|
926 | + http_build_query($model_object_data), |
|
927 | + http_build_query($conditions) |
|
928 | + ), |
|
929 | + __FILE__, |
|
930 | + __FUNCTION__, |
|
931 | + __LINE__ |
|
932 | + ); |
|
933 | + } else { |
|
934 | + $this->_total_updates++; |
|
935 | + EE_Error::add_success( |
|
936 | + sprintf( |
|
937 | + esc_html__( |
|
938 | + "%s with csv data '%s' was found in the database and didn't need updating because all the data is identical.", |
|
939 | + "event_espresso" |
|
940 | + ), |
|
941 | + $model->get_this_model_name(), |
|
942 | + implode(",", $model_object_data) |
|
943 | + ) |
|
944 | + ); |
|
945 | + } |
|
946 | + } |
|
947 | + } catch (EE_Error $e) { |
|
948 | + $this->_total_update_errors++; |
|
949 | + $basic_message = sprintf( |
|
950 | + esc_html__("Could not update %s with the csv data: %s because %s", "event_espresso"), |
|
951 | + $model->get_this_model_name(), |
|
952 | + implode(",", $model_object_data), |
|
953 | + $e->getMessage() |
|
954 | + ); |
|
955 | + $debug_message = $basic_message . ' Stack trace: ' . $e->getTraceAsString(); |
|
956 | + EE_Error::add_error("$basic_message | $debug_message", __FILE__, __FUNCTION__, __LINE__); |
|
957 | + } |
|
958 | + return $old_db_to_new_db_mapping; |
|
959 | + } |
|
960 | + |
|
961 | + /** |
|
962 | + * Gets the number of inserts performed since importer was instantiated or reset |
|
963 | + * |
|
964 | + * @return int |
|
965 | + */ |
|
966 | + public function get_total_inserts() |
|
967 | + { |
|
968 | + return $this->_total_inserts; |
|
969 | + } |
|
970 | + |
|
971 | + /** |
|
972 | + * Gets the number of insert errors since importer was instantiated or reset |
|
973 | + * |
|
974 | + * @return int |
|
975 | + */ |
|
976 | + public function get_total_insert_errors() |
|
977 | + { |
|
978 | + return $this->_total_insert_errors; |
|
979 | + } |
|
980 | + |
|
981 | + /** |
|
982 | + * Gets the number of updates performed since importer was instantiated or reset |
|
983 | + * |
|
984 | + * @return int |
|
985 | + */ |
|
986 | + public function get_total_updates() |
|
987 | + { |
|
988 | + return $this->_total_updates; |
|
989 | + } |
|
990 | + |
|
991 | + /** |
|
992 | + * Gets the number of update errors since importer was instantiated or reset |
|
993 | + * |
|
994 | + * @return int |
|
995 | + */ |
|
996 | + public function get_total_update_errors() |
|
997 | + { |
|
998 | + return $this->_total_update_errors; |
|
999 | + } |
|
1000 | 1000 | } |
@@ -114,7 +114,7 @@ discard block |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 | } |
@@ -15,450 +15,450 @@ |
||
15 | 15 | */ |
16 | 16 | class EE_Question_Form_Input |
17 | 17 | { |
18 | - /** |
|
19 | - * EE_Question object |
|
20 | - * |
|
21 | - * @access private |
|
22 | - * @var object |
|
23 | - */ |
|
24 | - private $_QST = null; |
|
25 | - |
|
26 | - /** |
|
27 | - * EE_Answer object |
|
28 | - * |
|
29 | - * @access private |
|
30 | - * @var object |
|
31 | - */ |
|
32 | - private $_ANS = null; |
|
33 | - |
|
34 | - /** |
|
35 | - * $_QST_meta |
|
36 | - * @access private |
|
37 | - * @var array |
|
38 | - */ |
|
39 | - private $_QST_meta = []; |
|
40 | - |
|
41 | - /** |
|
42 | - * $QST_input_name |
|
43 | - * @access private |
|
44 | - * @var string |
|
45 | - */ |
|
46 | - private $QST_input_name = ''; |
|
47 | - |
|
48 | - /** |
|
49 | - * $QST_input_id |
|
50 | - * @access private |
|
51 | - * @var string |
|
52 | - */ |
|
53 | - private $QST_input_id = ''; |
|
54 | - |
|
55 | - /** |
|
56 | - * $QST_input_class |
|
57 | - * @access private |
|
58 | - * @var string |
|
59 | - */ |
|
60 | - private $QST_input_class = ''; |
|
61 | - |
|
62 | - /** |
|
63 | - * @var bool $QST_disabled |
|
64 | - */ |
|
65 | - private $QST_disabled = false; |
|
66 | - |
|
67 | - /** |
|
68 | - * @var RequestInterface |
|
69 | - */ |
|
70 | - protected $request; |
|
71 | - |
|
72 | - /** |
|
73 | - * @var array |
|
74 | - */ |
|
75 | - protected $form_data; |
|
76 | - |
|
77 | - |
|
78 | - /** |
|
79 | - * constructor for questions |
|
80 | - * |
|
81 | - * @param EE_Question $QST EE_Question object |
|
82 | - * @param EE_Answer $ANS EE_Answer object |
|
83 | - * @param array $q_meta |
|
84 | - * @throws EE_Error |
|
85 | - * @throws ReflectionException |
|
86 | - */ |
|
87 | - public function __construct(EE_Question $QST = null, EE_Answer $ANS = null, $q_meta = []) |
|
88 | - { |
|
89 | - $this->request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
90 | - $this->form_data = $this->request->requestParams(); |
|
91 | - if (empty($QST) || empty($ANS)) { |
|
92 | - EE_Error::add_error( |
|
93 | - esc_html__('An error occurred. A valid EE_Question or EE_Answer object was not received.', 'event_espresso'), |
|
94 | - __FILE__, |
|
95 | - __FUNCTION__, |
|
96 | - __LINE__ |
|
97 | - ); |
|
98 | - return null; |
|
99 | - } |
|
100 | - $this->_QST = $QST; |
|
101 | - $this->_ANS = $ANS; |
|
102 | - $this->set_question_form_input_meta($q_meta); |
|
103 | - $this->set_question_form_input_init(); |
|
104 | - } |
|
105 | - |
|
106 | - |
|
107 | - /** |
|
108 | - * sets meta data for the question form input |
|
109 | - * |
|
110 | - * @access public |
|
111 | - * @param array $q_meta |
|
112 | - * @return void |
|
113 | - */ |
|
114 | - public function set_question_form_input_meta($q_meta = []) |
|
115 | - { |
|
116 | - $default_q_meta = [ |
|
117 | - 'att_nmbr' => 1, |
|
118 | - 'ticket_id' => '', |
|
119 | - 'date' => '', |
|
120 | - 'time' => '', |
|
121 | - 'input_name' => '', |
|
122 | - 'input_id' => '', |
|
123 | - 'input_class' => '', |
|
124 | - 'input_prefix' => 'qstn', |
|
125 | - 'append_qstn_id' => true, |
|
126 | - 'htmlentities' => true, |
|
127 | - 'allow_null' => false, |
|
128 | - ]; |
|
129 | - $this->_QST_meta = array_merge($default_q_meta, $q_meta); |
|
130 | - } |
|
131 | - |
|
132 | - |
|
133 | - /** |
|
134 | - * set_question_form_input_init |
|
135 | - * |
|
136 | - * @access public |
|
137 | - * @return void |
|
138 | - * @throws EE_Error |
|
139 | - * @throws ReflectionException |
|
140 | - */ |
|
141 | - public function set_question_form_input_init() |
|
142 | - { |
|
143 | - $qstn_id = $this->_QST->system_ID() ? $this->_QST->system_ID() : $this->_QST->ID(); |
|
144 | - $this->_set_input_name($qstn_id); |
|
145 | - $this->_set_input_id($qstn_id); |
|
146 | - $this->_set_input_class(); |
|
147 | - $this->set_question_form_input_answer($qstn_id); |
|
148 | - } |
|
149 | - |
|
150 | - |
|
151 | - /** |
|
152 | - * set_input_name |
|
153 | - * |
|
154 | - * @access private |
|
155 | - * @param $qstn_id |
|
156 | - * @return void |
|
157 | - * @throws EE_Error |
|
158 | - * @throws ReflectionException |
|
159 | - */ |
|
160 | - private function _set_input_name($qstn_id) |
|
161 | - { |
|
162 | - if (! empty($qstn_id)) { |
|
163 | - $ANS_ID = $this->get('ANS_ID'); |
|
164 | - $qstn_id = ! empty($ANS_ID) ? '[' . $qstn_id . '][' . $ANS_ID . ']' : '[' . $qstn_id . ']'; |
|
165 | - } |
|
166 | - $this->QST_input_name = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id) |
|
167 | - ? $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name'] . $qstn_id |
|
168 | - : $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name']; |
|
169 | - } |
|
170 | - |
|
171 | - |
|
172 | - /** |
|
173 | - * get property values for question form input |
|
174 | - * |
|
175 | - * @access public |
|
176 | - * @param string $property |
|
177 | - * @return mixed |
|
178 | - * @throws EE_Error |
|
179 | - * @throws ReflectionException |
|
180 | - */ |
|
181 | - public function get($property = null) |
|
182 | - { |
|
183 | - if (! empty($property)) { |
|
184 | - if (EEM_Question::instance()->has_field($property)) { |
|
185 | - return $this->_QST->get($property); |
|
186 | - } elseif (EEM_Answer::instance()->has_field($property)) { |
|
187 | - return $this->_ANS->get($property); |
|
188 | - } elseif ($this->_question_form_input_property_exists(__CLASS__, $property)) { |
|
189 | - return $this->{$property}; |
|
190 | - } |
|
191 | - } |
|
192 | - return null; |
|
193 | - } |
|
194 | - |
|
195 | - |
|
196 | - /** |
|
197 | - * _question_form_input_property_exists |
|
198 | - * |
|
199 | - * @access private |
|
200 | - * @param string $classname |
|
201 | - * @param string $property |
|
202 | - * @return boolean |
|
203 | - * @throws ReflectionException |
|
204 | - */ |
|
205 | - private function _question_form_input_property_exists($classname, $property) |
|
206 | - { |
|
207 | - // first try regular property exists method which works as expected in PHP 5.3+ |
|
208 | - $prop = EEH_Class_Tools::has_property($classname, $property); |
|
209 | - if (! $prop) { |
|
210 | - // use reflection for < PHP 5.3 as a double check when property is not found, possible due to access restriction |
|
211 | - $reflector = new ReflectionClass($classname); |
|
212 | - $prop = $reflector->hasProperty($property); |
|
213 | - } |
|
214 | - return $prop; |
|
215 | - } |
|
216 | - |
|
217 | - |
|
218 | - /** |
|
219 | - * set_input_id |
|
220 | - * |
|
221 | - * @access private |
|
222 | - * @param $qstn_id |
|
223 | - * @return void |
|
224 | - * @throws EE_Error |
|
225 | - * @throws ReflectionException |
|
226 | - */ |
|
227 | - private function _set_input_id($qstn_id) |
|
228 | - { |
|
229 | - $input_id = isset($this->_QST_meta['input_id']) && ! empty($this->_QST_meta['input_id']) |
|
230 | - ? $this->_QST_meta['input_id'] |
|
231 | - : sanitize_key(strip_tags($this->_QST->get('QST_display_text'))); |
|
232 | - $this->QST_input_id = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id) |
|
233 | - ? $input_id . '-' . $qstn_id |
|
234 | - : $input_id; |
|
235 | - } |
|
236 | - |
|
237 | - |
|
238 | - /** |
|
239 | - * set_input_class |
|
240 | - * |
|
241 | - * @access private |
|
242 | - * @return void |
|
243 | - */ |
|
244 | - private function _set_input_class() |
|
245 | - { |
|
246 | - $this->QST_input_class = isset($this->_QST_meta['input_class']) ? $this->_QST_meta['input_class'] : ''; |
|
247 | - } |
|
248 | - |
|
249 | - |
|
250 | - /** |
|
251 | - * set_question_form_input_answer |
|
252 | - * |
|
253 | - * @access public |
|
254 | - * @param mixed int | string $qstn_id |
|
255 | - * @return void |
|
256 | - * @throws EE_Error |
|
257 | - * @throws ReflectionException |
|
258 | - */ |
|
259 | - public function set_question_form_input_answer($qstn_id) |
|
260 | - { |
|
261 | - // check for answer in $this->form_data in case we are reprocessing a form after an error |
|
262 | - if ( |
|
263 | - isset($this->_QST_meta['EVT_ID']) |
|
264 | - && isset($this->_QST_meta['att_nmbr']) |
|
265 | - && isset($this->_QST_meta['date']) |
|
266 | - && isset($this->_QST_meta['time']) |
|
267 | - && isset($this->_QST_meta['price_id']) |
|
268 | - ) { |
|
269 | - $EVT_ID = $this->_QST_meta['EVT_ID']; |
|
270 | - $att_nmbr = $this->_QST_meta['att_nmbr']; |
|
271 | - $date = $this->_QST_meta['date']; |
|
272 | - $time = $this->_QST_meta['time']; |
|
273 | - $price_id = $this->_QST_meta['price_id']; |
|
274 | - if (isset($this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ])) { |
|
275 | - $answer = $this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ]; |
|
276 | - $this->_ANS->set('ANS_value', $answer); |
|
277 | - } |
|
278 | - } |
|
279 | - } |
|
280 | - |
|
281 | - |
|
282 | - /** |
|
283 | - * generate_question_form_inputs_for_object |
|
284 | - * |
|
285 | - * @access protected |
|
286 | - * @param bool|object $object $object |
|
287 | - * @param array $input_types |
|
288 | - * @return array |
|
289 | - * @throws EE_Error |
|
290 | - * @throws ReflectionException |
|
291 | - */ |
|
292 | - public static function generate_question_form_inputs_for_object($object = false, $input_types = []) |
|
293 | - { |
|
294 | - if (! is_object($object)) { |
|
295 | - return []; |
|
296 | - } |
|
297 | - $inputs = []; |
|
298 | - $fields = $object->get_model()->field_settings(false); |
|
299 | - foreach ($fields as $field_ID => $field) { |
|
300 | - if ($field instanceof EE_Model_Field_Base) { |
|
301 | - if (isset($input_types[ $field_ID ])) { |
|
302 | - // get saved value for field |
|
303 | - $value = $object->get($field_ID); |
|
304 | - // if no saved value, then use default |
|
305 | - $value = $value !== null ? $value : $field->get_default_value(); |
|
306 | - // determine question type |
|
307 | - $type = isset($input_types[ $field_ID ]) ? $input_types[ $field_ID ]['type'] : 'TEXT'; |
|
308 | - // input name |
|
309 | - $input_name = isset($input_types[ $field_ID ]) && isset($input_types[ $field_ID ]['input_name']) |
|
310 | - ? $input_types[ $field_ID ]['input_name'] . '[' . $field_ID . ']' |
|
311 | - : $field_ID; |
|
312 | - // css class for input |
|
313 | - $class = isset($input_types[ $field_ID ]['class']) && ! empty($input_types[ $field_ID ]['class']) |
|
314 | - ? ' ' . $input_types[ $field_ID ]['class'] |
|
315 | - : ''; |
|
316 | - // whether to apply htmlentities to answer |
|
317 | - $htmlentities = isset($input_types[ $field_ID ]['htmlentities']) |
|
318 | - ? $input_types[ $field_ID ]['htmlentities'] |
|
319 | - : true; |
|
320 | - // whether to apply htmlentities to answer |
|
321 | - $label_b4 = isset($input_types[ $field_ID ]['label_b4']) |
|
322 | - ? $input_types[ $field_ID ]['label_b4'] |
|
323 | - : false; |
|
324 | - // whether to apply htmlentities to answer |
|
325 | - $use_desc_4_label = isset($input_types[ $field_ID ]['use_desc_4_label']) |
|
326 | - ? $input_types[ $field_ID ]['use_desc_4_label'] |
|
327 | - : false; |
|
328 | - // whether input is disabled |
|
329 | - $disabled = isset($input_types[ $field_ID ]['disabled']) && $input_types[ $field_ID ]['disabled']; |
|
330 | - |
|
331 | - // create EE_Question_Form_Input object |
|
332 | - $QFI = new EE_Question_Form_Input( |
|
333 | - EE_Question::new_instance( |
|
334 | - [ |
|
335 | - 'QST_ID' => 0, |
|
336 | - 'QST_display_text' => $field->get_nicename(), |
|
337 | - 'QST_type' => $type, |
|
338 | - ] |
|
339 | - ), |
|
340 | - EE_Answer::new_instance( |
|
341 | - [ |
|
342 | - 'ANS_ID' => 0, |
|
343 | - 'QST_ID' => 0, |
|
344 | - 'REG_ID' => 0, |
|
345 | - 'ANS_value' => $value, |
|
346 | - ] |
|
347 | - ), |
|
348 | - [ |
|
349 | - 'input_id' => $field_ID . '-' . $object->ID(), |
|
350 | - 'input_name' => $input_name, |
|
351 | - 'input_class' => $field_ID . $class, |
|
352 | - 'input_prefix' => '', |
|
353 | - 'append_qstn_id' => false, |
|
354 | - 'htmlentities' => $htmlentities, |
|
355 | - 'label_b4' => $label_b4, |
|
356 | - 'use_desc_4_label' => $use_desc_4_label, |
|
357 | - ] |
|
358 | - ); |
|
359 | - // does question type have options ? |
|
360 | - if ( |
|
361 | - in_array($type, ['DROPDOWN', 'RADIO_BTN', 'CHECKBOX']) |
|
362 | - && isset($input_types[ $field_ID ]) |
|
363 | - && isset($input_types[ $field_ID ]['options']) |
|
364 | - ) { |
|
365 | - foreach ($input_types[ $field_ID ]['options'] as $option) { |
|
366 | - $option = stripslashes_deep($option); |
|
367 | - $option_id = ! empty($option['id']) ? $option['id'] : 0; |
|
368 | - $QSO = EE_Question_Option::new_instance( |
|
369 | - [ |
|
370 | - 'QSO_value' => (string) $option_id, |
|
371 | - 'QSO_desc' => $option['text'], |
|
372 | - 'QSO_deleted' => false, |
|
373 | - ] |
|
374 | - ); |
|
375 | - // all QST (and ANS) properties can be accessed indirectly thru QFI |
|
376 | - $QFI->add_temp_option($QSO); |
|
377 | - } |
|
378 | - } |
|
379 | - // we don't want ppl manually changing primary keys cuz that would just lead to total craziness man |
|
380 | - if ($disabled || $field_ID == $object->get_model()->primary_key_name()) { |
|
381 | - $QFI->set('QST_disabled', true); |
|
382 | - } |
|
383 | - $inputs[ $field_ID ] = $QFI; |
|
384 | - } |
|
385 | - } |
|
386 | - } |
|
387 | - return $inputs; |
|
388 | - } |
|
389 | - |
|
390 | - |
|
391 | - /** |
|
392 | - * add_temp_option |
|
393 | - * |
|
394 | - * @access public |
|
395 | - * @param EE_Question_Option $QSO EE_Question_Option |
|
396 | - * @return void |
|
397 | - */ |
|
398 | - public function add_temp_option(EE_Question_Option $QSO) |
|
399 | - { |
|
400 | - $this->_QST->add_temp_option($QSO); |
|
401 | - } |
|
402 | - |
|
403 | - |
|
404 | - /** |
|
405 | - * set property values for question form input |
|
406 | - * |
|
407 | - * @access public |
|
408 | - * @param string $property |
|
409 | - * @param mixed $value |
|
410 | - * @return void |
|
411 | - * @throws EE_Error |
|
412 | - * @throws ReflectionException |
|
413 | - */ |
|
414 | - public function set($property = null, $value = null) |
|
415 | - { |
|
416 | - if (! empty($property)) { |
|
417 | - if (EEM_Question::instance()->has_field($property)) { |
|
418 | - $this->_QST->set($property, $value); |
|
419 | - } elseif (EEM_Answer::instance()->has_field($property)) { |
|
420 | - $this->_ANS->set($property, $value); |
|
421 | - } elseif ($this->_question_form_input_property_exists(__CLASS__, $property)) { |
|
422 | - $this->{$property} = $value; |
|
423 | - } |
|
424 | - } |
|
425 | - } |
|
426 | - |
|
427 | - |
|
428 | - /** |
|
429 | - * _question_form_input_property_exists |
|
430 | - * |
|
431 | - * @access public |
|
432 | - * @param boolean $notDeletedOptionsOnly 1 |
|
433 | - * whether to return ALL options, or only the ones which have |
|
434 | - * not yet been deleted |
|
435 | - * @param string|array $selected_value_to_always_include , when retrieving options to an ANSWERED question, |
|
436 | - * we want to usually only show non-deleted options AND the |
|
437 | - * value that was selected for the answer, whether it was |
|
438 | - * trashed or not. |
|
439 | - * @return EE_Question_Option |
|
440 | - */ |
|
441 | - public function options($notDeletedOptionsOnly = true, $selected_value_to_always_include = null) |
|
442 | - { |
|
443 | - $temp_options = $this->_QST->temp_options(); |
|
444 | - return ! empty($temp_options) |
|
445 | - ? $temp_options |
|
446 | - : $this->_QST->options( |
|
447 | - $notDeletedOptionsOnly, |
|
448 | - $selected_value_to_always_include |
|
449 | - ); |
|
450 | - } |
|
451 | - |
|
452 | - |
|
453 | - /** |
|
454 | - * get_meta |
|
455 | - * |
|
456 | - * @access public |
|
457 | - * @param mixed $key |
|
458 | - * @return mixed |
|
459 | - */ |
|
460 | - public function get_meta($key = false) |
|
461 | - { |
|
462 | - return $key && isset($this->_QST_meta[ $key ]) ? $this->_QST_meta[ $key ] : false; |
|
463 | - } |
|
18 | + /** |
|
19 | + * EE_Question object |
|
20 | + * |
|
21 | + * @access private |
|
22 | + * @var object |
|
23 | + */ |
|
24 | + private $_QST = null; |
|
25 | + |
|
26 | + /** |
|
27 | + * EE_Answer object |
|
28 | + * |
|
29 | + * @access private |
|
30 | + * @var object |
|
31 | + */ |
|
32 | + private $_ANS = null; |
|
33 | + |
|
34 | + /** |
|
35 | + * $_QST_meta |
|
36 | + * @access private |
|
37 | + * @var array |
|
38 | + */ |
|
39 | + private $_QST_meta = []; |
|
40 | + |
|
41 | + /** |
|
42 | + * $QST_input_name |
|
43 | + * @access private |
|
44 | + * @var string |
|
45 | + */ |
|
46 | + private $QST_input_name = ''; |
|
47 | + |
|
48 | + /** |
|
49 | + * $QST_input_id |
|
50 | + * @access private |
|
51 | + * @var string |
|
52 | + */ |
|
53 | + private $QST_input_id = ''; |
|
54 | + |
|
55 | + /** |
|
56 | + * $QST_input_class |
|
57 | + * @access private |
|
58 | + * @var string |
|
59 | + */ |
|
60 | + private $QST_input_class = ''; |
|
61 | + |
|
62 | + /** |
|
63 | + * @var bool $QST_disabled |
|
64 | + */ |
|
65 | + private $QST_disabled = false; |
|
66 | + |
|
67 | + /** |
|
68 | + * @var RequestInterface |
|
69 | + */ |
|
70 | + protected $request; |
|
71 | + |
|
72 | + /** |
|
73 | + * @var array |
|
74 | + */ |
|
75 | + protected $form_data; |
|
76 | + |
|
77 | + |
|
78 | + /** |
|
79 | + * constructor for questions |
|
80 | + * |
|
81 | + * @param EE_Question $QST EE_Question object |
|
82 | + * @param EE_Answer $ANS EE_Answer object |
|
83 | + * @param array $q_meta |
|
84 | + * @throws EE_Error |
|
85 | + * @throws ReflectionException |
|
86 | + */ |
|
87 | + public function __construct(EE_Question $QST = null, EE_Answer $ANS = null, $q_meta = []) |
|
88 | + { |
|
89 | + $this->request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
90 | + $this->form_data = $this->request->requestParams(); |
|
91 | + if (empty($QST) || empty($ANS)) { |
|
92 | + EE_Error::add_error( |
|
93 | + esc_html__('An error occurred. A valid EE_Question or EE_Answer object was not received.', 'event_espresso'), |
|
94 | + __FILE__, |
|
95 | + __FUNCTION__, |
|
96 | + __LINE__ |
|
97 | + ); |
|
98 | + return null; |
|
99 | + } |
|
100 | + $this->_QST = $QST; |
|
101 | + $this->_ANS = $ANS; |
|
102 | + $this->set_question_form_input_meta($q_meta); |
|
103 | + $this->set_question_form_input_init(); |
|
104 | + } |
|
105 | + |
|
106 | + |
|
107 | + /** |
|
108 | + * sets meta data for the question form input |
|
109 | + * |
|
110 | + * @access public |
|
111 | + * @param array $q_meta |
|
112 | + * @return void |
|
113 | + */ |
|
114 | + public function set_question_form_input_meta($q_meta = []) |
|
115 | + { |
|
116 | + $default_q_meta = [ |
|
117 | + 'att_nmbr' => 1, |
|
118 | + 'ticket_id' => '', |
|
119 | + 'date' => '', |
|
120 | + 'time' => '', |
|
121 | + 'input_name' => '', |
|
122 | + 'input_id' => '', |
|
123 | + 'input_class' => '', |
|
124 | + 'input_prefix' => 'qstn', |
|
125 | + 'append_qstn_id' => true, |
|
126 | + 'htmlentities' => true, |
|
127 | + 'allow_null' => false, |
|
128 | + ]; |
|
129 | + $this->_QST_meta = array_merge($default_q_meta, $q_meta); |
|
130 | + } |
|
131 | + |
|
132 | + |
|
133 | + /** |
|
134 | + * set_question_form_input_init |
|
135 | + * |
|
136 | + * @access public |
|
137 | + * @return void |
|
138 | + * @throws EE_Error |
|
139 | + * @throws ReflectionException |
|
140 | + */ |
|
141 | + public function set_question_form_input_init() |
|
142 | + { |
|
143 | + $qstn_id = $this->_QST->system_ID() ? $this->_QST->system_ID() : $this->_QST->ID(); |
|
144 | + $this->_set_input_name($qstn_id); |
|
145 | + $this->_set_input_id($qstn_id); |
|
146 | + $this->_set_input_class(); |
|
147 | + $this->set_question_form_input_answer($qstn_id); |
|
148 | + } |
|
149 | + |
|
150 | + |
|
151 | + /** |
|
152 | + * set_input_name |
|
153 | + * |
|
154 | + * @access private |
|
155 | + * @param $qstn_id |
|
156 | + * @return void |
|
157 | + * @throws EE_Error |
|
158 | + * @throws ReflectionException |
|
159 | + */ |
|
160 | + private function _set_input_name($qstn_id) |
|
161 | + { |
|
162 | + if (! empty($qstn_id)) { |
|
163 | + $ANS_ID = $this->get('ANS_ID'); |
|
164 | + $qstn_id = ! empty($ANS_ID) ? '[' . $qstn_id . '][' . $ANS_ID . ']' : '[' . $qstn_id . ']'; |
|
165 | + } |
|
166 | + $this->QST_input_name = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id) |
|
167 | + ? $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name'] . $qstn_id |
|
168 | + : $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name']; |
|
169 | + } |
|
170 | + |
|
171 | + |
|
172 | + /** |
|
173 | + * get property values for question form input |
|
174 | + * |
|
175 | + * @access public |
|
176 | + * @param string $property |
|
177 | + * @return mixed |
|
178 | + * @throws EE_Error |
|
179 | + * @throws ReflectionException |
|
180 | + */ |
|
181 | + public function get($property = null) |
|
182 | + { |
|
183 | + if (! empty($property)) { |
|
184 | + if (EEM_Question::instance()->has_field($property)) { |
|
185 | + return $this->_QST->get($property); |
|
186 | + } elseif (EEM_Answer::instance()->has_field($property)) { |
|
187 | + return $this->_ANS->get($property); |
|
188 | + } elseif ($this->_question_form_input_property_exists(__CLASS__, $property)) { |
|
189 | + return $this->{$property}; |
|
190 | + } |
|
191 | + } |
|
192 | + return null; |
|
193 | + } |
|
194 | + |
|
195 | + |
|
196 | + /** |
|
197 | + * _question_form_input_property_exists |
|
198 | + * |
|
199 | + * @access private |
|
200 | + * @param string $classname |
|
201 | + * @param string $property |
|
202 | + * @return boolean |
|
203 | + * @throws ReflectionException |
|
204 | + */ |
|
205 | + private function _question_form_input_property_exists($classname, $property) |
|
206 | + { |
|
207 | + // first try regular property exists method which works as expected in PHP 5.3+ |
|
208 | + $prop = EEH_Class_Tools::has_property($classname, $property); |
|
209 | + if (! $prop) { |
|
210 | + // use reflection for < PHP 5.3 as a double check when property is not found, possible due to access restriction |
|
211 | + $reflector = new ReflectionClass($classname); |
|
212 | + $prop = $reflector->hasProperty($property); |
|
213 | + } |
|
214 | + return $prop; |
|
215 | + } |
|
216 | + |
|
217 | + |
|
218 | + /** |
|
219 | + * set_input_id |
|
220 | + * |
|
221 | + * @access private |
|
222 | + * @param $qstn_id |
|
223 | + * @return void |
|
224 | + * @throws EE_Error |
|
225 | + * @throws ReflectionException |
|
226 | + */ |
|
227 | + private function _set_input_id($qstn_id) |
|
228 | + { |
|
229 | + $input_id = isset($this->_QST_meta['input_id']) && ! empty($this->_QST_meta['input_id']) |
|
230 | + ? $this->_QST_meta['input_id'] |
|
231 | + : sanitize_key(strip_tags($this->_QST->get('QST_display_text'))); |
|
232 | + $this->QST_input_id = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id) |
|
233 | + ? $input_id . '-' . $qstn_id |
|
234 | + : $input_id; |
|
235 | + } |
|
236 | + |
|
237 | + |
|
238 | + /** |
|
239 | + * set_input_class |
|
240 | + * |
|
241 | + * @access private |
|
242 | + * @return void |
|
243 | + */ |
|
244 | + private function _set_input_class() |
|
245 | + { |
|
246 | + $this->QST_input_class = isset($this->_QST_meta['input_class']) ? $this->_QST_meta['input_class'] : ''; |
|
247 | + } |
|
248 | + |
|
249 | + |
|
250 | + /** |
|
251 | + * set_question_form_input_answer |
|
252 | + * |
|
253 | + * @access public |
|
254 | + * @param mixed int | string $qstn_id |
|
255 | + * @return void |
|
256 | + * @throws EE_Error |
|
257 | + * @throws ReflectionException |
|
258 | + */ |
|
259 | + public function set_question_form_input_answer($qstn_id) |
|
260 | + { |
|
261 | + // check for answer in $this->form_data in case we are reprocessing a form after an error |
|
262 | + if ( |
|
263 | + isset($this->_QST_meta['EVT_ID']) |
|
264 | + && isset($this->_QST_meta['att_nmbr']) |
|
265 | + && isset($this->_QST_meta['date']) |
|
266 | + && isset($this->_QST_meta['time']) |
|
267 | + && isset($this->_QST_meta['price_id']) |
|
268 | + ) { |
|
269 | + $EVT_ID = $this->_QST_meta['EVT_ID']; |
|
270 | + $att_nmbr = $this->_QST_meta['att_nmbr']; |
|
271 | + $date = $this->_QST_meta['date']; |
|
272 | + $time = $this->_QST_meta['time']; |
|
273 | + $price_id = $this->_QST_meta['price_id']; |
|
274 | + if (isset($this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ])) { |
|
275 | + $answer = $this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ]; |
|
276 | + $this->_ANS->set('ANS_value', $answer); |
|
277 | + } |
|
278 | + } |
|
279 | + } |
|
280 | + |
|
281 | + |
|
282 | + /** |
|
283 | + * generate_question_form_inputs_for_object |
|
284 | + * |
|
285 | + * @access protected |
|
286 | + * @param bool|object $object $object |
|
287 | + * @param array $input_types |
|
288 | + * @return array |
|
289 | + * @throws EE_Error |
|
290 | + * @throws ReflectionException |
|
291 | + */ |
|
292 | + public static function generate_question_form_inputs_for_object($object = false, $input_types = []) |
|
293 | + { |
|
294 | + if (! is_object($object)) { |
|
295 | + return []; |
|
296 | + } |
|
297 | + $inputs = []; |
|
298 | + $fields = $object->get_model()->field_settings(false); |
|
299 | + foreach ($fields as $field_ID => $field) { |
|
300 | + if ($field instanceof EE_Model_Field_Base) { |
|
301 | + if (isset($input_types[ $field_ID ])) { |
|
302 | + // get saved value for field |
|
303 | + $value = $object->get($field_ID); |
|
304 | + // if no saved value, then use default |
|
305 | + $value = $value !== null ? $value : $field->get_default_value(); |
|
306 | + // determine question type |
|
307 | + $type = isset($input_types[ $field_ID ]) ? $input_types[ $field_ID ]['type'] : 'TEXT'; |
|
308 | + // input name |
|
309 | + $input_name = isset($input_types[ $field_ID ]) && isset($input_types[ $field_ID ]['input_name']) |
|
310 | + ? $input_types[ $field_ID ]['input_name'] . '[' . $field_ID . ']' |
|
311 | + : $field_ID; |
|
312 | + // css class for input |
|
313 | + $class = isset($input_types[ $field_ID ]['class']) && ! empty($input_types[ $field_ID ]['class']) |
|
314 | + ? ' ' . $input_types[ $field_ID ]['class'] |
|
315 | + : ''; |
|
316 | + // whether to apply htmlentities to answer |
|
317 | + $htmlentities = isset($input_types[ $field_ID ]['htmlentities']) |
|
318 | + ? $input_types[ $field_ID ]['htmlentities'] |
|
319 | + : true; |
|
320 | + // whether to apply htmlentities to answer |
|
321 | + $label_b4 = isset($input_types[ $field_ID ]['label_b4']) |
|
322 | + ? $input_types[ $field_ID ]['label_b4'] |
|
323 | + : false; |
|
324 | + // whether to apply htmlentities to answer |
|
325 | + $use_desc_4_label = isset($input_types[ $field_ID ]['use_desc_4_label']) |
|
326 | + ? $input_types[ $field_ID ]['use_desc_4_label'] |
|
327 | + : false; |
|
328 | + // whether input is disabled |
|
329 | + $disabled = isset($input_types[ $field_ID ]['disabled']) && $input_types[ $field_ID ]['disabled']; |
|
330 | + |
|
331 | + // create EE_Question_Form_Input object |
|
332 | + $QFI = new EE_Question_Form_Input( |
|
333 | + EE_Question::new_instance( |
|
334 | + [ |
|
335 | + 'QST_ID' => 0, |
|
336 | + 'QST_display_text' => $field->get_nicename(), |
|
337 | + 'QST_type' => $type, |
|
338 | + ] |
|
339 | + ), |
|
340 | + EE_Answer::new_instance( |
|
341 | + [ |
|
342 | + 'ANS_ID' => 0, |
|
343 | + 'QST_ID' => 0, |
|
344 | + 'REG_ID' => 0, |
|
345 | + 'ANS_value' => $value, |
|
346 | + ] |
|
347 | + ), |
|
348 | + [ |
|
349 | + 'input_id' => $field_ID . '-' . $object->ID(), |
|
350 | + 'input_name' => $input_name, |
|
351 | + 'input_class' => $field_ID . $class, |
|
352 | + 'input_prefix' => '', |
|
353 | + 'append_qstn_id' => false, |
|
354 | + 'htmlentities' => $htmlentities, |
|
355 | + 'label_b4' => $label_b4, |
|
356 | + 'use_desc_4_label' => $use_desc_4_label, |
|
357 | + ] |
|
358 | + ); |
|
359 | + // does question type have options ? |
|
360 | + if ( |
|
361 | + in_array($type, ['DROPDOWN', 'RADIO_BTN', 'CHECKBOX']) |
|
362 | + && isset($input_types[ $field_ID ]) |
|
363 | + && isset($input_types[ $field_ID ]['options']) |
|
364 | + ) { |
|
365 | + foreach ($input_types[ $field_ID ]['options'] as $option) { |
|
366 | + $option = stripslashes_deep($option); |
|
367 | + $option_id = ! empty($option['id']) ? $option['id'] : 0; |
|
368 | + $QSO = EE_Question_Option::new_instance( |
|
369 | + [ |
|
370 | + 'QSO_value' => (string) $option_id, |
|
371 | + 'QSO_desc' => $option['text'], |
|
372 | + 'QSO_deleted' => false, |
|
373 | + ] |
|
374 | + ); |
|
375 | + // all QST (and ANS) properties can be accessed indirectly thru QFI |
|
376 | + $QFI->add_temp_option($QSO); |
|
377 | + } |
|
378 | + } |
|
379 | + // we don't want ppl manually changing primary keys cuz that would just lead to total craziness man |
|
380 | + if ($disabled || $field_ID == $object->get_model()->primary_key_name()) { |
|
381 | + $QFI->set('QST_disabled', true); |
|
382 | + } |
|
383 | + $inputs[ $field_ID ] = $QFI; |
|
384 | + } |
|
385 | + } |
|
386 | + } |
|
387 | + return $inputs; |
|
388 | + } |
|
389 | + |
|
390 | + |
|
391 | + /** |
|
392 | + * add_temp_option |
|
393 | + * |
|
394 | + * @access public |
|
395 | + * @param EE_Question_Option $QSO EE_Question_Option |
|
396 | + * @return void |
|
397 | + */ |
|
398 | + public function add_temp_option(EE_Question_Option $QSO) |
|
399 | + { |
|
400 | + $this->_QST->add_temp_option($QSO); |
|
401 | + } |
|
402 | + |
|
403 | + |
|
404 | + /** |
|
405 | + * set property values for question form input |
|
406 | + * |
|
407 | + * @access public |
|
408 | + * @param string $property |
|
409 | + * @param mixed $value |
|
410 | + * @return void |
|
411 | + * @throws EE_Error |
|
412 | + * @throws ReflectionException |
|
413 | + */ |
|
414 | + public function set($property = null, $value = null) |
|
415 | + { |
|
416 | + if (! empty($property)) { |
|
417 | + if (EEM_Question::instance()->has_field($property)) { |
|
418 | + $this->_QST->set($property, $value); |
|
419 | + } elseif (EEM_Answer::instance()->has_field($property)) { |
|
420 | + $this->_ANS->set($property, $value); |
|
421 | + } elseif ($this->_question_form_input_property_exists(__CLASS__, $property)) { |
|
422 | + $this->{$property} = $value; |
|
423 | + } |
|
424 | + } |
|
425 | + } |
|
426 | + |
|
427 | + |
|
428 | + /** |
|
429 | + * _question_form_input_property_exists |
|
430 | + * |
|
431 | + * @access public |
|
432 | + * @param boolean $notDeletedOptionsOnly 1 |
|
433 | + * whether to return ALL options, or only the ones which have |
|
434 | + * not yet been deleted |
|
435 | + * @param string|array $selected_value_to_always_include , when retrieving options to an ANSWERED question, |
|
436 | + * we want to usually only show non-deleted options AND the |
|
437 | + * value that was selected for the answer, whether it was |
|
438 | + * trashed or not. |
|
439 | + * @return EE_Question_Option |
|
440 | + */ |
|
441 | + public function options($notDeletedOptionsOnly = true, $selected_value_to_always_include = null) |
|
442 | + { |
|
443 | + $temp_options = $this->_QST->temp_options(); |
|
444 | + return ! empty($temp_options) |
|
445 | + ? $temp_options |
|
446 | + : $this->_QST->options( |
|
447 | + $notDeletedOptionsOnly, |
|
448 | + $selected_value_to_always_include |
|
449 | + ); |
|
450 | + } |
|
451 | + |
|
452 | + |
|
453 | + /** |
|
454 | + * get_meta |
|
455 | + * |
|
456 | + * @access public |
|
457 | + * @param mixed $key |
|
458 | + * @return mixed |
|
459 | + */ |
|
460 | + public function get_meta($key = false) |
|
461 | + { |
|
462 | + return $key && isset($this->_QST_meta[ $key ]) ? $this->_QST_meta[ $key ] : false; |
|
463 | + } |
|
464 | 464 | } |
@@ -88,7 +88,7 @@ discard block |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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); |
@@ -13,1742 +13,1742 @@ |
||
13 | 13 | */ |
14 | 14 | class EE_Line_Item extends EE_Base_Class implements EEI_Line_Item |
15 | 15 | { |
16 | - /** |
|
17 | - * for children line items (currently not a normal relation) |
|
18 | - * |
|
19 | - * @type EE_Line_Item[] |
|
20 | - */ |
|
21 | - protected $_children = array(); |
|
22 | - |
|
23 | - /** |
|
24 | - * for the parent line item |
|
25 | - * |
|
26 | - * @var EE_Line_Item |
|
27 | - */ |
|
28 | - protected $_parent; |
|
29 | - |
|
30 | - |
|
31 | - /** |
|
32 | - * @param array $props_n_values incoming values |
|
33 | - * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
34 | - * used.) |
|
35 | - * @param array $date_formats incoming date_formats in an array where the first value is the |
|
36 | - * date_format and the second value is the time format |
|
37 | - * @return EE_Line_Item |
|
38 | - * @throws EE_Error |
|
39 | - * @throws InvalidArgumentException |
|
40 | - * @throws InvalidDataTypeException |
|
41 | - * @throws InvalidInterfaceException |
|
42 | - * @throws ReflectionException |
|
43 | - */ |
|
44 | - public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) |
|
45 | - { |
|
46 | - $has_object = parent::_check_for_object( |
|
47 | - $props_n_values, |
|
48 | - __CLASS__, |
|
49 | - $timezone, |
|
50 | - $date_formats |
|
51 | - ); |
|
52 | - return $has_object |
|
53 | - ? $has_object |
|
54 | - : new self($props_n_values, false, $timezone); |
|
55 | - } |
|
56 | - |
|
57 | - |
|
58 | - /** |
|
59 | - * @param array $props_n_values incoming values from the database |
|
60 | - * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
61 | - * the website will be used. |
|
62 | - * @return EE_Line_Item |
|
63 | - * @throws EE_Error |
|
64 | - * @throws InvalidArgumentException |
|
65 | - * @throws InvalidDataTypeException |
|
66 | - * @throws InvalidInterfaceException |
|
67 | - * @throws ReflectionException |
|
68 | - */ |
|
69 | - public static function new_instance_from_db($props_n_values = array(), $timezone = null) |
|
70 | - { |
|
71 | - return new self($props_n_values, true, $timezone); |
|
72 | - } |
|
73 | - |
|
74 | - |
|
75 | - /** |
|
76 | - * Adds some defaults if they're not specified |
|
77 | - * |
|
78 | - * @param array $fieldValues |
|
79 | - * @param bool $bydb |
|
80 | - * @param string $timezone |
|
81 | - * @throws EE_Error |
|
82 | - * @throws InvalidArgumentException |
|
83 | - * @throws InvalidDataTypeException |
|
84 | - * @throws InvalidInterfaceException |
|
85 | - * @throws ReflectionException |
|
86 | - */ |
|
87 | - protected function __construct($fieldValues = array(), $bydb = false, $timezone = '') |
|
88 | - { |
|
89 | - parent::__construct($fieldValues, $bydb, $timezone); |
|
90 | - if (! $this->get('LIN_code')) { |
|
91 | - $this->set_code($this->generate_code()); |
|
92 | - } |
|
93 | - } |
|
94 | - |
|
95 | - |
|
96 | - /** |
|
97 | - * Gets ID |
|
98 | - * |
|
99 | - * @return int |
|
100 | - * @throws EE_Error |
|
101 | - * @throws InvalidArgumentException |
|
102 | - * @throws InvalidDataTypeException |
|
103 | - * @throws InvalidInterfaceException |
|
104 | - * @throws ReflectionException |
|
105 | - */ |
|
106 | - public function ID() |
|
107 | - { |
|
108 | - return $this->get('LIN_ID'); |
|
109 | - } |
|
110 | - |
|
111 | - |
|
112 | - /** |
|
113 | - * Gets TXN_ID |
|
114 | - * |
|
115 | - * @return int |
|
116 | - * @throws EE_Error |
|
117 | - * @throws InvalidArgumentException |
|
118 | - * @throws InvalidDataTypeException |
|
119 | - * @throws InvalidInterfaceException |
|
120 | - * @throws ReflectionException |
|
121 | - */ |
|
122 | - public function TXN_ID() |
|
123 | - { |
|
124 | - return $this->get('TXN_ID'); |
|
125 | - } |
|
126 | - |
|
127 | - |
|
128 | - /** |
|
129 | - * Sets TXN_ID |
|
130 | - * |
|
131 | - * @param int $TXN_ID |
|
132 | - * @throws EE_Error |
|
133 | - * @throws InvalidArgumentException |
|
134 | - * @throws InvalidDataTypeException |
|
135 | - * @throws InvalidInterfaceException |
|
136 | - * @throws ReflectionException |
|
137 | - */ |
|
138 | - public function set_TXN_ID($TXN_ID) |
|
139 | - { |
|
140 | - $this->set('TXN_ID', $TXN_ID); |
|
141 | - } |
|
142 | - |
|
143 | - |
|
144 | - /** |
|
145 | - * Gets name |
|
146 | - * |
|
147 | - * @return string |
|
148 | - * @throws EE_Error |
|
149 | - * @throws InvalidArgumentException |
|
150 | - * @throws InvalidDataTypeException |
|
151 | - * @throws InvalidInterfaceException |
|
152 | - * @throws ReflectionException |
|
153 | - */ |
|
154 | - public function name() |
|
155 | - { |
|
156 | - $name = $this->get('LIN_name'); |
|
157 | - if (! $name) { |
|
158 | - $name = ucwords(str_replace('-', ' ', $this->type())); |
|
159 | - } |
|
160 | - return $name; |
|
161 | - } |
|
162 | - |
|
163 | - |
|
164 | - /** |
|
165 | - * Sets name |
|
166 | - * |
|
167 | - * @param string $name |
|
168 | - * @throws EE_Error |
|
169 | - * @throws InvalidArgumentException |
|
170 | - * @throws InvalidDataTypeException |
|
171 | - * @throws InvalidInterfaceException |
|
172 | - * @throws ReflectionException |
|
173 | - */ |
|
174 | - public function set_name($name) |
|
175 | - { |
|
176 | - $this->set('LIN_name', $name); |
|
177 | - } |
|
178 | - |
|
179 | - |
|
180 | - /** |
|
181 | - * Gets desc |
|
182 | - * |
|
183 | - * @return string |
|
184 | - * @throws EE_Error |
|
185 | - * @throws InvalidArgumentException |
|
186 | - * @throws InvalidDataTypeException |
|
187 | - * @throws InvalidInterfaceException |
|
188 | - * @throws ReflectionException |
|
189 | - */ |
|
190 | - public function desc() |
|
191 | - { |
|
192 | - return $this->get('LIN_desc'); |
|
193 | - } |
|
194 | - |
|
195 | - |
|
196 | - /** |
|
197 | - * Sets desc |
|
198 | - * |
|
199 | - * @param string $desc |
|
200 | - * @throws EE_Error |
|
201 | - * @throws InvalidArgumentException |
|
202 | - * @throws InvalidDataTypeException |
|
203 | - * @throws InvalidInterfaceException |
|
204 | - * @throws ReflectionException |
|
205 | - */ |
|
206 | - public function set_desc($desc) |
|
207 | - { |
|
208 | - $this->set('LIN_desc', $desc); |
|
209 | - } |
|
210 | - |
|
211 | - |
|
212 | - /** |
|
213 | - * Gets quantity |
|
214 | - * |
|
215 | - * @return int |
|
216 | - * @throws EE_Error |
|
217 | - * @throws InvalidArgumentException |
|
218 | - * @throws InvalidDataTypeException |
|
219 | - * @throws InvalidInterfaceException |
|
220 | - * @throws ReflectionException |
|
221 | - */ |
|
222 | - public function quantity() |
|
223 | - { |
|
224 | - return $this->get('LIN_quantity'); |
|
225 | - } |
|
226 | - |
|
227 | - |
|
228 | - /** |
|
229 | - * Sets quantity |
|
230 | - * |
|
231 | - * @param int $quantity |
|
232 | - * @throws EE_Error |
|
233 | - * @throws InvalidArgumentException |
|
234 | - * @throws InvalidDataTypeException |
|
235 | - * @throws InvalidInterfaceException |
|
236 | - * @throws ReflectionException |
|
237 | - */ |
|
238 | - public function set_quantity($quantity) |
|
239 | - { |
|
240 | - $this->set('LIN_quantity', max($quantity, 0)); |
|
241 | - } |
|
242 | - |
|
243 | - |
|
244 | - /** |
|
245 | - * Gets item_id |
|
246 | - * |
|
247 | - * @return string |
|
248 | - * @throws EE_Error |
|
249 | - * @throws InvalidArgumentException |
|
250 | - * @throws InvalidDataTypeException |
|
251 | - * @throws InvalidInterfaceException |
|
252 | - * @throws ReflectionException |
|
253 | - */ |
|
254 | - public function OBJ_ID() |
|
255 | - { |
|
256 | - return $this->get('OBJ_ID'); |
|
257 | - } |
|
258 | - |
|
259 | - |
|
260 | - /** |
|
261 | - * Sets item_id |
|
262 | - * |
|
263 | - * @param string $item_id |
|
264 | - * @throws EE_Error |
|
265 | - * @throws InvalidArgumentException |
|
266 | - * @throws InvalidDataTypeException |
|
267 | - * @throws InvalidInterfaceException |
|
268 | - * @throws ReflectionException |
|
269 | - */ |
|
270 | - public function set_OBJ_ID($item_id) |
|
271 | - { |
|
272 | - $this->set('OBJ_ID', $item_id); |
|
273 | - } |
|
274 | - |
|
275 | - |
|
276 | - /** |
|
277 | - * Gets item_type |
|
278 | - * |
|
279 | - * @return string |
|
280 | - * @throws EE_Error |
|
281 | - * @throws InvalidArgumentException |
|
282 | - * @throws InvalidDataTypeException |
|
283 | - * @throws InvalidInterfaceException |
|
284 | - * @throws ReflectionException |
|
285 | - */ |
|
286 | - public function OBJ_type() |
|
287 | - { |
|
288 | - return $this->get('OBJ_type'); |
|
289 | - } |
|
290 | - |
|
291 | - |
|
292 | - /** |
|
293 | - * Gets item_type |
|
294 | - * |
|
295 | - * @return string |
|
296 | - * @throws EE_Error |
|
297 | - * @throws InvalidArgumentException |
|
298 | - * @throws InvalidDataTypeException |
|
299 | - * @throws InvalidInterfaceException |
|
300 | - * @throws ReflectionException |
|
301 | - */ |
|
302 | - public function OBJ_type_i18n() |
|
303 | - { |
|
304 | - $obj_type = $this->OBJ_type(); |
|
305 | - switch ($obj_type) { |
|
306 | - case EEM_Line_Item::OBJ_TYPE_EVENT: |
|
307 | - $obj_type = esc_html__('Event', 'event_espresso'); |
|
308 | - break; |
|
309 | - case EEM_Line_Item::OBJ_TYPE_PRICE: |
|
310 | - $obj_type = esc_html__('Price', 'event_espresso'); |
|
311 | - break; |
|
312 | - case EEM_Line_Item::OBJ_TYPE_PROMOTION: |
|
313 | - $obj_type = esc_html__('Promotion', 'event_espresso'); |
|
314 | - break; |
|
315 | - case EEM_Line_Item::OBJ_TYPE_TICKET: |
|
316 | - $obj_type = esc_html__('Ticket', 'event_espresso'); |
|
317 | - break; |
|
318 | - case EEM_Line_Item::OBJ_TYPE_TRANSACTION: |
|
319 | - $obj_type = esc_html__('Transaction', 'event_espresso'); |
|
320 | - break; |
|
321 | - } |
|
322 | - return apply_filters('FHEE__EE_Line_Item__OBJ_type_i18n', $obj_type, $this); |
|
323 | - } |
|
324 | - |
|
325 | - |
|
326 | - /** |
|
327 | - * Sets item_type |
|
328 | - * |
|
329 | - * @param string $OBJ_type |
|
330 | - * @throws EE_Error |
|
331 | - * @throws InvalidArgumentException |
|
332 | - * @throws InvalidDataTypeException |
|
333 | - * @throws InvalidInterfaceException |
|
334 | - * @throws ReflectionException |
|
335 | - */ |
|
336 | - public function set_OBJ_type($OBJ_type) |
|
337 | - { |
|
338 | - $this->set('OBJ_type', $OBJ_type); |
|
339 | - } |
|
340 | - |
|
341 | - |
|
342 | - /** |
|
343 | - * Gets unit_price |
|
344 | - * |
|
345 | - * @return float |
|
346 | - * @throws EE_Error |
|
347 | - * @throws InvalidArgumentException |
|
348 | - * @throws InvalidDataTypeException |
|
349 | - * @throws InvalidInterfaceException |
|
350 | - * @throws ReflectionException |
|
351 | - */ |
|
352 | - public function unit_price() |
|
353 | - { |
|
354 | - return $this->get('LIN_unit_price'); |
|
355 | - } |
|
356 | - |
|
357 | - |
|
358 | - /** |
|
359 | - * Sets unit_price |
|
360 | - * |
|
361 | - * @param float $unit_price |
|
362 | - * @throws EE_Error |
|
363 | - * @throws InvalidArgumentException |
|
364 | - * @throws InvalidDataTypeException |
|
365 | - * @throws InvalidInterfaceException |
|
366 | - * @throws ReflectionException |
|
367 | - */ |
|
368 | - public function set_unit_price($unit_price) |
|
369 | - { |
|
370 | - $this->set('LIN_unit_price', $unit_price); |
|
371 | - } |
|
372 | - |
|
373 | - |
|
374 | - /** |
|
375 | - * Checks if this item is a percentage modifier or not |
|
376 | - * |
|
377 | - * @return boolean |
|
378 | - * @throws EE_Error |
|
379 | - * @throws InvalidArgumentException |
|
380 | - * @throws InvalidDataTypeException |
|
381 | - * @throws InvalidInterfaceException |
|
382 | - * @throws ReflectionException |
|
383 | - */ |
|
384 | - public function is_percent() |
|
385 | - { |
|
386 | - if ($this->is_tax_sub_total()) { |
|
387 | - // tax subtotals HAVE a percent on them, that percentage only applies |
|
388 | - // to taxable items, so its' an exception. Treat it like a flat line item |
|
389 | - return false; |
|
390 | - } |
|
391 | - $unit_price = abs($this->get('LIN_unit_price')); |
|
392 | - $percent = abs($this->get('LIN_percent')); |
|
393 | - if ($unit_price < .001 && $percent) { |
|
394 | - return true; |
|
395 | - } |
|
396 | - if ($unit_price >= .001 && ! $percent) { |
|
397 | - return false; |
|
398 | - } |
|
399 | - if ($unit_price >= .001 && $percent) { |
|
400 | - throw new EE_Error( |
|
401 | - sprintf( |
|
402 | - esc_html__( |
|
403 | - 'A Line Item can not have a unit price of (%s) AND a percent (%s)!', |
|
404 | - 'event_espresso' |
|
405 | - ), |
|
406 | - $unit_price, |
|
407 | - $percent |
|
408 | - ) |
|
409 | - ); |
|
410 | - } |
|
411 | - // if they're both 0, assume its not a percent item |
|
412 | - return false; |
|
413 | - } |
|
414 | - |
|
415 | - |
|
416 | - /** |
|
417 | - * Gets percent (between 100-.001) |
|
418 | - * |
|
419 | - * @return float |
|
420 | - * @throws EE_Error |
|
421 | - * @throws InvalidArgumentException |
|
422 | - * @throws InvalidDataTypeException |
|
423 | - * @throws InvalidInterfaceException |
|
424 | - * @throws ReflectionException |
|
425 | - */ |
|
426 | - public function percent() |
|
427 | - { |
|
428 | - return $this->get('LIN_percent'); |
|
429 | - } |
|
430 | - |
|
431 | - |
|
432 | - /** |
|
433 | - * Sets percent (between 100-0.01) |
|
434 | - * |
|
435 | - * @param float $percent |
|
436 | - * @throws EE_Error |
|
437 | - * @throws InvalidArgumentException |
|
438 | - * @throws InvalidDataTypeException |
|
439 | - * @throws InvalidInterfaceException |
|
440 | - * @throws ReflectionException |
|
441 | - */ |
|
442 | - public function set_percent($percent) |
|
443 | - { |
|
444 | - $this->set('LIN_percent', $percent); |
|
445 | - } |
|
446 | - |
|
447 | - |
|
448 | - /** |
|
449 | - * Gets total |
|
450 | - * |
|
451 | - * @return float |
|
452 | - * @throws EE_Error |
|
453 | - * @throws InvalidArgumentException |
|
454 | - * @throws InvalidDataTypeException |
|
455 | - * @throws InvalidInterfaceException |
|
456 | - * @throws ReflectionException |
|
457 | - */ |
|
458 | - public function total() |
|
459 | - { |
|
460 | - return $this->get('LIN_total'); |
|
461 | - } |
|
462 | - |
|
463 | - |
|
464 | - /** |
|
465 | - * Sets total |
|
466 | - * |
|
467 | - * @param float $total |
|
468 | - * @throws EE_Error |
|
469 | - * @throws InvalidArgumentException |
|
470 | - * @throws InvalidDataTypeException |
|
471 | - * @throws InvalidInterfaceException |
|
472 | - * @throws ReflectionException |
|
473 | - */ |
|
474 | - public function set_total($total) |
|
475 | - { |
|
476 | - $this->set('LIN_total', $total); |
|
477 | - } |
|
478 | - |
|
479 | - |
|
480 | - /** |
|
481 | - * Gets order |
|
482 | - * |
|
483 | - * @return int |
|
484 | - * @throws EE_Error |
|
485 | - * @throws InvalidArgumentException |
|
486 | - * @throws InvalidDataTypeException |
|
487 | - * @throws InvalidInterfaceException |
|
488 | - * @throws ReflectionException |
|
489 | - */ |
|
490 | - public function order() |
|
491 | - { |
|
492 | - return $this->get('LIN_order'); |
|
493 | - } |
|
494 | - |
|
495 | - |
|
496 | - /** |
|
497 | - * Sets order |
|
498 | - * |
|
499 | - * @param int $order |
|
500 | - * @throws EE_Error |
|
501 | - * @throws InvalidArgumentException |
|
502 | - * @throws InvalidDataTypeException |
|
503 | - * @throws InvalidInterfaceException |
|
504 | - * @throws ReflectionException |
|
505 | - */ |
|
506 | - public function set_order($order) |
|
507 | - { |
|
508 | - $this->set('LIN_order', $order); |
|
509 | - } |
|
510 | - |
|
511 | - |
|
512 | - /** |
|
513 | - * Gets parent |
|
514 | - * |
|
515 | - * @return int |
|
516 | - * @throws EE_Error |
|
517 | - * @throws InvalidArgumentException |
|
518 | - * @throws InvalidDataTypeException |
|
519 | - * @throws InvalidInterfaceException |
|
520 | - * @throws ReflectionException |
|
521 | - */ |
|
522 | - public function parent_ID() |
|
523 | - { |
|
524 | - return $this->get('LIN_parent'); |
|
525 | - } |
|
526 | - |
|
527 | - |
|
528 | - /** |
|
529 | - * Sets parent |
|
530 | - * |
|
531 | - * @param int $parent |
|
532 | - * @throws EE_Error |
|
533 | - * @throws InvalidArgumentException |
|
534 | - * @throws InvalidDataTypeException |
|
535 | - * @throws InvalidInterfaceException |
|
536 | - * @throws ReflectionException |
|
537 | - */ |
|
538 | - public function set_parent_ID($parent) |
|
539 | - { |
|
540 | - $this->set('LIN_parent', $parent); |
|
541 | - } |
|
542 | - |
|
543 | - |
|
544 | - /** |
|
545 | - * Gets type |
|
546 | - * |
|
547 | - * @return string |
|
548 | - * @throws EE_Error |
|
549 | - * @throws InvalidArgumentException |
|
550 | - * @throws InvalidDataTypeException |
|
551 | - * @throws InvalidInterfaceException |
|
552 | - * @throws ReflectionException |
|
553 | - */ |
|
554 | - public function type() |
|
555 | - { |
|
556 | - return $this->get('LIN_type'); |
|
557 | - } |
|
558 | - |
|
559 | - |
|
560 | - /** |
|
561 | - * Sets type |
|
562 | - * |
|
563 | - * @param string $type |
|
564 | - * @throws EE_Error |
|
565 | - * @throws InvalidArgumentException |
|
566 | - * @throws InvalidDataTypeException |
|
567 | - * @throws InvalidInterfaceException |
|
568 | - * @throws ReflectionException |
|
569 | - */ |
|
570 | - public function set_type($type) |
|
571 | - { |
|
572 | - $this->set('LIN_type', $type); |
|
573 | - } |
|
574 | - |
|
575 | - |
|
576 | - /** |
|
577 | - * Gets the line item of which this item is a composite. Eg, if this is a subtotal, the parent might be a total\ |
|
578 | - * 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 |
|
579 | - * it uses its cached reference to its parent line item (which would have been set by `EE_Line_Item::set_parent()` |
|
580 | - * or indirectly by `EE_Line_item::add_child_line_item()`) |
|
581 | - * |
|
582 | - * @return EE_Base_Class|EE_Line_Item |
|
583 | - * @throws EE_Error |
|
584 | - * @throws InvalidArgumentException |
|
585 | - * @throws InvalidDataTypeException |
|
586 | - * @throws InvalidInterfaceException |
|
587 | - * @throws ReflectionException |
|
588 | - */ |
|
589 | - public function parent() |
|
590 | - { |
|
591 | - return $this->ID() |
|
592 | - ? $this->get_model()->get_one_by_ID($this->parent_ID()) |
|
593 | - : $this->_parent; |
|
594 | - } |
|
595 | - |
|
596 | - |
|
597 | - /** |
|
598 | - * Gets ALL the children of this line item (ie, all the parts that contribute towards this total). |
|
599 | - * |
|
600 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
601 | - * @throws EE_Error |
|
602 | - * @throws InvalidArgumentException |
|
603 | - * @throws InvalidDataTypeException |
|
604 | - * @throws InvalidInterfaceException |
|
605 | - * @throws ReflectionException |
|
606 | - */ |
|
607 | - public function children() |
|
608 | - { |
|
609 | - if ($this->ID()) { |
|
610 | - return $this->get_model()->get_all( |
|
611 | - array( |
|
612 | - array('LIN_parent' => $this->ID()), |
|
613 | - 'order_by' => array('LIN_order' => 'ASC'), |
|
614 | - ) |
|
615 | - ); |
|
616 | - } |
|
617 | - if (! is_array($this->_children)) { |
|
618 | - $this->_children = array(); |
|
619 | - } |
|
620 | - return $this->_children; |
|
621 | - } |
|
622 | - |
|
623 | - |
|
624 | - /** |
|
625 | - * Gets code |
|
626 | - * |
|
627 | - * @return string |
|
628 | - * @throws EE_Error |
|
629 | - * @throws InvalidArgumentException |
|
630 | - * @throws InvalidDataTypeException |
|
631 | - * @throws InvalidInterfaceException |
|
632 | - * @throws ReflectionException |
|
633 | - */ |
|
634 | - public function code() |
|
635 | - { |
|
636 | - return $this->get('LIN_code'); |
|
637 | - } |
|
638 | - |
|
639 | - |
|
640 | - /** |
|
641 | - * Sets code |
|
642 | - * |
|
643 | - * @param string $code |
|
644 | - * @throws EE_Error |
|
645 | - * @throws InvalidArgumentException |
|
646 | - * @throws InvalidDataTypeException |
|
647 | - * @throws InvalidInterfaceException |
|
648 | - * @throws ReflectionException |
|
649 | - */ |
|
650 | - public function set_code($code) |
|
651 | - { |
|
652 | - $this->set('LIN_code', $code); |
|
653 | - } |
|
654 | - |
|
655 | - |
|
656 | - /** |
|
657 | - * Gets is_taxable |
|
658 | - * |
|
659 | - * @return boolean |
|
660 | - * @throws EE_Error |
|
661 | - * @throws InvalidArgumentException |
|
662 | - * @throws InvalidDataTypeException |
|
663 | - * @throws InvalidInterfaceException |
|
664 | - * @throws ReflectionException |
|
665 | - */ |
|
666 | - public function is_taxable() |
|
667 | - { |
|
668 | - return $this->get('LIN_is_taxable'); |
|
669 | - } |
|
670 | - |
|
671 | - |
|
672 | - /** |
|
673 | - * Sets is_taxable |
|
674 | - * |
|
675 | - * @param boolean $is_taxable |
|
676 | - * @throws EE_Error |
|
677 | - * @throws InvalidArgumentException |
|
678 | - * @throws InvalidDataTypeException |
|
679 | - * @throws InvalidInterfaceException |
|
680 | - * @throws ReflectionException |
|
681 | - */ |
|
682 | - public function set_is_taxable($is_taxable) |
|
683 | - { |
|
684 | - $this->set('LIN_is_taxable', $is_taxable); |
|
685 | - } |
|
686 | - |
|
687 | - |
|
688 | - /** |
|
689 | - * Gets the object that this model-joins-to. |
|
690 | - * returns one of the model objects that the field OBJ_ID can point to... see the 'OBJ_ID' field on |
|
691 | - * EEM_Promotion_Object |
|
692 | - * Eg, if this line item join model object is for a ticket, this will return the EE_Ticket object |
|
693 | - * |
|
694 | - * @return EE_Base_Class | NULL |
|
695 | - * @throws EE_Error |
|
696 | - * @throws InvalidArgumentException |
|
697 | - * @throws InvalidDataTypeException |
|
698 | - * @throws InvalidInterfaceException |
|
699 | - * @throws ReflectionException |
|
700 | - */ |
|
701 | - public function get_object() |
|
702 | - { |
|
703 | - $model_name_of_related_obj = $this->OBJ_type(); |
|
704 | - return $this->get_model()->has_relation($model_name_of_related_obj) |
|
705 | - ? $this->get_first_related($model_name_of_related_obj) |
|
706 | - : null; |
|
707 | - } |
|
708 | - |
|
709 | - |
|
710 | - /** |
|
711 | - * Like EE_Line_Item::get_object(), but can only ever actually return an EE_Ticket. |
|
712 | - * (IE, if this line item is for a price or something else, will return NULL) |
|
713 | - * |
|
714 | - * @param array $query_params |
|
715 | - * @return EE_Base_Class|EE_Ticket |
|
716 | - * @throws EE_Error |
|
717 | - * @throws InvalidArgumentException |
|
718 | - * @throws InvalidDataTypeException |
|
719 | - * @throws InvalidInterfaceException |
|
720 | - * @throws ReflectionException |
|
721 | - */ |
|
722 | - public function ticket($query_params = array()) |
|
723 | - { |
|
724 | - // we're going to assume that when this method is called |
|
725 | - // we always want to receive the attached ticket EVEN if that ticket is archived. |
|
726 | - // This can be overridden via the incoming $query_params argument |
|
727 | - $remove_defaults = array('default_where_conditions' => 'none'); |
|
728 | - $query_params = array_merge($remove_defaults, $query_params); |
|
729 | - return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TICKET, $query_params); |
|
730 | - } |
|
731 | - |
|
732 | - |
|
733 | - /** |
|
734 | - * Gets the EE_Datetime that's related to the ticket, IF this is for a ticket |
|
735 | - * |
|
736 | - * @return EE_Datetime | NULL |
|
737 | - * @throws EE_Error |
|
738 | - * @throws InvalidArgumentException |
|
739 | - * @throws InvalidDataTypeException |
|
740 | - * @throws InvalidInterfaceException |
|
741 | - * @throws ReflectionException |
|
742 | - */ |
|
743 | - public function get_ticket_datetime() |
|
744 | - { |
|
745 | - if ($this->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) { |
|
746 | - $ticket = $this->ticket(); |
|
747 | - if ($ticket instanceof EE_Ticket) { |
|
748 | - $datetime = $ticket->first_datetime(); |
|
749 | - if ($datetime instanceof EE_Datetime) { |
|
750 | - return $datetime; |
|
751 | - } |
|
752 | - } |
|
753 | - } |
|
754 | - return null; |
|
755 | - } |
|
756 | - |
|
757 | - |
|
758 | - /** |
|
759 | - * Gets the event's name that's related to the ticket, if this is for |
|
760 | - * a ticket |
|
761 | - * |
|
762 | - * @return string |
|
763 | - * @throws EE_Error |
|
764 | - * @throws InvalidArgumentException |
|
765 | - * @throws InvalidDataTypeException |
|
766 | - * @throws InvalidInterfaceException |
|
767 | - * @throws ReflectionException |
|
768 | - */ |
|
769 | - public function ticket_event_name() |
|
770 | - { |
|
771 | - $event_name = esc_html__('Unknown', 'event_espresso'); |
|
772 | - $event = $this->ticket_event(); |
|
773 | - if ($event instanceof EE_Event) { |
|
774 | - $event_name = $event->name(); |
|
775 | - } |
|
776 | - return $event_name; |
|
777 | - } |
|
778 | - |
|
779 | - |
|
780 | - /** |
|
781 | - * Gets the event that's related to the ticket, if this line item represents a ticket. |
|
782 | - * |
|
783 | - * @return EE_Event|null |
|
784 | - * @throws EE_Error |
|
785 | - * @throws InvalidArgumentException |
|
786 | - * @throws InvalidDataTypeException |
|
787 | - * @throws InvalidInterfaceException |
|
788 | - * @throws ReflectionException |
|
789 | - */ |
|
790 | - public function ticket_event() |
|
791 | - { |
|
792 | - $event = null; |
|
793 | - $ticket = $this->ticket(); |
|
794 | - if ($ticket instanceof EE_Ticket) { |
|
795 | - $datetime = $ticket->first_datetime(); |
|
796 | - if ($datetime instanceof EE_Datetime) { |
|
797 | - $event = $datetime->event(); |
|
798 | - } |
|
799 | - } |
|
800 | - return $event; |
|
801 | - } |
|
802 | - |
|
803 | - |
|
804 | - /** |
|
805 | - * Gets the first datetime for this lien item, assuming it's for a ticket |
|
806 | - * |
|
807 | - * @param string $date_format |
|
808 | - * @param string $time_format |
|
809 | - * @return string |
|
810 | - * @throws EE_Error |
|
811 | - * @throws InvalidArgumentException |
|
812 | - * @throws InvalidDataTypeException |
|
813 | - * @throws InvalidInterfaceException |
|
814 | - * @throws ReflectionException |
|
815 | - */ |
|
816 | - public function ticket_datetime_start($date_format = '', $time_format = '') |
|
817 | - { |
|
818 | - $first_datetime_string = esc_html__('Unknown', 'event_espresso'); |
|
819 | - $datetime = $this->get_ticket_datetime(); |
|
820 | - if ($datetime) { |
|
821 | - $first_datetime_string = $datetime->start_date_and_time($date_format, $time_format); |
|
822 | - } |
|
823 | - return $first_datetime_string; |
|
824 | - } |
|
825 | - |
|
826 | - |
|
827 | - /** |
|
828 | - * Adds the line item as a child to this line item. If there is another child line |
|
829 | - * item with the same LIN_code, it is overwritten by this new one |
|
830 | - * |
|
831 | - * @param EEI_Line_Item $line_item |
|
832 | - * @param bool $set_order |
|
833 | - * @return bool success |
|
834 | - * @throws EE_Error |
|
835 | - * @throws InvalidArgumentException |
|
836 | - * @throws InvalidDataTypeException |
|
837 | - * @throws InvalidInterfaceException |
|
838 | - * @throws ReflectionException |
|
839 | - */ |
|
840 | - public function add_child_line_item(EEI_Line_Item $line_item, $set_order = true) |
|
841 | - { |
|
842 | - // should we calculate the LIN_order for this line item ? |
|
843 | - if ($set_order || $line_item->order() === null) { |
|
844 | - $line_item->set_order(count($this->children())); |
|
845 | - } |
|
846 | - if ($this->ID()) { |
|
847 | - // check for any duplicate line items (with the same code), if so, this replaces it |
|
848 | - $line_item_with_same_code = $this->get_child_line_item($line_item->code()); |
|
849 | - if ($line_item_with_same_code instanceof EE_Line_Item && $line_item_with_same_code !== $line_item) { |
|
850 | - $this->delete_child_line_item($line_item_with_same_code->code()); |
|
851 | - } |
|
852 | - $line_item->set_parent_ID($this->ID()); |
|
853 | - if ($this->TXN_ID()) { |
|
854 | - $line_item->set_TXN_ID($this->TXN_ID()); |
|
855 | - } |
|
856 | - return $line_item->save(); |
|
857 | - } |
|
858 | - $this->_children[ $line_item->code() ] = $line_item; |
|
859 | - if ($line_item->parent() !== $this) { |
|
860 | - $line_item->set_parent($this); |
|
861 | - } |
|
862 | - return true; |
|
863 | - } |
|
864 | - |
|
865 | - |
|
866 | - /** |
|
867 | - * Similar to EE_Base_Class::_add_relation_to, except this isn't a normal relation. |
|
868 | - * If this line item is saved to the DB, this is just a wrapper for set_parent_ID() and save() |
|
869 | - * However, if this line item is NOT saved to the DB, this just caches the parent on |
|
870 | - * the EE_Line_Item::_parent property. |
|
871 | - * |
|
872 | - * @param EE_Line_Item $line_item |
|
873 | - * @throws EE_Error |
|
874 | - * @throws InvalidArgumentException |
|
875 | - * @throws InvalidDataTypeException |
|
876 | - * @throws InvalidInterfaceException |
|
877 | - * @throws ReflectionException |
|
878 | - */ |
|
879 | - public function set_parent($line_item) |
|
880 | - { |
|
881 | - if ($this->ID()) { |
|
882 | - if (! $line_item->ID()) { |
|
883 | - $line_item->save(); |
|
884 | - } |
|
885 | - $this->set_parent_ID($line_item->ID()); |
|
886 | - $this->save(); |
|
887 | - } else { |
|
888 | - $this->_parent = $line_item; |
|
889 | - $this->set_parent_ID($line_item->ID()); |
|
890 | - } |
|
891 | - } |
|
892 | - |
|
893 | - |
|
894 | - /** |
|
895 | - * Gets the child line item as specified by its code. Because this returns an object (by reference) |
|
896 | - * you can modify this child line item and the parent (this object) can know about them |
|
897 | - * because it also has a reference to that line item |
|
898 | - * |
|
899 | - * @param string $code |
|
900 | - * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL |
|
901 | - * @throws EE_Error |
|
902 | - * @throws InvalidArgumentException |
|
903 | - * @throws InvalidDataTypeException |
|
904 | - * @throws InvalidInterfaceException |
|
905 | - * @throws ReflectionException |
|
906 | - */ |
|
907 | - public function get_child_line_item($code) |
|
908 | - { |
|
909 | - if ($this->ID()) { |
|
910 | - return $this->get_model()->get_one( |
|
911 | - array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code)) |
|
912 | - ); |
|
913 | - } |
|
914 | - return isset($this->_children[ $code ]) |
|
915 | - ? $this->_children[ $code ] |
|
916 | - : null; |
|
917 | - } |
|
918 | - |
|
919 | - |
|
920 | - /** |
|
921 | - * Returns how many items are deleted (or, if this item has not been saved ot the DB yet, just how many it HAD |
|
922 | - * cached on it) |
|
923 | - * |
|
924 | - * @return int |
|
925 | - * @throws EE_Error |
|
926 | - * @throws InvalidArgumentException |
|
927 | - * @throws InvalidDataTypeException |
|
928 | - * @throws InvalidInterfaceException |
|
929 | - * @throws ReflectionException |
|
930 | - */ |
|
931 | - public function delete_children_line_items() |
|
932 | - { |
|
933 | - if ($this->ID()) { |
|
934 | - return $this->get_model()->delete(array(array('LIN_parent' => $this->ID()))); |
|
935 | - } |
|
936 | - $count = count($this->_children); |
|
937 | - $this->_children = array(); |
|
938 | - return $count; |
|
939 | - } |
|
940 | - |
|
941 | - |
|
942 | - /** |
|
943 | - * If this line item has been saved to the DB, deletes its child with LIN_code == $code. If this line |
|
944 | - * HAS NOT been saved to the DB, removes the child line item with index $code. |
|
945 | - * Also searches through the child's children for a matching line item. However, once a line item has been found |
|
946 | - * and deleted, stops searching (so if there are line items with duplicate codes, only the first one found will be |
|
947 | - * deleted) |
|
948 | - * |
|
949 | - * @param string $code |
|
950 | - * @param bool $stop_search_once_found |
|
951 | - * @return int count of items deleted (or simply removed from the line item's cache, if not has not been saved to |
|
952 | - * the DB yet) |
|
953 | - * @throws EE_Error |
|
954 | - * @throws InvalidArgumentException |
|
955 | - * @throws InvalidDataTypeException |
|
956 | - * @throws InvalidInterfaceException |
|
957 | - * @throws ReflectionException |
|
958 | - */ |
|
959 | - public function delete_child_line_item($code, $stop_search_once_found = true) |
|
960 | - { |
|
961 | - if ($this->ID()) { |
|
962 | - $items_deleted = 0; |
|
963 | - if ($this->code() === $code) { |
|
964 | - $items_deleted += EEH_Line_Item::delete_all_child_items($this); |
|
965 | - $items_deleted += (int) $this->delete(); |
|
966 | - if ($stop_search_once_found) { |
|
967 | - return $items_deleted; |
|
968 | - } |
|
969 | - } |
|
970 | - foreach ($this->children() as $child_line_item) { |
|
971 | - $items_deleted += $child_line_item->delete_child_line_item($code, $stop_search_once_found); |
|
972 | - } |
|
973 | - return $items_deleted; |
|
974 | - } |
|
975 | - if (isset($this->_children[ $code ])) { |
|
976 | - unset($this->_children[ $code ]); |
|
977 | - return 1; |
|
978 | - } |
|
979 | - return 0; |
|
980 | - } |
|
981 | - |
|
982 | - |
|
983 | - /** |
|
984 | - * If this line item is in the database, is of the type subtotal, and |
|
985 | - * has no children, why do we have it? It should be deleted so this function |
|
986 | - * does that |
|
987 | - * |
|
988 | - * @return boolean |
|
989 | - * @throws EE_Error |
|
990 | - * @throws InvalidArgumentException |
|
991 | - * @throws InvalidDataTypeException |
|
992 | - * @throws InvalidInterfaceException |
|
993 | - * @throws ReflectionException |
|
994 | - */ |
|
995 | - public function delete_if_childless_subtotal() |
|
996 | - { |
|
997 | - if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && ! $this->children()) { |
|
998 | - return $this->delete(); |
|
999 | - } |
|
1000 | - return false; |
|
1001 | - } |
|
1002 | - |
|
1003 | - |
|
1004 | - /** |
|
1005 | - * Creates a code and returns a string. doesn't assign the code to this model object |
|
1006 | - * |
|
1007 | - * @return string |
|
1008 | - * @throws EE_Error |
|
1009 | - * @throws InvalidArgumentException |
|
1010 | - * @throws InvalidDataTypeException |
|
1011 | - * @throws InvalidInterfaceException |
|
1012 | - * @throws ReflectionException |
|
1013 | - */ |
|
1014 | - public function generate_code() |
|
1015 | - { |
|
1016 | - // each line item in the cart requires a unique identifier |
|
1017 | - return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime()); |
|
1018 | - } |
|
1019 | - |
|
1020 | - |
|
1021 | - /** |
|
1022 | - * @return bool |
|
1023 | - * @throws EE_Error |
|
1024 | - * @throws InvalidArgumentException |
|
1025 | - * @throws InvalidDataTypeException |
|
1026 | - * @throws InvalidInterfaceException |
|
1027 | - * @throws ReflectionException |
|
1028 | - */ |
|
1029 | - public function is_tax() |
|
1030 | - { |
|
1031 | - return $this->type() === EEM_Line_Item::type_tax; |
|
1032 | - } |
|
1033 | - |
|
1034 | - |
|
1035 | - /** |
|
1036 | - * @return bool |
|
1037 | - * @throws EE_Error |
|
1038 | - * @throws InvalidArgumentException |
|
1039 | - * @throws InvalidDataTypeException |
|
1040 | - * @throws InvalidInterfaceException |
|
1041 | - * @throws ReflectionException |
|
1042 | - */ |
|
1043 | - public function is_tax_sub_total() |
|
1044 | - { |
|
1045 | - return $this->type() === EEM_Line_Item::type_tax_sub_total; |
|
1046 | - } |
|
1047 | - |
|
1048 | - |
|
1049 | - /** |
|
1050 | - * @return bool |
|
1051 | - * @throws EE_Error |
|
1052 | - * @throws InvalidArgumentException |
|
1053 | - * @throws InvalidDataTypeException |
|
1054 | - * @throws InvalidInterfaceException |
|
1055 | - * @throws ReflectionException |
|
1056 | - */ |
|
1057 | - public function is_line_item() |
|
1058 | - { |
|
1059 | - return $this->type() === EEM_Line_Item::type_line_item; |
|
1060 | - } |
|
1061 | - |
|
1062 | - |
|
1063 | - /** |
|
1064 | - * @return bool |
|
1065 | - * @throws EE_Error |
|
1066 | - * @throws InvalidArgumentException |
|
1067 | - * @throws InvalidDataTypeException |
|
1068 | - * @throws InvalidInterfaceException |
|
1069 | - * @throws ReflectionException |
|
1070 | - */ |
|
1071 | - public function is_sub_line_item() |
|
1072 | - { |
|
1073 | - return $this->type() === EEM_Line_Item::type_sub_line_item; |
|
1074 | - } |
|
1075 | - |
|
1076 | - |
|
1077 | - /** |
|
1078 | - * @return bool |
|
1079 | - * @throws EE_Error |
|
1080 | - * @throws InvalidArgumentException |
|
1081 | - * @throws InvalidDataTypeException |
|
1082 | - * @throws InvalidInterfaceException |
|
1083 | - * @throws ReflectionException |
|
1084 | - */ |
|
1085 | - public function is_sub_total() |
|
1086 | - { |
|
1087 | - return $this->type() === EEM_Line_Item::type_sub_total; |
|
1088 | - } |
|
1089 | - |
|
1090 | - |
|
1091 | - /** |
|
1092 | - * Whether or not this line item is a cancellation line item |
|
1093 | - * |
|
1094 | - * @return boolean |
|
1095 | - * @throws EE_Error |
|
1096 | - * @throws InvalidArgumentException |
|
1097 | - * @throws InvalidDataTypeException |
|
1098 | - * @throws InvalidInterfaceException |
|
1099 | - * @throws ReflectionException |
|
1100 | - */ |
|
1101 | - public function is_cancellation() |
|
1102 | - { |
|
1103 | - return EEM_Line_Item::type_cancellation === $this->type(); |
|
1104 | - } |
|
1105 | - |
|
1106 | - |
|
1107 | - /** |
|
1108 | - * @return bool |
|
1109 | - * @throws EE_Error |
|
1110 | - * @throws InvalidArgumentException |
|
1111 | - * @throws InvalidDataTypeException |
|
1112 | - * @throws InvalidInterfaceException |
|
1113 | - * @throws ReflectionException |
|
1114 | - */ |
|
1115 | - public function is_total() |
|
1116 | - { |
|
1117 | - return $this->type() === EEM_Line_Item::type_total; |
|
1118 | - } |
|
1119 | - |
|
1120 | - |
|
1121 | - /** |
|
1122 | - * @return bool |
|
1123 | - * @throws EE_Error |
|
1124 | - * @throws InvalidArgumentException |
|
1125 | - * @throws InvalidDataTypeException |
|
1126 | - * @throws InvalidInterfaceException |
|
1127 | - * @throws ReflectionException |
|
1128 | - */ |
|
1129 | - public function is_cancelled() |
|
1130 | - { |
|
1131 | - return $this->type() === EEM_Line_Item::type_cancellation; |
|
1132 | - } |
|
1133 | - |
|
1134 | - |
|
1135 | - /** |
|
1136 | - * @return string like '2, 004.00', formatted according to the localized currency |
|
1137 | - * @throws EE_Error |
|
1138 | - * @throws InvalidArgumentException |
|
1139 | - * @throws InvalidDataTypeException |
|
1140 | - * @throws InvalidInterfaceException |
|
1141 | - * @throws ReflectionException |
|
1142 | - */ |
|
1143 | - public function unit_price_no_code() |
|
1144 | - { |
|
1145 | - return $this->get_pretty('LIN_unit_price', 'no_currency_code'); |
|
1146 | - } |
|
1147 | - |
|
1148 | - |
|
1149 | - /** |
|
1150 | - * @return string like '2, 004.00', formatted according to the localized currency |
|
1151 | - * @throws EE_Error |
|
1152 | - * @throws InvalidArgumentException |
|
1153 | - * @throws InvalidDataTypeException |
|
1154 | - * @throws InvalidInterfaceException |
|
1155 | - * @throws ReflectionException |
|
1156 | - */ |
|
1157 | - public function total_no_code() |
|
1158 | - { |
|
1159 | - return $this->get_pretty('LIN_total', 'no_currency_code'); |
|
1160 | - } |
|
1161 | - |
|
1162 | - |
|
1163 | - /** |
|
1164 | - * Gets the final total on this item, taking taxes into account. |
|
1165 | - * Has the side-effect of setting the sub-total as it was just calculated. |
|
1166 | - * If this is used on a grand-total line item, also updates the transaction's |
|
1167 | - * TXN_total (provided this line item is allowed to persist, otherwise we don't |
|
1168 | - * want to change a persistable transaction with info from a non-persistent line item) |
|
1169 | - * |
|
1170 | - * @param bool $update_txn_status |
|
1171 | - * @return float |
|
1172 | - * @throws EE_Error |
|
1173 | - * @throws InvalidArgumentException |
|
1174 | - * @throws InvalidDataTypeException |
|
1175 | - * @throws InvalidInterfaceException |
|
1176 | - * @throws ReflectionException |
|
1177 | - * @throws RuntimeException |
|
1178 | - */ |
|
1179 | - public function recalculate_total_including_taxes($update_txn_status = false) |
|
1180 | - { |
|
1181 | - $pre_tax_total = $this->recalculate_pre_tax_total(); |
|
1182 | - $tax_total = $this->recalculate_taxes_and_tax_total(); |
|
1183 | - $total = $pre_tax_total + $tax_total; |
|
1184 | - // no negative totals plz |
|
1185 | - $total = max($total, 0); |
|
1186 | - $this->set_total($total); |
|
1187 | - // only update the related transaction's total |
|
1188 | - // if we intend to save this line item and its a grand total |
|
1189 | - if ( |
|
1190 | - $this->allow_persist() && $this->type() === EEM_Line_Item::type_total |
|
1191 | - && $this->transaction() |
|
1192 | - instanceof |
|
1193 | - EE_Transaction |
|
1194 | - ) { |
|
1195 | - $this->transaction()->set_total($total); |
|
1196 | - if ($update_txn_status) { |
|
1197 | - // don't save the TXN because that will be done below |
|
1198 | - // and the following method only saves if the status changes |
|
1199 | - $this->transaction()->update_status_based_on_total_paid(false); |
|
1200 | - } |
|
1201 | - if ($this->transaction()->ID()) { |
|
1202 | - $this->transaction()->save(); |
|
1203 | - } |
|
1204 | - } |
|
1205 | - $this->maybe_save(); |
|
1206 | - return $total; |
|
1207 | - } |
|
1208 | - |
|
1209 | - |
|
1210 | - /** |
|
1211 | - * Recursively goes through all the children and recalculates sub-totals EXCEPT for |
|
1212 | - * tax-sub-totals (they're a an odd beast). Updates the 'total' on each line item according to either its |
|
1213 | - * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and |
|
1214 | - * when this is called on the grand total |
|
1215 | - * |
|
1216 | - * @return float |
|
1217 | - * @throws EE_Error |
|
1218 | - * @throws InvalidArgumentException |
|
1219 | - * @throws InvalidDataTypeException |
|
1220 | - * @throws InvalidInterfaceException |
|
1221 | - * @throws ReflectionException |
|
1222 | - */ |
|
1223 | - public function recalculate_pre_tax_total() |
|
1224 | - { |
|
1225 | - $total = 0; |
|
1226 | - $my_children = $this->children(); |
|
1227 | - $has_children = ! empty($my_children); |
|
1228 | - if ($has_children && $this->is_line_item()) { |
|
1229 | - $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children); |
|
1230 | - } elseif (! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) { |
|
1231 | - $total = $this->unit_price() * $this->quantity(); |
|
1232 | - } elseif ($this->is_sub_total() || $this->is_total()) { |
|
1233 | - $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children); |
|
1234 | - } elseif ($this->is_tax_sub_total() || $this->is_tax() || $this->is_cancelled()) { |
|
1235 | - // completely ignore tax totals, tax sub-totals, and cancelled line items, when calculating the pre-tax-total |
|
1236 | - return 0; |
|
1237 | - } |
|
1238 | - // ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events) |
|
1239 | - if ( |
|
1240 | - ! $this->is_line_item() && ! $this->is_sub_line_item() && ! $this->is_cancellation() |
|
1241 | - ) { |
|
1242 | - if ($this->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_EVENT) { |
|
1243 | - $this->set_quantity(1); |
|
1244 | - } |
|
1245 | - if (! $this->is_percent()) { |
|
1246 | - $this->set_unit_price($total); |
|
1247 | - } |
|
1248 | - } |
|
1249 | - // we don't want to bother saving grand totals, because that needs to factor in taxes anyways |
|
1250 | - // so it ought to be |
|
1251 | - if (! $this->is_total()) { |
|
1252 | - $this->set_total($total); |
|
1253 | - // if not a percent line item, make sure we keep the unit price in sync |
|
1254 | - if ( |
|
1255 | - $has_children |
|
1256 | - && $this->is_line_item() |
|
1257 | - && ! $this->is_percent() |
|
1258 | - ) { |
|
1259 | - if ($this->quantity() === 0) { |
|
1260 | - $new_unit_price = 0; |
|
1261 | - } else { |
|
1262 | - $new_unit_price = $this->total() / $this->quantity(); |
|
1263 | - } |
|
1264 | - $this->set_unit_price($new_unit_price); |
|
1265 | - } |
|
1266 | - $this->maybe_save(); |
|
1267 | - } |
|
1268 | - return $total; |
|
1269 | - } |
|
1270 | - |
|
1271 | - |
|
1272 | - /** |
|
1273 | - * Calculates the pretax total when this line item is a subtotal or total line item. |
|
1274 | - * Basically does a sum-then-round approach (ie, any percent line item that are children |
|
1275 | - * will calculate their total based on the un-rounded total we're working with so far, and |
|
1276 | - * THEN round the result; instead of rounding as we go like with sub-line-items) |
|
1277 | - * |
|
1278 | - * @param float $calculated_total_so_far |
|
1279 | - * @param EE_Line_Item[] $my_children |
|
1280 | - * @return float |
|
1281 | - * @throws EE_Error |
|
1282 | - * @throws InvalidArgumentException |
|
1283 | - * @throws InvalidDataTypeException |
|
1284 | - * @throws InvalidInterfaceException |
|
1285 | - * @throws ReflectionException |
|
1286 | - */ |
|
1287 | - protected function _recalculate_pretax_total_for_subtotal($calculated_total_so_far, $my_children = null) |
|
1288 | - { |
|
1289 | - if ($my_children === null) { |
|
1290 | - $my_children = $this->children(); |
|
1291 | - } |
|
1292 | - $subtotal_quantity = 0; |
|
1293 | - // get the total of all its children |
|
1294 | - foreach ($my_children as $child_line_item) { |
|
1295 | - if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) { |
|
1296 | - // percentage line items are based on total so far |
|
1297 | - if ($child_line_item->is_percent()) { |
|
1298 | - // round as we go so that the line items add up ok |
|
1299 | - $percent_total = round( |
|
1300 | - $calculated_total_so_far * $child_line_item->percent() / 100, |
|
1301 | - EE_Registry::instance()->CFG->currency->dec_plc |
|
1302 | - ); |
|
1303 | - $child_line_item->set_total($percent_total); |
|
1304 | - // so far all percent line items should have a quantity of 1 |
|
1305 | - // (ie, no double percent discounts. Although that might be requested someday) |
|
1306 | - $child_line_item->set_quantity(1); |
|
1307 | - $child_line_item->maybe_save(); |
|
1308 | - $calculated_total_so_far += $percent_total; |
|
1309 | - } else { |
|
1310 | - // verify flat sub-line-item quantities match their parent |
|
1311 | - if ($child_line_item->is_sub_line_item()) { |
|
1312 | - $child_line_item->set_quantity($this->quantity()); |
|
1313 | - } |
|
1314 | - $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
1315 | - $subtotal_quantity += $child_line_item->quantity(); |
|
1316 | - } |
|
1317 | - } |
|
1318 | - } |
|
1319 | - if ($this->is_sub_total()) { |
|
1320 | - // no negative totals plz |
|
1321 | - $calculated_total_so_far = max($calculated_total_so_far, 0); |
|
1322 | - $subtotal_quantity = $subtotal_quantity > 0 ? 1 : 0; |
|
1323 | - $this->set_quantity($subtotal_quantity); |
|
1324 | - $this->maybe_save(); |
|
1325 | - } |
|
1326 | - return $calculated_total_so_far; |
|
1327 | - } |
|
1328 | - |
|
1329 | - |
|
1330 | - /** |
|
1331 | - * Calculates the pretax total for a normal line item, in a round-then-sum approach |
|
1332 | - * (where each sub-line-item is applied to the base price for the line item |
|
1333 | - * and the result is immediately rounded, rather than summing all the sub-line-items |
|
1334 | - * then rounding, like we do when recalculating pretax totals on totals and subtotals). |
|
1335 | - * |
|
1336 | - * @param float $calculated_total_so_far |
|
1337 | - * @param EE_Line_Item[] $my_children |
|
1338 | - * @return float |
|
1339 | - * @throws EE_Error |
|
1340 | - * @throws InvalidArgumentException |
|
1341 | - * @throws InvalidDataTypeException |
|
1342 | - * @throws InvalidInterfaceException |
|
1343 | - * @throws ReflectionException |
|
1344 | - */ |
|
1345 | - protected function _recalculate_pretax_total_for_line_item($calculated_total_so_far, $my_children = null) |
|
1346 | - { |
|
1347 | - if ($my_children === null) { |
|
1348 | - $my_children = $this->children(); |
|
1349 | - } |
|
1350 | - // we need to keep track of the running total for a single item, |
|
1351 | - // because we need to round as we go |
|
1352 | - $unit_price_for_total = 0; |
|
1353 | - $quantity_for_total = 1; |
|
1354 | - // get the total of all its children |
|
1355 | - foreach ($my_children as $child_line_item) { |
|
1356 | - if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) { |
|
1357 | - if ($child_line_item->is_percent()) { |
|
1358 | - // it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity |
|
1359 | - // not total multiplied by percent, because that ignores rounding along-the-way |
|
1360 | - $percent_unit_price = round( |
|
1361 | - $unit_price_for_total * $child_line_item->percent() / 100, |
|
1362 | - EE_Registry::instance()->CFG->currency->dec_plc |
|
1363 | - ); |
|
1364 | - $percent_total = $percent_unit_price * $quantity_for_total; |
|
1365 | - $child_line_item->set_total($percent_total); |
|
1366 | - // so far all percent line items should have a quantity of 1 |
|
1367 | - // (ie, no double percent discounts. Although that might be requested someday) |
|
1368 | - $child_line_item->set_quantity(1); |
|
1369 | - $child_line_item->maybe_save(); |
|
1370 | - $calculated_total_so_far += $percent_total; |
|
1371 | - $unit_price_for_total += $percent_unit_price; |
|
1372 | - } else { |
|
1373 | - // verify flat sub-line-item quantities match their parent |
|
1374 | - if ($child_line_item->is_sub_line_item()) { |
|
1375 | - $child_line_item->set_quantity($this->quantity()); |
|
1376 | - } |
|
1377 | - $quantity_for_total = $child_line_item->quantity(); |
|
1378 | - $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
1379 | - $unit_price_for_total += $child_line_item->unit_price(); |
|
1380 | - } |
|
1381 | - } |
|
1382 | - } |
|
1383 | - return $calculated_total_so_far; |
|
1384 | - } |
|
1385 | - |
|
1386 | - |
|
1387 | - /** |
|
1388 | - * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets |
|
1389 | - * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items |
|
1390 | - * and tax sub-total if already in the DB |
|
1391 | - * |
|
1392 | - * @return float |
|
1393 | - * @throws EE_Error |
|
1394 | - * @throws InvalidArgumentException |
|
1395 | - * @throws InvalidDataTypeException |
|
1396 | - * @throws InvalidInterfaceException |
|
1397 | - * @throws ReflectionException |
|
1398 | - */ |
|
1399 | - public function recalculate_taxes_and_tax_total() |
|
1400 | - { |
|
1401 | - // get all taxes |
|
1402 | - $taxes = $this->tax_descendants(); |
|
1403 | - // calculate the pretax total |
|
1404 | - $taxable_total = $this->taxable_total(); |
|
1405 | - $tax_total = 0; |
|
1406 | - foreach ($taxes as $tax) { |
|
1407 | - $total_on_this_tax = $taxable_total * $tax->percent() / 100; |
|
1408 | - // remember the total on this line item |
|
1409 | - $tax->set_total($total_on_this_tax); |
|
1410 | - $tax->maybe_save(); |
|
1411 | - $tax_total += $tax->total(); |
|
1412 | - } |
|
1413 | - $this->_recalculate_tax_sub_total(); |
|
1414 | - return $tax_total; |
|
1415 | - } |
|
1416 | - |
|
1417 | - |
|
1418 | - /** |
|
1419 | - * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated |
|
1420 | - * |
|
1421 | - * @return void |
|
1422 | - * @throws EE_Error |
|
1423 | - * @throws InvalidArgumentException |
|
1424 | - * @throws InvalidDataTypeException |
|
1425 | - * @throws InvalidInterfaceException |
|
1426 | - * @throws ReflectionException |
|
1427 | - */ |
|
1428 | - private function _recalculate_tax_sub_total() |
|
1429 | - { |
|
1430 | - if ($this->is_tax_sub_total()) { |
|
1431 | - $total = 0; |
|
1432 | - $total_percent = 0; |
|
1433 | - // simply loop through all its children (which should be taxes) and sum their total |
|
1434 | - foreach ($this->children() as $child_tax) { |
|
1435 | - if ($child_tax instanceof EE_Line_Item) { |
|
1436 | - $total += $child_tax->total(); |
|
1437 | - $total_percent += $child_tax->percent(); |
|
1438 | - } |
|
1439 | - } |
|
1440 | - $this->set_total($total); |
|
1441 | - $this->set_percent($total_percent); |
|
1442 | - $this->maybe_save(); |
|
1443 | - } elseif ($this->is_total()) { |
|
1444 | - foreach ($this->children() as $maybe_tax_subtotal) { |
|
1445 | - if ($maybe_tax_subtotal instanceof EE_Line_Item) { |
|
1446 | - $maybe_tax_subtotal->_recalculate_tax_sub_total(); |
|
1447 | - } |
|
1448 | - } |
|
1449 | - } |
|
1450 | - } |
|
1451 | - |
|
1452 | - |
|
1453 | - /** |
|
1454 | - * Gets the total tax on this line item. Assumes taxes have already been calculated using |
|
1455 | - * recalculate_taxes_and_total |
|
1456 | - * |
|
1457 | - * @return float |
|
1458 | - * @throws EE_Error |
|
1459 | - * @throws InvalidArgumentException |
|
1460 | - * @throws InvalidDataTypeException |
|
1461 | - * @throws InvalidInterfaceException |
|
1462 | - * @throws ReflectionException |
|
1463 | - */ |
|
1464 | - public function get_total_tax() |
|
1465 | - { |
|
1466 | - $this->_recalculate_tax_sub_total(); |
|
1467 | - $total = 0; |
|
1468 | - foreach ($this->tax_descendants() as $tax_line_item) { |
|
1469 | - if ($tax_line_item instanceof EE_Line_Item) { |
|
1470 | - $total += $tax_line_item->total(); |
|
1471 | - } |
|
1472 | - } |
|
1473 | - return $total; |
|
1474 | - } |
|
1475 | - |
|
1476 | - |
|
1477 | - /** |
|
1478 | - * Gets the total for all the items purchased only |
|
1479 | - * |
|
1480 | - * @return float |
|
1481 | - * @throws EE_Error |
|
1482 | - * @throws InvalidArgumentException |
|
1483 | - * @throws InvalidDataTypeException |
|
1484 | - * @throws InvalidInterfaceException |
|
1485 | - * @throws ReflectionException |
|
1486 | - */ |
|
1487 | - public function get_items_total() |
|
1488 | - { |
|
1489 | - // by default, let's make sure we're consistent with the existing line item |
|
1490 | - if ($this->is_total()) { |
|
1491 | - $pretax_subtotal_li = EEH_Line_Item::get_pre_tax_subtotal($this); |
|
1492 | - if ($pretax_subtotal_li instanceof EE_Line_Item) { |
|
1493 | - return $pretax_subtotal_li->total(); |
|
1494 | - } |
|
1495 | - } |
|
1496 | - $total = 0; |
|
1497 | - foreach ($this->get_items() as $item) { |
|
1498 | - if ($item instanceof EE_Line_Item) { |
|
1499 | - $total += $item->total(); |
|
1500 | - } |
|
1501 | - } |
|
1502 | - return $total; |
|
1503 | - } |
|
1504 | - |
|
1505 | - |
|
1506 | - /** |
|
1507 | - * Gets all the descendants (ie, children or children of children etc) that |
|
1508 | - * are of the type 'tax' |
|
1509 | - * |
|
1510 | - * @return EE_Line_Item[] |
|
1511 | - * @throws EE_Error |
|
1512 | - */ |
|
1513 | - public function tax_descendants() |
|
1514 | - { |
|
1515 | - return EEH_Line_Item::get_tax_descendants($this); |
|
1516 | - } |
|
1517 | - |
|
1518 | - |
|
1519 | - /** |
|
1520 | - * Gets all the real items purchased which are children of this item |
|
1521 | - * |
|
1522 | - * @return EE_Line_Item[] |
|
1523 | - * @throws EE_Error |
|
1524 | - */ |
|
1525 | - public function get_items() |
|
1526 | - { |
|
1527 | - return EEH_Line_Item::get_line_item_descendants($this); |
|
1528 | - } |
|
1529 | - |
|
1530 | - |
|
1531 | - /** |
|
1532 | - * Returns the amount taxable among this line item's children (or if it has no children, |
|
1533 | - * how much of it is taxable). Does not recalculate totals or subtotals. |
|
1534 | - * If the taxable total is negative, (eg, if none of the tickets were taxable, |
|
1535 | - * but there is a "Taxable" discount), returns 0. |
|
1536 | - * |
|
1537 | - * @return float |
|
1538 | - * @throws EE_Error |
|
1539 | - * @throws InvalidArgumentException |
|
1540 | - * @throws InvalidDataTypeException |
|
1541 | - * @throws InvalidInterfaceException |
|
1542 | - * @throws ReflectionException |
|
1543 | - */ |
|
1544 | - public function taxable_total() |
|
1545 | - { |
|
1546 | - $total = 0; |
|
1547 | - if ($this->children()) { |
|
1548 | - foreach ($this->children() as $child_line_item) { |
|
1549 | - if ($child_line_item->type() === EEM_Line_Item::type_line_item && $child_line_item->is_taxable()) { |
|
1550 | - // if it's a percent item, only take into account the percent |
|
1551 | - // that's taxable too (the taxable total so far) |
|
1552 | - if ($child_line_item->is_percent()) { |
|
1553 | - $total += ($total * $child_line_item->percent() / 100); |
|
1554 | - } else { |
|
1555 | - $total += $child_line_item->total(); |
|
1556 | - } |
|
1557 | - } elseif ($child_line_item->type() === EEM_Line_Item::type_sub_total) { |
|
1558 | - $total += $child_line_item->taxable_total(); |
|
1559 | - } |
|
1560 | - } |
|
1561 | - } |
|
1562 | - return max($total, 0); |
|
1563 | - } |
|
1564 | - |
|
1565 | - |
|
1566 | - /** |
|
1567 | - * Gets the transaction for this line item |
|
1568 | - * |
|
1569 | - * @return EE_Base_Class|EE_Transaction |
|
1570 | - * @throws EE_Error |
|
1571 | - * @throws InvalidArgumentException |
|
1572 | - * @throws InvalidDataTypeException |
|
1573 | - * @throws InvalidInterfaceException |
|
1574 | - * @throws ReflectionException |
|
1575 | - */ |
|
1576 | - public function transaction() |
|
1577 | - { |
|
1578 | - return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TRANSACTION); |
|
1579 | - } |
|
1580 | - |
|
1581 | - |
|
1582 | - /** |
|
1583 | - * Saves this line item to the DB, and recursively saves its descendants. |
|
1584 | - * Because there currently is no proper parent-child relation on the model, |
|
1585 | - * save_this_and_cached() will NOT save the descendants. |
|
1586 | - * Also sets the transaction on this line item and all its descendants before saving |
|
1587 | - * |
|
1588 | - * @param int $txn_id if none is provided, assumes $this->TXN_ID() |
|
1589 | - * @return int count of items saved |
|
1590 | - * @throws EE_Error |
|
1591 | - * @throws InvalidArgumentException |
|
1592 | - * @throws InvalidDataTypeException |
|
1593 | - * @throws InvalidInterfaceException |
|
1594 | - * @throws ReflectionException |
|
1595 | - */ |
|
1596 | - public function save_this_and_descendants_to_txn($txn_id = null) |
|
1597 | - { |
|
1598 | - $count = 0; |
|
1599 | - if (! $txn_id) { |
|
1600 | - $txn_id = $this->TXN_ID(); |
|
1601 | - } |
|
1602 | - $this->set_TXN_ID($txn_id); |
|
1603 | - $children = $this->children(); |
|
1604 | - $count += $this->save() |
|
1605 | - ? 1 |
|
1606 | - : 0; |
|
1607 | - foreach ($children as $child_line_item) { |
|
1608 | - if ($child_line_item instanceof EE_Line_Item) { |
|
1609 | - $child_line_item->set_parent_ID($this->ID()); |
|
1610 | - $count += $child_line_item->save_this_and_descendants_to_txn($txn_id); |
|
1611 | - } |
|
1612 | - } |
|
1613 | - return $count; |
|
1614 | - } |
|
1615 | - |
|
1616 | - |
|
1617 | - /** |
|
1618 | - * Saves this line item to the DB, and recursively saves its descendants. |
|
1619 | - * |
|
1620 | - * @return int count of items saved |
|
1621 | - * @throws EE_Error |
|
1622 | - * @throws InvalidArgumentException |
|
1623 | - * @throws InvalidDataTypeException |
|
1624 | - * @throws InvalidInterfaceException |
|
1625 | - * @throws ReflectionException |
|
1626 | - */ |
|
1627 | - public function save_this_and_descendants() |
|
1628 | - { |
|
1629 | - $count = 0; |
|
1630 | - $children = $this->children(); |
|
1631 | - $count += $this->save() |
|
1632 | - ? 1 |
|
1633 | - : 0; |
|
1634 | - foreach ($children as $child_line_item) { |
|
1635 | - if ($child_line_item instanceof EE_Line_Item) { |
|
1636 | - $child_line_item->set_parent_ID($this->ID()); |
|
1637 | - $count += $child_line_item->save_this_and_descendants(); |
|
1638 | - } |
|
1639 | - } |
|
1640 | - return $count; |
|
1641 | - } |
|
1642 | - |
|
1643 | - |
|
1644 | - /** |
|
1645 | - * returns the cancellation line item if this item was cancelled |
|
1646 | - * |
|
1647 | - * @return EE_Line_Item[] |
|
1648 | - * @throws InvalidArgumentException |
|
1649 | - * @throws InvalidInterfaceException |
|
1650 | - * @throws InvalidDataTypeException |
|
1651 | - * @throws ReflectionException |
|
1652 | - * @throws EE_Error |
|
1653 | - */ |
|
1654 | - public function get_cancellations() |
|
1655 | - { |
|
1656 | - EE_Registry::instance()->load_helper('Line_Item'); |
|
1657 | - return EEH_Line_Item::get_descendants_of_type($this, EEM_Line_Item::type_cancellation); |
|
1658 | - } |
|
1659 | - |
|
1660 | - |
|
1661 | - /** |
|
1662 | - * If this item has an ID, then this saves it again to update the db |
|
1663 | - * |
|
1664 | - * @return int count of items saved |
|
1665 | - * @throws EE_Error |
|
1666 | - * @throws InvalidArgumentException |
|
1667 | - * @throws InvalidDataTypeException |
|
1668 | - * @throws InvalidInterfaceException |
|
1669 | - * @throws ReflectionException |
|
1670 | - */ |
|
1671 | - public function maybe_save() |
|
1672 | - { |
|
1673 | - if ($this->ID()) { |
|
1674 | - return $this->save(); |
|
1675 | - } |
|
1676 | - return false; |
|
1677 | - } |
|
1678 | - |
|
1679 | - |
|
1680 | - /** |
|
1681 | - * clears the cached children and parent from the line item |
|
1682 | - * |
|
1683 | - * @return void |
|
1684 | - */ |
|
1685 | - public function clear_related_line_item_cache() |
|
1686 | - { |
|
1687 | - $this->_children = array(); |
|
1688 | - $this->_parent = null; |
|
1689 | - } |
|
1690 | - |
|
1691 | - |
|
1692 | - /** |
|
1693 | - * @param bool $raw |
|
1694 | - * @return int |
|
1695 | - * @throws EE_Error |
|
1696 | - * @throws InvalidArgumentException |
|
1697 | - * @throws InvalidDataTypeException |
|
1698 | - * @throws InvalidInterfaceException |
|
1699 | - * @throws ReflectionException |
|
1700 | - */ |
|
1701 | - public function timestamp($raw = false) |
|
1702 | - { |
|
1703 | - return $raw |
|
1704 | - ? $this->get_raw('LIN_timestamp') |
|
1705 | - : $this->get('LIN_timestamp'); |
|
1706 | - } |
|
1707 | - |
|
1708 | - |
|
1709 | - |
|
1710 | - |
|
1711 | - /************************* DEPRECATED *************************/ |
|
1712 | - /** |
|
1713 | - * @deprecated 4.6.0 |
|
1714 | - * @param string $type one of the constants on EEM_Line_Item |
|
1715 | - * @return EE_Line_Item[] |
|
1716 | - * @throws EE_Error |
|
1717 | - */ |
|
1718 | - protected function _get_descendants_of_type($type) |
|
1719 | - { |
|
1720 | - EE_Error::doing_it_wrong( |
|
1721 | - 'EE_Line_Item::_get_descendants_of_type()', |
|
1722 | - sprintf( |
|
1723 | - esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
1724 | - 'EEH_Line_Item::get_descendants_of_type()' |
|
1725 | - ), |
|
1726 | - '4.6.0' |
|
1727 | - ); |
|
1728 | - return EEH_Line_Item::get_descendants_of_type($this, $type); |
|
1729 | - } |
|
1730 | - |
|
1731 | - |
|
1732 | - /** |
|
1733 | - * @deprecated 4.6.0 |
|
1734 | - * @param string $type like one of the EEM_Line_Item::type_* |
|
1735 | - * @return EE_Line_Item |
|
1736 | - * @throws EE_Error |
|
1737 | - * @throws InvalidArgumentException |
|
1738 | - * @throws InvalidDataTypeException |
|
1739 | - * @throws InvalidInterfaceException |
|
1740 | - * @throws ReflectionException |
|
1741 | - */ |
|
1742 | - public function get_nearest_descendant_of_type($type) |
|
1743 | - { |
|
1744 | - EE_Error::doing_it_wrong( |
|
1745 | - 'EE_Line_Item::get_nearest_descendant_of_type()', |
|
1746 | - sprintf( |
|
1747 | - esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
1748 | - 'EEH_Line_Item::get_nearest_descendant_of_type()' |
|
1749 | - ), |
|
1750 | - '4.6.0' |
|
1751 | - ); |
|
1752 | - return EEH_Line_Item::get_nearest_descendant_of_type($this, $type); |
|
1753 | - } |
|
16 | + /** |
|
17 | + * for children line items (currently not a normal relation) |
|
18 | + * |
|
19 | + * @type EE_Line_Item[] |
|
20 | + */ |
|
21 | + protected $_children = array(); |
|
22 | + |
|
23 | + /** |
|
24 | + * for the parent line item |
|
25 | + * |
|
26 | + * @var EE_Line_Item |
|
27 | + */ |
|
28 | + protected $_parent; |
|
29 | + |
|
30 | + |
|
31 | + /** |
|
32 | + * @param array $props_n_values incoming values |
|
33 | + * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
34 | + * used.) |
|
35 | + * @param array $date_formats incoming date_formats in an array where the first value is the |
|
36 | + * date_format and the second value is the time format |
|
37 | + * @return EE_Line_Item |
|
38 | + * @throws EE_Error |
|
39 | + * @throws InvalidArgumentException |
|
40 | + * @throws InvalidDataTypeException |
|
41 | + * @throws InvalidInterfaceException |
|
42 | + * @throws ReflectionException |
|
43 | + */ |
|
44 | + public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) |
|
45 | + { |
|
46 | + $has_object = parent::_check_for_object( |
|
47 | + $props_n_values, |
|
48 | + __CLASS__, |
|
49 | + $timezone, |
|
50 | + $date_formats |
|
51 | + ); |
|
52 | + return $has_object |
|
53 | + ? $has_object |
|
54 | + : new self($props_n_values, false, $timezone); |
|
55 | + } |
|
56 | + |
|
57 | + |
|
58 | + /** |
|
59 | + * @param array $props_n_values incoming values from the database |
|
60 | + * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
61 | + * the website will be used. |
|
62 | + * @return EE_Line_Item |
|
63 | + * @throws EE_Error |
|
64 | + * @throws InvalidArgumentException |
|
65 | + * @throws InvalidDataTypeException |
|
66 | + * @throws InvalidInterfaceException |
|
67 | + * @throws ReflectionException |
|
68 | + */ |
|
69 | + public static function new_instance_from_db($props_n_values = array(), $timezone = null) |
|
70 | + { |
|
71 | + return new self($props_n_values, true, $timezone); |
|
72 | + } |
|
73 | + |
|
74 | + |
|
75 | + /** |
|
76 | + * Adds some defaults if they're not specified |
|
77 | + * |
|
78 | + * @param array $fieldValues |
|
79 | + * @param bool $bydb |
|
80 | + * @param string $timezone |
|
81 | + * @throws EE_Error |
|
82 | + * @throws InvalidArgumentException |
|
83 | + * @throws InvalidDataTypeException |
|
84 | + * @throws InvalidInterfaceException |
|
85 | + * @throws ReflectionException |
|
86 | + */ |
|
87 | + protected function __construct($fieldValues = array(), $bydb = false, $timezone = '') |
|
88 | + { |
|
89 | + parent::__construct($fieldValues, $bydb, $timezone); |
|
90 | + if (! $this->get('LIN_code')) { |
|
91 | + $this->set_code($this->generate_code()); |
|
92 | + } |
|
93 | + } |
|
94 | + |
|
95 | + |
|
96 | + /** |
|
97 | + * Gets ID |
|
98 | + * |
|
99 | + * @return int |
|
100 | + * @throws EE_Error |
|
101 | + * @throws InvalidArgumentException |
|
102 | + * @throws InvalidDataTypeException |
|
103 | + * @throws InvalidInterfaceException |
|
104 | + * @throws ReflectionException |
|
105 | + */ |
|
106 | + public function ID() |
|
107 | + { |
|
108 | + return $this->get('LIN_ID'); |
|
109 | + } |
|
110 | + |
|
111 | + |
|
112 | + /** |
|
113 | + * Gets TXN_ID |
|
114 | + * |
|
115 | + * @return int |
|
116 | + * @throws EE_Error |
|
117 | + * @throws InvalidArgumentException |
|
118 | + * @throws InvalidDataTypeException |
|
119 | + * @throws InvalidInterfaceException |
|
120 | + * @throws ReflectionException |
|
121 | + */ |
|
122 | + public function TXN_ID() |
|
123 | + { |
|
124 | + return $this->get('TXN_ID'); |
|
125 | + } |
|
126 | + |
|
127 | + |
|
128 | + /** |
|
129 | + * Sets TXN_ID |
|
130 | + * |
|
131 | + * @param int $TXN_ID |
|
132 | + * @throws EE_Error |
|
133 | + * @throws InvalidArgumentException |
|
134 | + * @throws InvalidDataTypeException |
|
135 | + * @throws InvalidInterfaceException |
|
136 | + * @throws ReflectionException |
|
137 | + */ |
|
138 | + public function set_TXN_ID($TXN_ID) |
|
139 | + { |
|
140 | + $this->set('TXN_ID', $TXN_ID); |
|
141 | + } |
|
142 | + |
|
143 | + |
|
144 | + /** |
|
145 | + * Gets name |
|
146 | + * |
|
147 | + * @return string |
|
148 | + * @throws EE_Error |
|
149 | + * @throws InvalidArgumentException |
|
150 | + * @throws InvalidDataTypeException |
|
151 | + * @throws InvalidInterfaceException |
|
152 | + * @throws ReflectionException |
|
153 | + */ |
|
154 | + public function name() |
|
155 | + { |
|
156 | + $name = $this->get('LIN_name'); |
|
157 | + if (! $name) { |
|
158 | + $name = ucwords(str_replace('-', ' ', $this->type())); |
|
159 | + } |
|
160 | + return $name; |
|
161 | + } |
|
162 | + |
|
163 | + |
|
164 | + /** |
|
165 | + * Sets name |
|
166 | + * |
|
167 | + * @param string $name |
|
168 | + * @throws EE_Error |
|
169 | + * @throws InvalidArgumentException |
|
170 | + * @throws InvalidDataTypeException |
|
171 | + * @throws InvalidInterfaceException |
|
172 | + * @throws ReflectionException |
|
173 | + */ |
|
174 | + public function set_name($name) |
|
175 | + { |
|
176 | + $this->set('LIN_name', $name); |
|
177 | + } |
|
178 | + |
|
179 | + |
|
180 | + /** |
|
181 | + * Gets desc |
|
182 | + * |
|
183 | + * @return string |
|
184 | + * @throws EE_Error |
|
185 | + * @throws InvalidArgumentException |
|
186 | + * @throws InvalidDataTypeException |
|
187 | + * @throws InvalidInterfaceException |
|
188 | + * @throws ReflectionException |
|
189 | + */ |
|
190 | + public function desc() |
|
191 | + { |
|
192 | + return $this->get('LIN_desc'); |
|
193 | + } |
|
194 | + |
|
195 | + |
|
196 | + /** |
|
197 | + * Sets desc |
|
198 | + * |
|
199 | + * @param string $desc |
|
200 | + * @throws EE_Error |
|
201 | + * @throws InvalidArgumentException |
|
202 | + * @throws InvalidDataTypeException |
|
203 | + * @throws InvalidInterfaceException |
|
204 | + * @throws ReflectionException |
|
205 | + */ |
|
206 | + public function set_desc($desc) |
|
207 | + { |
|
208 | + $this->set('LIN_desc', $desc); |
|
209 | + } |
|
210 | + |
|
211 | + |
|
212 | + /** |
|
213 | + * Gets quantity |
|
214 | + * |
|
215 | + * @return int |
|
216 | + * @throws EE_Error |
|
217 | + * @throws InvalidArgumentException |
|
218 | + * @throws InvalidDataTypeException |
|
219 | + * @throws InvalidInterfaceException |
|
220 | + * @throws ReflectionException |
|
221 | + */ |
|
222 | + public function quantity() |
|
223 | + { |
|
224 | + return $this->get('LIN_quantity'); |
|
225 | + } |
|
226 | + |
|
227 | + |
|
228 | + /** |
|
229 | + * Sets quantity |
|
230 | + * |
|
231 | + * @param int $quantity |
|
232 | + * @throws EE_Error |
|
233 | + * @throws InvalidArgumentException |
|
234 | + * @throws InvalidDataTypeException |
|
235 | + * @throws InvalidInterfaceException |
|
236 | + * @throws ReflectionException |
|
237 | + */ |
|
238 | + public function set_quantity($quantity) |
|
239 | + { |
|
240 | + $this->set('LIN_quantity', max($quantity, 0)); |
|
241 | + } |
|
242 | + |
|
243 | + |
|
244 | + /** |
|
245 | + * Gets item_id |
|
246 | + * |
|
247 | + * @return string |
|
248 | + * @throws EE_Error |
|
249 | + * @throws InvalidArgumentException |
|
250 | + * @throws InvalidDataTypeException |
|
251 | + * @throws InvalidInterfaceException |
|
252 | + * @throws ReflectionException |
|
253 | + */ |
|
254 | + public function OBJ_ID() |
|
255 | + { |
|
256 | + return $this->get('OBJ_ID'); |
|
257 | + } |
|
258 | + |
|
259 | + |
|
260 | + /** |
|
261 | + * Sets item_id |
|
262 | + * |
|
263 | + * @param string $item_id |
|
264 | + * @throws EE_Error |
|
265 | + * @throws InvalidArgumentException |
|
266 | + * @throws InvalidDataTypeException |
|
267 | + * @throws InvalidInterfaceException |
|
268 | + * @throws ReflectionException |
|
269 | + */ |
|
270 | + public function set_OBJ_ID($item_id) |
|
271 | + { |
|
272 | + $this->set('OBJ_ID', $item_id); |
|
273 | + } |
|
274 | + |
|
275 | + |
|
276 | + /** |
|
277 | + * Gets item_type |
|
278 | + * |
|
279 | + * @return string |
|
280 | + * @throws EE_Error |
|
281 | + * @throws InvalidArgumentException |
|
282 | + * @throws InvalidDataTypeException |
|
283 | + * @throws InvalidInterfaceException |
|
284 | + * @throws ReflectionException |
|
285 | + */ |
|
286 | + public function OBJ_type() |
|
287 | + { |
|
288 | + return $this->get('OBJ_type'); |
|
289 | + } |
|
290 | + |
|
291 | + |
|
292 | + /** |
|
293 | + * Gets item_type |
|
294 | + * |
|
295 | + * @return string |
|
296 | + * @throws EE_Error |
|
297 | + * @throws InvalidArgumentException |
|
298 | + * @throws InvalidDataTypeException |
|
299 | + * @throws InvalidInterfaceException |
|
300 | + * @throws ReflectionException |
|
301 | + */ |
|
302 | + public function OBJ_type_i18n() |
|
303 | + { |
|
304 | + $obj_type = $this->OBJ_type(); |
|
305 | + switch ($obj_type) { |
|
306 | + case EEM_Line_Item::OBJ_TYPE_EVENT: |
|
307 | + $obj_type = esc_html__('Event', 'event_espresso'); |
|
308 | + break; |
|
309 | + case EEM_Line_Item::OBJ_TYPE_PRICE: |
|
310 | + $obj_type = esc_html__('Price', 'event_espresso'); |
|
311 | + break; |
|
312 | + case EEM_Line_Item::OBJ_TYPE_PROMOTION: |
|
313 | + $obj_type = esc_html__('Promotion', 'event_espresso'); |
|
314 | + break; |
|
315 | + case EEM_Line_Item::OBJ_TYPE_TICKET: |
|
316 | + $obj_type = esc_html__('Ticket', 'event_espresso'); |
|
317 | + break; |
|
318 | + case EEM_Line_Item::OBJ_TYPE_TRANSACTION: |
|
319 | + $obj_type = esc_html__('Transaction', 'event_espresso'); |
|
320 | + break; |
|
321 | + } |
|
322 | + return apply_filters('FHEE__EE_Line_Item__OBJ_type_i18n', $obj_type, $this); |
|
323 | + } |
|
324 | + |
|
325 | + |
|
326 | + /** |
|
327 | + * Sets item_type |
|
328 | + * |
|
329 | + * @param string $OBJ_type |
|
330 | + * @throws EE_Error |
|
331 | + * @throws InvalidArgumentException |
|
332 | + * @throws InvalidDataTypeException |
|
333 | + * @throws InvalidInterfaceException |
|
334 | + * @throws ReflectionException |
|
335 | + */ |
|
336 | + public function set_OBJ_type($OBJ_type) |
|
337 | + { |
|
338 | + $this->set('OBJ_type', $OBJ_type); |
|
339 | + } |
|
340 | + |
|
341 | + |
|
342 | + /** |
|
343 | + * Gets unit_price |
|
344 | + * |
|
345 | + * @return float |
|
346 | + * @throws EE_Error |
|
347 | + * @throws InvalidArgumentException |
|
348 | + * @throws InvalidDataTypeException |
|
349 | + * @throws InvalidInterfaceException |
|
350 | + * @throws ReflectionException |
|
351 | + */ |
|
352 | + public function unit_price() |
|
353 | + { |
|
354 | + return $this->get('LIN_unit_price'); |
|
355 | + } |
|
356 | + |
|
357 | + |
|
358 | + /** |
|
359 | + * Sets unit_price |
|
360 | + * |
|
361 | + * @param float $unit_price |
|
362 | + * @throws EE_Error |
|
363 | + * @throws InvalidArgumentException |
|
364 | + * @throws InvalidDataTypeException |
|
365 | + * @throws InvalidInterfaceException |
|
366 | + * @throws ReflectionException |
|
367 | + */ |
|
368 | + public function set_unit_price($unit_price) |
|
369 | + { |
|
370 | + $this->set('LIN_unit_price', $unit_price); |
|
371 | + } |
|
372 | + |
|
373 | + |
|
374 | + /** |
|
375 | + * Checks if this item is a percentage modifier or not |
|
376 | + * |
|
377 | + * @return boolean |
|
378 | + * @throws EE_Error |
|
379 | + * @throws InvalidArgumentException |
|
380 | + * @throws InvalidDataTypeException |
|
381 | + * @throws InvalidInterfaceException |
|
382 | + * @throws ReflectionException |
|
383 | + */ |
|
384 | + public function is_percent() |
|
385 | + { |
|
386 | + if ($this->is_tax_sub_total()) { |
|
387 | + // tax subtotals HAVE a percent on them, that percentage only applies |
|
388 | + // to taxable items, so its' an exception. Treat it like a flat line item |
|
389 | + return false; |
|
390 | + } |
|
391 | + $unit_price = abs($this->get('LIN_unit_price')); |
|
392 | + $percent = abs($this->get('LIN_percent')); |
|
393 | + if ($unit_price < .001 && $percent) { |
|
394 | + return true; |
|
395 | + } |
|
396 | + if ($unit_price >= .001 && ! $percent) { |
|
397 | + return false; |
|
398 | + } |
|
399 | + if ($unit_price >= .001 && $percent) { |
|
400 | + throw new EE_Error( |
|
401 | + sprintf( |
|
402 | + esc_html__( |
|
403 | + 'A Line Item can not have a unit price of (%s) AND a percent (%s)!', |
|
404 | + 'event_espresso' |
|
405 | + ), |
|
406 | + $unit_price, |
|
407 | + $percent |
|
408 | + ) |
|
409 | + ); |
|
410 | + } |
|
411 | + // if they're both 0, assume its not a percent item |
|
412 | + return false; |
|
413 | + } |
|
414 | + |
|
415 | + |
|
416 | + /** |
|
417 | + * Gets percent (between 100-.001) |
|
418 | + * |
|
419 | + * @return float |
|
420 | + * @throws EE_Error |
|
421 | + * @throws InvalidArgumentException |
|
422 | + * @throws InvalidDataTypeException |
|
423 | + * @throws InvalidInterfaceException |
|
424 | + * @throws ReflectionException |
|
425 | + */ |
|
426 | + public function percent() |
|
427 | + { |
|
428 | + return $this->get('LIN_percent'); |
|
429 | + } |
|
430 | + |
|
431 | + |
|
432 | + /** |
|
433 | + * Sets percent (between 100-0.01) |
|
434 | + * |
|
435 | + * @param float $percent |
|
436 | + * @throws EE_Error |
|
437 | + * @throws InvalidArgumentException |
|
438 | + * @throws InvalidDataTypeException |
|
439 | + * @throws InvalidInterfaceException |
|
440 | + * @throws ReflectionException |
|
441 | + */ |
|
442 | + public function set_percent($percent) |
|
443 | + { |
|
444 | + $this->set('LIN_percent', $percent); |
|
445 | + } |
|
446 | + |
|
447 | + |
|
448 | + /** |
|
449 | + * Gets total |
|
450 | + * |
|
451 | + * @return float |
|
452 | + * @throws EE_Error |
|
453 | + * @throws InvalidArgumentException |
|
454 | + * @throws InvalidDataTypeException |
|
455 | + * @throws InvalidInterfaceException |
|
456 | + * @throws ReflectionException |
|
457 | + */ |
|
458 | + public function total() |
|
459 | + { |
|
460 | + return $this->get('LIN_total'); |
|
461 | + } |
|
462 | + |
|
463 | + |
|
464 | + /** |
|
465 | + * Sets total |
|
466 | + * |
|
467 | + * @param float $total |
|
468 | + * @throws EE_Error |
|
469 | + * @throws InvalidArgumentException |
|
470 | + * @throws InvalidDataTypeException |
|
471 | + * @throws InvalidInterfaceException |
|
472 | + * @throws ReflectionException |
|
473 | + */ |
|
474 | + public function set_total($total) |
|
475 | + { |
|
476 | + $this->set('LIN_total', $total); |
|
477 | + } |
|
478 | + |
|
479 | + |
|
480 | + /** |
|
481 | + * Gets order |
|
482 | + * |
|
483 | + * @return int |
|
484 | + * @throws EE_Error |
|
485 | + * @throws InvalidArgumentException |
|
486 | + * @throws InvalidDataTypeException |
|
487 | + * @throws InvalidInterfaceException |
|
488 | + * @throws ReflectionException |
|
489 | + */ |
|
490 | + public function order() |
|
491 | + { |
|
492 | + return $this->get('LIN_order'); |
|
493 | + } |
|
494 | + |
|
495 | + |
|
496 | + /** |
|
497 | + * Sets order |
|
498 | + * |
|
499 | + * @param int $order |
|
500 | + * @throws EE_Error |
|
501 | + * @throws InvalidArgumentException |
|
502 | + * @throws InvalidDataTypeException |
|
503 | + * @throws InvalidInterfaceException |
|
504 | + * @throws ReflectionException |
|
505 | + */ |
|
506 | + public function set_order($order) |
|
507 | + { |
|
508 | + $this->set('LIN_order', $order); |
|
509 | + } |
|
510 | + |
|
511 | + |
|
512 | + /** |
|
513 | + * Gets parent |
|
514 | + * |
|
515 | + * @return int |
|
516 | + * @throws EE_Error |
|
517 | + * @throws InvalidArgumentException |
|
518 | + * @throws InvalidDataTypeException |
|
519 | + * @throws InvalidInterfaceException |
|
520 | + * @throws ReflectionException |
|
521 | + */ |
|
522 | + public function parent_ID() |
|
523 | + { |
|
524 | + return $this->get('LIN_parent'); |
|
525 | + } |
|
526 | + |
|
527 | + |
|
528 | + /** |
|
529 | + * Sets parent |
|
530 | + * |
|
531 | + * @param int $parent |
|
532 | + * @throws EE_Error |
|
533 | + * @throws InvalidArgumentException |
|
534 | + * @throws InvalidDataTypeException |
|
535 | + * @throws InvalidInterfaceException |
|
536 | + * @throws ReflectionException |
|
537 | + */ |
|
538 | + public function set_parent_ID($parent) |
|
539 | + { |
|
540 | + $this->set('LIN_parent', $parent); |
|
541 | + } |
|
542 | + |
|
543 | + |
|
544 | + /** |
|
545 | + * Gets type |
|
546 | + * |
|
547 | + * @return string |
|
548 | + * @throws EE_Error |
|
549 | + * @throws InvalidArgumentException |
|
550 | + * @throws InvalidDataTypeException |
|
551 | + * @throws InvalidInterfaceException |
|
552 | + * @throws ReflectionException |
|
553 | + */ |
|
554 | + public function type() |
|
555 | + { |
|
556 | + return $this->get('LIN_type'); |
|
557 | + } |
|
558 | + |
|
559 | + |
|
560 | + /** |
|
561 | + * Sets type |
|
562 | + * |
|
563 | + * @param string $type |
|
564 | + * @throws EE_Error |
|
565 | + * @throws InvalidArgumentException |
|
566 | + * @throws InvalidDataTypeException |
|
567 | + * @throws InvalidInterfaceException |
|
568 | + * @throws ReflectionException |
|
569 | + */ |
|
570 | + public function set_type($type) |
|
571 | + { |
|
572 | + $this->set('LIN_type', $type); |
|
573 | + } |
|
574 | + |
|
575 | + |
|
576 | + /** |
|
577 | + * Gets the line item of which this item is a composite. Eg, if this is a subtotal, the parent might be a total\ |
|
578 | + * 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 |
|
579 | + * it uses its cached reference to its parent line item (which would have been set by `EE_Line_Item::set_parent()` |
|
580 | + * or indirectly by `EE_Line_item::add_child_line_item()`) |
|
581 | + * |
|
582 | + * @return EE_Base_Class|EE_Line_Item |
|
583 | + * @throws EE_Error |
|
584 | + * @throws InvalidArgumentException |
|
585 | + * @throws InvalidDataTypeException |
|
586 | + * @throws InvalidInterfaceException |
|
587 | + * @throws ReflectionException |
|
588 | + */ |
|
589 | + public function parent() |
|
590 | + { |
|
591 | + return $this->ID() |
|
592 | + ? $this->get_model()->get_one_by_ID($this->parent_ID()) |
|
593 | + : $this->_parent; |
|
594 | + } |
|
595 | + |
|
596 | + |
|
597 | + /** |
|
598 | + * Gets ALL the children of this line item (ie, all the parts that contribute towards this total). |
|
599 | + * |
|
600 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
601 | + * @throws EE_Error |
|
602 | + * @throws InvalidArgumentException |
|
603 | + * @throws InvalidDataTypeException |
|
604 | + * @throws InvalidInterfaceException |
|
605 | + * @throws ReflectionException |
|
606 | + */ |
|
607 | + public function children() |
|
608 | + { |
|
609 | + if ($this->ID()) { |
|
610 | + return $this->get_model()->get_all( |
|
611 | + array( |
|
612 | + array('LIN_parent' => $this->ID()), |
|
613 | + 'order_by' => array('LIN_order' => 'ASC'), |
|
614 | + ) |
|
615 | + ); |
|
616 | + } |
|
617 | + if (! is_array($this->_children)) { |
|
618 | + $this->_children = array(); |
|
619 | + } |
|
620 | + return $this->_children; |
|
621 | + } |
|
622 | + |
|
623 | + |
|
624 | + /** |
|
625 | + * Gets code |
|
626 | + * |
|
627 | + * @return string |
|
628 | + * @throws EE_Error |
|
629 | + * @throws InvalidArgumentException |
|
630 | + * @throws InvalidDataTypeException |
|
631 | + * @throws InvalidInterfaceException |
|
632 | + * @throws ReflectionException |
|
633 | + */ |
|
634 | + public function code() |
|
635 | + { |
|
636 | + return $this->get('LIN_code'); |
|
637 | + } |
|
638 | + |
|
639 | + |
|
640 | + /** |
|
641 | + * Sets code |
|
642 | + * |
|
643 | + * @param string $code |
|
644 | + * @throws EE_Error |
|
645 | + * @throws InvalidArgumentException |
|
646 | + * @throws InvalidDataTypeException |
|
647 | + * @throws InvalidInterfaceException |
|
648 | + * @throws ReflectionException |
|
649 | + */ |
|
650 | + public function set_code($code) |
|
651 | + { |
|
652 | + $this->set('LIN_code', $code); |
|
653 | + } |
|
654 | + |
|
655 | + |
|
656 | + /** |
|
657 | + * Gets is_taxable |
|
658 | + * |
|
659 | + * @return boolean |
|
660 | + * @throws EE_Error |
|
661 | + * @throws InvalidArgumentException |
|
662 | + * @throws InvalidDataTypeException |
|
663 | + * @throws InvalidInterfaceException |
|
664 | + * @throws ReflectionException |
|
665 | + */ |
|
666 | + public function is_taxable() |
|
667 | + { |
|
668 | + return $this->get('LIN_is_taxable'); |
|
669 | + } |
|
670 | + |
|
671 | + |
|
672 | + /** |
|
673 | + * Sets is_taxable |
|
674 | + * |
|
675 | + * @param boolean $is_taxable |
|
676 | + * @throws EE_Error |
|
677 | + * @throws InvalidArgumentException |
|
678 | + * @throws InvalidDataTypeException |
|
679 | + * @throws InvalidInterfaceException |
|
680 | + * @throws ReflectionException |
|
681 | + */ |
|
682 | + public function set_is_taxable($is_taxable) |
|
683 | + { |
|
684 | + $this->set('LIN_is_taxable', $is_taxable); |
|
685 | + } |
|
686 | + |
|
687 | + |
|
688 | + /** |
|
689 | + * Gets the object that this model-joins-to. |
|
690 | + * returns one of the model objects that the field OBJ_ID can point to... see the 'OBJ_ID' field on |
|
691 | + * EEM_Promotion_Object |
|
692 | + * Eg, if this line item join model object is for a ticket, this will return the EE_Ticket object |
|
693 | + * |
|
694 | + * @return EE_Base_Class | NULL |
|
695 | + * @throws EE_Error |
|
696 | + * @throws InvalidArgumentException |
|
697 | + * @throws InvalidDataTypeException |
|
698 | + * @throws InvalidInterfaceException |
|
699 | + * @throws ReflectionException |
|
700 | + */ |
|
701 | + public function get_object() |
|
702 | + { |
|
703 | + $model_name_of_related_obj = $this->OBJ_type(); |
|
704 | + return $this->get_model()->has_relation($model_name_of_related_obj) |
|
705 | + ? $this->get_first_related($model_name_of_related_obj) |
|
706 | + : null; |
|
707 | + } |
|
708 | + |
|
709 | + |
|
710 | + /** |
|
711 | + * Like EE_Line_Item::get_object(), but can only ever actually return an EE_Ticket. |
|
712 | + * (IE, if this line item is for a price or something else, will return NULL) |
|
713 | + * |
|
714 | + * @param array $query_params |
|
715 | + * @return EE_Base_Class|EE_Ticket |
|
716 | + * @throws EE_Error |
|
717 | + * @throws InvalidArgumentException |
|
718 | + * @throws InvalidDataTypeException |
|
719 | + * @throws InvalidInterfaceException |
|
720 | + * @throws ReflectionException |
|
721 | + */ |
|
722 | + public function ticket($query_params = array()) |
|
723 | + { |
|
724 | + // we're going to assume that when this method is called |
|
725 | + // we always want to receive the attached ticket EVEN if that ticket is archived. |
|
726 | + // This can be overridden via the incoming $query_params argument |
|
727 | + $remove_defaults = array('default_where_conditions' => 'none'); |
|
728 | + $query_params = array_merge($remove_defaults, $query_params); |
|
729 | + return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TICKET, $query_params); |
|
730 | + } |
|
731 | + |
|
732 | + |
|
733 | + /** |
|
734 | + * Gets the EE_Datetime that's related to the ticket, IF this is for a ticket |
|
735 | + * |
|
736 | + * @return EE_Datetime | NULL |
|
737 | + * @throws EE_Error |
|
738 | + * @throws InvalidArgumentException |
|
739 | + * @throws InvalidDataTypeException |
|
740 | + * @throws InvalidInterfaceException |
|
741 | + * @throws ReflectionException |
|
742 | + */ |
|
743 | + public function get_ticket_datetime() |
|
744 | + { |
|
745 | + if ($this->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) { |
|
746 | + $ticket = $this->ticket(); |
|
747 | + if ($ticket instanceof EE_Ticket) { |
|
748 | + $datetime = $ticket->first_datetime(); |
|
749 | + if ($datetime instanceof EE_Datetime) { |
|
750 | + return $datetime; |
|
751 | + } |
|
752 | + } |
|
753 | + } |
|
754 | + return null; |
|
755 | + } |
|
756 | + |
|
757 | + |
|
758 | + /** |
|
759 | + * Gets the event's name that's related to the ticket, if this is for |
|
760 | + * a ticket |
|
761 | + * |
|
762 | + * @return string |
|
763 | + * @throws EE_Error |
|
764 | + * @throws InvalidArgumentException |
|
765 | + * @throws InvalidDataTypeException |
|
766 | + * @throws InvalidInterfaceException |
|
767 | + * @throws ReflectionException |
|
768 | + */ |
|
769 | + public function ticket_event_name() |
|
770 | + { |
|
771 | + $event_name = esc_html__('Unknown', 'event_espresso'); |
|
772 | + $event = $this->ticket_event(); |
|
773 | + if ($event instanceof EE_Event) { |
|
774 | + $event_name = $event->name(); |
|
775 | + } |
|
776 | + return $event_name; |
|
777 | + } |
|
778 | + |
|
779 | + |
|
780 | + /** |
|
781 | + * Gets the event that's related to the ticket, if this line item represents a ticket. |
|
782 | + * |
|
783 | + * @return EE_Event|null |
|
784 | + * @throws EE_Error |
|
785 | + * @throws InvalidArgumentException |
|
786 | + * @throws InvalidDataTypeException |
|
787 | + * @throws InvalidInterfaceException |
|
788 | + * @throws ReflectionException |
|
789 | + */ |
|
790 | + public function ticket_event() |
|
791 | + { |
|
792 | + $event = null; |
|
793 | + $ticket = $this->ticket(); |
|
794 | + if ($ticket instanceof EE_Ticket) { |
|
795 | + $datetime = $ticket->first_datetime(); |
|
796 | + if ($datetime instanceof EE_Datetime) { |
|
797 | + $event = $datetime->event(); |
|
798 | + } |
|
799 | + } |
|
800 | + return $event; |
|
801 | + } |
|
802 | + |
|
803 | + |
|
804 | + /** |
|
805 | + * Gets the first datetime for this lien item, assuming it's for a ticket |
|
806 | + * |
|
807 | + * @param string $date_format |
|
808 | + * @param string $time_format |
|
809 | + * @return string |
|
810 | + * @throws EE_Error |
|
811 | + * @throws InvalidArgumentException |
|
812 | + * @throws InvalidDataTypeException |
|
813 | + * @throws InvalidInterfaceException |
|
814 | + * @throws ReflectionException |
|
815 | + */ |
|
816 | + public function ticket_datetime_start($date_format = '', $time_format = '') |
|
817 | + { |
|
818 | + $first_datetime_string = esc_html__('Unknown', 'event_espresso'); |
|
819 | + $datetime = $this->get_ticket_datetime(); |
|
820 | + if ($datetime) { |
|
821 | + $first_datetime_string = $datetime->start_date_and_time($date_format, $time_format); |
|
822 | + } |
|
823 | + return $first_datetime_string; |
|
824 | + } |
|
825 | + |
|
826 | + |
|
827 | + /** |
|
828 | + * Adds the line item as a child to this line item. If there is another child line |
|
829 | + * item with the same LIN_code, it is overwritten by this new one |
|
830 | + * |
|
831 | + * @param EEI_Line_Item $line_item |
|
832 | + * @param bool $set_order |
|
833 | + * @return bool success |
|
834 | + * @throws EE_Error |
|
835 | + * @throws InvalidArgumentException |
|
836 | + * @throws InvalidDataTypeException |
|
837 | + * @throws InvalidInterfaceException |
|
838 | + * @throws ReflectionException |
|
839 | + */ |
|
840 | + public function add_child_line_item(EEI_Line_Item $line_item, $set_order = true) |
|
841 | + { |
|
842 | + // should we calculate the LIN_order for this line item ? |
|
843 | + if ($set_order || $line_item->order() === null) { |
|
844 | + $line_item->set_order(count($this->children())); |
|
845 | + } |
|
846 | + if ($this->ID()) { |
|
847 | + // check for any duplicate line items (with the same code), if so, this replaces it |
|
848 | + $line_item_with_same_code = $this->get_child_line_item($line_item->code()); |
|
849 | + if ($line_item_with_same_code instanceof EE_Line_Item && $line_item_with_same_code !== $line_item) { |
|
850 | + $this->delete_child_line_item($line_item_with_same_code->code()); |
|
851 | + } |
|
852 | + $line_item->set_parent_ID($this->ID()); |
|
853 | + if ($this->TXN_ID()) { |
|
854 | + $line_item->set_TXN_ID($this->TXN_ID()); |
|
855 | + } |
|
856 | + return $line_item->save(); |
|
857 | + } |
|
858 | + $this->_children[ $line_item->code() ] = $line_item; |
|
859 | + if ($line_item->parent() !== $this) { |
|
860 | + $line_item->set_parent($this); |
|
861 | + } |
|
862 | + return true; |
|
863 | + } |
|
864 | + |
|
865 | + |
|
866 | + /** |
|
867 | + * Similar to EE_Base_Class::_add_relation_to, except this isn't a normal relation. |
|
868 | + * If this line item is saved to the DB, this is just a wrapper for set_parent_ID() and save() |
|
869 | + * However, if this line item is NOT saved to the DB, this just caches the parent on |
|
870 | + * the EE_Line_Item::_parent property. |
|
871 | + * |
|
872 | + * @param EE_Line_Item $line_item |
|
873 | + * @throws EE_Error |
|
874 | + * @throws InvalidArgumentException |
|
875 | + * @throws InvalidDataTypeException |
|
876 | + * @throws InvalidInterfaceException |
|
877 | + * @throws ReflectionException |
|
878 | + */ |
|
879 | + public function set_parent($line_item) |
|
880 | + { |
|
881 | + if ($this->ID()) { |
|
882 | + if (! $line_item->ID()) { |
|
883 | + $line_item->save(); |
|
884 | + } |
|
885 | + $this->set_parent_ID($line_item->ID()); |
|
886 | + $this->save(); |
|
887 | + } else { |
|
888 | + $this->_parent = $line_item; |
|
889 | + $this->set_parent_ID($line_item->ID()); |
|
890 | + } |
|
891 | + } |
|
892 | + |
|
893 | + |
|
894 | + /** |
|
895 | + * Gets the child line item as specified by its code. Because this returns an object (by reference) |
|
896 | + * you can modify this child line item and the parent (this object) can know about them |
|
897 | + * because it also has a reference to that line item |
|
898 | + * |
|
899 | + * @param string $code |
|
900 | + * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL |
|
901 | + * @throws EE_Error |
|
902 | + * @throws InvalidArgumentException |
|
903 | + * @throws InvalidDataTypeException |
|
904 | + * @throws InvalidInterfaceException |
|
905 | + * @throws ReflectionException |
|
906 | + */ |
|
907 | + public function get_child_line_item($code) |
|
908 | + { |
|
909 | + if ($this->ID()) { |
|
910 | + return $this->get_model()->get_one( |
|
911 | + array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code)) |
|
912 | + ); |
|
913 | + } |
|
914 | + return isset($this->_children[ $code ]) |
|
915 | + ? $this->_children[ $code ] |
|
916 | + : null; |
|
917 | + } |
|
918 | + |
|
919 | + |
|
920 | + /** |
|
921 | + * Returns how many items are deleted (or, if this item has not been saved ot the DB yet, just how many it HAD |
|
922 | + * cached on it) |
|
923 | + * |
|
924 | + * @return int |
|
925 | + * @throws EE_Error |
|
926 | + * @throws InvalidArgumentException |
|
927 | + * @throws InvalidDataTypeException |
|
928 | + * @throws InvalidInterfaceException |
|
929 | + * @throws ReflectionException |
|
930 | + */ |
|
931 | + public function delete_children_line_items() |
|
932 | + { |
|
933 | + if ($this->ID()) { |
|
934 | + return $this->get_model()->delete(array(array('LIN_parent' => $this->ID()))); |
|
935 | + } |
|
936 | + $count = count($this->_children); |
|
937 | + $this->_children = array(); |
|
938 | + return $count; |
|
939 | + } |
|
940 | + |
|
941 | + |
|
942 | + /** |
|
943 | + * If this line item has been saved to the DB, deletes its child with LIN_code == $code. If this line |
|
944 | + * HAS NOT been saved to the DB, removes the child line item with index $code. |
|
945 | + * Also searches through the child's children for a matching line item. However, once a line item has been found |
|
946 | + * and deleted, stops searching (so if there are line items with duplicate codes, only the first one found will be |
|
947 | + * deleted) |
|
948 | + * |
|
949 | + * @param string $code |
|
950 | + * @param bool $stop_search_once_found |
|
951 | + * @return int count of items deleted (or simply removed from the line item's cache, if not has not been saved to |
|
952 | + * the DB yet) |
|
953 | + * @throws EE_Error |
|
954 | + * @throws InvalidArgumentException |
|
955 | + * @throws InvalidDataTypeException |
|
956 | + * @throws InvalidInterfaceException |
|
957 | + * @throws ReflectionException |
|
958 | + */ |
|
959 | + public function delete_child_line_item($code, $stop_search_once_found = true) |
|
960 | + { |
|
961 | + if ($this->ID()) { |
|
962 | + $items_deleted = 0; |
|
963 | + if ($this->code() === $code) { |
|
964 | + $items_deleted += EEH_Line_Item::delete_all_child_items($this); |
|
965 | + $items_deleted += (int) $this->delete(); |
|
966 | + if ($stop_search_once_found) { |
|
967 | + return $items_deleted; |
|
968 | + } |
|
969 | + } |
|
970 | + foreach ($this->children() as $child_line_item) { |
|
971 | + $items_deleted += $child_line_item->delete_child_line_item($code, $stop_search_once_found); |
|
972 | + } |
|
973 | + return $items_deleted; |
|
974 | + } |
|
975 | + if (isset($this->_children[ $code ])) { |
|
976 | + unset($this->_children[ $code ]); |
|
977 | + return 1; |
|
978 | + } |
|
979 | + return 0; |
|
980 | + } |
|
981 | + |
|
982 | + |
|
983 | + /** |
|
984 | + * If this line item is in the database, is of the type subtotal, and |
|
985 | + * has no children, why do we have it? It should be deleted so this function |
|
986 | + * does that |
|
987 | + * |
|
988 | + * @return boolean |
|
989 | + * @throws EE_Error |
|
990 | + * @throws InvalidArgumentException |
|
991 | + * @throws InvalidDataTypeException |
|
992 | + * @throws InvalidInterfaceException |
|
993 | + * @throws ReflectionException |
|
994 | + */ |
|
995 | + public function delete_if_childless_subtotal() |
|
996 | + { |
|
997 | + if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && ! $this->children()) { |
|
998 | + return $this->delete(); |
|
999 | + } |
|
1000 | + return false; |
|
1001 | + } |
|
1002 | + |
|
1003 | + |
|
1004 | + /** |
|
1005 | + * Creates a code and returns a string. doesn't assign the code to this model object |
|
1006 | + * |
|
1007 | + * @return string |
|
1008 | + * @throws EE_Error |
|
1009 | + * @throws InvalidArgumentException |
|
1010 | + * @throws InvalidDataTypeException |
|
1011 | + * @throws InvalidInterfaceException |
|
1012 | + * @throws ReflectionException |
|
1013 | + */ |
|
1014 | + public function generate_code() |
|
1015 | + { |
|
1016 | + // each line item in the cart requires a unique identifier |
|
1017 | + return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime()); |
|
1018 | + } |
|
1019 | + |
|
1020 | + |
|
1021 | + /** |
|
1022 | + * @return bool |
|
1023 | + * @throws EE_Error |
|
1024 | + * @throws InvalidArgumentException |
|
1025 | + * @throws InvalidDataTypeException |
|
1026 | + * @throws InvalidInterfaceException |
|
1027 | + * @throws ReflectionException |
|
1028 | + */ |
|
1029 | + public function is_tax() |
|
1030 | + { |
|
1031 | + return $this->type() === EEM_Line_Item::type_tax; |
|
1032 | + } |
|
1033 | + |
|
1034 | + |
|
1035 | + /** |
|
1036 | + * @return bool |
|
1037 | + * @throws EE_Error |
|
1038 | + * @throws InvalidArgumentException |
|
1039 | + * @throws InvalidDataTypeException |
|
1040 | + * @throws InvalidInterfaceException |
|
1041 | + * @throws ReflectionException |
|
1042 | + */ |
|
1043 | + public function is_tax_sub_total() |
|
1044 | + { |
|
1045 | + return $this->type() === EEM_Line_Item::type_tax_sub_total; |
|
1046 | + } |
|
1047 | + |
|
1048 | + |
|
1049 | + /** |
|
1050 | + * @return bool |
|
1051 | + * @throws EE_Error |
|
1052 | + * @throws InvalidArgumentException |
|
1053 | + * @throws InvalidDataTypeException |
|
1054 | + * @throws InvalidInterfaceException |
|
1055 | + * @throws ReflectionException |
|
1056 | + */ |
|
1057 | + public function is_line_item() |
|
1058 | + { |
|
1059 | + return $this->type() === EEM_Line_Item::type_line_item; |
|
1060 | + } |
|
1061 | + |
|
1062 | + |
|
1063 | + /** |
|
1064 | + * @return bool |
|
1065 | + * @throws EE_Error |
|
1066 | + * @throws InvalidArgumentException |
|
1067 | + * @throws InvalidDataTypeException |
|
1068 | + * @throws InvalidInterfaceException |
|
1069 | + * @throws ReflectionException |
|
1070 | + */ |
|
1071 | + public function is_sub_line_item() |
|
1072 | + { |
|
1073 | + return $this->type() === EEM_Line_Item::type_sub_line_item; |
|
1074 | + } |
|
1075 | + |
|
1076 | + |
|
1077 | + /** |
|
1078 | + * @return bool |
|
1079 | + * @throws EE_Error |
|
1080 | + * @throws InvalidArgumentException |
|
1081 | + * @throws InvalidDataTypeException |
|
1082 | + * @throws InvalidInterfaceException |
|
1083 | + * @throws ReflectionException |
|
1084 | + */ |
|
1085 | + public function is_sub_total() |
|
1086 | + { |
|
1087 | + return $this->type() === EEM_Line_Item::type_sub_total; |
|
1088 | + } |
|
1089 | + |
|
1090 | + |
|
1091 | + /** |
|
1092 | + * Whether or not this line item is a cancellation line item |
|
1093 | + * |
|
1094 | + * @return boolean |
|
1095 | + * @throws EE_Error |
|
1096 | + * @throws InvalidArgumentException |
|
1097 | + * @throws InvalidDataTypeException |
|
1098 | + * @throws InvalidInterfaceException |
|
1099 | + * @throws ReflectionException |
|
1100 | + */ |
|
1101 | + public function is_cancellation() |
|
1102 | + { |
|
1103 | + return EEM_Line_Item::type_cancellation === $this->type(); |
|
1104 | + } |
|
1105 | + |
|
1106 | + |
|
1107 | + /** |
|
1108 | + * @return bool |
|
1109 | + * @throws EE_Error |
|
1110 | + * @throws InvalidArgumentException |
|
1111 | + * @throws InvalidDataTypeException |
|
1112 | + * @throws InvalidInterfaceException |
|
1113 | + * @throws ReflectionException |
|
1114 | + */ |
|
1115 | + public function is_total() |
|
1116 | + { |
|
1117 | + return $this->type() === EEM_Line_Item::type_total; |
|
1118 | + } |
|
1119 | + |
|
1120 | + |
|
1121 | + /** |
|
1122 | + * @return bool |
|
1123 | + * @throws EE_Error |
|
1124 | + * @throws InvalidArgumentException |
|
1125 | + * @throws InvalidDataTypeException |
|
1126 | + * @throws InvalidInterfaceException |
|
1127 | + * @throws ReflectionException |
|
1128 | + */ |
|
1129 | + public function is_cancelled() |
|
1130 | + { |
|
1131 | + return $this->type() === EEM_Line_Item::type_cancellation; |
|
1132 | + } |
|
1133 | + |
|
1134 | + |
|
1135 | + /** |
|
1136 | + * @return string like '2, 004.00', formatted according to the localized currency |
|
1137 | + * @throws EE_Error |
|
1138 | + * @throws InvalidArgumentException |
|
1139 | + * @throws InvalidDataTypeException |
|
1140 | + * @throws InvalidInterfaceException |
|
1141 | + * @throws ReflectionException |
|
1142 | + */ |
|
1143 | + public function unit_price_no_code() |
|
1144 | + { |
|
1145 | + return $this->get_pretty('LIN_unit_price', 'no_currency_code'); |
|
1146 | + } |
|
1147 | + |
|
1148 | + |
|
1149 | + /** |
|
1150 | + * @return string like '2, 004.00', formatted according to the localized currency |
|
1151 | + * @throws EE_Error |
|
1152 | + * @throws InvalidArgumentException |
|
1153 | + * @throws InvalidDataTypeException |
|
1154 | + * @throws InvalidInterfaceException |
|
1155 | + * @throws ReflectionException |
|
1156 | + */ |
|
1157 | + public function total_no_code() |
|
1158 | + { |
|
1159 | + return $this->get_pretty('LIN_total', 'no_currency_code'); |
|
1160 | + } |
|
1161 | + |
|
1162 | + |
|
1163 | + /** |
|
1164 | + * Gets the final total on this item, taking taxes into account. |
|
1165 | + * Has the side-effect of setting the sub-total as it was just calculated. |
|
1166 | + * If this is used on a grand-total line item, also updates the transaction's |
|
1167 | + * TXN_total (provided this line item is allowed to persist, otherwise we don't |
|
1168 | + * want to change a persistable transaction with info from a non-persistent line item) |
|
1169 | + * |
|
1170 | + * @param bool $update_txn_status |
|
1171 | + * @return float |
|
1172 | + * @throws EE_Error |
|
1173 | + * @throws InvalidArgumentException |
|
1174 | + * @throws InvalidDataTypeException |
|
1175 | + * @throws InvalidInterfaceException |
|
1176 | + * @throws ReflectionException |
|
1177 | + * @throws RuntimeException |
|
1178 | + */ |
|
1179 | + public function recalculate_total_including_taxes($update_txn_status = false) |
|
1180 | + { |
|
1181 | + $pre_tax_total = $this->recalculate_pre_tax_total(); |
|
1182 | + $tax_total = $this->recalculate_taxes_and_tax_total(); |
|
1183 | + $total = $pre_tax_total + $tax_total; |
|
1184 | + // no negative totals plz |
|
1185 | + $total = max($total, 0); |
|
1186 | + $this->set_total($total); |
|
1187 | + // only update the related transaction's total |
|
1188 | + // if we intend to save this line item and its a grand total |
|
1189 | + if ( |
|
1190 | + $this->allow_persist() && $this->type() === EEM_Line_Item::type_total |
|
1191 | + && $this->transaction() |
|
1192 | + instanceof |
|
1193 | + EE_Transaction |
|
1194 | + ) { |
|
1195 | + $this->transaction()->set_total($total); |
|
1196 | + if ($update_txn_status) { |
|
1197 | + // don't save the TXN because that will be done below |
|
1198 | + // and the following method only saves if the status changes |
|
1199 | + $this->transaction()->update_status_based_on_total_paid(false); |
|
1200 | + } |
|
1201 | + if ($this->transaction()->ID()) { |
|
1202 | + $this->transaction()->save(); |
|
1203 | + } |
|
1204 | + } |
|
1205 | + $this->maybe_save(); |
|
1206 | + return $total; |
|
1207 | + } |
|
1208 | + |
|
1209 | + |
|
1210 | + /** |
|
1211 | + * Recursively goes through all the children and recalculates sub-totals EXCEPT for |
|
1212 | + * tax-sub-totals (they're a an odd beast). Updates the 'total' on each line item according to either its |
|
1213 | + * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and |
|
1214 | + * when this is called on the grand total |
|
1215 | + * |
|
1216 | + * @return float |
|
1217 | + * @throws EE_Error |
|
1218 | + * @throws InvalidArgumentException |
|
1219 | + * @throws InvalidDataTypeException |
|
1220 | + * @throws InvalidInterfaceException |
|
1221 | + * @throws ReflectionException |
|
1222 | + */ |
|
1223 | + public function recalculate_pre_tax_total() |
|
1224 | + { |
|
1225 | + $total = 0; |
|
1226 | + $my_children = $this->children(); |
|
1227 | + $has_children = ! empty($my_children); |
|
1228 | + if ($has_children && $this->is_line_item()) { |
|
1229 | + $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children); |
|
1230 | + } elseif (! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) { |
|
1231 | + $total = $this->unit_price() * $this->quantity(); |
|
1232 | + } elseif ($this->is_sub_total() || $this->is_total()) { |
|
1233 | + $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children); |
|
1234 | + } elseif ($this->is_tax_sub_total() || $this->is_tax() || $this->is_cancelled()) { |
|
1235 | + // completely ignore tax totals, tax sub-totals, and cancelled line items, when calculating the pre-tax-total |
|
1236 | + return 0; |
|
1237 | + } |
|
1238 | + // ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events) |
|
1239 | + if ( |
|
1240 | + ! $this->is_line_item() && ! $this->is_sub_line_item() && ! $this->is_cancellation() |
|
1241 | + ) { |
|
1242 | + if ($this->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_EVENT) { |
|
1243 | + $this->set_quantity(1); |
|
1244 | + } |
|
1245 | + if (! $this->is_percent()) { |
|
1246 | + $this->set_unit_price($total); |
|
1247 | + } |
|
1248 | + } |
|
1249 | + // we don't want to bother saving grand totals, because that needs to factor in taxes anyways |
|
1250 | + // so it ought to be |
|
1251 | + if (! $this->is_total()) { |
|
1252 | + $this->set_total($total); |
|
1253 | + // if not a percent line item, make sure we keep the unit price in sync |
|
1254 | + if ( |
|
1255 | + $has_children |
|
1256 | + && $this->is_line_item() |
|
1257 | + && ! $this->is_percent() |
|
1258 | + ) { |
|
1259 | + if ($this->quantity() === 0) { |
|
1260 | + $new_unit_price = 0; |
|
1261 | + } else { |
|
1262 | + $new_unit_price = $this->total() / $this->quantity(); |
|
1263 | + } |
|
1264 | + $this->set_unit_price($new_unit_price); |
|
1265 | + } |
|
1266 | + $this->maybe_save(); |
|
1267 | + } |
|
1268 | + return $total; |
|
1269 | + } |
|
1270 | + |
|
1271 | + |
|
1272 | + /** |
|
1273 | + * Calculates the pretax total when this line item is a subtotal or total line item. |
|
1274 | + * Basically does a sum-then-round approach (ie, any percent line item that are children |
|
1275 | + * will calculate their total based on the un-rounded total we're working with so far, and |
|
1276 | + * THEN round the result; instead of rounding as we go like with sub-line-items) |
|
1277 | + * |
|
1278 | + * @param float $calculated_total_so_far |
|
1279 | + * @param EE_Line_Item[] $my_children |
|
1280 | + * @return float |
|
1281 | + * @throws EE_Error |
|
1282 | + * @throws InvalidArgumentException |
|
1283 | + * @throws InvalidDataTypeException |
|
1284 | + * @throws InvalidInterfaceException |
|
1285 | + * @throws ReflectionException |
|
1286 | + */ |
|
1287 | + protected function _recalculate_pretax_total_for_subtotal($calculated_total_so_far, $my_children = null) |
|
1288 | + { |
|
1289 | + if ($my_children === null) { |
|
1290 | + $my_children = $this->children(); |
|
1291 | + } |
|
1292 | + $subtotal_quantity = 0; |
|
1293 | + // get the total of all its children |
|
1294 | + foreach ($my_children as $child_line_item) { |
|
1295 | + if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) { |
|
1296 | + // percentage line items are based on total so far |
|
1297 | + if ($child_line_item->is_percent()) { |
|
1298 | + // round as we go so that the line items add up ok |
|
1299 | + $percent_total = round( |
|
1300 | + $calculated_total_so_far * $child_line_item->percent() / 100, |
|
1301 | + EE_Registry::instance()->CFG->currency->dec_plc |
|
1302 | + ); |
|
1303 | + $child_line_item->set_total($percent_total); |
|
1304 | + // so far all percent line items should have a quantity of 1 |
|
1305 | + // (ie, no double percent discounts. Although that might be requested someday) |
|
1306 | + $child_line_item->set_quantity(1); |
|
1307 | + $child_line_item->maybe_save(); |
|
1308 | + $calculated_total_so_far += $percent_total; |
|
1309 | + } else { |
|
1310 | + // verify flat sub-line-item quantities match their parent |
|
1311 | + if ($child_line_item->is_sub_line_item()) { |
|
1312 | + $child_line_item->set_quantity($this->quantity()); |
|
1313 | + } |
|
1314 | + $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
1315 | + $subtotal_quantity += $child_line_item->quantity(); |
|
1316 | + } |
|
1317 | + } |
|
1318 | + } |
|
1319 | + if ($this->is_sub_total()) { |
|
1320 | + // no negative totals plz |
|
1321 | + $calculated_total_so_far = max($calculated_total_so_far, 0); |
|
1322 | + $subtotal_quantity = $subtotal_quantity > 0 ? 1 : 0; |
|
1323 | + $this->set_quantity($subtotal_quantity); |
|
1324 | + $this->maybe_save(); |
|
1325 | + } |
|
1326 | + return $calculated_total_so_far; |
|
1327 | + } |
|
1328 | + |
|
1329 | + |
|
1330 | + /** |
|
1331 | + * Calculates the pretax total for a normal line item, in a round-then-sum approach |
|
1332 | + * (where each sub-line-item is applied to the base price for the line item |
|
1333 | + * and the result is immediately rounded, rather than summing all the sub-line-items |
|
1334 | + * then rounding, like we do when recalculating pretax totals on totals and subtotals). |
|
1335 | + * |
|
1336 | + * @param float $calculated_total_so_far |
|
1337 | + * @param EE_Line_Item[] $my_children |
|
1338 | + * @return float |
|
1339 | + * @throws EE_Error |
|
1340 | + * @throws InvalidArgumentException |
|
1341 | + * @throws InvalidDataTypeException |
|
1342 | + * @throws InvalidInterfaceException |
|
1343 | + * @throws ReflectionException |
|
1344 | + */ |
|
1345 | + protected function _recalculate_pretax_total_for_line_item($calculated_total_so_far, $my_children = null) |
|
1346 | + { |
|
1347 | + if ($my_children === null) { |
|
1348 | + $my_children = $this->children(); |
|
1349 | + } |
|
1350 | + // we need to keep track of the running total for a single item, |
|
1351 | + // because we need to round as we go |
|
1352 | + $unit_price_for_total = 0; |
|
1353 | + $quantity_for_total = 1; |
|
1354 | + // get the total of all its children |
|
1355 | + foreach ($my_children as $child_line_item) { |
|
1356 | + if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) { |
|
1357 | + if ($child_line_item->is_percent()) { |
|
1358 | + // it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity |
|
1359 | + // not total multiplied by percent, because that ignores rounding along-the-way |
|
1360 | + $percent_unit_price = round( |
|
1361 | + $unit_price_for_total * $child_line_item->percent() / 100, |
|
1362 | + EE_Registry::instance()->CFG->currency->dec_plc |
|
1363 | + ); |
|
1364 | + $percent_total = $percent_unit_price * $quantity_for_total; |
|
1365 | + $child_line_item->set_total($percent_total); |
|
1366 | + // so far all percent line items should have a quantity of 1 |
|
1367 | + // (ie, no double percent discounts. Although that might be requested someday) |
|
1368 | + $child_line_item->set_quantity(1); |
|
1369 | + $child_line_item->maybe_save(); |
|
1370 | + $calculated_total_so_far += $percent_total; |
|
1371 | + $unit_price_for_total += $percent_unit_price; |
|
1372 | + } else { |
|
1373 | + // verify flat sub-line-item quantities match their parent |
|
1374 | + if ($child_line_item->is_sub_line_item()) { |
|
1375 | + $child_line_item->set_quantity($this->quantity()); |
|
1376 | + } |
|
1377 | + $quantity_for_total = $child_line_item->quantity(); |
|
1378 | + $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
1379 | + $unit_price_for_total += $child_line_item->unit_price(); |
|
1380 | + } |
|
1381 | + } |
|
1382 | + } |
|
1383 | + return $calculated_total_so_far; |
|
1384 | + } |
|
1385 | + |
|
1386 | + |
|
1387 | + /** |
|
1388 | + * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets |
|
1389 | + * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items |
|
1390 | + * and tax sub-total if already in the DB |
|
1391 | + * |
|
1392 | + * @return float |
|
1393 | + * @throws EE_Error |
|
1394 | + * @throws InvalidArgumentException |
|
1395 | + * @throws InvalidDataTypeException |
|
1396 | + * @throws InvalidInterfaceException |
|
1397 | + * @throws ReflectionException |
|
1398 | + */ |
|
1399 | + public function recalculate_taxes_and_tax_total() |
|
1400 | + { |
|
1401 | + // get all taxes |
|
1402 | + $taxes = $this->tax_descendants(); |
|
1403 | + // calculate the pretax total |
|
1404 | + $taxable_total = $this->taxable_total(); |
|
1405 | + $tax_total = 0; |
|
1406 | + foreach ($taxes as $tax) { |
|
1407 | + $total_on_this_tax = $taxable_total * $tax->percent() / 100; |
|
1408 | + // remember the total on this line item |
|
1409 | + $tax->set_total($total_on_this_tax); |
|
1410 | + $tax->maybe_save(); |
|
1411 | + $tax_total += $tax->total(); |
|
1412 | + } |
|
1413 | + $this->_recalculate_tax_sub_total(); |
|
1414 | + return $tax_total; |
|
1415 | + } |
|
1416 | + |
|
1417 | + |
|
1418 | + /** |
|
1419 | + * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated |
|
1420 | + * |
|
1421 | + * @return void |
|
1422 | + * @throws EE_Error |
|
1423 | + * @throws InvalidArgumentException |
|
1424 | + * @throws InvalidDataTypeException |
|
1425 | + * @throws InvalidInterfaceException |
|
1426 | + * @throws ReflectionException |
|
1427 | + */ |
|
1428 | + private function _recalculate_tax_sub_total() |
|
1429 | + { |
|
1430 | + if ($this->is_tax_sub_total()) { |
|
1431 | + $total = 0; |
|
1432 | + $total_percent = 0; |
|
1433 | + // simply loop through all its children (which should be taxes) and sum their total |
|
1434 | + foreach ($this->children() as $child_tax) { |
|
1435 | + if ($child_tax instanceof EE_Line_Item) { |
|
1436 | + $total += $child_tax->total(); |
|
1437 | + $total_percent += $child_tax->percent(); |
|
1438 | + } |
|
1439 | + } |
|
1440 | + $this->set_total($total); |
|
1441 | + $this->set_percent($total_percent); |
|
1442 | + $this->maybe_save(); |
|
1443 | + } elseif ($this->is_total()) { |
|
1444 | + foreach ($this->children() as $maybe_tax_subtotal) { |
|
1445 | + if ($maybe_tax_subtotal instanceof EE_Line_Item) { |
|
1446 | + $maybe_tax_subtotal->_recalculate_tax_sub_total(); |
|
1447 | + } |
|
1448 | + } |
|
1449 | + } |
|
1450 | + } |
|
1451 | + |
|
1452 | + |
|
1453 | + /** |
|
1454 | + * Gets the total tax on this line item. Assumes taxes have already been calculated using |
|
1455 | + * recalculate_taxes_and_total |
|
1456 | + * |
|
1457 | + * @return float |
|
1458 | + * @throws EE_Error |
|
1459 | + * @throws InvalidArgumentException |
|
1460 | + * @throws InvalidDataTypeException |
|
1461 | + * @throws InvalidInterfaceException |
|
1462 | + * @throws ReflectionException |
|
1463 | + */ |
|
1464 | + public function get_total_tax() |
|
1465 | + { |
|
1466 | + $this->_recalculate_tax_sub_total(); |
|
1467 | + $total = 0; |
|
1468 | + foreach ($this->tax_descendants() as $tax_line_item) { |
|
1469 | + if ($tax_line_item instanceof EE_Line_Item) { |
|
1470 | + $total += $tax_line_item->total(); |
|
1471 | + } |
|
1472 | + } |
|
1473 | + return $total; |
|
1474 | + } |
|
1475 | + |
|
1476 | + |
|
1477 | + /** |
|
1478 | + * Gets the total for all the items purchased only |
|
1479 | + * |
|
1480 | + * @return float |
|
1481 | + * @throws EE_Error |
|
1482 | + * @throws InvalidArgumentException |
|
1483 | + * @throws InvalidDataTypeException |
|
1484 | + * @throws InvalidInterfaceException |
|
1485 | + * @throws ReflectionException |
|
1486 | + */ |
|
1487 | + public function get_items_total() |
|
1488 | + { |
|
1489 | + // by default, let's make sure we're consistent with the existing line item |
|
1490 | + if ($this->is_total()) { |
|
1491 | + $pretax_subtotal_li = EEH_Line_Item::get_pre_tax_subtotal($this); |
|
1492 | + if ($pretax_subtotal_li instanceof EE_Line_Item) { |
|
1493 | + return $pretax_subtotal_li->total(); |
|
1494 | + } |
|
1495 | + } |
|
1496 | + $total = 0; |
|
1497 | + foreach ($this->get_items() as $item) { |
|
1498 | + if ($item instanceof EE_Line_Item) { |
|
1499 | + $total += $item->total(); |
|
1500 | + } |
|
1501 | + } |
|
1502 | + return $total; |
|
1503 | + } |
|
1504 | + |
|
1505 | + |
|
1506 | + /** |
|
1507 | + * Gets all the descendants (ie, children or children of children etc) that |
|
1508 | + * are of the type 'tax' |
|
1509 | + * |
|
1510 | + * @return EE_Line_Item[] |
|
1511 | + * @throws EE_Error |
|
1512 | + */ |
|
1513 | + public function tax_descendants() |
|
1514 | + { |
|
1515 | + return EEH_Line_Item::get_tax_descendants($this); |
|
1516 | + } |
|
1517 | + |
|
1518 | + |
|
1519 | + /** |
|
1520 | + * Gets all the real items purchased which are children of this item |
|
1521 | + * |
|
1522 | + * @return EE_Line_Item[] |
|
1523 | + * @throws EE_Error |
|
1524 | + */ |
|
1525 | + public function get_items() |
|
1526 | + { |
|
1527 | + return EEH_Line_Item::get_line_item_descendants($this); |
|
1528 | + } |
|
1529 | + |
|
1530 | + |
|
1531 | + /** |
|
1532 | + * Returns the amount taxable among this line item's children (or if it has no children, |
|
1533 | + * how much of it is taxable). Does not recalculate totals or subtotals. |
|
1534 | + * If the taxable total is negative, (eg, if none of the tickets were taxable, |
|
1535 | + * but there is a "Taxable" discount), returns 0. |
|
1536 | + * |
|
1537 | + * @return float |
|
1538 | + * @throws EE_Error |
|
1539 | + * @throws InvalidArgumentException |
|
1540 | + * @throws InvalidDataTypeException |
|
1541 | + * @throws InvalidInterfaceException |
|
1542 | + * @throws ReflectionException |
|
1543 | + */ |
|
1544 | + public function taxable_total() |
|
1545 | + { |
|
1546 | + $total = 0; |
|
1547 | + if ($this->children()) { |
|
1548 | + foreach ($this->children() as $child_line_item) { |
|
1549 | + if ($child_line_item->type() === EEM_Line_Item::type_line_item && $child_line_item->is_taxable()) { |
|
1550 | + // if it's a percent item, only take into account the percent |
|
1551 | + // that's taxable too (the taxable total so far) |
|
1552 | + if ($child_line_item->is_percent()) { |
|
1553 | + $total += ($total * $child_line_item->percent() / 100); |
|
1554 | + } else { |
|
1555 | + $total += $child_line_item->total(); |
|
1556 | + } |
|
1557 | + } elseif ($child_line_item->type() === EEM_Line_Item::type_sub_total) { |
|
1558 | + $total += $child_line_item->taxable_total(); |
|
1559 | + } |
|
1560 | + } |
|
1561 | + } |
|
1562 | + return max($total, 0); |
|
1563 | + } |
|
1564 | + |
|
1565 | + |
|
1566 | + /** |
|
1567 | + * Gets the transaction for this line item |
|
1568 | + * |
|
1569 | + * @return EE_Base_Class|EE_Transaction |
|
1570 | + * @throws EE_Error |
|
1571 | + * @throws InvalidArgumentException |
|
1572 | + * @throws InvalidDataTypeException |
|
1573 | + * @throws InvalidInterfaceException |
|
1574 | + * @throws ReflectionException |
|
1575 | + */ |
|
1576 | + public function transaction() |
|
1577 | + { |
|
1578 | + return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TRANSACTION); |
|
1579 | + } |
|
1580 | + |
|
1581 | + |
|
1582 | + /** |
|
1583 | + * Saves this line item to the DB, and recursively saves its descendants. |
|
1584 | + * Because there currently is no proper parent-child relation on the model, |
|
1585 | + * save_this_and_cached() will NOT save the descendants. |
|
1586 | + * Also sets the transaction on this line item and all its descendants before saving |
|
1587 | + * |
|
1588 | + * @param int $txn_id if none is provided, assumes $this->TXN_ID() |
|
1589 | + * @return int count of items saved |
|
1590 | + * @throws EE_Error |
|
1591 | + * @throws InvalidArgumentException |
|
1592 | + * @throws InvalidDataTypeException |
|
1593 | + * @throws InvalidInterfaceException |
|
1594 | + * @throws ReflectionException |
|
1595 | + */ |
|
1596 | + public function save_this_and_descendants_to_txn($txn_id = null) |
|
1597 | + { |
|
1598 | + $count = 0; |
|
1599 | + if (! $txn_id) { |
|
1600 | + $txn_id = $this->TXN_ID(); |
|
1601 | + } |
|
1602 | + $this->set_TXN_ID($txn_id); |
|
1603 | + $children = $this->children(); |
|
1604 | + $count += $this->save() |
|
1605 | + ? 1 |
|
1606 | + : 0; |
|
1607 | + foreach ($children as $child_line_item) { |
|
1608 | + if ($child_line_item instanceof EE_Line_Item) { |
|
1609 | + $child_line_item->set_parent_ID($this->ID()); |
|
1610 | + $count += $child_line_item->save_this_and_descendants_to_txn($txn_id); |
|
1611 | + } |
|
1612 | + } |
|
1613 | + return $count; |
|
1614 | + } |
|
1615 | + |
|
1616 | + |
|
1617 | + /** |
|
1618 | + * Saves this line item to the DB, and recursively saves its descendants. |
|
1619 | + * |
|
1620 | + * @return int count of items saved |
|
1621 | + * @throws EE_Error |
|
1622 | + * @throws InvalidArgumentException |
|
1623 | + * @throws InvalidDataTypeException |
|
1624 | + * @throws InvalidInterfaceException |
|
1625 | + * @throws ReflectionException |
|
1626 | + */ |
|
1627 | + public function save_this_and_descendants() |
|
1628 | + { |
|
1629 | + $count = 0; |
|
1630 | + $children = $this->children(); |
|
1631 | + $count += $this->save() |
|
1632 | + ? 1 |
|
1633 | + : 0; |
|
1634 | + foreach ($children as $child_line_item) { |
|
1635 | + if ($child_line_item instanceof EE_Line_Item) { |
|
1636 | + $child_line_item->set_parent_ID($this->ID()); |
|
1637 | + $count += $child_line_item->save_this_and_descendants(); |
|
1638 | + } |
|
1639 | + } |
|
1640 | + return $count; |
|
1641 | + } |
|
1642 | + |
|
1643 | + |
|
1644 | + /** |
|
1645 | + * returns the cancellation line item if this item was cancelled |
|
1646 | + * |
|
1647 | + * @return EE_Line_Item[] |
|
1648 | + * @throws InvalidArgumentException |
|
1649 | + * @throws InvalidInterfaceException |
|
1650 | + * @throws InvalidDataTypeException |
|
1651 | + * @throws ReflectionException |
|
1652 | + * @throws EE_Error |
|
1653 | + */ |
|
1654 | + public function get_cancellations() |
|
1655 | + { |
|
1656 | + EE_Registry::instance()->load_helper('Line_Item'); |
|
1657 | + return EEH_Line_Item::get_descendants_of_type($this, EEM_Line_Item::type_cancellation); |
|
1658 | + } |
|
1659 | + |
|
1660 | + |
|
1661 | + /** |
|
1662 | + * If this item has an ID, then this saves it again to update the db |
|
1663 | + * |
|
1664 | + * @return int count of items saved |
|
1665 | + * @throws EE_Error |
|
1666 | + * @throws InvalidArgumentException |
|
1667 | + * @throws InvalidDataTypeException |
|
1668 | + * @throws InvalidInterfaceException |
|
1669 | + * @throws ReflectionException |
|
1670 | + */ |
|
1671 | + public function maybe_save() |
|
1672 | + { |
|
1673 | + if ($this->ID()) { |
|
1674 | + return $this->save(); |
|
1675 | + } |
|
1676 | + return false; |
|
1677 | + } |
|
1678 | + |
|
1679 | + |
|
1680 | + /** |
|
1681 | + * clears the cached children and parent from the line item |
|
1682 | + * |
|
1683 | + * @return void |
|
1684 | + */ |
|
1685 | + public function clear_related_line_item_cache() |
|
1686 | + { |
|
1687 | + $this->_children = array(); |
|
1688 | + $this->_parent = null; |
|
1689 | + } |
|
1690 | + |
|
1691 | + |
|
1692 | + /** |
|
1693 | + * @param bool $raw |
|
1694 | + * @return int |
|
1695 | + * @throws EE_Error |
|
1696 | + * @throws InvalidArgumentException |
|
1697 | + * @throws InvalidDataTypeException |
|
1698 | + * @throws InvalidInterfaceException |
|
1699 | + * @throws ReflectionException |
|
1700 | + */ |
|
1701 | + public function timestamp($raw = false) |
|
1702 | + { |
|
1703 | + return $raw |
|
1704 | + ? $this->get_raw('LIN_timestamp') |
|
1705 | + : $this->get('LIN_timestamp'); |
|
1706 | + } |
|
1707 | + |
|
1708 | + |
|
1709 | + |
|
1710 | + |
|
1711 | + /************************* DEPRECATED *************************/ |
|
1712 | + /** |
|
1713 | + * @deprecated 4.6.0 |
|
1714 | + * @param string $type one of the constants on EEM_Line_Item |
|
1715 | + * @return EE_Line_Item[] |
|
1716 | + * @throws EE_Error |
|
1717 | + */ |
|
1718 | + protected function _get_descendants_of_type($type) |
|
1719 | + { |
|
1720 | + EE_Error::doing_it_wrong( |
|
1721 | + 'EE_Line_Item::_get_descendants_of_type()', |
|
1722 | + sprintf( |
|
1723 | + esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
1724 | + 'EEH_Line_Item::get_descendants_of_type()' |
|
1725 | + ), |
|
1726 | + '4.6.0' |
|
1727 | + ); |
|
1728 | + return EEH_Line_Item::get_descendants_of_type($this, $type); |
|
1729 | + } |
|
1730 | + |
|
1731 | + |
|
1732 | + /** |
|
1733 | + * @deprecated 4.6.0 |
|
1734 | + * @param string $type like one of the EEM_Line_Item::type_* |
|
1735 | + * @return EE_Line_Item |
|
1736 | + * @throws EE_Error |
|
1737 | + * @throws InvalidArgumentException |
|
1738 | + * @throws InvalidDataTypeException |
|
1739 | + * @throws InvalidInterfaceException |
|
1740 | + * @throws ReflectionException |
|
1741 | + */ |
|
1742 | + public function get_nearest_descendant_of_type($type) |
|
1743 | + { |
|
1744 | + EE_Error::doing_it_wrong( |
|
1745 | + 'EE_Line_Item::get_nearest_descendant_of_type()', |
|
1746 | + sprintf( |
|
1747 | + esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
1748 | + 'EEH_Line_Item::get_nearest_descendant_of_type()' |
|
1749 | + ), |
|
1750 | + '4.6.0' |
|
1751 | + ); |
|
1752 | + return EEH_Line_Item::get_nearest_descendant_of_type($this, $type); |
|
1753 | + } |
|
1754 | 1754 | } |
@@ -154,19 +154,19 @@ |
||
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 | } |
@@ -20,172 +20,172 @@ |
||
20 | 20 | */ |
21 | 21 | class EventAttendees extends Block |
22 | 22 | { |
23 | - const BLOCK_TYPE = 'event-attendees'; |
|
23 | + const BLOCK_TYPE = 'event-attendees'; |
|
24 | 24 | |
25 | - /** |
|
26 | - * @var EventAttendeesBlockRenderer $renderer |
|
27 | - */ |
|
28 | - protected $renderer; |
|
25 | + /** |
|
26 | + * @var EventAttendeesBlockRenderer $renderer |
|
27 | + */ |
|
28 | + protected $renderer; |
|
29 | 29 | |
30 | 30 | |
31 | - /** |
|
32 | - * EventAttendees constructor. |
|
33 | - * |
|
34 | - * @param CoreBlocksAssetManager $block_asset_manager |
|
35 | - * @param RequestInterface $request |
|
36 | - * @param EventAttendeesBlockRenderer $renderer |
|
37 | - */ |
|
38 | - public function __construct( |
|
39 | - CoreBlocksAssetManager $block_asset_manager, |
|
40 | - RequestInterface $request, |
|
41 | - EventAttendeesBlockRenderer $renderer |
|
42 | - ) { |
|
43 | - parent::__construct($block_asset_manager, $request); |
|
44 | - $this->renderer = $renderer; |
|
45 | - } |
|
31 | + /** |
|
32 | + * EventAttendees constructor. |
|
33 | + * |
|
34 | + * @param CoreBlocksAssetManager $block_asset_manager |
|
35 | + * @param RequestInterface $request |
|
36 | + * @param EventAttendeesBlockRenderer $renderer |
|
37 | + */ |
|
38 | + public function __construct( |
|
39 | + CoreBlocksAssetManager $block_asset_manager, |
|
40 | + RequestInterface $request, |
|
41 | + EventAttendeesBlockRenderer $renderer |
|
42 | + ) { |
|
43 | + parent::__construct($block_asset_manager, $request); |
|
44 | + $this->renderer = $renderer; |
|
45 | + } |
|
46 | 46 | |
47 | 47 | |
48 | - /** |
|
49 | - * Perform any early setup required by the block |
|
50 | - * including setting the block type and supported post types |
|
51 | - * |
|
52 | - * @return void |
|
53 | - */ |
|
54 | - public function initialize() |
|
55 | - { |
|
56 | - $this->setBlockType(self::BLOCK_TYPE); |
|
57 | - $this->setSupportedRoutes( |
|
58 | - array( |
|
59 | - 'EventEspresso\core\domain\entities\route_match\specifications\admin\EspressoStandardPostTypeEditor', |
|
60 | - 'EventEspresso\core\domain\entities\route_match\specifications\admin\WordPressPostTypeEditor', |
|
61 | - 'EventEspresso\core\domain\entities\route_match\specifications\frontend\EspressoBlockRenderer', |
|
62 | - 'EventEspresso\core\domain\entities\route_match\specifications\frontend\AnyFrontendRequest' |
|
63 | - ) |
|
64 | - ); |
|
65 | - $EVT_ID = $this->request->getRequestParam('page') === 'espresso_events' |
|
66 | - ? $this->request->getRequestParam('post', 0, 'int') |
|
67 | - : 0; |
|
68 | - $this->setAttributes( |
|
69 | - array( |
|
70 | - 'eventId' => array( |
|
71 | - 'type' => 'number', |
|
72 | - 'default' => $EVT_ID, |
|
73 | - ), |
|
74 | - 'datetimeId' => array( |
|
75 | - 'type' => 'number', |
|
76 | - 'default' => 0, |
|
77 | - ), |
|
78 | - 'ticketId' => array( |
|
79 | - 'type' => 'number', |
|
80 | - 'default' => 0, |
|
81 | - ), |
|
82 | - 'status' => array( |
|
83 | - 'type' => 'string', |
|
84 | - 'default' => EEM_Registration::status_id_approved, |
|
85 | - ), |
|
86 | - 'limit' => array( |
|
87 | - 'type' => 'number', |
|
88 | - 'default' => 100, |
|
89 | - ), |
|
90 | - 'order' => array( |
|
91 | - 'type' => 'string', |
|
92 | - 'default' => 'ASC' |
|
93 | - ), |
|
94 | - 'orderBy' => array( |
|
95 | - 'type' => 'string', |
|
96 | - 'default' => 'lastThenFirstName', |
|
97 | - ), |
|
98 | - 'showGravatar' => array( |
|
99 | - 'type' => 'boolean', |
|
100 | - 'default' => false, |
|
101 | - ), |
|
102 | - 'avatarClass' => array( |
|
103 | - 'type' => 'string', |
|
104 | - 'default' => 'contact', |
|
105 | - ), |
|
106 | - 'avatarSize' => array( |
|
107 | - 'type' => 'number', |
|
108 | - 'default' => 24, |
|
109 | - ), |
|
110 | - 'displayOnArchives' => array( |
|
111 | - 'type' => 'boolean', |
|
112 | - 'default' => false, |
|
113 | - ), |
|
114 | - ) |
|
115 | - ); |
|
116 | - $this->setDynamic(); |
|
117 | - } |
|
48 | + /** |
|
49 | + * Perform any early setup required by the block |
|
50 | + * including setting the block type and supported post types |
|
51 | + * |
|
52 | + * @return void |
|
53 | + */ |
|
54 | + public function initialize() |
|
55 | + { |
|
56 | + $this->setBlockType(self::BLOCK_TYPE); |
|
57 | + $this->setSupportedRoutes( |
|
58 | + array( |
|
59 | + 'EventEspresso\core\domain\entities\route_match\specifications\admin\EspressoStandardPostTypeEditor', |
|
60 | + 'EventEspresso\core\domain\entities\route_match\specifications\admin\WordPressPostTypeEditor', |
|
61 | + 'EventEspresso\core\domain\entities\route_match\specifications\frontend\EspressoBlockRenderer', |
|
62 | + 'EventEspresso\core\domain\entities\route_match\specifications\frontend\AnyFrontendRequest' |
|
63 | + ) |
|
64 | + ); |
|
65 | + $EVT_ID = $this->request->getRequestParam('page') === 'espresso_events' |
|
66 | + ? $this->request->getRequestParam('post', 0, 'int') |
|
67 | + : 0; |
|
68 | + $this->setAttributes( |
|
69 | + array( |
|
70 | + 'eventId' => array( |
|
71 | + 'type' => 'number', |
|
72 | + 'default' => $EVT_ID, |
|
73 | + ), |
|
74 | + 'datetimeId' => array( |
|
75 | + 'type' => 'number', |
|
76 | + 'default' => 0, |
|
77 | + ), |
|
78 | + 'ticketId' => array( |
|
79 | + 'type' => 'number', |
|
80 | + 'default' => 0, |
|
81 | + ), |
|
82 | + 'status' => array( |
|
83 | + 'type' => 'string', |
|
84 | + 'default' => EEM_Registration::status_id_approved, |
|
85 | + ), |
|
86 | + 'limit' => array( |
|
87 | + 'type' => 'number', |
|
88 | + 'default' => 100, |
|
89 | + ), |
|
90 | + 'order' => array( |
|
91 | + 'type' => 'string', |
|
92 | + 'default' => 'ASC' |
|
93 | + ), |
|
94 | + 'orderBy' => array( |
|
95 | + 'type' => 'string', |
|
96 | + 'default' => 'lastThenFirstName', |
|
97 | + ), |
|
98 | + 'showGravatar' => array( |
|
99 | + 'type' => 'boolean', |
|
100 | + 'default' => false, |
|
101 | + ), |
|
102 | + 'avatarClass' => array( |
|
103 | + 'type' => 'string', |
|
104 | + 'default' => 'contact', |
|
105 | + ), |
|
106 | + 'avatarSize' => array( |
|
107 | + 'type' => 'number', |
|
108 | + 'default' => 24, |
|
109 | + ), |
|
110 | + 'displayOnArchives' => array( |
|
111 | + 'type' => 'boolean', |
|
112 | + 'default' => false, |
|
113 | + ), |
|
114 | + ) |
|
115 | + ); |
|
116 | + $this->setDynamic(); |
|
117 | + } |
|
118 | 118 | |
119 | 119 | |
120 | - /** |
|
121 | - * Returns an array where the key corresponds to the incoming attribute name from the WP block |
|
122 | - * and the value corresponds to the attribute name for the existing EspressoEventAttendees shortcode |
|
123 | - * |
|
124 | - * @since 4.9.71.p |
|
125 | - * @return array |
|
126 | - */ |
|
127 | - private function getAttributesMap() |
|
128 | - { |
|
129 | - return array( |
|
130 | - 'eventId' => 'absint', |
|
131 | - 'datetimeId' => 'absint', |
|
132 | - 'ticketId' => 'absint', |
|
133 | - 'status' => 'sanitize_text_field', |
|
134 | - 'limit' => 'intval', |
|
135 | - 'showGravatar' => 'bool', |
|
136 | - 'avatarClass' => 'sanitize_text_field', |
|
137 | - 'avatarSize' => 'absint', |
|
138 | - 'displayOnArchives' => 'bool', |
|
139 | - 'order' => 'sanitize_text_field', |
|
140 | - 'orderBy' => 'sanitize_text_field', |
|
141 | - ); |
|
142 | - } |
|
120 | + /** |
|
121 | + * Returns an array where the key corresponds to the incoming attribute name from the WP block |
|
122 | + * and the value corresponds to the attribute name for the existing EspressoEventAttendees shortcode |
|
123 | + * |
|
124 | + * @since 4.9.71.p |
|
125 | + * @return array |
|
126 | + */ |
|
127 | + private function getAttributesMap() |
|
128 | + { |
|
129 | + return array( |
|
130 | + 'eventId' => 'absint', |
|
131 | + 'datetimeId' => 'absint', |
|
132 | + 'ticketId' => 'absint', |
|
133 | + 'status' => 'sanitize_text_field', |
|
134 | + 'limit' => 'intval', |
|
135 | + 'showGravatar' => 'bool', |
|
136 | + 'avatarClass' => 'sanitize_text_field', |
|
137 | + 'avatarSize' => 'absint', |
|
138 | + 'displayOnArchives' => 'bool', |
|
139 | + 'order' => 'sanitize_text_field', |
|
140 | + 'orderBy' => 'sanitize_text_field', |
|
141 | + ); |
|
142 | + } |
|
143 | 143 | |
144 | 144 | |
145 | - /** |
|
146 | - * Sanitizes attributes. |
|
147 | - * |
|
148 | - * @param array $attributes |
|
149 | - * @return array |
|
150 | - */ |
|
151 | - private function sanitizeAttributes(array $attributes) |
|
152 | - { |
|
153 | - $sanitized_attributes = array(); |
|
154 | - foreach ($attributes as $attribute => $value) { |
|
155 | - $convert = $this->getAttributesMap(); |
|
156 | - if (isset($convert[ $attribute ])) { |
|
157 | - $sanitize = $convert[ $attribute ]; |
|
158 | - if ($sanitize === 'bool') { |
|
159 | - $sanitized_attributes[ $attribute ] = filter_var( |
|
160 | - $value, |
|
161 | - FILTER_VALIDATE_BOOLEAN |
|
162 | - ); |
|
163 | - } else { |
|
164 | - $sanitized_attributes[ $attribute ] = $sanitize($value); |
|
165 | - } |
|
166 | - // don't pass along attributes with a 0 value |
|
167 | - if ($sanitized_attributes[ $attribute ] === 0) { |
|
168 | - unset($sanitized_attributes[ $attribute ]); |
|
169 | - } |
|
170 | - } |
|
171 | - } |
|
172 | - return $attributes; |
|
173 | - } |
|
145 | + /** |
|
146 | + * Sanitizes attributes. |
|
147 | + * |
|
148 | + * @param array $attributes |
|
149 | + * @return array |
|
150 | + */ |
|
151 | + private function sanitizeAttributes(array $attributes) |
|
152 | + { |
|
153 | + $sanitized_attributes = array(); |
|
154 | + foreach ($attributes as $attribute => $value) { |
|
155 | + $convert = $this->getAttributesMap(); |
|
156 | + if (isset($convert[ $attribute ])) { |
|
157 | + $sanitize = $convert[ $attribute ]; |
|
158 | + if ($sanitize === 'bool') { |
|
159 | + $sanitized_attributes[ $attribute ] = filter_var( |
|
160 | + $value, |
|
161 | + FILTER_VALIDATE_BOOLEAN |
|
162 | + ); |
|
163 | + } else { |
|
164 | + $sanitized_attributes[ $attribute ] = $sanitize($value); |
|
165 | + } |
|
166 | + // don't pass along attributes with a 0 value |
|
167 | + if ($sanitized_attributes[ $attribute ] === 0) { |
|
168 | + unset($sanitized_attributes[ $attribute ]); |
|
169 | + } |
|
170 | + } |
|
171 | + } |
|
172 | + return $attributes; |
|
173 | + } |
|
174 | 174 | |
175 | 175 | |
176 | - /** |
|
177 | - * Returns the rendered HTML for the block |
|
178 | - * |
|
179 | - * @param array $attributes |
|
180 | - * @return string |
|
181 | - * @throws DomainException |
|
182 | - * @throws EE_Error |
|
183 | - */ |
|
184 | - public function renderBlock(array $attributes = array()) |
|
185 | - { |
|
186 | - $attributes = $this->sanitizeAttributes($attributes); |
|
187 | - return (is_archive() || is_front_page() || is_home()) && ! $attributes['displayOnArchives'] |
|
188 | - ? '' |
|
189 | - : $this->renderer->render($attributes); |
|
190 | - } |
|
176 | + /** |
|
177 | + * Returns the rendered HTML for the block |
|
178 | + * |
|
179 | + * @param array $attributes |
|
180 | + * @return string |
|
181 | + * @throws DomainException |
|
182 | + * @throws EE_Error |
|
183 | + */ |
|
184 | + public function renderBlock(array $attributes = array()) |
|
185 | + { |
|
186 | + $attributes = $this->sanitizeAttributes($attributes); |
|
187 | + return (is_archive() || is_front_page() || is_home()) && ! $attributes['displayOnArchives'] |
|
188 | + ? '' |
|
189 | + : $this->renderer->render($attributes); |
|
190 | + } |
|
191 | 191 | } |