@@ -4,7 +4,6 @@ |
||
4 | 4 | |
5 | 5 | use EE_Error; |
6 | 6 | use EE_Request; |
7 | -use EventEspresso\core\exceptions\ExceptionStackTraceDisplay; |
|
8 | 7 | use EventEspresso\core\exceptions\InvalidClassException; |
9 | 8 | use EventEspresso\core\exceptions\InvalidDataTypeException; |
10 | 9 | use EventEspresso\core\exceptions\InvalidEntityException; |
@@ -29,584 +29,584 @@ |
||
29 | 29 | abstract class SequentialStepFormManager |
30 | 30 | { |
31 | 31 | |
32 | - /** |
|
33 | - * a simplified URL with no form related parameters |
|
34 | - * that will be used to build the form's redirect URLs |
|
35 | - * |
|
36 | - * @var string $base_url |
|
37 | - */ |
|
38 | - private $base_url = ''; |
|
39 | - |
|
40 | - /** |
|
41 | - * the key used for the URL param that denotes the current form step |
|
42 | - * defaults to 'ee-form-step' |
|
43 | - * |
|
44 | - * @var string $form_step_url_key |
|
45 | - */ |
|
46 | - private $form_step_url_key = ''; |
|
47 | - |
|
48 | - /** |
|
49 | - * @var string $default_form_step |
|
50 | - */ |
|
51 | - private $default_form_step = ''; |
|
52 | - |
|
53 | - /** |
|
54 | - * @var string $form_action |
|
55 | - */ |
|
56 | - private $form_action; |
|
57 | - |
|
58 | - /** |
|
59 | - * value of one of the string constant above |
|
60 | - * |
|
61 | - * @var string $form_config |
|
62 | - */ |
|
63 | - private $form_config; |
|
64 | - |
|
65 | - /** |
|
66 | - * @var string $progress_step_style |
|
67 | - */ |
|
68 | - private $progress_step_style = ''; |
|
69 | - |
|
70 | - /** |
|
71 | - * @var EE_Request $request |
|
72 | - */ |
|
73 | - private $request; |
|
74 | - |
|
75 | - /** |
|
76 | - * @var Collection $form_steps |
|
77 | - */ |
|
78 | - protected $form_steps; |
|
79 | - |
|
80 | - /** |
|
81 | - * @var ProgressStepManager $progress_step_manager |
|
82 | - */ |
|
83 | - protected $progress_step_manager; |
|
84 | - |
|
85 | - |
|
86 | - /** |
|
87 | - * @return Collection|null |
|
88 | - */ |
|
89 | - abstract protected function getFormStepsCollection(); |
|
90 | - |
|
91 | - // phpcs:disable PEAR.Functions.ValidDefaultValue.NotAtEnd |
|
92 | - /** |
|
93 | - * StepsManager constructor |
|
94 | - * |
|
95 | - * @param string $base_url |
|
96 | - * @param string $default_form_step |
|
97 | - * @param string $form_action |
|
98 | - * @param string $form_config |
|
99 | - * @param EE_Request $request |
|
100 | - * @param string $progress_step_style |
|
101 | - * @throws InvalidDataTypeException |
|
102 | - * @throws InvalidArgumentException |
|
103 | - */ |
|
104 | - public function __construct( |
|
105 | - $base_url, |
|
106 | - $default_form_step, |
|
107 | - $form_action = '', |
|
108 | - $form_config = FormHandler::ADD_FORM_TAGS_AND_SUBMIT, |
|
109 | - $progress_step_style = 'number_bubbles', |
|
110 | - EE_Request $request |
|
111 | - ) { |
|
112 | - $this->setBaseUrl($base_url); |
|
113 | - $this->setDefaultFormStep($default_form_step); |
|
114 | - $this->setFormAction($form_action); |
|
115 | - $this->setFormConfig($form_config); |
|
116 | - $this->setProgressStepStyle($progress_step_style); |
|
117 | - $this->request = $request; |
|
118 | - } |
|
119 | - |
|
120 | - |
|
121 | - /** |
|
122 | - * @return string |
|
123 | - * @throws InvalidFormHandlerException |
|
124 | - */ |
|
125 | - public function baseUrl() |
|
126 | - { |
|
127 | - if (strpos($this->base_url, $this->getCurrentStep()->slug()) === false) { |
|
128 | - add_query_arg( |
|
129 | - array($this->form_step_url_key => $this->getCurrentStep()->slug()), |
|
130 | - $this->base_url |
|
131 | - ); |
|
132 | - } |
|
133 | - return $this->base_url; |
|
134 | - } |
|
135 | - |
|
136 | - |
|
137 | - /** |
|
138 | - * @param string $base_url |
|
139 | - * @throws InvalidDataTypeException |
|
140 | - * @throws InvalidArgumentException |
|
141 | - */ |
|
142 | - protected function setBaseUrl($base_url) |
|
143 | - { |
|
144 | - if (! is_string($base_url)) { |
|
145 | - throw new InvalidDataTypeException('$base_url', $base_url, 'string'); |
|
146 | - } |
|
147 | - if (empty($base_url)) { |
|
148 | - throw new InvalidArgumentException( |
|
149 | - esc_html__('The base URL can not be an empty string.', 'event_espresso') |
|
150 | - ); |
|
151 | - } |
|
152 | - $this->base_url = $base_url; |
|
153 | - } |
|
154 | - |
|
155 | - |
|
156 | - /** |
|
157 | - * @return string |
|
158 | - * @throws InvalidDataTypeException |
|
159 | - */ |
|
160 | - public function formStepUrlKey() |
|
161 | - { |
|
162 | - if (empty($this->form_step_url_key)) { |
|
163 | - $this->setFormStepUrlKey(); |
|
164 | - } |
|
165 | - return $this->form_step_url_key; |
|
166 | - } |
|
167 | - |
|
168 | - |
|
169 | - /** |
|
170 | - * @param string $form_step_url_key |
|
171 | - * @throws InvalidDataTypeException |
|
172 | - */ |
|
173 | - public function setFormStepUrlKey($form_step_url_key = 'ee-form-step') |
|
174 | - { |
|
175 | - if (! is_string($form_step_url_key)) { |
|
176 | - throw new InvalidDataTypeException('$form_step_key', $form_step_url_key, 'string'); |
|
177 | - } |
|
178 | - $this->form_step_url_key = ! empty($form_step_url_key) ? $form_step_url_key : 'ee-form-step'; |
|
179 | - } |
|
180 | - |
|
181 | - |
|
182 | - /** |
|
183 | - * @return string |
|
184 | - */ |
|
185 | - public function defaultFormStep() |
|
186 | - { |
|
187 | - return $this->default_form_step; |
|
188 | - } |
|
189 | - |
|
190 | - |
|
191 | - /** |
|
192 | - * @param $default_form_step |
|
193 | - * @throws InvalidDataTypeException |
|
194 | - */ |
|
195 | - protected function setDefaultFormStep($default_form_step) |
|
196 | - { |
|
197 | - if (! is_string($default_form_step)) { |
|
198 | - throw new InvalidDataTypeException('$default_form_step', $default_form_step, 'string'); |
|
199 | - } |
|
200 | - $this->default_form_step = $default_form_step; |
|
201 | - } |
|
202 | - |
|
203 | - |
|
204 | - /** |
|
205 | - * @return void |
|
206 | - * @throws \EventEspresso\core\exceptions\InvalidIdentifierException |
|
207 | - * @throws InvalidDataTypeException |
|
208 | - */ |
|
209 | - protected function setCurrentStepFromRequest() |
|
210 | - { |
|
211 | - $current_step_slug = $this->request()->get($this->formStepUrlKey(), $this->defaultFormStep()); |
|
212 | - if (! $this->form_steps->setCurrent($current_step_slug)) { |
|
213 | - throw new InvalidIdentifierException( |
|
214 | - $current_step_slug, |
|
215 | - $this->defaultFormStep(), |
|
216 | - $message = sprintf( |
|
217 | - esc_html__( |
|
218 | - 'The "%1$s" form step could not be set.', |
|
219 | - 'event_espresso' |
|
220 | - ), |
|
221 | - $current_step_slug |
|
222 | - ) |
|
223 | - ); |
|
224 | - } |
|
225 | - } |
|
226 | - |
|
227 | - |
|
228 | - /** |
|
229 | - * @return object|SequentialStepFormInterface |
|
230 | - * @throws InvalidFormHandlerException |
|
231 | - */ |
|
232 | - public function getCurrentStep() |
|
233 | - { |
|
234 | - if (! $this->form_steps->current() instanceof SequentialStepForm) { |
|
235 | - throw new InvalidFormHandlerException($this->form_steps->current()); |
|
236 | - } |
|
237 | - return $this->form_steps->current(); |
|
238 | - } |
|
239 | - |
|
240 | - |
|
241 | - /** |
|
242 | - * @return string |
|
243 | - * @throws InvalidFormHandlerException |
|
244 | - */ |
|
245 | - public function formAction() |
|
246 | - { |
|
247 | - if (! is_string($this->form_action) || empty($this->form_action)) { |
|
248 | - $this->form_action = $this->baseUrl(); |
|
249 | - } |
|
250 | - return $this->form_action; |
|
251 | - } |
|
252 | - |
|
253 | - |
|
254 | - /** |
|
255 | - * @param string $form_action |
|
256 | - * @throws InvalidDataTypeException |
|
257 | - */ |
|
258 | - public function setFormAction($form_action) |
|
259 | - { |
|
260 | - if (! is_string($form_action)) { |
|
261 | - throw new InvalidDataTypeException('$form_action', $form_action, 'string'); |
|
262 | - } |
|
263 | - $this->form_action = $form_action; |
|
264 | - } |
|
265 | - |
|
266 | - |
|
267 | - /** |
|
268 | - * @param array $form_action_args |
|
269 | - * @throws InvalidDataTypeException |
|
270 | - * @throws InvalidFormHandlerException |
|
271 | - */ |
|
272 | - public function addFormActionArgs($form_action_args = array()) |
|
273 | - { |
|
274 | - if (! is_array($form_action_args)) { |
|
275 | - throw new InvalidDataTypeException('$form_action_args', $form_action_args, 'array'); |
|
276 | - } |
|
277 | - $form_action_args = ! empty($form_action_args) |
|
278 | - ? $form_action_args |
|
279 | - : array($this->formStepUrlKey() => $this->form_steps->current()->slug()); |
|
280 | - $this->getCurrentStep()->setFormAction( |
|
281 | - add_query_arg($form_action_args, $this->formAction()) |
|
282 | - ); |
|
283 | - $this->form_action = $this->getCurrentStep()->formAction(); |
|
284 | - } |
|
285 | - |
|
286 | - |
|
287 | - /** |
|
288 | - * @return string |
|
289 | - */ |
|
290 | - public function formConfig() |
|
291 | - { |
|
292 | - return $this->form_config; |
|
293 | - } |
|
294 | - |
|
295 | - |
|
296 | - /** |
|
297 | - * @param string $form_config |
|
298 | - */ |
|
299 | - public function setFormConfig($form_config) |
|
300 | - { |
|
301 | - $this->form_config = $form_config; |
|
302 | - } |
|
303 | - |
|
304 | - |
|
305 | - /** |
|
306 | - * @return string |
|
307 | - */ |
|
308 | - public function progressStepStyle() |
|
309 | - { |
|
310 | - return $this->progress_step_style; |
|
311 | - } |
|
312 | - |
|
313 | - |
|
314 | - /** |
|
315 | - * @param string $progress_step_style |
|
316 | - */ |
|
317 | - public function setProgressStepStyle($progress_step_style) |
|
318 | - { |
|
319 | - $this->progress_step_style = $progress_step_style; |
|
320 | - } |
|
321 | - |
|
322 | - |
|
323 | - /** |
|
324 | - * @return EE_Request |
|
325 | - */ |
|
326 | - public function request() |
|
327 | - { |
|
328 | - return $this->request; |
|
329 | - } |
|
330 | - |
|
331 | - |
|
332 | - /** |
|
333 | - * @return Collection|null |
|
334 | - * @throws InvalidInterfaceException |
|
335 | - */ |
|
336 | - protected function getProgressStepsCollection() |
|
337 | - { |
|
338 | - static $collection = null; |
|
339 | - if (! $collection instanceof ProgressStepCollection) { |
|
340 | - $collection = new ProgressStepCollection(); |
|
341 | - } |
|
342 | - return $collection; |
|
343 | - } |
|
344 | - |
|
345 | - |
|
346 | - /** |
|
347 | - * @param Collection $progress_steps_collection |
|
348 | - * @return ProgressStepManager |
|
349 | - * @throws InvalidInterfaceException |
|
350 | - * @throws InvalidClassException |
|
351 | - * @throws InvalidDataTypeException |
|
352 | - * @throws InvalidEntityException |
|
353 | - * @throws InvalidFormHandlerException |
|
354 | - */ |
|
355 | - protected function generateProgressSteps(Collection $progress_steps_collection) |
|
356 | - { |
|
357 | - $current_step = $this->getCurrentStep(); |
|
358 | - /** @var SequentialStepForm $form_step */ |
|
359 | - foreach ($this->form_steps as $form_step) { |
|
360 | - // is this step active ? |
|
361 | - if (! $form_step->initialize()) { |
|
362 | - continue; |
|
363 | - } |
|
364 | - $progress_steps_collection->add( |
|
365 | - new ProgressStep( |
|
366 | - $form_step->order(), |
|
367 | - $form_step->slug(), |
|
368 | - $form_step->slug(), |
|
369 | - $form_step->formName() |
|
370 | - ), |
|
371 | - $form_step->slug() |
|
372 | - ); |
|
373 | - } |
|
374 | - // set collection pointer back to current step |
|
375 | - $this->form_steps->setCurrentUsingObject($current_step); |
|
376 | - return new ProgressStepManager( |
|
377 | - $this->progressStepStyle(), |
|
378 | - $this->defaultFormStep(), |
|
379 | - $this->formStepUrlKey(), |
|
380 | - $progress_steps_collection |
|
381 | - ); |
|
382 | - } |
|
383 | - |
|
384 | - |
|
385 | - /** |
|
386 | - * @throws InvalidClassException |
|
387 | - * @throws InvalidDataTypeException |
|
388 | - * @throws InvalidEntityException |
|
389 | - * @throws InvalidIdentifierException |
|
390 | - * @throws InvalidInterfaceException |
|
391 | - * @throws InvalidArgumentException |
|
392 | - * @throws InvalidFormHandlerException |
|
393 | - */ |
|
394 | - public function buildForm() |
|
395 | - { |
|
396 | - $this->buildCurrentStepFormForDisplay(); |
|
397 | - } |
|
398 | - |
|
399 | - |
|
400 | - /** |
|
401 | - * @param array $form_data |
|
402 | - * @throws InvalidArgumentException |
|
403 | - * @throws InvalidClassException |
|
404 | - * @throws InvalidDataTypeException |
|
405 | - * @throws InvalidEntityException |
|
406 | - * @throws InvalidFormHandlerException |
|
407 | - * @throws InvalidIdentifierException |
|
408 | - * @throws InvalidInterfaceException |
|
409 | - */ |
|
410 | - public function processForm($form_data = array()) |
|
411 | - { |
|
412 | - $this->buildCurrentStepFormForProcessing(); |
|
413 | - $this->processCurrentStepForm($form_data); |
|
414 | - } |
|
415 | - |
|
416 | - |
|
417 | - /** |
|
418 | - * @throws InvalidClassException |
|
419 | - * @throws InvalidDataTypeException |
|
420 | - * @throws InvalidEntityException |
|
421 | - * @throws InvalidInterfaceException |
|
422 | - * @throws InvalidIdentifierException |
|
423 | - * @throws InvalidArgumentException |
|
424 | - * @throws InvalidFormHandlerException |
|
425 | - */ |
|
426 | - public function buildCurrentStepFormForDisplay() |
|
427 | - { |
|
428 | - $form_step = $this->buildCurrentStepForm(); |
|
429 | - // no displayable content ? then skip straight to processing |
|
430 | - if (! $form_step->displayable()) { |
|
431 | - $this->addFormActionArgs(); |
|
432 | - $form_step->setFormAction($this->formAction()); |
|
433 | - wp_safe_redirect($form_step->formAction()); |
|
434 | - } |
|
435 | - } |
|
436 | - |
|
437 | - |
|
438 | - /** |
|
439 | - * @throws InvalidClassException |
|
440 | - * @throws InvalidDataTypeException |
|
441 | - * @throws InvalidEntityException |
|
442 | - * @throws InvalidInterfaceException |
|
443 | - * @throws InvalidIdentifierException |
|
444 | - * @throws InvalidArgumentException |
|
445 | - * @throws InvalidFormHandlerException |
|
446 | - */ |
|
447 | - public function buildCurrentStepFormForProcessing() |
|
448 | - { |
|
449 | - $this->buildCurrentStepForm(false); |
|
450 | - } |
|
451 | - |
|
452 | - |
|
453 | - /** |
|
454 | - * @param bool $for_display |
|
455 | - * @return SequentialStepFormInterface |
|
456 | - * @throws InvalidArgumentException |
|
457 | - * @throws InvalidClassException |
|
458 | - * @throws InvalidDataTypeException |
|
459 | - * @throws InvalidEntityException |
|
460 | - * @throws InvalidFormHandlerException |
|
461 | - * @throws InvalidIdentifierException |
|
462 | - * @throws InvalidInterfaceException |
|
463 | - */ |
|
464 | - private function buildCurrentStepForm($for_display = true) |
|
465 | - { |
|
466 | - $this->form_steps = $this->getFormStepsCollection(); |
|
467 | - $this->setCurrentStepFromRequest(); |
|
468 | - $form_step = $this->getCurrentStep(); |
|
469 | - if ($form_step->submitBtnText() === esc_html__('Submit', 'event_espresso')) { |
|
470 | - $form_step->setSubmitBtnText(esc_html__('Next Step', 'event_espresso')); |
|
471 | - } |
|
472 | - if ($for_display && $form_step->displayable()) { |
|
473 | - $this->progress_step_manager = $this->generateProgressSteps( |
|
474 | - $this->getProgressStepsCollection() |
|
475 | - ); |
|
476 | - $this->progress_step_manager->setCurrentStep( |
|
477 | - $form_step->slug() |
|
478 | - ); |
|
479 | - // mark all previous progress steps as completed |
|
480 | - $this->progress_step_manager->setPreviousStepsCompleted(); |
|
481 | - $this->progress_step_manager->enqueueStylesAndScripts(); |
|
482 | - $this->addFormActionArgs(); |
|
483 | - $form_step->setFormAction($this->formAction()); |
|
484 | - } else { |
|
485 | - $form_step->setRedirectUrl($this->baseUrl()); |
|
486 | - $form_step->addRedirectArgs( |
|
487 | - array($this->formStepUrlKey() => $this->form_steps->current()->slug()) |
|
488 | - ); |
|
489 | - } |
|
490 | - $form_step->generate(); |
|
491 | - if ($for_display) { |
|
492 | - $form_step->enqueueStylesAndScripts(); |
|
493 | - } |
|
494 | - return $form_step; |
|
495 | - } |
|
496 | - |
|
497 | - |
|
498 | - /** |
|
499 | - * @param bool $return_as_string |
|
500 | - * @return string |
|
501 | - * @throws InvalidFormHandlerException |
|
502 | - */ |
|
503 | - public function displayProgressSteps($return_as_string = true) |
|
504 | - { |
|
505 | - $form_step = $this->getCurrentStep(); |
|
506 | - if (! $form_step->displayable()) { |
|
507 | - return ''; |
|
508 | - } |
|
509 | - $progress_steps = apply_filters( |
|
510 | - 'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_SequentialStepFormManager__displayProgressSteps__before_steps', |
|
511 | - '' |
|
512 | - ); |
|
513 | - $progress_steps .= $this->progress_step_manager->displaySteps(); |
|
514 | - $progress_steps .= apply_filters( |
|
515 | - 'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_SequentialStepFormManager__displayProgressSteps__after_steps', |
|
516 | - '' |
|
517 | - ); |
|
518 | - if ($return_as_string) { |
|
519 | - return $progress_steps; |
|
520 | - } |
|
521 | - echo $progress_steps; |
|
522 | - return ''; |
|
523 | - } |
|
524 | - |
|
525 | - |
|
526 | - /** |
|
527 | - * @param bool $return_as_string |
|
528 | - * @return string |
|
529 | - * @throws InvalidFormHandlerException |
|
530 | - */ |
|
531 | - public function displayCurrentStepForm($return_as_string = true) |
|
532 | - { |
|
533 | - if ($return_as_string) { |
|
534 | - return $this->getCurrentStep()->display(); |
|
535 | - } |
|
536 | - echo $this->getCurrentStep()->display(); |
|
537 | - return ''; |
|
538 | - } |
|
539 | - |
|
540 | - |
|
541 | - /** |
|
542 | - * @param array $form_data |
|
543 | - * @return void |
|
544 | - * @throws InvalidArgumentException |
|
545 | - * @throws InvalidDataTypeException |
|
546 | - * @throws InvalidFormHandlerException |
|
547 | - */ |
|
548 | - public function processCurrentStepForm($form_data = array()) |
|
549 | - { |
|
550 | - // grab instance of current step because after calling next() below, |
|
551 | - // any calls to getCurrentStep() will return the "next" step because we advanced |
|
552 | - $current_step = $this->getCurrentStep(); |
|
553 | - try { |
|
554 | - // form processing should either throw exceptions or return true |
|
555 | - $current_step->process($form_data); |
|
556 | - } catch (Exception $e) { |
|
557 | - // something went wrong, convert the Exception to an EE_Error |
|
558 | - EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
559 | - // prevent redirect to next step or other if exception was thrown |
|
560 | - if ($current_step->redirectTo() === SequentialStepForm::REDIRECT_TO_NEXT_STEP |
|
561 | - || $current_step->redirectTo() === SequentialStepForm::REDIRECT_TO_OTHER |
|
562 | - ) { |
|
563 | - $current_step->setRedirectTo(SequentialStepForm::REDIRECT_TO_CURRENT_STEP); |
|
564 | - } |
|
565 | - } |
|
566 | - // save notices to a transient so that when we redirect back |
|
567 | - // to the display portion for this step |
|
568 | - // those notices can be displayed |
|
569 | - EE_Error::get_notices(false, true); |
|
570 | - $this->redirectForm($current_step); |
|
571 | - } |
|
572 | - |
|
573 | - |
|
574 | - /** |
|
575 | - * handles where to go to next |
|
576 | - * |
|
577 | - * @param SequentialStepFormInterface $current_step |
|
578 | - * @throws InvalidArgumentException |
|
579 | - * @throws InvalidDataTypeException |
|
580 | - * @throws InvalidFormHandlerException |
|
581 | - */ |
|
582 | - public function redirectForm(SequentialStepFormInterface $current_step) |
|
583 | - { |
|
584 | - $redirect_step = $current_step; |
|
585 | - switch ($current_step->redirectTo()) { |
|
586 | - case SequentialStepForm::REDIRECT_TO_OTHER: |
|
587 | - // going somewhere else, so just check out now |
|
588 | - wp_safe_redirect($redirect_step->redirectUrl()); |
|
589 | - exit(); |
|
590 | - break; |
|
591 | - case SequentialStepForm::REDIRECT_TO_PREV_STEP: |
|
592 | - $redirect_step = $this->form_steps->previous(); |
|
593 | - break; |
|
594 | - case SequentialStepForm::REDIRECT_TO_NEXT_STEP: |
|
595 | - $this->form_steps->next(); |
|
596 | - if ($this->form_steps->valid()) { |
|
597 | - $redirect_step = $this->form_steps->current(); |
|
598 | - } |
|
599 | - break; |
|
600 | - case SequentialStepForm::REDIRECT_TO_CURRENT_STEP: |
|
601 | - default: |
|
602 | - // $redirect_step is already set |
|
603 | - } |
|
604 | - $current_step->setRedirectUrl($this->baseUrl()); |
|
605 | - $current_step->addRedirectArgs( |
|
606 | - // use the slug for whatever step we are redirecting too |
|
607 | - array($this->formStepUrlKey() => $redirect_step->slug()) |
|
608 | - ); |
|
609 | - wp_safe_redirect($current_step->redirectUrl()); |
|
610 | - exit(); |
|
611 | - } |
|
32 | + /** |
|
33 | + * a simplified URL with no form related parameters |
|
34 | + * that will be used to build the form's redirect URLs |
|
35 | + * |
|
36 | + * @var string $base_url |
|
37 | + */ |
|
38 | + private $base_url = ''; |
|
39 | + |
|
40 | + /** |
|
41 | + * the key used for the URL param that denotes the current form step |
|
42 | + * defaults to 'ee-form-step' |
|
43 | + * |
|
44 | + * @var string $form_step_url_key |
|
45 | + */ |
|
46 | + private $form_step_url_key = ''; |
|
47 | + |
|
48 | + /** |
|
49 | + * @var string $default_form_step |
|
50 | + */ |
|
51 | + private $default_form_step = ''; |
|
52 | + |
|
53 | + /** |
|
54 | + * @var string $form_action |
|
55 | + */ |
|
56 | + private $form_action; |
|
57 | + |
|
58 | + /** |
|
59 | + * value of one of the string constant above |
|
60 | + * |
|
61 | + * @var string $form_config |
|
62 | + */ |
|
63 | + private $form_config; |
|
64 | + |
|
65 | + /** |
|
66 | + * @var string $progress_step_style |
|
67 | + */ |
|
68 | + private $progress_step_style = ''; |
|
69 | + |
|
70 | + /** |
|
71 | + * @var EE_Request $request |
|
72 | + */ |
|
73 | + private $request; |
|
74 | + |
|
75 | + /** |
|
76 | + * @var Collection $form_steps |
|
77 | + */ |
|
78 | + protected $form_steps; |
|
79 | + |
|
80 | + /** |
|
81 | + * @var ProgressStepManager $progress_step_manager |
|
82 | + */ |
|
83 | + protected $progress_step_manager; |
|
84 | + |
|
85 | + |
|
86 | + /** |
|
87 | + * @return Collection|null |
|
88 | + */ |
|
89 | + abstract protected function getFormStepsCollection(); |
|
90 | + |
|
91 | + // phpcs:disable PEAR.Functions.ValidDefaultValue.NotAtEnd |
|
92 | + /** |
|
93 | + * StepsManager constructor |
|
94 | + * |
|
95 | + * @param string $base_url |
|
96 | + * @param string $default_form_step |
|
97 | + * @param string $form_action |
|
98 | + * @param string $form_config |
|
99 | + * @param EE_Request $request |
|
100 | + * @param string $progress_step_style |
|
101 | + * @throws InvalidDataTypeException |
|
102 | + * @throws InvalidArgumentException |
|
103 | + */ |
|
104 | + public function __construct( |
|
105 | + $base_url, |
|
106 | + $default_form_step, |
|
107 | + $form_action = '', |
|
108 | + $form_config = FormHandler::ADD_FORM_TAGS_AND_SUBMIT, |
|
109 | + $progress_step_style = 'number_bubbles', |
|
110 | + EE_Request $request |
|
111 | + ) { |
|
112 | + $this->setBaseUrl($base_url); |
|
113 | + $this->setDefaultFormStep($default_form_step); |
|
114 | + $this->setFormAction($form_action); |
|
115 | + $this->setFormConfig($form_config); |
|
116 | + $this->setProgressStepStyle($progress_step_style); |
|
117 | + $this->request = $request; |
|
118 | + } |
|
119 | + |
|
120 | + |
|
121 | + /** |
|
122 | + * @return string |
|
123 | + * @throws InvalidFormHandlerException |
|
124 | + */ |
|
125 | + public function baseUrl() |
|
126 | + { |
|
127 | + if (strpos($this->base_url, $this->getCurrentStep()->slug()) === false) { |
|
128 | + add_query_arg( |
|
129 | + array($this->form_step_url_key => $this->getCurrentStep()->slug()), |
|
130 | + $this->base_url |
|
131 | + ); |
|
132 | + } |
|
133 | + return $this->base_url; |
|
134 | + } |
|
135 | + |
|
136 | + |
|
137 | + /** |
|
138 | + * @param string $base_url |
|
139 | + * @throws InvalidDataTypeException |
|
140 | + * @throws InvalidArgumentException |
|
141 | + */ |
|
142 | + protected function setBaseUrl($base_url) |
|
143 | + { |
|
144 | + if (! is_string($base_url)) { |
|
145 | + throw new InvalidDataTypeException('$base_url', $base_url, 'string'); |
|
146 | + } |
|
147 | + if (empty($base_url)) { |
|
148 | + throw new InvalidArgumentException( |
|
149 | + esc_html__('The base URL can not be an empty string.', 'event_espresso') |
|
150 | + ); |
|
151 | + } |
|
152 | + $this->base_url = $base_url; |
|
153 | + } |
|
154 | + |
|
155 | + |
|
156 | + /** |
|
157 | + * @return string |
|
158 | + * @throws InvalidDataTypeException |
|
159 | + */ |
|
160 | + public function formStepUrlKey() |
|
161 | + { |
|
162 | + if (empty($this->form_step_url_key)) { |
|
163 | + $this->setFormStepUrlKey(); |
|
164 | + } |
|
165 | + return $this->form_step_url_key; |
|
166 | + } |
|
167 | + |
|
168 | + |
|
169 | + /** |
|
170 | + * @param string $form_step_url_key |
|
171 | + * @throws InvalidDataTypeException |
|
172 | + */ |
|
173 | + public function setFormStepUrlKey($form_step_url_key = 'ee-form-step') |
|
174 | + { |
|
175 | + if (! is_string($form_step_url_key)) { |
|
176 | + throw new InvalidDataTypeException('$form_step_key', $form_step_url_key, 'string'); |
|
177 | + } |
|
178 | + $this->form_step_url_key = ! empty($form_step_url_key) ? $form_step_url_key : 'ee-form-step'; |
|
179 | + } |
|
180 | + |
|
181 | + |
|
182 | + /** |
|
183 | + * @return string |
|
184 | + */ |
|
185 | + public function defaultFormStep() |
|
186 | + { |
|
187 | + return $this->default_form_step; |
|
188 | + } |
|
189 | + |
|
190 | + |
|
191 | + /** |
|
192 | + * @param $default_form_step |
|
193 | + * @throws InvalidDataTypeException |
|
194 | + */ |
|
195 | + protected function setDefaultFormStep($default_form_step) |
|
196 | + { |
|
197 | + if (! is_string($default_form_step)) { |
|
198 | + throw new InvalidDataTypeException('$default_form_step', $default_form_step, 'string'); |
|
199 | + } |
|
200 | + $this->default_form_step = $default_form_step; |
|
201 | + } |
|
202 | + |
|
203 | + |
|
204 | + /** |
|
205 | + * @return void |
|
206 | + * @throws \EventEspresso\core\exceptions\InvalidIdentifierException |
|
207 | + * @throws InvalidDataTypeException |
|
208 | + */ |
|
209 | + protected function setCurrentStepFromRequest() |
|
210 | + { |
|
211 | + $current_step_slug = $this->request()->get($this->formStepUrlKey(), $this->defaultFormStep()); |
|
212 | + if (! $this->form_steps->setCurrent($current_step_slug)) { |
|
213 | + throw new InvalidIdentifierException( |
|
214 | + $current_step_slug, |
|
215 | + $this->defaultFormStep(), |
|
216 | + $message = sprintf( |
|
217 | + esc_html__( |
|
218 | + 'The "%1$s" form step could not be set.', |
|
219 | + 'event_espresso' |
|
220 | + ), |
|
221 | + $current_step_slug |
|
222 | + ) |
|
223 | + ); |
|
224 | + } |
|
225 | + } |
|
226 | + |
|
227 | + |
|
228 | + /** |
|
229 | + * @return object|SequentialStepFormInterface |
|
230 | + * @throws InvalidFormHandlerException |
|
231 | + */ |
|
232 | + public function getCurrentStep() |
|
233 | + { |
|
234 | + if (! $this->form_steps->current() instanceof SequentialStepForm) { |
|
235 | + throw new InvalidFormHandlerException($this->form_steps->current()); |
|
236 | + } |
|
237 | + return $this->form_steps->current(); |
|
238 | + } |
|
239 | + |
|
240 | + |
|
241 | + /** |
|
242 | + * @return string |
|
243 | + * @throws InvalidFormHandlerException |
|
244 | + */ |
|
245 | + public function formAction() |
|
246 | + { |
|
247 | + if (! is_string($this->form_action) || empty($this->form_action)) { |
|
248 | + $this->form_action = $this->baseUrl(); |
|
249 | + } |
|
250 | + return $this->form_action; |
|
251 | + } |
|
252 | + |
|
253 | + |
|
254 | + /** |
|
255 | + * @param string $form_action |
|
256 | + * @throws InvalidDataTypeException |
|
257 | + */ |
|
258 | + public function setFormAction($form_action) |
|
259 | + { |
|
260 | + if (! is_string($form_action)) { |
|
261 | + throw new InvalidDataTypeException('$form_action', $form_action, 'string'); |
|
262 | + } |
|
263 | + $this->form_action = $form_action; |
|
264 | + } |
|
265 | + |
|
266 | + |
|
267 | + /** |
|
268 | + * @param array $form_action_args |
|
269 | + * @throws InvalidDataTypeException |
|
270 | + * @throws InvalidFormHandlerException |
|
271 | + */ |
|
272 | + public function addFormActionArgs($form_action_args = array()) |
|
273 | + { |
|
274 | + if (! is_array($form_action_args)) { |
|
275 | + throw new InvalidDataTypeException('$form_action_args', $form_action_args, 'array'); |
|
276 | + } |
|
277 | + $form_action_args = ! empty($form_action_args) |
|
278 | + ? $form_action_args |
|
279 | + : array($this->formStepUrlKey() => $this->form_steps->current()->slug()); |
|
280 | + $this->getCurrentStep()->setFormAction( |
|
281 | + add_query_arg($form_action_args, $this->formAction()) |
|
282 | + ); |
|
283 | + $this->form_action = $this->getCurrentStep()->formAction(); |
|
284 | + } |
|
285 | + |
|
286 | + |
|
287 | + /** |
|
288 | + * @return string |
|
289 | + */ |
|
290 | + public function formConfig() |
|
291 | + { |
|
292 | + return $this->form_config; |
|
293 | + } |
|
294 | + |
|
295 | + |
|
296 | + /** |
|
297 | + * @param string $form_config |
|
298 | + */ |
|
299 | + public function setFormConfig($form_config) |
|
300 | + { |
|
301 | + $this->form_config = $form_config; |
|
302 | + } |
|
303 | + |
|
304 | + |
|
305 | + /** |
|
306 | + * @return string |
|
307 | + */ |
|
308 | + public function progressStepStyle() |
|
309 | + { |
|
310 | + return $this->progress_step_style; |
|
311 | + } |
|
312 | + |
|
313 | + |
|
314 | + /** |
|
315 | + * @param string $progress_step_style |
|
316 | + */ |
|
317 | + public function setProgressStepStyle($progress_step_style) |
|
318 | + { |
|
319 | + $this->progress_step_style = $progress_step_style; |
|
320 | + } |
|
321 | + |
|
322 | + |
|
323 | + /** |
|
324 | + * @return EE_Request |
|
325 | + */ |
|
326 | + public function request() |
|
327 | + { |
|
328 | + return $this->request; |
|
329 | + } |
|
330 | + |
|
331 | + |
|
332 | + /** |
|
333 | + * @return Collection|null |
|
334 | + * @throws InvalidInterfaceException |
|
335 | + */ |
|
336 | + protected function getProgressStepsCollection() |
|
337 | + { |
|
338 | + static $collection = null; |
|
339 | + if (! $collection instanceof ProgressStepCollection) { |
|
340 | + $collection = new ProgressStepCollection(); |
|
341 | + } |
|
342 | + return $collection; |
|
343 | + } |
|
344 | + |
|
345 | + |
|
346 | + /** |
|
347 | + * @param Collection $progress_steps_collection |
|
348 | + * @return ProgressStepManager |
|
349 | + * @throws InvalidInterfaceException |
|
350 | + * @throws InvalidClassException |
|
351 | + * @throws InvalidDataTypeException |
|
352 | + * @throws InvalidEntityException |
|
353 | + * @throws InvalidFormHandlerException |
|
354 | + */ |
|
355 | + protected function generateProgressSteps(Collection $progress_steps_collection) |
|
356 | + { |
|
357 | + $current_step = $this->getCurrentStep(); |
|
358 | + /** @var SequentialStepForm $form_step */ |
|
359 | + foreach ($this->form_steps as $form_step) { |
|
360 | + // is this step active ? |
|
361 | + if (! $form_step->initialize()) { |
|
362 | + continue; |
|
363 | + } |
|
364 | + $progress_steps_collection->add( |
|
365 | + new ProgressStep( |
|
366 | + $form_step->order(), |
|
367 | + $form_step->slug(), |
|
368 | + $form_step->slug(), |
|
369 | + $form_step->formName() |
|
370 | + ), |
|
371 | + $form_step->slug() |
|
372 | + ); |
|
373 | + } |
|
374 | + // set collection pointer back to current step |
|
375 | + $this->form_steps->setCurrentUsingObject($current_step); |
|
376 | + return new ProgressStepManager( |
|
377 | + $this->progressStepStyle(), |
|
378 | + $this->defaultFormStep(), |
|
379 | + $this->formStepUrlKey(), |
|
380 | + $progress_steps_collection |
|
381 | + ); |
|
382 | + } |
|
383 | + |
|
384 | + |
|
385 | + /** |
|
386 | + * @throws InvalidClassException |
|
387 | + * @throws InvalidDataTypeException |
|
388 | + * @throws InvalidEntityException |
|
389 | + * @throws InvalidIdentifierException |
|
390 | + * @throws InvalidInterfaceException |
|
391 | + * @throws InvalidArgumentException |
|
392 | + * @throws InvalidFormHandlerException |
|
393 | + */ |
|
394 | + public function buildForm() |
|
395 | + { |
|
396 | + $this->buildCurrentStepFormForDisplay(); |
|
397 | + } |
|
398 | + |
|
399 | + |
|
400 | + /** |
|
401 | + * @param array $form_data |
|
402 | + * @throws InvalidArgumentException |
|
403 | + * @throws InvalidClassException |
|
404 | + * @throws InvalidDataTypeException |
|
405 | + * @throws InvalidEntityException |
|
406 | + * @throws InvalidFormHandlerException |
|
407 | + * @throws InvalidIdentifierException |
|
408 | + * @throws InvalidInterfaceException |
|
409 | + */ |
|
410 | + public function processForm($form_data = array()) |
|
411 | + { |
|
412 | + $this->buildCurrentStepFormForProcessing(); |
|
413 | + $this->processCurrentStepForm($form_data); |
|
414 | + } |
|
415 | + |
|
416 | + |
|
417 | + /** |
|
418 | + * @throws InvalidClassException |
|
419 | + * @throws InvalidDataTypeException |
|
420 | + * @throws InvalidEntityException |
|
421 | + * @throws InvalidInterfaceException |
|
422 | + * @throws InvalidIdentifierException |
|
423 | + * @throws InvalidArgumentException |
|
424 | + * @throws InvalidFormHandlerException |
|
425 | + */ |
|
426 | + public function buildCurrentStepFormForDisplay() |
|
427 | + { |
|
428 | + $form_step = $this->buildCurrentStepForm(); |
|
429 | + // no displayable content ? then skip straight to processing |
|
430 | + if (! $form_step->displayable()) { |
|
431 | + $this->addFormActionArgs(); |
|
432 | + $form_step->setFormAction($this->formAction()); |
|
433 | + wp_safe_redirect($form_step->formAction()); |
|
434 | + } |
|
435 | + } |
|
436 | + |
|
437 | + |
|
438 | + /** |
|
439 | + * @throws InvalidClassException |
|
440 | + * @throws InvalidDataTypeException |
|
441 | + * @throws InvalidEntityException |
|
442 | + * @throws InvalidInterfaceException |
|
443 | + * @throws InvalidIdentifierException |
|
444 | + * @throws InvalidArgumentException |
|
445 | + * @throws InvalidFormHandlerException |
|
446 | + */ |
|
447 | + public function buildCurrentStepFormForProcessing() |
|
448 | + { |
|
449 | + $this->buildCurrentStepForm(false); |
|
450 | + } |
|
451 | + |
|
452 | + |
|
453 | + /** |
|
454 | + * @param bool $for_display |
|
455 | + * @return SequentialStepFormInterface |
|
456 | + * @throws InvalidArgumentException |
|
457 | + * @throws InvalidClassException |
|
458 | + * @throws InvalidDataTypeException |
|
459 | + * @throws InvalidEntityException |
|
460 | + * @throws InvalidFormHandlerException |
|
461 | + * @throws InvalidIdentifierException |
|
462 | + * @throws InvalidInterfaceException |
|
463 | + */ |
|
464 | + private function buildCurrentStepForm($for_display = true) |
|
465 | + { |
|
466 | + $this->form_steps = $this->getFormStepsCollection(); |
|
467 | + $this->setCurrentStepFromRequest(); |
|
468 | + $form_step = $this->getCurrentStep(); |
|
469 | + if ($form_step->submitBtnText() === esc_html__('Submit', 'event_espresso')) { |
|
470 | + $form_step->setSubmitBtnText(esc_html__('Next Step', 'event_espresso')); |
|
471 | + } |
|
472 | + if ($for_display && $form_step->displayable()) { |
|
473 | + $this->progress_step_manager = $this->generateProgressSteps( |
|
474 | + $this->getProgressStepsCollection() |
|
475 | + ); |
|
476 | + $this->progress_step_manager->setCurrentStep( |
|
477 | + $form_step->slug() |
|
478 | + ); |
|
479 | + // mark all previous progress steps as completed |
|
480 | + $this->progress_step_manager->setPreviousStepsCompleted(); |
|
481 | + $this->progress_step_manager->enqueueStylesAndScripts(); |
|
482 | + $this->addFormActionArgs(); |
|
483 | + $form_step->setFormAction($this->formAction()); |
|
484 | + } else { |
|
485 | + $form_step->setRedirectUrl($this->baseUrl()); |
|
486 | + $form_step->addRedirectArgs( |
|
487 | + array($this->formStepUrlKey() => $this->form_steps->current()->slug()) |
|
488 | + ); |
|
489 | + } |
|
490 | + $form_step->generate(); |
|
491 | + if ($for_display) { |
|
492 | + $form_step->enqueueStylesAndScripts(); |
|
493 | + } |
|
494 | + return $form_step; |
|
495 | + } |
|
496 | + |
|
497 | + |
|
498 | + /** |
|
499 | + * @param bool $return_as_string |
|
500 | + * @return string |
|
501 | + * @throws InvalidFormHandlerException |
|
502 | + */ |
|
503 | + public function displayProgressSteps($return_as_string = true) |
|
504 | + { |
|
505 | + $form_step = $this->getCurrentStep(); |
|
506 | + if (! $form_step->displayable()) { |
|
507 | + return ''; |
|
508 | + } |
|
509 | + $progress_steps = apply_filters( |
|
510 | + 'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_SequentialStepFormManager__displayProgressSteps__before_steps', |
|
511 | + '' |
|
512 | + ); |
|
513 | + $progress_steps .= $this->progress_step_manager->displaySteps(); |
|
514 | + $progress_steps .= apply_filters( |
|
515 | + 'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_SequentialStepFormManager__displayProgressSteps__after_steps', |
|
516 | + '' |
|
517 | + ); |
|
518 | + if ($return_as_string) { |
|
519 | + return $progress_steps; |
|
520 | + } |
|
521 | + echo $progress_steps; |
|
522 | + return ''; |
|
523 | + } |
|
524 | + |
|
525 | + |
|
526 | + /** |
|
527 | + * @param bool $return_as_string |
|
528 | + * @return string |
|
529 | + * @throws InvalidFormHandlerException |
|
530 | + */ |
|
531 | + public function displayCurrentStepForm($return_as_string = true) |
|
532 | + { |
|
533 | + if ($return_as_string) { |
|
534 | + return $this->getCurrentStep()->display(); |
|
535 | + } |
|
536 | + echo $this->getCurrentStep()->display(); |
|
537 | + return ''; |
|
538 | + } |
|
539 | + |
|
540 | + |
|
541 | + /** |
|
542 | + * @param array $form_data |
|
543 | + * @return void |
|
544 | + * @throws InvalidArgumentException |
|
545 | + * @throws InvalidDataTypeException |
|
546 | + * @throws InvalidFormHandlerException |
|
547 | + */ |
|
548 | + public function processCurrentStepForm($form_data = array()) |
|
549 | + { |
|
550 | + // grab instance of current step because after calling next() below, |
|
551 | + // any calls to getCurrentStep() will return the "next" step because we advanced |
|
552 | + $current_step = $this->getCurrentStep(); |
|
553 | + try { |
|
554 | + // form processing should either throw exceptions or return true |
|
555 | + $current_step->process($form_data); |
|
556 | + } catch (Exception $e) { |
|
557 | + // something went wrong, convert the Exception to an EE_Error |
|
558 | + EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
559 | + // prevent redirect to next step or other if exception was thrown |
|
560 | + if ($current_step->redirectTo() === SequentialStepForm::REDIRECT_TO_NEXT_STEP |
|
561 | + || $current_step->redirectTo() === SequentialStepForm::REDIRECT_TO_OTHER |
|
562 | + ) { |
|
563 | + $current_step->setRedirectTo(SequentialStepForm::REDIRECT_TO_CURRENT_STEP); |
|
564 | + } |
|
565 | + } |
|
566 | + // save notices to a transient so that when we redirect back |
|
567 | + // to the display portion for this step |
|
568 | + // those notices can be displayed |
|
569 | + EE_Error::get_notices(false, true); |
|
570 | + $this->redirectForm($current_step); |
|
571 | + } |
|
572 | + |
|
573 | + |
|
574 | + /** |
|
575 | + * handles where to go to next |
|
576 | + * |
|
577 | + * @param SequentialStepFormInterface $current_step |
|
578 | + * @throws InvalidArgumentException |
|
579 | + * @throws InvalidDataTypeException |
|
580 | + * @throws InvalidFormHandlerException |
|
581 | + */ |
|
582 | + public function redirectForm(SequentialStepFormInterface $current_step) |
|
583 | + { |
|
584 | + $redirect_step = $current_step; |
|
585 | + switch ($current_step->redirectTo()) { |
|
586 | + case SequentialStepForm::REDIRECT_TO_OTHER: |
|
587 | + // going somewhere else, so just check out now |
|
588 | + wp_safe_redirect($redirect_step->redirectUrl()); |
|
589 | + exit(); |
|
590 | + break; |
|
591 | + case SequentialStepForm::REDIRECT_TO_PREV_STEP: |
|
592 | + $redirect_step = $this->form_steps->previous(); |
|
593 | + break; |
|
594 | + case SequentialStepForm::REDIRECT_TO_NEXT_STEP: |
|
595 | + $this->form_steps->next(); |
|
596 | + if ($this->form_steps->valid()) { |
|
597 | + $redirect_step = $this->form_steps->current(); |
|
598 | + } |
|
599 | + break; |
|
600 | + case SequentialStepForm::REDIRECT_TO_CURRENT_STEP: |
|
601 | + default: |
|
602 | + // $redirect_step is already set |
|
603 | + } |
|
604 | + $current_step->setRedirectUrl($this->baseUrl()); |
|
605 | + $current_step->addRedirectArgs( |
|
606 | + // use the slug for whatever step we are redirecting too |
|
607 | + array($this->formStepUrlKey() => $redirect_step->slug()) |
|
608 | + ); |
|
609 | + wp_safe_redirect($current_step->redirectUrl()); |
|
610 | + exit(); |
|
611 | + } |
|
612 | 612 | } |
@@ -13,19 +13,19 @@ |
||
13 | 13 | class EE_Credit_Card_Validation_Strategy extends EE_Text_Validation_Strategy |
14 | 14 | { |
15 | 15 | |
16 | - /** |
|
17 | - * @param null $validation_error_message |
|
18 | - */ |
|
19 | - public function __construct($validation_error_message = null) |
|
20 | - { |
|
21 | - if (! $validation_error_message) { |
|
22 | - $validation_error_message = __("Please enter a valid credit card number", "event_espresso"); |
|
23 | - } |
|
24 | - parent::__construct( |
|
25 | - $validation_error_message, |
|
26 | - // @codingStandardsIgnoreStart |
|
27 | - '~^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|2[2-7][0-9]{14}|6011[0-9]{12}|3(?:0[0-5]|[68][0-9])[0-9]{11}|3[47][0-9]{13})$~' |
|
28 | - // @codingStandardsIgnoreEnd |
|
29 | - ); |
|
30 | - } |
|
16 | + /** |
|
17 | + * @param null $validation_error_message |
|
18 | + */ |
|
19 | + public function __construct($validation_error_message = null) |
|
20 | + { |
|
21 | + if (! $validation_error_message) { |
|
22 | + $validation_error_message = __("Please enter a valid credit card number", "event_espresso"); |
|
23 | + } |
|
24 | + parent::__construct( |
|
25 | + $validation_error_message, |
|
26 | + // @codingStandardsIgnoreStart |
|
27 | + '~^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|2[2-7][0-9]{14}|6011[0-9]{12}|3(?:0[0-5]|[68][0-9])[0-9]{11}|3[47][0-9]{13})$~' |
|
28 | + // @codingStandardsIgnoreEnd |
|
29 | + ); |
|
30 | + } |
|
31 | 31 | } |
@@ -18,7 +18,7 @@ |
||
18 | 18 | */ |
19 | 19 | public function __construct($validation_error_message = null) |
20 | 20 | { |
21 | - if (! $validation_error_message) { |
|
21 | + if ( ! $validation_error_message) { |
|
22 | 22 | $validation_error_message = __("Please enter a valid credit card number", "event_espresso"); |
23 | 23 | } |
24 | 24 | parent::__construct( |
@@ -1,56 +1,56 @@ discard block |
||
1 | 1 | <div class="headline-feature"> |
2 | 2 | <h2 class="about-headline-callout"><?php esc_html_e('Welcome to Event Espresso 4!', 'event_espresso'); ?></h2> |
3 | 3 | <p><?php |
4 | - echo sprintf( |
|
5 | - esc_html__( |
|
6 | - 'Manage your events from your WordPress dashboard. Reduce your admin, reduce your costs, make your life easier! This is the Caffeinated/Regular version of Event Espresso, but we also have a hosted version called %sEvent Smart%s for customers that want to cut back on their hosting and security expenses.', |
|
7 | - 'event_espresso' |
|
8 | - ), |
|
9 | - '<a href="https://eventsmart.com//?utm_source=ee4_decaf&utm_medium=link&utm_campaign=espresso_about_tab&utm_content=EE4+Caffeinated">', |
|
10 | - '</a>' |
|
11 | - ); ?></p> |
|
4 | + echo sprintf( |
|
5 | + esc_html__( |
|
6 | + 'Manage your events from your WordPress dashboard. Reduce your admin, reduce your costs, make your life easier! This is the Caffeinated/Regular version of Event Espresso, but we also have a hosted version called %sEvent Smart%s for customers that want to cut back on their hosting and security expenses.', |
|
7 | + 'event_espresso' |
|
8 | + ), |
|
9 | + '<a href="https://eventsmart.com//?utm_source=ee4_decaf&utm_medium=link&utm_campaign=espresso_about_tab&utm_content=EE4+Caffeinated">', |
|
10 | + '</a>' |
|
11 | + ); ?></p> |
|
12 | 12 | <h2><?php |
13 | - esc_html_e( |
|
14 | - 'Powering 40,000+ event websites; $100 million in ticket sales per year!', |
|
15 | - 'event_espresso' |
|
16 | - ); ?></h2> |
|
13 | + esc_html_e( |
|
14 | + 'Powering 40,000+ event websites; $100 million in ticket sales per year!', |
|
15 | + 'event_espresso' |
|
16 | + ); ?></h2> |
|
17 | 17 | <p><?php |
18 | - echo sprintf( |
|
19 | - esc_html__( |
|
20 | - 'Event Espresso is a %sWordPress event manager%s which makes it easy for you to register attendees for classes, workshops, events, trainings, conferences or concerts, all from your WordPress website. Event Espresso events are created from the WordPress admin area. You can create signup forms to collect information about your attendees, accept payments, and create reports. The lite version of the plugin provides everything that you need to manage your event using WordPress.', |
|
21 | - 'event_espresso' |
|
22 | - ), |
|
23 | - '<a href="http://eventespresso.com/?utm_source=wordpress_org&utm_medium=link&utm_campaign=espresso_about_tab&utm_content=EE4+Decaf" rel="nofollow">', |
|
24 | - '</a>' |
|
25 | - ); ?></p> |
|
18 | + echo sprintf( |
|
19 | + esc_html__( |
|
20 | + 'Event Espresso is a %sWordPress event manager%s which makes it easy for you to register attendees for classes, workshops, events, trainings, conferences or concerts, all from your WordPress website. Event Espresso events are created from the WordPress admin area. You can create signup forms to collect information about your attendees, accept payments, and create reports. The lite version of the plugin provides everything that you need to manage your event using WordPress.', |
|
21 | + 'event_espresso' |
|
22 | + ), |
|
23 | + '<a href="http://eventespresso.com/?utm_source=wordpress_org&utm_medium=link&utm_campaign=espresso_about_tab&utm_content=EE4+Decaf" rel="nofollow">', |
|
24 | + '</a>' |
|
25 | + ); ?></p> |
|
26 | 26 | </div> |
27 | 27 | <div class="feature-section has-3-columns is-fullwidth three-col"> |
28 | 28 | <div class="column col"> |
29 | 29 | <img src="<?php echo EE_GLOBAL_ASSETS_URL; ?>images/screenshots/publish_meta_box.jpg"> |
30 | 30 | <h3><?php esc_html_e('Optimized aesthetic', 'event_espresso'); ?></h3> |
31 | 31 | <p><?php |
32 | - esc_html_e( |
|
33 | - 'The Event Espresso 4 dashboard has a fresh, uncluttered design that embraces clarity and simplicity.', |
|
34 | - 'event_espresso' |
|
35 | - ); ?></p> |
|
32 | + esc_html_e( |
|
33 | + 'The Event Espresso 4 dashboard has a fresh, uncluttered design that embraces clarity and simplicity.', |
|
34 | + 'event_espresso' |
|
35 | + ); ?></p> |
|
36 | 36 | </div> |
37 | 37 | <div class="column col"> |
38 | 38 | <img src="<?php echo EE_GLOBAL_ASSETS_URL; ?>images/screenshots/registrations-overview.jpg"> |
39 | 39 | <h3><?php esc_html_e('Integrated management', 'event_espresso'); ?></h3> |
40 | 40 | <p><?php |
41 | - esc_html_e( |
|
42 | - 'We’ve made it easier to know who your customers are and how they’ve done business with you over time.', |
|
43 | - 'event_espresso' |
|
44 | - ); ?></p> |
|
41 | + esc_html_e( |
|
42 | + 'We’ve made it easier to know who your customers are and how they’ve done business with you over time.', |
|
43 | + 'event_espresso' |
|
44 | + ); ?></p> |
|
45 | 45 | </div> |
46 | 46 | <div class="column col last-feature"> |
47 | 47 | <img src="<?php echo EE_GLOBAL_ASSETS_URL; ?>images/screenshots/refined-bookkeeping.jpg"> |
48 | 48 | <h3><?php esc_html_e('Easy bookkeeping', 'event_espresso'); ?></h3> |
49 | 49 | <p><?php |
50 | - esc_html_e( |
|
51 | - 'Registrations, payment, and transactions have been substantially improved in Event Espresso 4.', |
|
52 | - 'event_espresso' |
|
53 | - ); ?></p> |
|
50 | + esc_html_e( |
|
51 | + 'Registrations, payment, and transactions have been substantially improved in Event Espresso 4.', |
|
52 | + 'event_espresso' |
|
53 | + ); ?></p> |
|
54 | 54 | </div> |
55 | 55 | </div> |
56 | 56 | |
@@ -62,16 +62,16 @@ discard block |
||
62 | 62 | <div class="column col"> |
63 | 63 | <h3><?php esc_html_e('Higher customer retention', 'event_espresso'); ?></h3> |
64 | 64 | <p><?php |
65 | - esc_html_e( |
|
66 | - 'The Event Espresso 4 registration process is faster than ever. With quick ticket selections, single page check-out, and customizable notifications! Registration that can scale to your business needs.', |
|
67 | - 'event_espresso' |
|
68 | - ); ?></p> |
|
65 | + esc_html_e( |
|
66 | + 'The Event Espresso 4 registration process is faster than ever. With quick ticket selections, single page check-out, and customizable notifications! Registration that can scale to your business needs.', |
|
67 | + 'event_espresso' |
|
68 | + ); ?></p> |
|
69 | 69 | <h4><?php esc_html_e('Ticket selection boxes on any post page or post', 'event_espresso'); ?></h4> |
70 | 70 | <p><?php |
71 | - esc_html_e( |
|
72 | - 'Customers can easily register for classes, events, or conferences, in just a few simple steps. No matter how you use it, Event Espresso 4 will adapt to a multitude of different ticketing and pricing scenarios.', |
|
73 | - 'event_espresso' |
|
74 | - ); ?></p> |
|
71 | + esc_html_e( |
|
72 | + 'Customers can easily register for classes, events, or conferences, in just a few simple steps. No matter how you use it, Event Espresso 4 will adapt to a multitude of different ticketing and pricing scenarios.', |
|
73 | + 'event_espresso' |
|
74 | + ); ?></p> |
|
75 | 75 | </div> |
76 | 76 | <div class="column col last-feature about-colors-img"> |
77 | 77 | <img src="<?php echo EE_GLOBAL_ASSETS_URL; ?>images/screenshots/registrtation-page-large.jpg"> |
@@ -85,21 +85,21 @@ discard block |
||
85 | 85 | <div class="column col"> |
86 | 86 | <h3><?php esc_html_e('Refined event management', 'event_espresso'); ?></h3> |
87 | 87 | <p><?php |
88 | - esc_html_e( |
|
89 | - 'The new event management screen lets you survey your events at a glance. Want more information? Click to view more. Quickly add/edit prices, dates, or information in any event.', |
|
90 | - 'event_espresso' |
|
91 | - ); ?></p> |
|
88 | + esc_html_e( |
|
89 | + 'The new event management screen lets you survey your events at a glance. Want more information? Click to view more. Quickly add/edit prices, dates, or information in any event.', |
|
90 | + 'event_espresso' |
|
91 | + ); ?></p> |
|
92 | 92 | <h4><?php esc_html_e('Smoother price types, taxes, and price modifiers', 'event_espresso'); ?></h4> |
93 | 93 | <p><?php |
94 | - esc_html_e( |
|
95 | - 'Price Types allow you to create new prices that adjust the default ticket (base) price for your system-default ticket', |
|
96 | - 'event_espresso' |
|
97 | - ); ?>.</p> |
|
94 | + esc_html_e( |
|
95 | + 'Price Types allow you to create new prices that adjust the default ticket (base) price for your system-default ticket', |
|
96 | + 'event_espresso' |
|
97 | + ); ?>.</p> |
|
98 | 98 | <p><?php |
99 | - esc_html_e( |
|
100 | - 'Easily categorize a price modifier and indicate how that price gets applied to the running total when a transaction occurs.', |
|
101 | - 'event_espresso' |
|
102 | - ); ?></p> |
|
99 | + esc_html_e( |
|
100 | + 'Easily categorize a price modifier and indicate how that price gets applied to the running total when a transaction occurs.', |
|
101 | + 'event_espresso' |
|
102 | + ); ?></p> |
|
103 | 103 | </div> |
104 | 104 | <div class="column col last-feature about-themes-img"> |
105 | 105 | <img src="<?php echo EE_GLOBAL_ASSETS_URL; ?>images/screenshots/event-management.jpg"> |
@@ -109,68 +109,68 @@ discard block |
||
109 | 109 | <hr> |
110 | 110 | |
111 | 111 | <h2 class="about-headline-callout"><?php |
112 | - esc_html_e( |
|
113 | - 'People Like You Manage Event Registration with WordPress', |
|
114 | - 'event_espresso' |
|
115 | - ); ?></h2> |
|
112 | + esc_html_e( |
|
113 | + 'People Like You Manage Event Registration with WordPress', |
|
114 | + 'event_espresso' |
|
115 | + ); ?></h2> |
|
116 | 116 | <div class="feature-section has-2-columns is-fullwidth two-col"> |
117 | 117 | <div class="column col"> |
118 | 118 | <p><?php |
119 | - echo sprintf( |
|
120 | - esc_html__( |
|
121 | - 'Trusted by thousands, Event Espresso is the best WordPress event online registration and ticketing manager plugin–and the best supported with full-time support. Turn your existing blog or website into a %sfully-featured event management website%s and a new way to make money. With Event Espresso you get it all; everything from custom registration forms and emails, seating limits, multiple price options, and discount codes to printable tickets.', |
|
122 | - 'event_espresso' |
|
123 | - ), |
|
124 | - '<strong>', |
|
125 | - '</strong>' |
|
126 | - ); ?></p> |
|
127 | - <p><?php |
|
128 | - esc_html_e( |
|
129 | - 'Event Espresso works perfectly for classes, workshops, fundraisers, sporting, trainings, conferences, networking, religion, social, non-profit, and nearly any other type of event.', |
|
130 | - 'event_espresso' |
|
131 | - ); ?></p> |
|
119 | + echo sprintf( |
|
120 | + esc_html__( |
|
121 | + 'Trusted by thousands, Event Espresso is the best WordPress event online registration and ticketing manager plugin–and the best supported with full-time support. Turn your existing blog or website into a %sfully-featured event management website%s and a new way to make money. With Event Espresso you get it all; everything from custom registration forms and emails, seating limits, multiple price options, and discount codes to printable tickets.', |
|
122 | + 'event_espresso' |
|
123 | + ), |
|
124 | + '<strong>', |
|
125 | + '</strong>' |
|
126 | + ); ?></p> |
|
127 | + <p><?php |
|
128 | + esc_html_e( |
|
129 | + 'Event Espresso works perfectly for classes, workshops, fundraisers, sporting, trainings, conferences, networking, religion, social, non-profit, and nearly any other type of event.', |
|
130 | + 'event_espresso' |
|
131 | + ); ?></p> |
|
132 | 132 | </div> |
133 | 133 | <div class="column col"> |
134 | 134 | <p><?php |
135 | - echo sprintf( |
|
136 | - esc_html__( |
|
137 | - 'Our online event registration software can %smake your organization more profitable and efficient%s by helping you save money on registration and ticketing fees, reduce the countless hours of time you spend manually processing registrations, create a “green” and paperless event registration process and you will be open for business to accept registrations and payment 24/7.', |
|
138 | - 'event_espresso' |
|
139 | - ), |
|
140 | - '<strong>', |
|
141 | - '</strong>' |
|
142 | - ); ?></p> |
|
143 | - <p><?php |
|
144 | - esc_html_e( |
|
145 | - 'If you\'re doing event registration and ticketing any other way, then you’re wasting time and money. We offer packages and prices to fit any budget, so get started with your online event registration and ticketing management system today.', |
|
146 | - 'event_espresso' |
|
147 | - ); ?></p> |
|
135 | + echo sprintf( |
|
136 | + esc_html__( |
|
137 | + 'Our online event registration software can %smake your organization more profitable and efficient%s by helping you save money on registration and ticketing fees, reduce the countless hours of time you spend manually processing registrations, create a “green” and paperless event registration process and you will be open for business to accept registrations and payment 24/7.', |
|
138 | + 'event_espresso' |
|
139 | + ), |
|
140 | + '<strong>', |
|
141 | + '</strong>' |
|
142 | + ); ?></p> |
|
143 | + <p><?php |
|
144 | + esc_html_e( |
|
145 | + 'If you\'re doing event registration and ticketing any other way, then you’re wasting time and money. We offer packages and prices to fit any budget, so get started with your online event registration and ticketing management system today.', |
|
146 | + 'event_espresso' |
|
147 | + ); ?></p> |
|
148 | 148 | </div> |
149 | 149 | </div> |
150 | 150 | |
151 | 151 | <div class="feature-section has-2-columns is-fullwidth two-col"> |
152 | 152 | <div class="column col"> |
153 | 153 | <h3><?php |
154 | - esc_html_e( |
|
155 | - 'Turn your blog into a complete event registration and management system', |
|
156 | - 'event_espresso' |
|
157 | - ); ?></h3> |
|
158 | - <p><?php |
|
159 | - esc_html_e( |
|
160 | - 'Create a beautiful event page with ticket selection, venue details, and an integrated single page checkout system. With WordPress, Event Espresso, and Espresso Arabica 2014 (based on the "Twenty Fourteen" theme by WordPress), your events will certainly sell out faster than ever!', |
|
161 | - 'event_espresso' |
|
162 | - ); ?></p> |
|
163 | - <p><?php |
|
164 | - esc_html_e( |
|
165 | - 'With a striking design that does not compromise the simplicity of WordPress and Event Espresso 4, Espresso Arabica 2014 will be the best event theme on the market.', |
|
166 | - 'event_espresso' |
|
167 | - ); ?></p> |
|
168 | - <p><?php |
|
169 | - echo sprintf( |
|
170 | - esc_html__('%sLearn more >>%s', 'event_espresso'), |
|
171 | - '<a href="http://eventespresso.com/wiki/setup-event-espresso-arabica-theme/">', |
|
172 | - '</a>' |
|
173 | - ); ?></p> |
|
154 | + esc_html_e( |
|
155 | + 'Turn your blog into a complete event registration and management system', |
|
156 | + 'event_espresso' |
|
157 | + ); ?></h3> |
|
158 | + <p><?php |
|
159 | + esc_html_e( |
|
160 | + 'Create a beautiful event page with ticket selection, venue details, and an integrated single page checkout system. With WordPress, Event Espresso, and Espresso Arabica 2014 (based on the "Twenty Fourteen" theme by WordPress), your events will certainly sell out faster than ever!', |
|
161 | + 'event_espresso' |
|
162 | + ); ?></p> |
|
163 | + <p><?php |
|
164 | + esc_html_e( |
|
165 | + 'With a striking design that does not compromise the simplicity of WordPress and Event Espresso 4, Espresso Arabica 2014 will be the best event theme on the market.', |
|
166 | + 'event_espresso' |
|
167 | + ); ?></p> |
|
168 | + <p><?php |
|
169 | + echo sprintf( |
|
170 | + esc_html__('%sLearn more >>%s', 'event_espresso'), |
|
171 | + '<a href="http://eventespresso.com/wiki/setup-event-espresso-arabica-theme/">', |
|
172 | + '</a>' |
|
173 | + ); ?></p> |
|
174 | 174 | </div> |
175 | 175 | <div class="column col"><img src="<?php echo EE_GLOBAL_ASSETS_URL; ?>images/screenshots/single-event-page.jpg"></div> |
176 | 176 | </div> |
@@ -183,10 +183,10 @@ discard block |
||
183 | 183 | <div class="feature-section has-1-column is-fullwidth is-wide one-col"> |
184 | 184 | <div class="column col"> |
185 | 185 | <p><?php |
186 | - esc_html_e( |
|
187 | - 'We’ve made it super easy to integrate Event Espresso with almost any properly coded WordPress theme, including many of the thousands of themes available on WordPress.org. The image below shows the same Event Espresso ticketing page across three diffrent WordPress themes.', |
|
188 | - 'event_espresso' |
|
189 | - ); ?></p> |
|
186 | + esc_html_e( |
|
187 | + 'We’ve made it super easy to integrate Event Espresso with almost any properly coded WordPress theme, including many of the thousands of themes available on WordPress.org. The image below shows the same Event Espresso ticketing page across three diffrent WordPress themes.', |
|
188 | + 'event_espresso' |
|
189 | + ); ?></p> |
|
190 | 190 | <p><img class="about-overview-img" src="<?php echo EE_GLOBAL_ASSETS_URL; ?>images/screenshots/multiple-themes.jpg"/></p> |
191 | 191 | </div> |
192 | 192 | </div> |
@@ -1,24 +1,24 @@ discard block |
||
1 | 1 | <?php |
2 | 2 | // maintenance mode on? |
3 | 3 | if (EE_Maintenance_Mode::instance()->level() == EE_Maintenance_Mode::level_2_complete_maintenance) { |
4 | - ?> |
|
4 | + ?> |
|
5 | 5 | <div class="ee-attention"> |
6 | 6 | <h2 class="ee-maintenance-mode-callout"> |
7 | 7 | <?php esc_html_e( |
8 | - 'Event Espresso is in full maintenance mode.', |
|
9 | - 'event_espresso' |
|
10 | - ); ?></h2> |
|
8 | + 'Event Espresso is in full maintenance mode.', |
|
9 | + 'event_espresso' |
|
10 | + ); ?></h2> |
|
11 | 11 | <p> |
12 | 12 | <?php |
13 | - printf( |
|
14 | - esc_html__( |
|
15 | - 'A previous version of Event Espresso has detected. But before anything else can happen, we need to know whether or not to migrate (copy over) your existing event data so that it can be utilized by EE4. For more instructions on what to do, please visit the %sEvent Espresso Maintenance%s page.', |
|
16 | - 'event_espresso' |
|
17 | - ), |
|
18 | - '<a href="admin.php?page=espresso_maintenance_settings">', |
|
19 | - '</a>' |
|
20 | - ); |
|
21 | - ?> |
|
13 | + printf( |
|
14 | + esc_html__( |
|
15 | + 'A previous version of Event Espresso has detected. But before anything else can happen, we need to know whether or not to migrate (copy over) your existing event data so that it can be utilized by EE4. For more instructions on what to do, please visit the %sEvent Espresso Maintenance%s page.', |
|
16 | + 'event_espresso' |
|
17 | + ), |
|
18 | + '<a href="admin.php?page=espresso_maintenance_settings">', |
|
19 | + '</a>' |
|
20 | + ); |
|
21 | + ?> |
|
22 | 22 | </p> |
23 | 23 | </div> |
24 | 24 | <?php |
@@ -27,62 +27,62 @@ discard block |
||
27 | 27 | <div class="headline-feature"> |
28 | 28 | <h2 class="about-headline-callout"> |
29 | 29 | <?php esc_html_e( |
30 | - 'Welcome to the Decaf (free) Version of Event Espresso 4!', |
|
31 | - 'event_espresso' |
|
32 | - ); ?></h2> |
|
30 | + 'Welcome to the Decaf (free) Version of Event Espresso 4!', |
|
31 | + 'event_espresso' |
|
32 | + ); ?></h2> |
|
33 | 33 | <p><?php |
34 | - echo sprintf( |
|
35 | - esc_html__( |
|
36 | - 'Manage your events from your WordPress dashboard. Reduce your admin, reduce your costs, make your life easier! This is the Decaf version of Event Espresso, but we also have a premium version called %sEvent Espreso 4 Regular%s and a hosted version called %sEvent Smart%s (SaaS).', |
|
37 | - 'event_espresso' |
|
38 | - ), |
|
39 | - '<a href="?page=espresso_about&action=decafvpro">', |
|
40 | - '</a>', |
|
41 | - '<a href="https://eventsmart.com//?utm_source=ee4_decaf&utm_medium=link&utm_campaign=espresso_about_tab&utm_content=EE4+Decaf">', |
|
42 | - '</a>' |
|
43 | - ); ?></p> |
|
34 | + echo sprintf( |
|
35 | + esc_html__( |
|
36 | + 'Manage your events from your WordPress dashboard. Reduce your admin, reduce your costs, make your life easier! This is the Decaf version of Event Espresso, but we also have a premium version called %sEvent Espreso 4 Regular%s and a hosted version called %sEvent Smart%s (SaaS).', |
|
37 | + 'event_espresso' |
|
38 | + ), |
|
39 | + '<a href="?page=espresso_about&action=decafvpro">', |
|
40 | + '</a>', |
|
41 | + '<a href="https://eventsmart.com//?utm_source=ee4_decaf&utm_medium=link&utm_campaign=espresso_about_tab&utm_content=EE4+Decaf">', |
|
42 | + '</a>' |
|
43 | + ); ?></p> |
|
44 | 44 | <h2> |
45 | 45 | <?php esc_html_e( |
46 | - 'Powering 40,000+ event websites; $100 million in ticket sales per year!', |
|
47 | - 'event_espresso' |
|
48 | - ); ?></h2> |
|
46 | + 'Powering 40,000+ event websites; $100 million in ticket sales per year!', |
|
47 | + 'event_espresso' |
|
48 | + ); ?></h2> |
|
49 | 49 | <p><?php |
50 | - echo sprintf( |
|
51 | - esc_html__( |
|
52 | - 'Event Espresso is a %sWordPress event manager%s which makes it easy for you to register attendees for classes, workshops, events, trainings, conferences or concerts, all from your WordPress website. Event Espresso events are created from the WordPress admin area. You can create signup forms to collect information about your attendees, accept payments, and create reports. The Decaf (free) version of the plugin provides everything that you need to manage your event using WordPress.', |
|
53 | - 'event_espresso' |
|
54 | - ), |
|
55 | - '<a href="http://eventespresso.com/?utm_source=wordpress_org&utm_medium=link&utm_campaign=plugin_description_tab&utm_content=EE4+Decaf">', |
|
56 | - '</a>' |
|
57 | - ); ?></p> |
|
50 | + echo sprintf( |
|
51 | + esc_html__( |
|
52 | + 'Event Espresso is a %sWordPress event manager%s which makes it easy for you to register attendees for classes, workshops, events, trainings, conferences or concerts, all from your WordPress website. Event Espresso events are created from the WordPress admin area. You can create signup forms to collect information about your attendees, accept payments, and create reports. The Decaf (free) version of the plugin provides everything that you need to manage your event using WordPress.', |
|
53 | + 'event_espresso' |
|
54 | + ), |
|
55 | + '<a href="http://eventespresso.com/?utm_source=wordpress_org&utm_medium=link&utm_campaign=plugin_description_tab&utm_content=EE4+Decaf">', |
|
56 | + '</a>' |
|
57 | + ); ?></p> |
|
58 | 58 | </div> |
59 | 59 | <div class="feature-section has-3-columns is-fullwidth three-col"> |
60 | 60 | <div class="column col"> |
61 | 61 | <img src="<?php echo EE_GLOBAL_ASSETS_URL; ?>images/screenshots/publish_meta_box.jpg"> |
62 | 62 | <h3><?php esc_html_e('Optimized aesthetic', 'event_espresso'); ?></h3> |
63 | 63 | <p><?php |
64 | - esc_html_e( |
|
65 | - 'The Event Espresso 4 dashboard has a fresh, uncluttered design that embraces clarity and simplicity.', |
|
66 | - 'event_espresso' |
|
67 | - ); ?></p> |
|
64 | + esc_html_e( |
|
65 | + 'The Event Espresso 4 dashboard has a fresh, uncluttered design that embraces clarity and simplicity.', |
|
66 | + 'event_espresso' |
|
67 | + ); ?></p> |
|
68 | 68 | </div> |
69 | 69 | <div class="column col"> |
70 | 70 | <img src="<?php echo EE_GLOBAL_ASSETS_URL; ?>images/screenshots/registrations-overview.jpg"> |
71 | 71 | <h3><?php esc_html_e('Integrated management', 'event_espresso'); ?></h3> |
72 | 72 | <p><?php |
73 | - esc_html_e( |
|
74 | - 'We’ve made it easier to know who your customers are and how they’ve done business with you over time.', |
|
75 | - 'event_espresso' |
|
76 | - ); ?></p> |
|
73 | + esc_html_e( |
|
74 | + 'We’ve made it easier to know who your customers are and how they’ve done business with you over time.', |
|
75 | + 'event_espresso' |
|
76 | + ); ?></p> |
|
77 | 77 | </div> |
78 | 78 | <div class="column col last-feature"> |
79 | 79 | <img src="<?php echo EE_GLOBAL_ASSETS_URL; ?>images/screenshots/refined-bookkeeping.jpg"> |
80 | 80 | <h3><?php esc_html_e('Easy bookkeeping', 'event_espresso'); ?></h3> |
81 | 81 | <p><?php |
82 | - esc_html_e( |
|
83 | - 'Registrations, payment, and transactions have been substantially improved in Event Espresso 4.', |
|
84 | - 'event_espresso' |
|
85 | - ); ?></p> |
|
82 | + esc_html_e( |
|
83 | + 'Registrations, payment, and transactions have been substantially improved in Event Espresso 4.', |
|
84 | + 'event_espresso' |
|
85 | + ); ?></p> |
|
86 | 86 | </div> |
87 | 87 | </div> |
88 | 88 | |
@@ -92,16 +92,16 @@ discard block |
||
92 | 92 | <div class="column col"> |
93 | 93 | <h3><?php esc_html_e('Higher customer retention', 'event_espresso'); ?></h3> |
94 | 94 | <p><?php |
95 | - esc_html_e( |
|
96 | - 'The Event Espresso 4 registration process is faster than ever. With quick ticket selections, single page check-out, and customizable notifications! Registration that can scale to your business needs.', |
|
97 | - 'event_espresso' |
|
98 | - ); ?></p> |
|
95 | + esc_html_e( |
|
96 | + 'The Event Espresso 4 registration process is faster than ever. With quick ticket selections, single page check-out, and customizable notifications! Registration that can scale to your business needs.', |
|
97 | + 'event_espresso' |
|
98 | + ); ?></p> |
|
99 | 99 | <h4><?php esc_html_e('Ticket selection boxes on any post page or post', 'event_espresso'); ?></h4> |
100 | 100 | <p><?php |
101 | - esc_html_e( |
|
102 | - 'Customers can easily register for classes, events, or conferences, in just a few simple steps. No matter how you use it, Event Espresso 4 will adapt to a multitude of different ticketing and pricing scenarios.', |
|
103 | - 'event_espresso' |
|
104 | - ); ?></p> |
|
101 | + esc_html_e( |
|
102 | + 'Customers can easily register for classes, events, or conferences, in just a few simple steps. No matter how you use it, Event Espresso 4 will adapt to a multitude of different ticketing and pricing scenarios.', |
|
103 | + 'event_espresso' |
|
104 | + ); ?></p> |
|
105 | 105 | </div> |
106 | 106 | <div class="column col last-feature about-colors-img"> |
107 | 107 | <img src="<?php echo EE_GLOBAL_ASSETS_URL; ?>images/screenshots/registrtation-page-large.jpg"> |
@@ -112,22 +112,22 @@ discard block |
||
112 | 112 | <div class="column col"> |
113 | 113 | <h3><?php esc_html_e('Refined event management', 'event_espresso'); ?></h3> |
114 | 114 | <p><?php |
115 | - esc_html_e( |
|
116 | - 'The new event management screen lets you survey your events at a glance. Want more information? Click to view more. Quickly add/edit prices, dates, or information in any event.', |
|
117 | - 'event_espresso' |
|
118 | - ); ?></p> |
|
115 | + esc_html_e( |
|
116 | + 'The new event management screen lets you survey your events at a glance. Want more information? Click to view more. Quickly add/edit prices, dates, or information in any event.', |
|
117 | + 'event_espresso' |
|
118 | + ); ?></p> |
|
119 | 119 | <h4><?php |
120 | - esc_html_e('Smoother price types, taxes, and price modifiers', 'event_espresso'); ?></h4> |
|
120 | + esc_html_e('Smoother price types, taxes, and price modifiers', 'event_espresso'); ?></h4> |
|
121 | 121 | <p><?php |
122 | - esc_html_e( |
|
123 | - 'Price Types allow you to create new prices that adjust the default ticket (base) price for your system-default ticket', |
|
124 | - 'event_espresso' |
|
125 | - ); ?>.</p> |
|
122 | + esc_html_e( |
|
123 | + 'Price Types allow you to create new prices that adjust the default ticket (base) price for your system-default ticket', |
|
124 | + 'event_espresso' |
|
125 | + ); ?>.</p> |
|
126 | 126 | <p><?php |
127 | - esc_html_e( |
|
128 | - 'Easily categorize a price modifier and indicate how that price gets applied to the running total when a transaction occurs.', |
|
129 | - 'event_espresso' |
|
130 | - ); ?></p> |
|
127 | + esc_html_e( |
|
128 | + 'Easily categorize a price modifier and indicate how that price gets applied to the running total when a transaction occurs.', |
|
129 | + 'event_espresso' |
|
130 | + ); ?></p> |
|
131 | 131 | </div> |
132 | 132 | <div class="column col last-feature about-themes-img"> |
133 | 133 | <img src="<?php echo EE_GLOBAL_ASSETS_URL; ?>images/screenshots/event-management.jpg"> |
@@ -137,68 +137,68 @@ discard block |
||
137 | 137 | <hr> |
138 | 138 | |
139 | 139 | <h2 class="about-headline-callout"><?php |
140 | - esc_html_e( |
|
141 | - 'People Like You Manage Event Registration with WordPress', |
|
142 | - 'event_espresso' |
|
143 | - ); ?></h2> |
|
140 | + esc_html_e( |
|
141 | + 'People Like You Manage Event Registration with WordPress', |
|
142 | + 'event_espresso' |
|
143 | + ); ?></h2> |
|
144 | 144 | <div class="feature-section has-2-columns is-fullwidth two-col"> |
145 | 145 | <div class="column col"> |
146 | 146 | <p><?php |
147 | - echo sprintf( |
|
148 | - esc_html__( |
|
149 | - 'Trusted by thousands, Event Espresso is the best WordPress event online registration and ticketing manager plugin–and the best supported with full-time support. Turn your existing blog or website into a %sfully-featured event management website%s and a new way to make money. With Event Espresso you get it all; everything from custom registration forms and emails, seating limits, multiple price options, and discount codes to printable tickets.', |
|
150 | - 'event_espresso' |
|
151 | - ), |
|
152 | - '<strong>', |
|
153 | - '</strong>' |
|
154 | - ); ?></p> |
|
155 | - <p><?php |
|
156 | - esc_html_e( |
|
157 | - 'Event Espresso works perfectly for classes, workshops, fundraisers, sporting, trainings, conferences, networking, religion, social, non-profit, and nearly any other type of event.', |
|
158 | - 'event_espresso' |
|
159 | - ); ?></p> |
|
147 | + echo sprintf( |
|
148 | + esc_html__( |
|
149 | + 'Trusted by thousands, Event Espresso is the best WordPress event online registration and ticketing manager plugin–and the best supported with full-time support. Turn your existing blog or website into a %sfully-featured event management website%s and a new way to make money. With Event Espresso you get it all; everything from custom registration forms and emails, seating limits, multiple price options, and discount codes to printable tickets.', |
|
150 | + 'event_espresso' |
|
151 | + ), |
|
152 | + '<strong>', |
|
153 | + '</strong>' |
|
154 | + ); ?></p> |
|
155 | + <p><?php |
|
156 | + esc_html_e( |
|
157 | + 'Event Espresso works perfectly for classes, workshops, fundraisers, sporting, trainings, conferences, networking, religion, social, non-profit, and nearly any other type of event.', |
|
158 | + 'event_espresso' |
|
159 | + ); ?></p> |
|
160 | 160 | </div> |
161 | 161 | <div class="column col"> |
162 | 162 | <p><?php |
163 | - echo sprintf( |
|
164 | - esc_html__( |
|
165 | - 'Our online event registration software can %smake your organization more profitable and efficient%s by helping you save money on registration and ticketing fees, reduce the countless hours of time you spend manually processing registrations, create a “green” and paperless event registration process and you will be open for business to accept registrations and payment 24/7.', |
|
166 | - 'event_espresso' |
|
167 | - ), |
|
168 | - '<strong>', |
|
169 | - '</strong>' |
|
170 | - ); ?></p> |
|
171 | - <p><?php |
|
172 | - esc_html_e( |
|
173 | - 'If you\'re doing event registration and ticketing any other way, then you’re wasting time and money. We offer packages and prices to fit any budget, so get started with your online event registration and ticketing management system today.', |
|
174 | - 'event_espresso' |
|
175 | - ); ?></p> |
|
163 | + echo sprintf( |
|
164 | + esc_html__( |
|
165 | + 'Our online event registration software can %smake your organization more profitable and efficient%s by helping you save money on registration and ticketing fees, reduce the countless hours of time you spend manually processing registrations, create a “green” and paperless event registration process and you will be open for business to accept registrations and payment 24/7.', |
|
166 | + 'event_espresso' |
|
167 | + ), |
|
168 | + '<strong>', |
|
169 | + '</strong>' |
|
170 | + ); ?></p> |
|
171 | + <p><?php |
|
172 | + esc_html_e( |
|
173 | + 'If you\'re doing event registration and ticketing any other way, then you’re wasting time and money. We offer packages and prices to fit any budget, so get started with your online event registration and ticketing management system today.', |
|
174 | + 'event_espresso' |
|
175 | + ); ?></p> |
|
176 | 176 | </div> |
177 | 177 | </div> |
178 | 178 | |
179 | 179 | <div class="feature-section has-2-columns is-fullwidth two-col"> |
180 | 180 | <div class="column col"> |
181 | 181 | <h3><?php |
182 | - esc_html_e( |
|
183 | - 'Turn your blog into a complete event registration and management system', |
|
184 | - 'event_espresso' |
|
185 | - ); ?></h3> |
|
186 | - <p><?php |
|
187 | - esc_html_e( |
|
188 | - 'Create a beautiful event page with ticket selection, venue details, and an integrated single page checkout system. With WordPress, Event Espresso, and Espresso Arabica 2014 (based on the "Twenty Fourteen" theme by WordPress), your events will certainly sell out faster than ever!', |
|
189 | - 'event_espresso' |
|
190 | - ); ?></p> |
|
191 | - <p><?php |
|
192 | - esc_html_e( |
|
193 | - 'With a striking design that does not compromise the simplicity of WordPress and Event Espresso 4, Espresso Arabica 2014 will be the best event theme on the market.', |
|
194 | - 'event_espresso' |
|
195 | - ); ?></p> |
|
196 | - <p><?php |
|
197 | - echo sprintf( |
|
198 | - esc_html__('%sLearn more >>%s', 'event_espresso'), |
|
199 | - '<a href="http://eventespresso.com/wiki/setup-event-espresso-arabica-theme/">', |
|
200 | - '</a>' |
|
201 | - ); ?></p> |
|
182 | + esc_html_e( |
|
183 | + 'Turn your blog into a complete event registration and management system', |
|
184 | + 'event_espresso' |
|
185 | + ); ?></h3> |
|
186 | + <p><?php |
|
187 | + esc_html_e( |
|
188 | + 'Create a beautiful event page with ticket selection, venue details, and an integrated single page checkout system. With WordPress, Event Espresso, and Espresso Arabica 2014 (based on the "Twenty Fourteen" theme by WordPress), your events will certainly sell out faster than ever!', |
|
189 | + 'event_espresso' |
|
190 | + ); ?></p> |
|
191 | + <p><?php |
|
192 | + esc_html_e( |
|
193 | + 'With a striking design that does not compromise the simplicity of WordPress and Event Espresso 4, Espresso Arabica 2014 will be the best event theme on the market.', |
|
194 | + 'event_espresso' |
|
195 | + ); ?></p> |
|
196 | + <p><?php |
|
197 | + echo sprintf( |
|
198 | + esc_html__('%sLearn more >>%s', 'event_espresso'), |
|
199 | + '<a href="http://eventespresso.com/wiki/setup-event-espresso-arabica-theme/">', |
|
200 | + '</a>' |
|
201 | + ); ?></p> |
|
202 | 202 | </div> |
203 | 203 | <div class="column col"><img src="<?php echo EE_GLOBAL_ASSETS_URL; ?>images/screenshots/single-event-page.jpg"></div> |
204 | 204 | </div> |
@@ -209,10 +209,10 @@ discard block |
||
209 | 209 | <div class="feature-section has-1-column is-fullwidth is-wide one-col"> |
210 | 210 | <div class="column col"> |
211 | 211 | <p><?php |
212 | - esc_html_e( |
|
213 | - 'We’ve made it super easy to integrate Event Espresso with almost any properly coded WordPress theme, including many of the thousands of themes available on WordPress.org. The image below shows the same Event Espresso ticketing page across three diffrent WordPress themes.', |
|
214 | - 'event_espresso' |
|
215 | - ); ?></p> |
|
212 | + esc_html_e( |
|
213 | + 'We’ve made it super easy to integrate Event Espresso with almost any properly coded WordPress theme, including many of the thousands of themes available on WordPress.org. The image below shows the same Event Espresso ticketing page across three diffrent WordPress themes.', |
|
214 | + 'event_espresso' |
|
215 | + ); ?></p> |
|
216 | 216 | <p><img class="about-overview-img" src="<?php echo EE_GLOBAL_ASSETS_URL; ?>images/screenshots/multiple-themes.jpg"/></p> |
217 | 217 | </div> |
218 | 218 | </div> |
@@ -1,19 +1,19 @@ discard block |
||
1 | 1 | <h2 style="text-align: left;"><?php esc_html_e('Who uses Event Espresso?', 'event_espresso'); ?></h2> |
2 | 2 | <p><?php |
3 | - echo sprintf( |
|
4 | - esc_html__( |
|
5 | - 'Event Espresso is used by over 40,000 event organizers across the world. They host %sconferences%s, %sart classes%s, training courses, concerts, fundraisers, workshops, %sfilm festivals%s, %spaint and wine%s, and more.', |
|
6 | - 'event_espresso' |
|
7 | - ), |
|
8 | - '<a href="https://eventespresso.com/use-cases/conferences/?utm_source=wordpress_org&utm_medium=link&utm_campaign=decaf_about_page&utm_content=Decaf+vs+Regular">', |
|
9 | - '</a>', |
|
10 | - '<a href="https://eventespresso.com/use-cases/art-classes/?utm_source=wordpress_org&utm_medium=link&utm_campaign=decaf_about_page&utm_content=Decaf+vs+Regular">', |
|
11 | - '</a>', |
|
12 | - '<a href="https://eventespresso.com/use-cases/film-festival-ticketing-software/?utm_source=wordpress_org&utm_medium=link&utm_campaign=decaf_about_page&utm_content=Decaf+vs+Regular">', |
|
13 | - '</a>', |
|
14 | - '<a href="https://eventespresso.com/use-cases/paint-wine-party-ticketing-software/?utm_source=wordpress_org&utm_medium=link&utm_campaign=decaf_about_page&utm_content=Decaf+vs+Regular">', |
|
15 | - '</a>' |
|
16 | - ); ?></p> |
|
3 | + echo sprintf( |
|
4 | + esc_html__( |
|
5 | + 'Event Espresso is used by over 40,000 event organizers across the world. They host %sconferences%s, %sart classes%s, training courses, concerts, fundraisers, workshops, %sfilm festivals%s, %spaint and wine%s, and more.', |
|
6 | + 'event_espresso' |
|
7 | + ), |
|
8 | + '<a href="https://eventespresso.com/use-cases/conferences/?utm_source=wordpress_org&utm_medium=link&utm_campaign=decaf_about_page&utm_content=Decaf+vs+Regular">', |
|
9 | + '</a>', |
|
10 | + '<a href="https://eventespresso.com/use-cases/art-classes/?utm_source=wordpress_org&utm_medium=link&utm_campaign=decaf_about_page&utm_content=Decaf+vs+Regular">', |
|
11 | + '</a>', |
|
12 | + '<a href="https://eventespresso.com/use-cases/film-festival-ticketing-software/?utm_source=wordpress_org&utm_medium=link&utm_campaign=decaf_about_page&utm_content=Decaf+vs+Regular">', |
|
13 | + '</a>', |
|
14 | + '<a href="https://eventespresso.com/use-cases/paint-wine-party-ticketing-software/?utm_source=wordpress_org&utm_medium=link&utm_campaign=decaf_about_page&utm_content=Decaf+vs+Regular">', |
|
15 | + '</a>' |
|
16 | + ); ?></p> |
|
17 | 17 | |
18 | 18 | <h2 class="about-headline-callout"><?php esc_html_e('Rave Reviews About Event Espresso 4', 'event_espresso'); ?></h2> |
19 | 19 | <p>See what people have to say about the Event Espresso software and support services on <a |
@@ -135,16 +135,16 @@ discard block |
||
135 | 135 | |
136 | 136 | </div> |
137 | 137 | <?php |
138 | - if (! defined('EE_CAF_URL')) { |
|
139 | - ?> |
|
138 | + if (! defined('EE_CAF_URL')) { |
|
139 | + ?> |
|
140 | 140 | <div align="right"><a |
141 | 141 | href="https://eventespresso.com/pricing/?utm_source=wordpress_org&utm_medium=link&utm_campaign=decaf_about_page&utm_content=reviews+tab" |
142 | 142 | target="_blank" class="button button-primary button-hero"><span |
143 | 143 | class="dashicons dashicons-cart"></span><?php esc_html_e('Upgrade Now!', 'event_espresso') ?></a> |
144 | 144 | </div> |
145 | 145 | <?php |
146 | - } |
|
147 | - ?> |
|
146 | + } |
|
147 | + ?> |
|
148 | 148 | |
149 | 149 | <hr/> |
150 | 150 | <div class="feature-section has-3-columns is-fullwidth three-col"> |
@@ -255,16 +255,16 @@ discard block |
||
255 | 255 | |
256 | 256 | </div> |
257 | 257 | <?php |
258 | - if (! defined('EE_CAF_URL')) { |
|
259 | - ?> |
|
258 | + if (! defined('EE_CAF_URL')) { |
|
259 | + ?> |
|
260 | 260 | <div align="right"><a |
261 | 261 | href="https://eventespresso.com/pricing/?utm_source=wordpress_org&utm_medium=link&utm_campaign=decaf_about_page&utm_content=reviews+tab" |
262 | 262 | target="_blank" class="button button-primary button-hero"><span |
263 | 263 | class="dashicons dashicons-cart"></span><?php esc_html_e('Upgrade Now!', 'event_espresso') ?></a> |
264 | 264 | </div> |
265 | 265 | <?php |
266 | - } |
|
267 | - ?> |
|
266 | + } |
|
267 | + ?> |
|
268 | 268 | |
269 | 269 | <hr/> |
270 | 270 | <div class="feature-section has-3-columns is-fullwidth three-col"> |
@@ -366,13 +366,13 @@ discard block |
||
366 | 366 | </div> |
367 | 367 | </div> |
368 | 368 | <?php |
369 | - if (! defined('EE_CAF_URL')) { |
|
370 | - ?> |
|
369 | + if (! defined('EE_CAF_URL')) { |
|
370 | + ?> |
|
371 | 371 | <div align="right"><a |
372 | 372 | href="https://eventespresso.com/pricing/?utm_source=wordpress_org&utm_medium=link&utm_campaign=decaf_about_page&utm_content=reviews+tab" |
373 | 373 | target="_blank" class="button button-primary button-hero"><span |
374 | 374 | class="dashicons dashicons-cart"></span><?php esc_html_e('Upgrade Now!', 'event_espresso') ?></a> |
375 | 375 | </div> |
376 | 376 | <?php |
377 | - } |
|
378 | - ?> |
|
379 | 377 | \ No newline at end of file |
378 | + } |
|
379 | + ?> |
|
380 | 380 | \ No newline at end of file |
@@ -35,13 +35,13 @@ discard block |
||
35 | 35 | |
36 | 36 | <div class="contact-details-buttons"> |
37 | 37 | <?php |
38 | - if ($att_check instanceof EE_Attendee |
|
39 | - && EE_Registry::instance()->CAP->current_user_can( |
|
40 | - 'ee_edit_contact', |
|
41 | - 'view_or_edit_contact_button', |
|
42 | - $att_check->ID() |
|
43 | - )) : |
|
44 | - ?> |
|
38 | + if ($att_check instanceof EE_Attendee |
|
39 | + && EE_Registry::instance()->CAP->current_user_can( |
|
40 | + 'ee_edit_contact', |
|
41 | + 'view_or_edit_contact_button', |
|
42 | + $att_check->ID() |
|
43 | + )) : |
|
44 | + ?> |
|
45 | 45 | <a class="button button-small" href="<?php echo $att_edit_link; ?>" |
46 | 46 | title="<?php echo esc_attr($att_edit_label); ?>"> |
47 | 47 | <span class="ee-icon ee-icon-user-edit"></span><?php echo $att_edit_label; ?> |
@@ -49,15 +49,15 @@ discard block |
||
49 | 49 | <?php if (! empty($create_link)) : ?> |
50 | 50 | <a class="button button-small" href="<?php echo $create_link; ?>" |
51 | 51 | title="<?php |
52 | - esc_attr_e( |
|
53 | - 'This registration shares the contact details for the primary registration in this group. If you\'d like this registration to have its own details, you can do so by clicking this button', |
|
54 | - 'event_espresso' |
|
55 | - ); ?>"> |
|
52 | + esc_attr_e( |
|
53 | + 'This registration shares the contact details for the primary registration in this group. If you\'d like this registration to have its own details, you can do so by clicking this button', |
|
54 | + 'event_espresso' |
|
55 | + ); ?>"> |
|
56 | 56 | <span class="ee-icon ee-icon-user-add-new"></span><?php echo $create_label; ?> |
57 | 57 | </a> |
58 | 58 | <?php endif; ?> |
59 | 59 | <div style="clear:both"></div> |
60 | 60 | <?php |
61 | - endif; |
|
61 | + endif; |
|
62 | 62 | ?> |
63 | 63 | </div> |
@@ -2,7 +2,7 @@ discard block |
||
2 | 2 | <div class="clearfix"> |
3 | 3 | <span class="admin-side-mbox-label-spn lt-grey-txt float-left"> |
4 | 4 | <?php esc_html_e('Name', 'event_espresso'); ?> |
5 | - </span><?php echo $fname . ' ' . $lname; ?> |
|
5 | + </span><?php echo $fname.' '.$lname; ?> |
|
6 | 6 | </div> |
7 | 7 | <div class="clearfix"> |
8 | 8 | <span class="admin-side-mbox-label-spn lt-grey-txt float-left"> |
@@ -16,7 +16,7 @@ discard block |
||
16 | 16 | <span class="admin-side-mbox-label-spn lt-grey-txt float-left"> |
17 | 17 | <?php esc_html_e('Phone #', 'event_espresso'); ?> |
18 | 18 | </span> |
19 | - <?php if (! empty($phone)) : ?> |
|
19 | + <?php if ( ! empty($phone)) : ?> |
|
20 | 20 | <a href="tel:<?php echo $phone; ?>"> |
21 | 21 | <?php echo $phone; ?> |
22 | 22 | </a> |
@@ -46,7 +46,7 @@ discard block |
||
46 | 46 | title="<?php echo esc_attr($att_edit_label); ?>"> |
47 | 47 | <span class="ee-icon ee-icon-user-edit"></span><?php echo $att_edit_label; ?> |
48 | 48 | </a> |
49 | - <?php if (! empty($create_link)) : ?> |
|
49 | + <?php if ( ! empty($create_link)) : ?> |
|
50 | 50 | <a class="button button-small" href="<?php echo $create_link; ?>" |
51 | 51 | title="<?php |
52 | 52 | esc_attr_e( |
@@ -15,596 +15,596 @@ |
||
15 | 15 | class EE_Cron_Tasks extends EE_Base |
16 | 16 | { |
17 | 17 | |
18 | - /** |
|
19 | - * WordPress doesn't allow duplicate crons within 10 minutes of the original, |
|
20 | - * so we'll set our retry time for just over 10 minutes to avoid that |
|
21 | - */ |
|
22 | - const reschedule_timeout = 605; |
|
23 | - |
|
24 | - |
|
25 | - /** |
|
26 | - * @var EE_Cron_Tasks |
|
27 | - */ |
|
28 | - private static $_instance; |
|
29 | - |
|
30 | - |
|
31 | - /** |
|
32 | - * @return EE_Cron_Tasks |
|
33 | - * @throws ReflectionException |
|
34 | - * @throws EE_Error |
|
35 | - * @throws InvalidArgumentException |
|
36 | - * @throws InvalidInterfaceException |
|
37 | - * @throws InvalidDataTypeException |
|
38 | - */ |
|
39 | - public static function instance() |
|
40 | - { |
|
41 | - if (! self::$_instance instanceof EE_Cron_Tasks) { |
|
42 | - self::$_instance = new self(); |
|
43 | - } |
|
44 | - return self::$_instance; |
|
45 | - } |
|
46 | - |
|
47 | - |
|
48 | - /** |
|
49 | - * @access private |
|
50 | - * @throws InvalidDataTypeException |
|
51 | - * @throws InvalidInterfaceException |
|
52 | - * @throws InvalidArgumentException |
|
53 | - * @throws EE_Error |
|
54 | - * @throws ReflectionException |
|
55 | - */ |
|
56 | - private function __construct() |
|
57 | - { |
|
58 | - do_action('AHEE_log', __CLASS__, __FUNCTION__); |
|
59 | - // verify that WP Cron is enabled |
|
60 | - if (defined('DISABLE_WP_CRON') |
|
61 | - && DISABLE_WP_CRON |
|
62 | - && is_admin() |
|
63 | - && ! get_option('ee_disabled_wp_cron_check') |
|
64 | - ) { |
|
65 | - /** |
|
66 | - * This needs to be delayed until after the config is loaded because EE_Cron_Tasks is constructed before |
|
67 | - * config is loaded. |
|
68 | - * This is intentionally using a anonymous function so that its not easily de-registered. Client code |
|
69 | - * wanting to not have this functionality can just register its own action at a priority after this one to |
|
70 | - * reverse any changes. |
|
71 | - */ |
|
72 | - add_action( |
|
73 | - 'AHEE__EE_System__load_core_configuration__complete', |
|
74 | - function () { |
|
75 | - EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request = true; |
|
76 | - EE_Registry::instance()->NET_CFG->update_config(true, false); |
|
77 | - add_option('ee_disabled_wp_cron_check', 1, '', false); |
|
78 | - } |
|
79 | - ); |
|
80 | - } |
|
81 | - // UPDATE TRANSACTION WITH PAYMENT |
|
82 | - add_action( |
|
83 | - 'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2', |
|
84 | - array('EE_Cron_Tasks', 'setup_update_for_transaction_with_payment'), |
|
85 | - 10, |
|
86 | - 2 |
|
87 | - ); |
|
88 | - // ABANDONED / EXPIRED TRANSACTION CHECK |
|
89 | - add_action( |
|
90 | - 'AHEE__EE_Cron_Tasks__expired_transaction_check', |
|
91 | - array('EE_Cron_Tasks', 'expired_transaction_check'), |
|
92 | - 10, |
|
93 | - 1 |
|
94 | - ); |
|
95 | - // CLEAN OUT JUNK TRANSACTIONS AND RELATED DATA |
|
96 | - add_action( |
|
97 | - 'AHEE__EE_Cron_Tasks__clean_up_junk_transactions', |
|
98 | - array('EE_Cron_Tasks', 'clean_out_junk_transactions') |
|
99 | - ); |
|
100 | - // logging |
|
101 | - add_action( |
|
102 | - 'AHEE__EE_System__load_core_configuration__complete', |
|
103 | - array('EE_Cron_Tasks', 'log_scheduled_ee_crons') |
|
104 | - ); |
|
105 | - EE_Registry::instance()->load_lib('Messages_Scheduler'); |
|
106 | - // clean out old gateway logs |
|
107 | - add_action( |
|
108 | - 'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs', |
|
109 | - array('EE_Cron_Tasks', 'clean_out_old_gateway_logs') |
|
110 | - ); |
|
111 | - } |
|
112 | - |
|
113 | - |
|
114 | - /** |
|
115 | - * @access protected |
|
116 | - * @return void |
|
117 | - */ |
|
118 | - public static function log_scheduled_ee_crons() |
|
119 | - { |
|
120 | - $ee_crons = array( |
|
121 | - 'AHEE__EE_Cron_Tasks__update_transaction_with_payment', |
|
122 | - 'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions', |
|
123 | - 'AHEE__EE_Cron_Tasks__clean_up_junk_transactions', |
|
124 | - ); |
|
125 | - $crons = (array) get_option('cron'); |
|
126 | - if (! is_array($crons)) { |
|
127 | - return; |
|
128 | - } |
|
129 | - foreach ($crons as $timestamp => $cron) { |
|
130 | - /** @var array[] $cron */ |
|
131 | - foreach ($ee_crons as $ee_cron) { |
|
132 | - if (isset($cron[ $ee_cron ]) && is_array($cron[ $ee_cron ])) { |
|
133 | - do_action('AHEE_log', __CLASS__, __FUNCTION__, $ee_cron, 'scheduled EE cron'); |
|
134 | - foreach ($cron[ $ee_cron ] as $ee_cron_details) { |
|
135 | - if (! empty($ee_cron_details['args'])) { |
|
136 | - do_action( |
|
137 | - 'AHEE_log', |
|
138 | - __CLASS__, |
|
139 | - __FUNCTION__, |
|
140 | - print_r($ee_cron_details['args'], true), |
|
141 | - "{$ee_cron} args" |
|
142 | - ); |
|
143 | - } |
|
144 | - } |
|
145 | - } |
|
146 | - } |
|
147 | - } |
|
148 | - } |
|
149 | - |
|
150 | - |
|
151 | - /** |
|
152 | - * reschedule_cron_for_transactions_if_maintenance_mode |
|
153 | - * if Maintenance Mode is active, this will reschedule a cron to run again in 10 minutes |
|
154 | - * |
|
155 | - * @param string $cron_task |
|
156 | - * @param array $TXN_IDs |
|
157 | - * @return bool |
|
158 | - * @throws DomainException |
|
159 | - */ |
|
160 | - public static function reschedule_cron_for_transactions_if_maintenance_mode($cron_task, array $TXN_IDs) |
|
161 | - { |
|
162 | - if (! method_exists('EE_Cron_Tasks', $cron_task)) { |
|
163 | - throw new DomainException( |
|
164 | - sprintf( |
|
165 | - __('"%1$s" is not valid method on EE_Cron_Tasks.', 'event_espresso'), |
|
166 | - $cron_task |
|
167 | - ) |
|
168 | - ); |
|
169 | - } |
|
170 | - // reschedule the cron if we can't hit the db right now |
|
171 | - if (! EE_Maintenance_Mode::instance()->models_can_query()) { |
|
172 | - foreach ($TXN_IDs as $TXN_ID => $additional_vars) { |
|
173 | - // ensure $additional_vars is an array |
|
174 | - $additional_vars = is_array($additional_vars) ? $additional_vars : array($additional_vars); |
|
175 | - // reset cron job for the TXN |
|
176 | - call_user_func_array( |
|
177 | - array('EE_Cron_Tasks', $cron_task), |
|
178 | - array_merge( |
|
179 | - array( |
|
180 | - time() + (10 * MINUTE_IN_SECONDS), |
|
181 | - $TXN_ID, |
|
182 | - ), |
|
183 | - $additional_vars |
|
184 | - ) |
|
185 | - ); |
|
186 | - } |
|
187 | - return true; |
|
188 | - } |
|
189 | - return false; |
|
190 | - } |
|
191 | - |
|
192 | - |
|
193 | - |
|
194 | - |
|
195 | - /**************** UPDATE TRANSACTION WITH PAYMENT ****************/ |
|
196 | - |
|
197 | - |
|
198 | - /** |
|
199 | - * array of TXN IDs and the payment |
|
200 | - * |
|
201 | - * @var array |
|
202 | - */ |
|
203 | - protected static $_update_transactions_with_payment = array(); |
|
204 | - |
|
205 | - |
|
206 | - /** |
|
207 | - * schedule_update_transaction_with_payment |
|
208 | - * sets a wp_schedule_single_event() for updating any TXNs that may |
|
209 | - * require updating due to recently received payments |
|
210 | - * |
|
211 | - * @param int $timestamp |
|
212 | - * @param int $TXN_ID |
|
213 | - * @param int $PAY_ID |
|
214 | - */ |
|
215 | - public static function schedule_update_transaction_with_payment( |
|
216 | - $timestamp, |
|
217 | - $TXN_ID, |
|
218 | - $PAY_ID |
|
219 | - ) { |
|
220 | - do_action('AHEE_log', __CLASS__, __FUNCTION__); |
|
221 | - // validate $TXN_ID and $timestamp |
|
222 | - $TXN_ID = absint($TXN_ID); |
|
223 | - $timestamp = absint($timestamp); |
|
224 | - if ($TXN_ID && $timestamp) { |
|
225 | - wp_schedule_single_event( |
|
226 | - $timestamp, |
|
227 | - 'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2', |
|
228 | - array($TXN_ID, $PAY_ID) |
|
229 | - ); |
|
230 | - } |
|
231 | - } |
|
232 | - |
|
233 | - |
|
234 | - /** |
|
235 | - * setup_update_for_transaction_with_payment |
|
236 | - * this is the callback for the action hook: |
|
237 | - * 'AHEE__EE_Cron_Tasks__update_transaction_with_payment' |
|
238 | - * which is setup by EE_Cron_Tasks::schedule_update_transaction_with_payment(). |
|
239 | - * The passed TXN_ID and associated payment gets added to an array, and then |
|
240 | - * the EE_Cron_Tasks::update_transaction_with_payment() function is hooked into |
|
241 | - * 'shutdown' which will actually handle the processing of any |
|
242 | - * transactions requiring updating, because doing so now would be too early |
|
243 | - * and the required resources may not be available |
|
244 | - * |
|
245 | - * @param int $TXN_ID |
|
246 | - * @param int $PAY_ID |
|
247 | - */ |
|
248 | - public static function setup_update_for_transaction_with_payment($TXN_ID = 0, $PAY_ID = 0) |
|
249 | - { |
|
250 | - do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID'); |
|
251 | - if (absint($TXN_ID)) { |
|
252 | - self::$_update_transactions_with_payment[ $TXN_ID ] = $PAY_ID; |
|
253 | - add_action( |
|
254 | - 'shutdown', |
|
255 | - array('EE_Cron_Tasks', 'update_transaction_with_payment'), |
|
256 | - 5 |
|
257 | - ); |
|
258 | - } |
|
259 | - } |
|
260 | - |
|
261 | - |
|
262 | - /** |
|
263 | - * update_transaction_with_payment |
|
264 | - * loops through the self::$_abandoned_transactions array |
|
265 | - * and attempts to finalize any TXNs that have not been completed |
|
266 | - * but have had their sessions expired, most likely due to a user not |
|
267 | - * returning from an off-site payment gateway |
|
268 | - * |
|
269 | - * @throws EE_Error |
|
270 | - * @throws DomainException |
|
271 | - * @throws InvalidDataTypeException |
|
272 | - * @throws InvalidInterfaceException |
|
273 | - * @throws InvalidArgumentException |
|
274 | - * @throws ReflectionException |
|
275 | - * @throws RuntimeException |
|
276 | - */ |
|
277 | - public static function update_transaction_with_payment() |
|
278 | - { |
|
279 | - do_action('AHEE_log', __CLASS__, __FUNCTION__); |
|
280 | - if (// are there any TXNs that need cleaning up ? |
|
281 | - empty(self::$_update_transactions_with_payment) |
|
282 | - // reschedule the cron if we can't hit the db right now |
|
283 | - || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode( |
|
284 | - 'schedule_update_transaction_with_payment', |
|
285 | - self::$_update_transactions_with_payment |
|
286 | - ) |
|
287 | - ) { |
|
288 | - return; |
|
289 | - } |
|
290 | - /** @type EE_Payment_Processor $payment_processor */ |
|
291 | - $payment_processor = EE_Registry::instance()->load_core('Payment_Processor'); |
|
292 | - // set revisit flag for payment processor |
|
293 | - $payment_processor->set_revisit(); |
|
294 | - // load EEM_Transaction |
|
295 | - EE_Registry::instance()->load_model('Transaction'); |
|
296 | - foreach (self::$_update_transactions_with_payment as $TXN_ID => $PAY_ID) { |
|
297 | - // reschedule the cron if we can't hit the db right now |
|
298 | - if (! EE_Maintenance_Mode::instance()->models_can_query()) { |
|
299 | - // reset cron job for updating the TXN |
|
300 | - EE_Cron_Tasks::schedule_update_transaction_with_payment( |
|
301 | - time() + EE_Cron_Tasks::reschedule_timeout, |
|
302 | - $TXN_ID, |
|
303 | - $PAY_ID |
|
304 | - ); |
|
305 | - continue; |
|
306 | - } |
|
307 | - $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID); |
|
308 | - $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID); |
|
309 | - // verify transaction |
|
310 | - if ($transaction instanceof EE_Transaction && $payment instanceof EE_Payment) { |
|
311 | - // now try to update the TXN with any payments |
|
312 | - $payment_processor->update_txn_based_on_payment($transaction, $payment, true, true); |
|
313 | - } |
|
314 | - unset(self::$_update_transactions_with_payment[ $TXN_ID ]); |
|
315 | - } |
|
316 | - } |
|
317 | - |
|
318 | - |
|
319 | - |
|
320 | - /************ END OF UPDATE TRANSACTION WITH PAYMENT ************/ |
|
321 | - |
|
322 | - |
|
323 | - /***************** EXPIRED TRANSACTION CHECK *****************/ |
|
324 | - |
|
325 | - |
|
326 | - /** |
|
327 | - * array of TXN IDs |
|
328 | - * |
|
329 | - * @var array |
|
330 | - */ |
|
331 | - protected static $_expired_transactions = array(); |
|
332 | - |
|
333 | - |
|
334 | - /** |
|
335 | - * schedule_expired_transaction_check |
|
336 | - * sets a wp_schedule_single_event() for following up on TXNs after their session has expired |
|
337 | - * |
|
338 | - * @param int $timestamp |
|
339 | - * @param int $TXN_ID |
|
340 | - */ |
|
341 | - public static function schedule_expired_transaction_check( |
|
342 | - $timestamp, |
|
343 | - $TXN_ID |
|
344 | - ) { |
|
345 | - // validate $TXN_ID and $timestamp |
|
346 | - $TXN_ID = absint($TXN_ID); |
|
347 | - $timestamp = absint($timestamp); |
|
348 | - if ($TXN_ID && $timestamp) { |
|
349 | - wp_schedule_single_event( |
|
350 | - $timestamp, |
|
351 | - 'AHEE__EE_Cron_Tasks__expired_transaction_check', |
|
352 | - array($TXN_ID) |
|
353 | - ); |
|
354 | - } |
|
355 | - } |
|
356 | - |
|
357 | - |
|
358 | - /** |
|
359 | - * expired_transaction_check |
|
360 | - * this is the callback for the action hook: |
|
361 | - * 'AHEE__EE_Cron_Tasks__transaction_session_expiration_check' |
|
362 | - * which is utilized by wp_schedule_single_event() |
|
363 | - * in \EED_Single_Page_Checkout::_initialize_transaction(). |
|
364 | - * The passed TXN_ID gets added to an array, and then the |
|
365 | - * process_expired_transactions() function is hooked into |
|
366 | - * 'AHEE__EE_System__core_loaded_and_ready' which will actually handle the |
|
367 | - * processing of any failed transactions, because doing so now would be |
|
368 | - * too early and the required resources may not be available |
|
369 | - * |
|
370 | - * @param int $TXN_ID |
|
371 | - */ |
|
372 | - public static function expired_transaction_check($TXN_ID = 0) |
|
373 | - { |
|
374 | - if (absint($TXN_ID)) { |
|
375 | - self::$_expired_transactions[ $TXN_ID ] = $TXN_ID; |
|
376 | - add_action( |
|
377 | - 'shutdown', |
|
378 | - array('EE_Cron_Tasks', 'process_expired_transactions'), |
|
379 | - 5 |
|
380 | - ); |
|
381 | - } |
|
382 | - } |
|
383 | - |
|
384 | - |
|
385 | - /** |
|
386 | - * process_expired_transactions |
|
387 | - * loops through the self::$_expired_transactions array and processes any failed TXNs |
|
388 | - * |
|
389 | - * @throws EE_Error |
|
390 | - * @throws InvalidDataTypeException |
|
391 | - * @throws InvalidInterfaceException |
|
392 | - * @throws InvalidArgumentException |
|
393 | - * @throws ReflectionException |
|
394 | - * @throws DomainException |
|
395 | - * @throws RuntimeException |
|
396 | - */ |
|
397 | - public static function process_expired_transactions() |
|
398 | - { |
|
399 | - if (// are there any TXNs that need cleaning up ? |
|
400 | - empty(self::$_expired_transactions) |
|
401 | - // reschedule the cron if we can't hit the db right now |
|
402 | - || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode( |
|
403 | - 'schedule_expired_transaction_check', |
|
404 | - self::$_expired_transactions |
|
405 | - ) |
|
406 | - ) { |
|
407 | - return; |
|
408 | - } |
|
409 | - /** @type EE_Transaction_Processor $transaction_processor */ |
|
410 | - $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
411 | - // set revisit flag for txn processor |
|
412 | - $transaction_processor->set_revisit(); |
|
413 | - // load EEM_Transaction |
|
414 | - EE_Registry::instance()->load_model('Transaction'); |
|
415 | - foreach (self::$_expired_transactions as $TXN_ID) { |
|
416 | - $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID); |
|
417 | - // verify transaction and whether it is failed or not |
|
418 | - if ($transaction instanceof EE_Transaction) { |
|
419 | - switch ($transaction->status_ID()) { |
|
420 | - // Completed TXNs |
|
421 | - case EEM_Transaction::complete_status_code: |
|
422 | - /** @type EE_Transaction_Processor $transaction_processor */ |
|
423 | - $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
424 | - $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment( |
|
425 | - $transaction, |
|
426 | - $transaction->last_payment() |
|
427 | - ); |
|
428 | - do_action( |
|
429 | - 'AHEE__EE_Cron_Tasks__process_expired_transactions__completed_transaction', |
|
430 | - $transaction |
|
431 | - ); |
|
432 | - break; |
|
433 | - // Overpaid TXNs |
|
434 | - case EEM_Transaction::overpaid_status_code: |
|
435 | - do_action( |
|
436 | - 'AHEE__EE_Cron_Tasks__process_expired_transactions__overpaid_transaction', |
|
437 | - $transaction |
|
438 | - ); |
|
439 | - break; |
|
440 | - // Incomplete TXNs |
|
441 | - case EEM_Transaction::incomplete_status_code: |
|
442 | - do_action( |
|
443 | - 'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction', |
|
444 | - $transaction |
|
445 | - ); |
|
446 | - // todo : move business logic into EE_Transaction_Processor for finalizing abandoned transactions |
|
447 | - break; |
|
448 | - // Abandoned TXNs |
|
449 | - case EEM_Transaction::abandoned_status_code: |
|
450 | - // run hook before updating transaction, primarily so |
|
451 | - // EED_Ticket_Sales_Monitor::process_abandoned_transactions() can release reserved tickets |
|
452 | - do_action( |
|
453 | - 'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction', |
|
454 | - $transaction |
|
455 | - ); |
|
456 | - // don't finalize the TXN if it has already been completed |
|
457 | - if ($transaction->all_reg_steps_completed() !== true) { |
|
458 | - /** @type EE_Payment_Processor $payment_processor */ |
|
459 | - $payment_processor = EE_Registry::instance()->load_core('Payment_Processor'); |
|
460 | - // let's simulate an IPN here which will trigger any notifications that need to go out |
|
461 | - $payment_processor->update_txn_based_on_payment( |
|
462 | - $transaction, |
|
463 | - $transaction->last_payment(), |
|
464 | - true, |
|
465 | - true |
|
466 | - ); |
|
467 | - } |
|
468 | - break; |
|
469 | - // Failed TXNs |
|
470 | - case EEM_Transaction::failed_status_code: |
|
471 | - do_action( |
|
472 | - 'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction', |
|
473 | - $transaction |
|
474 | - ); |
|
475 | - // todo : |
|
476 | - // perform garbage collection here and remove clean_out_junk_transactions() |
|
477 | - // $registrations = $transaction->registrations(); |
|
478 | - // if (! empty($registrations)) { |
|
479 | - // foreach ($registrations as $registration) { |
|
480 | - // if ($registration instanceof EE_Registration) { |
|
481 | - // $delete_registration = true; |
|
482 | - // if ($registration->attendee() instanceof EE_Attendee) { |
|
483 | - // $delete_registration = false; |
|
484 | - // } |
|
485 | - // if ($delete_registration) { |
|
486 | - // $registration->delete_permanently(); |
|
487 | - // $registration->delete_related_permanently(); |
|
488 | - // } |
|
489 | - // } |
|
490 | - // } |
|
491 | - // } |
|
492 | - break; |
|
493 | - } |
|
494 | - } |
|
495 | - unset(self::$_expired_transactions[ $TXN_ID ]); |
|
496 | - } |
|
497 | - } |
|
498 | - |
|
499 | - |
|
500 | - |
|
501 | - /************* END OF EXPIRED TRANSACTION CHECK *************/ |
|
502 | - |
|
503 | - |
|
504 | - /************* START CLEAN UP BOT TRANSACTIONS **********************/ |
|
505 | - |
|
506 | - |
|
507 | - /** |
|
508 | - * callback for 'AHEE__EE_Cron_Tasks__clean_up_junk_transactions' |
|
509 | - * which is setup during activation to run on an hourly cron |
|
510 | - * |
|
511 | - * @throws EE_Error |
|
512 | - * @throws InvalidArgumentException |
|
513 | - * @throws InvalidDataTypeException |
|
514 | - * @throws InvalidInterfaceException |
|
515 | - * @throws DomainException |
|
516 | - */ |
|
517 | - public static function clean_out_junk_transactions() |
|
518 | - { |
|
519 | - if (EE_Maintenance_Mode::instance()->models_can_query()) { |
|
520 | - EED_Ticket_Sales_Monitor::reset_reservation_counts(); |
|
521 | - EEM_Transaction::instance('')->delete_junk_transactions(); |
|
522 | - EEM_Registration::instance('')->delete_registrations_with_no_transaction(); |
|
523 | - EEM_Line_Item::instance('')->delete_line_items_with_no_transaction(); |
|
524 | - } |
|
525 | - } |
|
526 | - |
|
527 | - |
|
528 | - /** |
|
529 | - * Deletes old gateway logs. After about a week we usually don't need them for debugging. But folks can filter that. |
|
530 | - * |
|
531 | - * @throws EE_Error |
|
532 | - * @throws InvalidDataTypeException |
|
533 | - * @throws InvalidInterfaceException |
|
534 | - * @throws InvalidArgumentException |
|
535 | - */ |
|
536 | - public static function clean_out_old_gateway_logs() |
|
537 | - { |
|
538 | - if (EE_Maintenance_Mode::instance()->models_can_query()) { |
|
539 | - $reg_config = LoaderFactory::getLoader()->load('EE_Registration_Config'); |
|
540 | - $time_diff_for_comparison = apply_filters( |
|
541 | - 'FHEE__EE_Cron_Tasks__clean_out_old_gateway_logs__time_diff_for_comparison', |
|
542 | - '-' . $reg_config->gateway_log_lifespan |
|
543 | - ); |
|
544 | - EEM_Change_Log::instance()->delete_gateway_logs_older_than(new DateTime($time_diff_for_comparison)); |
|
545 | - } |
|
546 | - } |
|
547 | - |
|
548 | - |
|
549 | - /***************** FINALIZE ABANDONED TRANSACTIONS *****************/ |
|
550 | - |
|
551 | - |
|
552 | - /** |
|
553 | - * @var array |
|
554 | - */ |
|
555 | - protected static $_abandoned_transactions = array(); |
|
556 | - |
|
557 | - |
|
558 | - /** |
|
559 | - * @deprecated |
|
560 | - * @param int $timestamp |
|
561 | - * @param int $TXN_ID |
|
562 | - */ |
|
563 | - public static function schedule_finalize_abandoned_transactions_check($timestamp, $TXN_ID) |
|
564 | - { |
|
565 | - EE_Cron_Tasks::schedule_expired_transaction_check($timestamp, $TXN_ID); |
|
566 | - } |
|
567 | - |
|
568 | - |
|
569 | - /** |
|
570 | - * @deprecated |
|
571 | - * @param int $TXN_ID |
|
572 | - */ |
|
573 | - public static function check_for_abandoned_transactions($TXN_ID = 0) |
|
574 | - { |
|
575 | - EE_Cron_Tasks::expired_transaction_check($TXN_ID); |
|
576 | - } |
|
577 | - |
|
578 | - |
|
579 | - /** |
|
580 | - * @deprecated |
|
581 | - * @throws EE_Error |
|
582 | - * @throws DomainException |
|
583 | - * @throws InvalidDataTypeException |
|
584 | - * @throws InvalidInterfaceException |
|
585 | - * @throws InvalidArgumentException |
|
586 | - * @throws ReflectionException |
|
587 | - * @throws RuntimeException |
|
588 | - */ |
|
589 | - public static function finalize_abandoned_transactions() |
|
590 | - { |
|
591 | - do_action('AHEE_log', __CLASS__, __FUNCTION__); |
|
592 | - if (// are there any TXNs that need cleaning up ? |
|
593 | - empty(self::$_abandoned_transactions) |
|
594 | - // reschedule the cron if we can't hit the db right now |
|
595 | - || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode( |
|
596 | - 'schedule_expired_transaction_check', |
|
597 | - self::$_abandoned_transactions |
|
598 | - ) |
|
599 | - ) { |
|
600 | - return; |
|
601 | - } |
|
602 | - // combine our arrays of transaction IDs |
|
603 | - self::$_expired_transactions = self::$_abandoned_transactions + self::$_expired_transactions; |
|
604 | - // and deal with abandoned transactions here now... |
|
605 | - EE_Cron_Tasks::process_expired_transactions(); |
|
606 | - } |
|
607 | - |
|
608 | - |
|
609 | - /************* END OF FINALIZE ABANDONED TRANSACTIONS *************/ |
|
18 | + /** |
|
19 | + * WordPress doesn't allow duplicate crons within 10 minutes of the original, |
|
20 | + * so we'll set our retry time for just over 10 minutes to avoid that |
|
21 | + */ |
|
22 | + const reschedule_timeout = 605; |
|
23 | + |
|
24 | + |
|
25 | + /** |
|
26 | + * @var EE_Cron_Tasks |
|
27 | + */ |
|
28 | + private static $_instance; |
|
29 | + |
|
30 | + |
|
31 | + /** |
|
32 | + * @return EE_Cron_Tasks |
|
33 | + * @throws ReflectionException |
|
34 | + * @throws EE_Error |
|
35 | + * @throws InvalidArgumentException |
|
36 | + * @throws InvalidInterfaceException |
|
37 | + * @throws InvalidDataTypeException |
|
38 | + */ |
|
39 | + public static function instance() |
|
40 | + { |
|
41 | + if (! self::$_instance instanceof EE_Cron_Tasks) { |
|
42 | + self::$_instance = new self(); |
|
43 | + } |
|
44 | + return self::$_instance; |
|
45 | + } |
|
46 | + |
|
47 | + |
|
48 | + /** |
|
49 | + * @access private |
|
50 | + * @throws InvalidDataTypeException |
|
51 | + * @throws InvalidInterfaceException |
|
52 | + * @throws InvalidArgumentException |
|
53 | + * @throws EE_Error |
|
54 | + * @throws ReflectionException |
|
55 | + */ |
|
56 | + private function __construct() |
|
57 | + { |
|
58 | + do_action('AHEE_log', __CLASS__, __FUNCTION__); |
|
59 | + // verify that WP Cron is enabled |
|
60 | + if (defined('DISABLE_WP_CRON') |
|
61 | + && DISABLE_WP_CRON |
|
62 | + && is_admin() |
|
63 | + && ! get_option('ee_disabled_wp_cron_check') |
|
64 | + ) { |
|
65 | + /** |
|
66 | + * This needs to be delayed until after the config is loaded because EE_Cron_Tasks is constructed before |
|
67 | + * config is loaded. |
|
68 | + * This is intentionally using a anonymous function so that its not easily de-registered. Client code |
|
69 | + * wanting to not have this functionality can just register its own action at a priority after this one to |
|
70 | + * reverse any changes. |
|
71 | + */ |
|
72 | + add_action( |
|
73 | + 'AHEE__EE_System__load_core_configuration__complete', |
|
74 | + function () { |
|
75 | + EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request = true; |
|
76 | + EE_Registry::instance()->NET_CFG->update_config(true, false); |
|
77 | + add_option('ee_disabled_wp_cron_check', 1, '', false); |
|
78 | + } |
|
79 | + ); |
|
80 | + } |
|
81 | + // UPDATE TRANSACTION WITH PAYMENT |
|
82 | + add_action( |
|
83 | + 'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2', |
|
84 | + array('EE_Cron_Tasks', 'setup_update_for_transaction_with_payment'), |
|
85 | + 10, |
|
86 | + 2 |
|
87 | + ); |
|
88 | + // ABANDONED / EXPIRED TRANSACTION CHECK |
|
89 | + add_action( |
|
90 | + 'AHEE__EE_Cron_Tasks__expired_transaction_check', |
|
91 | + array('EE_Cron_Tasks', 'expired_transaction_check'), |
|
92 | + 10, |
|
93 | + 1 |
|
94 | + ); |
|
95 | + // CLEAN OUT JUNK TRANSACTIONS AND RELATED DATA |
|
96 | + add_action( |
|
97 | + 'AHEE__EE_Cron_Tasks__clean_up_junk_transactions', |
|
98 | + array('EE_Cron_Tasks', 'clean_out_junk_transactions') |
|
99 | + ); |
|
100 | + // logging |
|
101 | + add_action( |
|
102 | + 'AHEE__EE_System__load_core_configuration__complete', |
|
103 | + array('EE_Cron_Tasks', 'log_scheduled_ee_crons') |
|
104 | + ); |
|
105 | + EE_Registry::instance()->load_lib('Messages_Scheduler'); |
|
106 | + // clean out old gateway logs |
|
107 | + add_action( |
|
108 | + 'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs', |
|
109 | + array('EE_Cron_Tasks', 'clean_out_old_gateway_logs') |
|
110 | + ); |
|
111 | + } |
|
112 | + |
|
113 | + |
|
114 | + /** |
|
115 | + * @access protected |
|
116 | + * @return void |
|
117 | + */ |
|
118 | + public static function log_scheduled_ee_crons() |
|
119 | + { |
|
120 | + $ee_crons = array( |
|
121 | + 'AHEE__EE_Cron_Tasks__update_transaction_with_payment', |
|
122 | + 'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions', |
|
123 | + 'AHEE__EE_Cron_Tasks__clean_up_junk_transactions', |
|
124 | + ); |
|
125 | + $crons = (array) get_option('cron'); |
|
126 | + if (! is_array($crons)) { |
|
127 | + return; |
|
128 | + } |
|
129 | + foreach ($crons as $timestamp => $cron) { |
|
130 | + /** @var array[] $cron */ |
|
131 | + foreach ($ee_crons as $ee_cron) { |
|
132 | + if (isset($cron[ $ee_cron ]) && is_array($cron[ $ee_cron ])) { |
|
133 | + do_action('AHEE_log', __CLASS__, __FUNCTION__, $ee_cron, 'scheduled EE cron'); |
|
134 | + foreach ($cron[ $ee_cron ] as $ee_cron_details) { |
|
135 | + if (! empty($ee_cron_details['args'])) { |
|
136 | + do_action( |
|
137 | + 'AHEE_log', |
|
138 | + __CLASS__, |
|
139 | + __FUNCTION__, |
|
140 | + print_r($ee_cron_details['args'], true), |
|
141 | + "{$ee_cron} args" |
|
142 | + ); |
|
143 | + } |
|
144 | + } |
|
145 | + } |
|
146 | + } |
|
147 | + } |
|
148 | + } |
|
149 | + |
|
150 | + |
|
151 | + /** |
|
152 | + * reschedule_cron_for_transactions_if_maintenance_mode |
|
153 | + * if Maintenance Mode is active, this will reschedule a cron to run again in 10 minutes |
|
154 | + * |
|
155 | + * @param string $cron_task |
|
156 | + * @param array $TXN_IDs |
|
157 | + * @return bool |
|
158 | + * @throws DomainException |
|
159 | + */ |
|
160 | + public static function reschedule_cron_for_transactions_if_maintenance_mode($cron_task, array $TXN_IDs) |
|
161 | + { |
|
162 | + if (! method_exists('EE_Cron_Tasks', $cron_task)) { |
|
163 | + throw new DomainException( |
|
164 | + sprintf( |
|
165 | + __('"%1$s" is not valid method on EE_Cron_Tasks.', 'event_espresso'), |
|
166 | + $cron_task |
|
167 | + ) |
|
168 | + ); |
|
169 | + } |
|
170 | + // reschedule the cron if we can't hit the db right now |
|
171 | + if (! EE_Maintenance_Mode::instance()->models_can_query()) { |
|
172 | + foreach ($TXN_IDs as $TXN_ID => $additional_vars) { |
|
173 | + // ensure $additional_vars is an array |
|
174 | + $additional_vars = is_array($additional_vars) ? $additional_vars : array($additional_vars); |
|
175 | + // reset cron job for the TXN |
|
176 | + call_user_func_array( |
|
177 | + array('EE_Cron_Tasks', $cron_task), |
|
178 | + array_merge( |
|
179 | + array( |
|
180 | + time() + (10 * MINUTE_IN_SECONDS), |
|
181 | + $TXN_ID, |
|
182 | + ), |
|
183 | + $additional_vars |
|
184 | + ) |
|
185 | + ); |
|
186 | + } |
|
187 | + return true; |
|
188 | + } |
|
189 | + return false; |
|
190 | + } |
|
191 | + |
|
192 | + |
|
193 | + |
|
194 | + |
|
195 | + /**************** UPDATE TRANSACTION WITH PAYMENT ****************/ |
|
196 | + |
|
197 | + |
|
198 | + /** |
|
199 | + * array of TXN IDs and the payment |
|
200 | + * |
|
201 | + * @var array |
|
202 | + */ |
|
203 | + protected static $_update_transactions_with_payment = array(); |
|
204 | + |
|
205 | + |
|
206 | + /** |
|
207 | + * schedule_update_transaction_with_payment |
|
208 | + * sets a wp_schedule_single_event() for updating any TXNs that may |
|
209 | + * require updating due to recently received payments |
|
210 | + * |
|
211 | + * @param int $timestamp |
|
212 | + * @param int $TXN_ID |
|
213 | + * @param int $PAY_ID |
|
214 | + */ |
|
215 | + public static function schedule_update_transaction_with_payment( |
|
216 | + $timestamp, |
|
217 | + $TXN_ID, |
|
218 | + $PAY_ID |
|
219 | + ) { |
|
220 | + do_action('AHEE_log', __CLASS__, __FUNCTION__); |
|
221 | + // validate $TXN_ID and $timestamp |
|
222 | + $TXN_ID = absint($TXN_ID); |
|
223 | + $timestamp = absint($timestamp); |
|
224 | + if ($TXN_ID && $timestamp) { |
|
225 | + wp_schedule_single_event( |
|
226 | + $timestamp, |
|
227 | + 'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2', |
|
228 | + array($TXN_ID, $PAY_ID) |
|
229 | + ); |
|
230 | + } |
|
231 | + } |
|
232 | + |
|
233 | + |
|
234 | + /** |
|
235 | + * setup_update_for_transaction_with_payment |
|
236 | + * this is the callback for the action hook: |
|
237 | + * 'AHEE__EE_Cron_Tasks__update_transaction_with_payment' |
|
238 | + * which is setup by EE_Cron_Tasks::schedule_update_transaction_with_payment(). |
|
239 | + * The passed TXN_ID and associated payment gets added to an array, and then |
|
240 | + * the EE_Cron_Tasks::update_transaction_with_payment() function is hooked into |
|
241 | + * 'shutdown' which will actually handle the processing of any |
|
242 | + * transactions requiring updating, because doing so now would be too early |
|
243 | + * and the required resources may not be available |
|
244 | + * |
|
245 | + * @param int $TXN_ID |
|
246 | + * @param int $PAY_ID |
|
247 | + */ |
|
248 | + public static function setup_update_for_transaction_with_payment($TXN_ID = 0, $PAY_ID = 0) |
|
249 | + { |
|
250 | + do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID'); |
|
251 | + if (absint($TXN_ID)) { |
|
252 | + self::$_update_transactions_with_payment[ $TXN_ID ] = $PAY_ID; |
|
253 | + add_action( |
|
254 | + 'shutdown', |
|
255 | + array('EE_Cron_Tasks', 'update_transaction_with_payment'), |
|
256 | + 5 |
|
257 | + ); |
|
258 | + } |
|
259 | + } |
|
260 | + |
|
261 | + |
|
262 | + /** |
|
263 | + * update_transaction_with_payment |
|
264 | + * loops through the self::$_abandoned_transactions array |
|
265 | + * and attempts to finalize any TXNs that have not been completed |
|
266 | + * but have had their sessions expired, most likely due to a user not |
|
267 | + * returning from an off-site payment gateway |
|
268 | + * |
|
269 | + * @throws EE_Error |
|
270 | + * @throws DomainException |
|
271 | + * @throws InvalidDataTypeException |
|
272 | + * @throws InvalidInterfaceException |
|
273 | + * @throws InvalidArgumentException |
|
274 | + * @throws ReflectionException |
|
275 | + * @throws RuntimeException |
|
276 | + */ |
|
277 | + public static function update_transaction_with_payment() |
|
278 | + { |
|
279 | + do_action('AHEE_log', __CLASS__, __FUNCTION__); |
|
280 | + if (// are there any TXNs that need cleaning up ? |
|
281 | + empty(self::$_update_transactions_with_payment) |
|
282 | + // reschedule the cron if we can't hit the db right now |
|
283 | + || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode( |
|
284 | + 'schedule_update_transaction_with_payment', |
|
285 | + self::$_update_transactions_with_payment |
|
286 | + ) |
|
287 | + ) { |
|
288 | + return; |
|
289 | + } |
|
290 | + /** @type EE_Payment_Processor $payment_processor */ |
|
291 | + $payment_processor = EE_Registry::instance()->load_core('Payment_Processor'); |
|
292 | + // set revisit flag for payment processor |
|
293 | + $payment_processor->set_revisit(); |
|
294 | + // load EEM_Transaction |
|
295 | + EE_Registry::instance()->load_model('Transaction'); |
|
296 | + foreach (self::$_update_transactions_with_payment as $TXN_ID => $PAY_ID) { |
|
297 | + // reschedule the cron if we can't hit the db right now |
|
298 | + if (! EE_Maintenance_Mode::instance()->models_can_query()) { |
|
299 | + // reset cron job for updating the TXN |
|
300 | + EE_Cron_Tasks::schedule_update_transaction_with_payment( |
|
301 | + time() + EE_Cron_Tasks::reschedule_timeout, |
|
302 | + $TXN_ID, |
|
303 | + $PAY_ID |
|
304 | + ); |
|
305 | + continue; |
|
306 | + } |
|
307 | + $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID); |
|
308 | + $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID); |
|
309 | + // verify transaction |
|
310 | + if ($transaction instanceof EE_Transaction && $payment instanceof EE_Payment) { |
|
311 | + // now try to update the TXN with any payments |
|
312 | + $payment_processor->update_txn_based_on_payment($transaction, $payment, true, true); |
|
313 | + } |
|
314 | + unset(self::$_update_transactions_with_payment[ $TXN_ID ]); |
|
315 | + } |
|
316 | + } |
|
317 | + |
|
318 | + |
|
319 | + |
|
320 | + /************ END OF UPDATE TRANSACTION WITH PAYMENT ************/ |
|
321 | + |
|
322 | + |
|
323 | + /***************** EXPIRED TRANSACTION CHECK *****************/ |
|
324 | + |
|
325 | + |
|
326 | + /** |
|
327 | + * array of TXN IDs |
|
328 | + * |
|
329 | + * @var array |
|
330 | + */ |
|
331 | + protected static $_expired_transactions = array(); |
|
332 | + |
|
333 | + |
|
334 | + /** |
|
335 | + * schedule_expired_transaction_check |
|
336 | + * sets a wp_schedule_single_event() for following up on TXNs after their session has expired |
|
337 | + * |
|
338 | + * @param int $timestamp |
|
339 | + * @param int $TXN_ID |
|
340 | + */ |
|
341 | + public static function schedule_expired_transaction_check( |
|
342 | + $timestamp, |
|
343 | + $TXN_ID |
|
344 | + ) { |
|
345 | + // validate $TXN_ID and $timestamp |
|
346 | + $TXN_ID = absint($TXN_ID); |
|
347 | + $timestamp = absint($timestamp); |
|
348 | + if ($TXN_ID && $timestamp) { |
|
349 | + wp_schedule_single_event( |
|
350 | + $timestamp, |
|
351 | + 'AHEE__EE_Cron_Tasks__expired_transaction_check', |
|
352 | + array($TXN_ID) |
|
353 | + ); |
|
354 | + } |
|
355 | + } |
|
356 | + |
|
357 | + |
|
358 | + /** |
|
359 | + * expired_transaction_check |
|
360 | + * this is the callback for the action hook: |
|
361 | + * 'AHEE__EE_Cron_Tasks__transaction_session_expiration_check' |
|
362 | + * which is utilized by wp_schedule_single_event() |
|
363 | + * in \EED_Single_Page_Checkout::_initialize_transaction(). |
|
364 | + * The passed TXN_ID gets added to an array, and then the |
|
365 | + * process_expired_transactions() function is hooked into |
|
366 | + * 'AHEE__EE_System__core_loaded_and_ready' which will actually handle the |
|
367 | + * processing of any failed transactions, because doing so now would be |
|
368 | + * too early and the required resources may not be available |
|
369 | + * |
|
370 | + * @param int $TXN_ID |
|
371 | + */ |
|
372 | + public static function expired_transaction_check($TXN_ID = 0) |
|
373 | + { |
|
374 | + if (absint($TXN_ID)) { |
|
375 | + self::$_expired_transactions[ $TXN_ID ] = $TXN_ID; |
|
376 | + add_action( |
|
377 | + 'shutdown', |
|
378 | + array('EE_Cron_Tasks', 'process_expired_transactions'), |
|
379 | + 5 |
|
380 | + ); |
|
381 | + } |
|
382 | + } |
|
383 | + |
|
384 | + |
|
385 | + /** |
|
386 | + * process_expired_transactions |
|
387 | + * loops through the self::$_expired_transactions array and processes any failed TXNs |
|
388 | + * |
|
389 | + * @throws EE_Error |
|
390 | + * @throws InvalidDataTypeException |
|
391 | + * @throws InvalidInterfaceException |
|
392 | + * @throws InvalidArgumentException |
|
393 | + * @throws ReflectionException |
|
394 | + * @throws DomainException |
|
395 | + * @throws RuntimeException |
|
396 | + */ |
|
397 | + public static function process_expired_transactions() |
|
398 | + { |
|
399 | + if (// are there any TXNs that need cleaning up ? |
|
400 | + empty(self::$_expired_transactions) |
|
401 | + // reschedule the cron if we can't hit the db right now |
|
402 | + || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode( |
|
403 | + 'schedule_expired_transaction_check', |
|
404 | + self::$_expired_transactions |
|
405 | + ) |
|
406 | + ) { |
|
407 | + return; |
|
408 | + } |
|
409 | + /** @type EE_Transaction_Processor $transaction_processor */ |
|
410 | + $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
411 | + // set revisit flag for txn processor |
|
412 | + $transaction_processor->set_revisit(); |
|
413 | + // load EEM_Transaction |
|
414 | + EE_Registry::instance()->load_model('Transaction'); |
|
415 | + foreach (self::$_expired_transactions as $TXN_ID) { |
|
416 | + $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID); |
|
417 | + // verify transaction and whether it is failed or not |
|
418 | + if ($transaction instanceof EE_Transaction) { |
|
419 | + switch ($transaction->status_ID()) { |
|
420 | + // Completed TXNs |
|
421 | + case EEM_Transaction::complete_status_code: |
|
422 | + /** @type EE_Transaction_Processor $transaction_processor */ |
|
423 | + $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
424 | + $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment( |
|
425 | + $transaction, |
|
426 | + $transaction->last_payment() |
|
427 | + ); |
|
428 | + do_action( |
|
429 | + 'AHEE__EE_Cron_Tasks__process_expired_transactions__completed_transaction', |
|
430 | + $transaction |
|
431 | + ); |
|
432 | + break; |
|
433 | + // Overpaid TXNs |
|
434 | + case EEM_Transaction::overpaid_status_code: |
|
435 | + do_action( |
|
436 | + 'AHEE__EE_Cron_Tasks__process_expired_transactions__overpaid_transaction', |
|
437 | + $transaction |
|
438 | + ); |
|
439 | + break; |
|
440 | + // Incomplete TXNs |
|
441 | + case EEM_Transaction::incomplete_status_code: |
|
442 | + do_action( |
|
443 | + 'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction', |
|
444 | + $transaction |
|
445 | + ); |
|
446 | + // todo : move business logic into EE_Transaction_Processor for finalizing abandoned transactions |
|
447 | + break; |
|
448 | + // Abandoned TXNs |
|
449 | + case EEM_Transaction::abandoned_status_code: |
|
450 | + // run hook before updating transaction, primarily so |
|
451 | + // EED_Ticket_Sales_Monitor::process_abandoned_transactions() can release reserved tickets |
|
452 | + do_action( |
|
453 | + 'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction', |
|
454 | + $transaction |
|
455 | + ); |
|
456 | + // don't finalize the TXN if it has already been completed |
|
457 | + if ($transaction->all_reg_steps_completed() !== true) { |
|
458 | + /** @type EE_Payment_Processor $payment_processor */ |
|
459 | + $payment_processor = EE_Registry::instance()->load_core('Payment_Processor'); |
|
460 | + // let's simulate an IPN here which will trigger any notifications that need to go out |
|
461 | + $payment_processor->update_txn_based_on_payment( |
|
462 | + $transaction, |
|
463 | + $transaction->last_payment(), |
|
464 | + true, |
|
465 | + true |
|
466 | + ); |
|
467 | + } |
|
468 | + break; |
|
469 | + // Failed TXNs |
|
470 | + case EEM_Transaction::failed_status_code: |
|
471 | + do_action( |
|
472 | + 'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction', |
|
473 | + $transaction |
|
474 | + ); |
|
475 | + // todo : |
|
476 | + // perform garbage collection here and remove clean_out_junk_transactions() |
|
477 | + // $registrations = $transaction->registrations(); |
|
478 | + // if (! empty($registrations)) { |
|
479 | + // foreach ($registrations as $registration) { |
|
480 | + // if ($registration instanceof EE_Registration) { |
|
481 | + // $delete_registration = true; |
|
482 | + // if ($registration->attendee() instanceof EE_Attendee) { |
|
483 | + // $delete_registration = false; |
|
484 | + // } |
|
485 | + // if ($delete_registration) { |
|
486 | + // $registration->delete_permanently(); |
|
487 | + // $registration->delete_related_permanently(); |
|
488 | + // } |
|
489 | + // } |
|
490 | + // } |
|
491 | + // } |
|
492 | + break; |
|
493 | + } |
|
494 | + } |
|
495 | + unset(self::$_expired_transactions[ $TXN_ID ]); |
|
496 | + } |
|
497 | + } |
|
498 | + |
|
499 | + |
|
500 | + |
|
501 | + /************* END OF EXPIRED TRANSACTION CHECK *************/ |
|
502 | + |
|
503 | + |
|
504 | + /************* START CLEAN UP BOT TRANSACTIONS **********************/ |
|
505 | + |
|
506 | + |
|
507 | + /** |
|
508 | + * callback for 'AHEE__EE_Cron_Tasks__clean_up_junk_transactions' |
|
509 | + * which is setup during activation to run on an hourly cron |
|
510 | + * |
|
511 | + * @throws EE_Error |
|
512 | + * @throws InvalidArgumentException |
|
513 | + * @throws InvalidDataTypeException |
|
514 | + * @throws InvalidInterfaceException |
|
515 | + * @throws DomainException |
|
516 | + */ |
|
517 | + public static function clean_out_junk_transactions() |
|
518 | + { |
|
519 | + if (EE_Maintenance_Mode::instance()->models_can_query()) { |
|
520 | + EED_Ticket_Sales_Monitor::reset_reservation_counts(); |
|
521 | + EEM_Transaction::instance('')->delete_junk_transactions(); |
|
522 | + EEM_Registration::instance('')->delete_registrations_with_no_transaction(); |
|
523 | + EEM_Line_Item::instance('')->delete_line_items_with_no_transaction(); |
|
524 | + } |
|
525 | + } |
|
526 | + |
|
527 | + |
|
528 | + /** |
|
529 | + * Deletes old gateway logs. After about a week we usually don't need them for debugging. But folks can filter that. |
|
530 | + * |
|
531 | + * @throws EE_Error |
|
532 | + * @throws InvalidDataTypeException |
|
533 | + * @throws InvalidInterfaceException |
|
534 | + * @throws InvalidArgumentException |
|
535 | + */ |
|
536 | + public static function clean_out_old_gateway_logs() |
|
537 | + { |
|
538 | + if (EE_Maintenance_Mode::instance()->models_can_query()) { |
|
539 | + $reg_config = LoaderFactory::getLoader()->load('EE_Registration_Config'); |
|
540 | + $time_diff_for_comparison = apply_filters( |
|
541 | + 'FHEE__EE_Cron_Tasks__clean_out_old_gateway_logs__time_diff_for_comparison', |
|
542 | + '-' . $reg_config->gateway_log_lifespan |
|
543 | + ); |
|
544 | + EEM_Change_Log::instance()->delete_gateway_logs_older_than(new DateTime($time_diff_for_comparison)); |
|
545 | + } |
|
546 | + } |
|
547 | + |
|
548 | + |
|
549 | + /***************** FINALIZE ABANDONED TRANSACTIONS *****************/ |
|
550 | + |
|
551 | + |
|
552 | + /** |
|
553 | + * @var array |
|
554 | + */ |
|
555 | + protected static $_abandoned_transactions = array(); |
|
556 | + |
|
557 | + |
|
558 | + /** |
|
559 | + * @deprecated |
|
560 | + * @param int $timestamp |
|
561 | + * @param int $TXN_ID |
|
562 | + */ |
|
563 | + public static function schedule_finalize_abandoned_transactions_check($timestamp, $TXN_ID) |
|
564 | + { |
|
565 | + EE_Cron_Tasks::schedule_expired_transaction_check($timestamp, $TXN_ID); |
|
566 | + } |
|
567 | + |
|
568 | + |
|
569 | + /** |
|
570 | + * @deprecated |
|
571 | + * @param int $TXN_ID |
|
572 | + */ |
|
573 | + public static function check_for_abandoned_transactions($TXN_ID = 0) |
|
574 | + { |
|
575 | + EE_Cron_Tasks::expired_transaction_check($TXN_ID); |
|
576 | + } |
|
577 | + |
|
578 | + |
|
579 | + /** |
|
580 | + * @deprecated |
|
581 | + * @throws EE_Error |
|
582 | + * @throws DomainException |
|
583 | + * @throws InvalidDataTypeException |
|
584 | + * @throws InvalidInterfaceException |
|
585 | + * @throws InvalidArgumentException |
|
586 | + * @throws ReflectionException |
|
587 | + * @throws RuntimeException |
|
588 | + */ |
|
589 | + public static function finalize_abandoned_transactions() |
|
590 | + { |
|
591 | + do_action('AHEE_log', __CLASS__, __FUNCTION__); |
|
592 | + if (// are there any TXNs that need cleaning up ? |
|
593 | + empty(self::$_abandoned_transactions) |
|
594 | + // reschedule the cron if we can't hit the db right now |
|
595 | + || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode( |
|
596 | + 'schedule_expired_transaction_check', |
|
597 | + self::$_abandoned_transactions |
|
598 | + ) |
|
599 | + ) { |
|
600 | + return; |
|
601 | + } |
|
602 | + // combine our arrays of transaction IDs |
|
603 | + self::$_expired_transactions = self::$_abandoned_transactions + self::$_expired_transactions; |
|
604 | + // and deal with abandoned transactions here now... |
|
605 | + EE_Cron_Tasks::process_expired_transactions(); |
|
606 | + } |
|
607 | + |
|
608 | + |
|
609 | + /************* END OF FINALIZE ABANDONED TRANSACTIONS *************/ |
|
610 | 610 | } |
@@ -22,239 +22,239 @@ |
||
22 | 22 | class ThankYouPageIpnMonitor |
23 | 23 | { |
24 | 24 | |
25 | - /** |
|
26 | - * @var string $heartbeat |
|
27 | - */ |
|
28 | - private $heartbeat; |
|
25 | + /** |
|
26 | + * @var string $heartbeat |
|
27 | + */ |
|
28 | + private $heartbeat; |
|
29 | 29 | |
30 | - /** |
|
31 | - * @var EED_Thank_You_Page $thank_you_page |
|
32 | - */ |
|
33 | - private $thank_you_page; |
|
30 | + /** |
|
31 | + * @var EED_Thank_You_Page $thank_you_page |
|
32 | + */ |
|
33 | + private $thank_you_page; |
|
34 | 34 | |
35 | - /** |
|
36 | - * @var EE_Transaction $transaction |
|
37 | - */ |
|
38 | - private $transaction; |
|
35 | + /** |
|
36 | + * @var EE_Transaction $transaction |
|
37 | + */ |
|
38 | + private $transaction; |
|
39 | 39 | |
40 | 40 | |
41 | - /** |
|
42 | - * EventEditorHeartbeat constructor. |
|
43 | - */ |
|
44 | - public function __construct() |
|
45 | - { |
|
46 | - $this->heartbeat = WordpressHeartbeat::RESPONSE_KEY_THANK_YOU_PAGE; |
|
47 | - add_filter('heartbeat_received', array($this, 'heartbeatResponse'), 10, 3); |
|
48 | - add_filter('heartbeat_nopriv_received', array($this, 'heartbeatResponse'), 10, 3); |
|
49 | - } |
|
41 | + /** |
|
42 | + * EventEditorHeartbeat constructor. |
|
43 | + */ |
|
44 | + public function __construct() |
|
45 | + { |
|
46 | + $this->heartbeat = WordpressHeartbeat::RESPONSE_KEY_THANK_YOU_PAGE; |
|
47 | + add_filter('heartbeat_received', array($this, 'heartbeatResponse'), 10, 3); |
|
48 | + add_filter('heartbeat_nopriv_received', array($this, 'heartbeatResponse'), 10, 3); |
|
49 | + } |
|
50 | 50 | |
51 | 51 | |
52 | - /** |
|
53 | - * thank_you_page_IPN_monitor |
|
54 | - * this basically just pulls the TXN based on the reg_url_link sent from the server, |
|
55 | - * then checks that the TXN status is not failed, and that no other errors have been generated. |
|
56 | - * it also calculates the IPN wait time since the Thank You page was first loaded |
|
57 | - * |
|
58 | - * @param array $response |
|
59 | - * @param array $data |
|
60 | - * @return array |
|
61 | - * @throws EE_Error |
|
62 | - * @throws InvalidArgumentException |
|
63 | - * @throws InvalidDataTypeException |
|
64 | - * @throws InvalidInterfaceException |
|
65 | - * @throws ReflectionException |
|
66 | - */ |
|
67 | - public function heartbeatResponse($response = array(), $data = array()) |
|
68 | - { |
|
69 | - // does this heartbeat contain our data ? |
|
70 | - if (! isset($data[ $this->heartbeat ])) { |
|
71 | - return $response; |
|
72 | - } |
|
73 | - // check for reg_url_link in the incoming heartbeat data |
|
74 | - if (! isset($data[ $this->heartbeat ]['e_reg_url_link'])) { |
|
75 | - $response[ $this->heartbeat ] = array( |
|
76 | - 'errors' => ! empty($notices['errors']) |
|
77 | - ? $notices['errors'] |
|
78 | - : __( |
|
79 | - 'No transaction information could be retrieved because the registration URL link is missing or invalid.', |
|
80 | - 'event_espresso' |
|
81 | - ), |
|
82 | - ); |
|
83 | - return $response; |
|
84 | - } |
|
85 | - // kk heartbeat has our data |
|
86 | - $response = $this->initializeThankYouPageAndTransaction($response, $data); |
|
87 | - // if something went wrong... |
|
88 | - if (isset($response[ $this->heartbeat ]['errors'])) { |
|
89 | - return $response; |
|
90 | - } |
|
91 | - // grab transient of Transaction's status |
|
92 | - $txn_status = isset($data[ $this->heartbeat ]['txn_status']) |
|
93 | - ? $data[ $this->heartbeat ]['txn_status'] |
|
94 | - : null; |
|
95 | - $response = $this->getTransactionDetails($txn_status, $response, $data); |
|
96 | - // no payment data yet? |
|
97 | - if (isset($response[ $this->heartbeat ]['still_waiting'])) { |
|
98 | - return $response; |
|
99 | - } |
|
100 | - // TXN is happening so let's get the payments now |
|
101 | - // if we've already gotten payments then the heartbeat data will contain the timestamp of the last time we checked |
|
102 | - $since = isset($data[ $this->heartbeat ]['get_payments_since']) |
|
103 | - ? $data[ $this->heartbeat ]['get_payments_since'] |
|
104 | - : 0; |
|
105 | - return $this->paymentDetails($response, $since); |
|
106 | - } |
|
52 | + /** |
|
53 | + * thank_you_page_IPN_monitor |
|
54 | + * this basically just pulls the TXN based on the reg_url_link sent from the server, |
|
55 | + * then checks that the TXN status is not failed, and that no other errors have been generated. |
|
56 | + * it also calculates the IPN wait time since the Thank You page was first loaded |
|
57 | + * |
|
58 | + * @param array $response |
|
59 | + * @param array $data |
|
60 | + * @return array |
|
61 | + * @throws EE_Error |
|
62 | + * @throws InvalidArgumentException |
|
63 | + * @throws InvalidDataTypeException |
|
64 | + * @throws InvalidInterfaceException |
|
65 | + * @throws ReflectionException |
|
66 | + */ |
|
67 | + public function heartbeatResponse($response = array(), $data = array()) |
|
68 | + { |
|
69 | + // does this heartbeat contain our data ? |
|
70 | + if (! isset($data[ $this->heartbeat ])) { |
|
71 | + return $response; |
|
72 | + } |
|
73 | + // check for reg_url_link in the incoming heartbeat data |
|
74 | + if (! isset($data[ $this->heartbeat ]['e_reg_url_link'])) { |
|
75 | + $response[ $this->heartbeat ] = array( |
|
76 | + 'errors' => ! empty($notices['errors']) |
|
77 | + ? $notices['errors'] |
|
78 | + : __( |
|
79 | + 'No transaction information could be retrieved because the registration URL link is missing or invalid.', |
|
80 | + 'event_espresso' |
|
81 | + ), |
|
82 | + ); |
|
83 | + return $response; |
|
84 | + } |
|
85 | + // kk heartbeat has our data |
|
86 | + $response = $this->initializeThankYouPageAndTransaction($response, $data); |
|
87 | + // if something went wrong... |
|
88 | + if (isset($response[ $this->heartbeat ]['errors'])) { |
|
89 | + return $response; |
|
90 | + } |
|
91 | + // grab transient of Transaction's status |
|
92 | + $txn_status = isset($data[ $this->heartbeat ]['txn_status']) |
|
93 | + ? $data[ $this->heartbeat ]['txn_status'] |
|
94 | + : null; |
|
95 | + $response = $this->getTransactionDetails($txn_status, $response, $data); |
|
96 | + // no payment data yet? |
|
97 | + if (isset($response[ $this->heartbeat ]['still_waiting'])) { |
|
98 | + return $response; |
|
99 | + } |
|
100 | + // TXN is happening so let's get the payments now |
|
101 | + // if we've already gotten payments then the heartbeat data will contain the timestamp of the last time we checked |
|
102 | + $since = isset($data[ $this->heartbeat ]['get_payments_since']) |
|
103 | + ? $data[ $this->heartbeat ]['get_payments_since'] |
|
104 | + : 0; |
|
105 | + return $this->paymentDetails($response, $since); |
|
106 | + } |
|
107 | 107 | |
108 | 108 | |
109 | - /** |
|
110 | - * @param array $response |
|
111 | - * @param array $data |
|
112 | - * @return array |
|
113 | - * @throws EE_Error |
|
114 | - * @throws InvalidArgumentException |
|
115 | - * @throws InvalidDataTypeException |
|
116 | - * @throws InvalidInterfaceException |
|
117 | - */ |
|
118 | - private function initializeThankYouPageAndTransaction($response, $data) |
|
119 | - { |
|
120 | - require_once EE_MODULES . 'thank_you_page/EED_Thank_You_Page.module.php'; |
|
121 | - // set_definitions, instantiate the thank you page class, and get the ball rolling |
|
122 | - EED_Thank_You_Page::set_definitions(); |
|
123 | - $this->thank_you_page = EED_Thank_You_Page::instance(); |
|
124 | - $this->thank_you_page->set_reg_url_link($data[ $this->heartbeat ]['e_reg_url_link']); |
|
125 | - $this->thank_you_page->init(); |
|
126 | - // get TXN |
|
127 | - $transaction = $this->thank_you_page->get_txn(); |
|
128 | - // no TXN? then get out |
|
129 | - if (! $transaction instanceof EE_Transaction) { |
|
130 | - $notices = EE_Error::get_notices(); |
|
131 | - $response[ $this->heartbeat ] = array( |
|
132 | - 'errors' => ! empty($notices['errors']) |
|
133 | - ? $notices['errors'] |
|
134 | - : sprintf( |
|
135 | - __( |
|
136 | - 'The information for your transaction could not be retrieved from the server or the transaction data received was invalid because of a technical reason. (%s)', |
|
137 | - 'event_espresso' |
|
138 | - ), |
|
139 | - __LINE__ |
|
140 | - ), |
|
141 | - ); |
|
142 | - return $response; |
|
143 | - } |
|
144 | - $this->transaction = $transaction; |
|
145 | - return $response; |
|
146 | - } |
|
109 | + /** |
|
110 | + * @param array $response |
|
111 | + * @param array $data |
|
112 | + * @return array |
|
113 | + * @throws EE_Error |
|
114 | + * @throws InvalidArgumentException |
|
115 | + * @throws InvalidDataTypeException |
|
116 | + * @throws InvalidInterfaceException |
|
117 | + */ |
|
118 | + private function initializeThankYouPageAndTransaction($response, $data) |
|
119 | + { |
|
120 | + require_once EE_MODULES . 'thank_you_page/EED_Thank_You_Page.module.php'; |
|
121 | + // set_definitions, instantiate the thank you page class, and get the ball rolling |
|
122 | + EED_Thank_You_Page::set_definitions(); |
|
123 | + $this->thank_you_page = EED_Thank_You_Page::instance(); |
|
124 | + $this->thank_you_page->set_reg_url_link($data[ $this->heartbeat ]['e_reg_url_link']); |
|
125 | + $this->thank_you_page->init(); |
|
126 | + // get TXN |
|
127 | + $transaction = $this->thank_you_page->get_txn(); |
|
128 | + // no TXN? then get out |
|
129 | + if (! $transaction instanceof EE_Transaction) { |
|
130 | + $notices = EE_Error::get_notices(); |
|
131 | + $response[ $this->heartbeat ] = array( |
|
132 | + 'errors' => ! empty($notices['errors']) |
|
133 | + ? $notices['errors'] |
|
134 | + : sprintf( |
|
135 | + __( |
|
136 | + 'The information for your transaction could not be retrieved from the server or the transaction data received was invalid because of a technical reason. (%s)', |
|
137 | + 'event_espresso' |
|
138 | + ), |
|
139 | + __LINE__ |
|
140 | + ), |
|
141 | + ); |
|
142 | + return $response; |
|
143 | + } |
|
144 | + $this->transaction = $transaction; |
|
145 | + return $response; |
|
146 | + } |
|
147 | 147 | |
148 | 148 | |
149 | - /** |
|
150 | - * @param string $txn_status |
|
151 | - * @param array $response |
|
152 | - * @param array $data |
|
153 | - * @return array |
|
154 | - * @throws EE_Error |
|
155 | - * @throws InvalidArgumentException |
|
156 | - * @throws InvalidDataTypeException |
|
157 | - * @throws InvalidInterfaceException |
|
158 | - * @throws ReflectionException |
|
159 | - */ |
|
160 | - private function getTransactionDetails($txn_status, $response, $data) |
|
161 | - { |
|
162 | - // has the TXN status changed since we last checked (or empty because this is the first time running through this code)? |
|
163 | - if ($txn_status !== $this->transaction->status_ID()) { |
|
164 | - // switch between two possible basic outcomes |
|
165 | - switch ($this->transaction->status_ID()) { |
|
166 | - // TXN has been updated in some way |
|
167 | - case EEM_Transaction::overpaid_status_code: |
|
168 | - case EEM_Transaction::complete_status_code: |
|
169 | - case EEM_Transaction::incomplete_status_code: |
|
170 | - // send updated TXN results back to client, |
|
171 | - return $this->setTransactionDetails($response); |
|
172 | - // or we have a bad TXN, or really slow IPN, so calculate the wait time and send that back... |
|
173 | - case EEM_Transaction::failed_status_code: |
|
174 | - default: |
|
175 | - // keep on waiting... |
|
176 | - return $this->updateServerWaitTime($data[ $this->heartbeat ]); |
|
177 | - } |
|
178 | - // or is the TXN still failed (never been updated) ??? |
|
179 | - } elseif ($this->transaction->failed()) { |
|
180 | - // keep on waiting... |
|
181 | - return $this->updateServerWaitTime($data[ $this->heartbeat ]); |
|
182 | - } |
|
183 | - return $response; |
|
184 | - } |
|
149 | + /** |
|
150 | + * @param string $txn_status |
|
151 | + * @param array $response |
|
152 | + * @param array $data |
|
153 | + * @return array |
|
154 | + * @throws EE_Error |
|
155 | + * @throws InvalidArgumentException |
|
156 | + * @throws InvalidDataTypeException |
|
157 | + * @throws InvalidInterfaceException |
|
158 | + * @throws ReflectionException |
|
159 | + */ |
|
160 | + private function getTransactionDetails($txn_status, $response, $data) |
|
161 | + { |
|
162 | + // has the TXN status changed since we last checked (or empty because this is the first time running through this code)? |
|
163 | + if ($txn_status !== $this->transaction->status_ID()) { |
|
164 | + // switch between two possible basic outcomes |
|
165 | + switch ($this->transaction->status_ID()) { |
|
166 | + // TXN has been updated in some way |
|
167 | + case EEM_Transaction::overpaid_status_code: |
|
168 | + case EEM_Transaction::complete_status_code: |
|
169 | + case EEM_Transaction::incomplete_status_code: |
|
170 | + // send updated TXN results back to client, |
|
171 | + return $this->setTransactionDetails($response); |
|
172 | + // or we have a bad TXN, or really slow IPN, so calculate the wait time and send that back... |
|
173 | + case EEM_Transaction::failed_status_code: |
|
174 | + default: |
|
175 | + // keep on waiting... |
|
176 | + return $this->updateServerWaitTime($data[ $this->heartbeat ]); |
|
177 | + } |
|
178 | + // or is the TXN still failed (never been updated) ??? |
|
179 | + } elseif ($this->transaction->failed()) { |
|
180 | + // keep on waiting... |
|
181 | + return $this->updateServerWaitTime($data[ $this->heartbeat ]); |
|
182 | + } |
|
183 | + return $response; |
|
184 | + } |
|
185 | 185 | |
186 | 186 | |
187 | - /** |
|
188 | - * @param array $response |
|
189 | - * @param boolean $status_only |
|
190 | - * @return array |
|
191 | - * @throws EE_Error |
|
192 | - * @throws InvalidArgumentException |
|
193 | - * @throws InvalidDataTypeException |
|
194 | - * @throws InvalidInterfaceException |
|
195 | - * @throws ReflectionException |
|
196 | - */ |
|
197 | - private function setTransactionDetails($response, $status_only = false) |
|
198 | - { |
|
199 | - if (! $status_only && ! isset($response[ $this->heartbeat ]['transaction_details'])) { |
|
200 | - $response[ $this->heartbeat ]['transaction_details'] = $this->thank_you_page->get_transaction_details(); |
|
201 | - } |
|
202 | - if (! isset($response[ $this->heartbeat ]['txn_status'])) { |
|
203 | - $response[ $this->heartbeat ]['txn_status'] = $this->transaction->status_ID(); |
|
204 | - } |
|
205 | - return $response; |
|
206 | - } |
|
187 | + /** |
|
188 | + * @param array $response |
|
189 | + * @param boolean $status_only |
|
190 | + * @return array |
|
191 | + * @throws EE_Error |
|
192 | + * @throws InvalidArgumentException |
|
193 | + * @throws InvalidDataTypeException |
|
194 | + * @throws InvalidInterfaceException |
|
195 | + * @throws ReflectionException |
|
196 | + */ |
|
197 | + private function setTransactionDetails($response, $status_only = false) |
|
198 | + { |
|
199 | + if (! $status_only && ! isset($response[ $this->heartbeat ]['transaction_details'])) { |
|
200 | + $response[ $this->heartbeat ]['transaction_details'] = $this->thank_you_page->get_transaction_details(); |
|
201 | + } |
|
202 | + if (! isset($response[ $this->heartbeat ]['txn_status'])) { |
|
203 | + $response[ $this->heartbeat ]['txn_status'] = $this->transaction->status_ID(); |
|
204 | + } |
|
205 | + return $response; |
|
206 | + } |
|
207 | 207 | |
208 | 208 | |
209 | - /** |
|
210 | - * @param array $response |
|
211 | - * @param int $since |
|
212 | - * @return array |
|
213 | - * @throws EE_Error |
|
214 | - * @throws InvalidArgumentException |
|
215 | - * @throws InvalidDataTypeException |
|
216 | - * @throws InvalidInterfaceException |
|
217 | - * @throws ReflectionException |
|
218 | - */ |
|
219 | - private function paymentDetails($response, $since) |
|
220 | - { |
|
221 | - // then check for payments |
|
222 | - $payments = $this->thank_you_page->get_txn_payments($since); |
|
223 | - // has a payment been processed ? |
|
224 | - if (! empty($payments) || $this->thank_you_page->isOfflinePaymentMethod()) { |
|
225 | - if ($since) { |
|
226 | - $response[ $this->heartbeat ]['new_payments'] = $this->thank_you_page->get_new_payments($payments); |
|
227 | - $response = $this->setTransactionDetails($response); |
|
228 | - } else { |
|
229 | - $response[ $this->heartbeat ]['payment_details'] = $this->thank_you_page->get_payment_details( |
|
230 | - $payments |
|
231 | - ); |
|
232 | - } |
|
233 | - // reset time to check for payments |
|
234 | - $response[ $this->heartbeat ]['get_payments_since'] = time(); |
|
235 | - } else { |
|
236 | - $response[ $this->heartbeat ]['get_payments_since'] = $since; |
|
237 | - } |
|
238 | - return $response; |
|
239 | - } |
|
209 | + /** |
|
210 | + * @param array $response |
|
211 | + * @param int $since |
|
212 | + * @return array |
|
213 | + * @throws EE_Error |
|
214 | + * @throws InvalidArgumentException |
|
215 | + * @throws InvalidDataTypeException |
|
216 | + * @throws InvalidInterfaceException |
|
217 | + * @throws ReflectionException |
|
218 | + */ |
|
219 | + private function paymentDetails($response, $since) |
|
220 | + { |
|
221 | + // then check for payments |
|
222 | + $payments = $this->thank_you_page->get_txn_payments($since); |
|
223 | + // has a payment been processed ? |
|
224 | + if (! empty($payments) || $this->thank_you_page->isOfflinePaymentMethod()) { |
|
225 | + if ($since) { |
|
226 | + $response[ $this->heartbeat ]['new_payments'] = $this->thank_you_page->get_new_payments($payments); |
|
227 | + $response = $this->setTransactionDetails($response); |
|
228 | + } else { |
|
229 | + $response[ $this->heartbeat ]['payment_details'] = $this->thank_you_page->get_payment_details( |
|
230 | + $payments |
|
231 | + ); |
|
232 | + } |
|
233 | + // reset time to check for payments |
|
234 | + $response[ $this->heartbeat ]['get_payments_since'] = time(); |
|
235 | + } else { |
|
236 | + $response[ $this->heartbeat ]['get_payments_since'] = $since; |
|
237 | + } |
|
238 | + return $response; |
|
239 | + } |
|
240 | 240 | |
241 | 241 | |
242 | - /** |
|
243 | - * @param array $thank_you_page_data thank you page portion of the incoming JSON array |
|
244 | - * from the WP heartbeat data |
|
245 | - * @return array |
|
246 | - * @throws EE_Error |
|
247 | - * @throws InvalidArgumentException |
|
248 | - * @throws InvalidDataTypeException |
|
249 | - * @throws InvalidInterfaceException |
|
250 | - * @throws ReflectionException |
|
251 | - */ |
|
252 | - private function updateServerWaitTime($thank_you_page_data) |
|
253 | - { |
|
254 | - $response[ $this->heartbeat ]['still_waiting'] = isset($thank_you_page_data['initial_access']) |
|
255 | - ? time() - $thank_you_page_data['initial_access'] |
|
256 | - : 0; |
|
257 | - $response = $this->setTransactionDetails($response, true); |
|
258 | - return $response; |
|
259 | - } |
|
242 | + /** |
|
243 | + * @param array $thank_you_page_data thank you page portion of the incoming JSON array |
|
244 | + * from the WP heartbeat data |
|
245 | + * @return array |
|
246 | + * @throws EE_Error |
|
247 | + * @throws InvalidArgumentException |
|
248 | + * @throws InvalidDataTypeException |
|
249 | + * @throws InvalidInterfaceException |
|
250 | + * @throws ReflectionException |
|
251 | + */ |
|
252 | + private function updateServerWaitTime($thank_you_page_data) |
|
253 | + { |
|
254 | + $response[ $this->heartbeat ]['still_waiting'] = isset($thank_you_page_data['initial_access']) |
|
255 | + ? time() - $thank_you_page_data['initial_access'] |
|
256 | + : 0; |
|
257 | + $response = $this->setTransactionDetails($response, true); |
|
258 | + return $response; |
|
259 | + } |
|
260 | 260 | } |
@@ -67,12 +67,12 @@ discard block |
||
67 | 67 | public function heartbeatResponse($response = array(), $data = array()) |
68 | 68 | { |
69 | 69 | // does this heartbeat contain our data ? |
70 | - if (! isset($data[ $this->heartbeat ])) { |
|
70 | + if ( ! isset($data[$this->heartbeat])) { |
|
71 | 71 | return $response; |
72 | 72 | } |
73 | 73 | // check for reg_url_link in the incoming heartbeat data |
74 | - if (! isset($data[ $this->heartbeat ]['e_reg_url_link'])) { |
|
75 | - $response[ $this->heartbeat ] = array( |
|
74 | + if ( ! isset($data[$this->heartbeat]['e_reg_url_link'])) { |
|
75 | + $response[$this->heartbeat] = array( |
|
76 | 76 | 'errors' => ! empty($notices['errors']) |
77 | 77 | ? $notices['errors'] |
78 | 78 | : __( |
@@ -85,22 +85,22 @@ discard block |
||
85 | 85 | // kk heartbeat has our data |
86 | 86 | $response = $this->initializeThankYouPageAndTransaction($response, $data); |
87 | 87 | // if something went wrong... |
88 | - if (isset($response[ $this->heartbeat ]['errors'])) { |
|
88 | + if (isset($response[$this->heartbeat]['errors'])) { |
|
89 | 89 | return $response; |
90 | 90 | } |
91 | 91 | // grab transient of Transaction's status |
92 | - $txn_status = isset($data[ $this->heartbeat ]['txn_status']) |
|
93 | - ? $data[ $this->heartbeat ]['txn_status'] |
|
92 | + $txn_status = isset($data[$this->heartbeat]['txn_status']) |
|
93 | + ? $data[$this->heartbeat]['txn_status'] |
|
94 | 94 | : null; |
95 | 95 | $response = $this->getTransactionDetails($txn_status, $response, $data); |
96 | 96 | // no payment data yet? |
97 | - if (isset($response[ $this->heartbeat ]['still_waiting'])) { |
|
97 | + if (isset($response[$this->heartbeat]['still_waiting'])) { |
|
98 | 98 | return $response; |
99 | 99 | } |
100 | 100 | // TXN is happening so let's get the payments now |
101 | 101 | // if we've already gotten payments then the heartbeat data will contain the timestamp of the last time we checked |
102 | - $since = isset($data[ $this->heartbeat ]['get_payments_since']) |
|
103 | - ? $data[ $this->heartbeat ]['get_payments_since'] |
|
102 | + $since = isset($data[$this->heartbeat]['get_payments_since']) |
|
103 | + ? $data[$this->heartbeat]['get_payments_since'] |
|
104 | 104 | : 0; |
105 | 105 | return $this->paymentDetails($response, $since); |
106 | 106 | } |
@@ -117,18 +117,18 @@ discard block |
||
117 | 117 | */ |
118 | 118 | private function initializeThankYouPageAndTransaction($response, $data) |
119 | 119 | { |
120 | - require_once EE_MODULES . 'thank_you_page/EED_Thank_You_Page.module.php'; |
|
120 | + require_once EE_MODULES.'thank_you_page/EED_Thank_You_Page.module.php'; |
|
121 | 121 | // set_definitions, instantiate the thank you page class, and get the ball rolling |
122 | 122 | EED_Thank_You_Page::set_definitions(); |
123 | 123 | $this->thank_you_page = EED_Thank_You_Page::instance(); |
124 | - $this->thank_you_page->set_reg_url_link($data[ $this->heartbeat ]['e_reg_url_link']); |
|
124 | + $this->thank_you_page->set_reg_url_link($data[$this->heartbeat]['e_reg_url_link']); |
|
125 | 125 | $this->thank_you_page->init(); |
126 | 126 | // get TXN |
127 | 127 | $transaction = $this->thank_you_page->get_txn(); |
128 | 128 | // no TXN? then get out |
129 | - if (! $transaction instanceof EE_Transaction) { |
|
129 | + if ( ! $transaction instanceof EE_Transaction) { |
|
130 | 130 | $notices = EE_Error::get_notices(); |
131 | - $response[ $this->heartbeat ] = array( |
|
131 | + $response[$this->heartbeat] = array( |
|
132 | 132 | 'errors' => ! empty($notices['errors']) |
133 | 133 | ? $notices['errors'] |
134 | 134 | : sprintf( |
@@ -173,12 +173,12 @@ discard block |
||
173 | 173 | case EEM_Transaction::failed_status_code: |
174 | 174 | default: |
175 | 175 | // keep on waiting... |
176 | - return $this->updateServerWaitTime($data[ $this->heartbeat ]); |
|
176 | + return $this->updateServerWaitTime($data[$this->heartbeat]); |
|
177 | 177 | } |
178 | 178 | // or is the TXN still failed (never been updated) ??? |
179 | 179 | } elseif ($this->transaction->failed()) { |
180 | 180 | // keep on waiting... |
181 | - return $this->updateServerWaitTime($data[ $this->heartbeat ]); |
|
181 | + return $this->updateServerWaitTime($data[$this->heartbeat]); |
|
182 | 182 | } |
183 | 183 | return $response; |
184 | 184 | } |
@@ -196,11 +196,11 @@ discard block |
||
196 | 196 | */ |
197 | 197 | private function setTransactionDetails($response, $status_only = false) |
198 | 198 | { |
199 | - if (! $status_only && ! isset($response[ $this->heartbeat ]['transaction_details'])) { |
|
200 | - $response[ $this->heartbeat ]['transaction_details'] = $this->thank_you_page->get_transaction_details(); |
|
199 | + if ( ! $status_only && ! isset($response[$this->heartbeat]['transaction_details'])) { |
|
200 | + $response[$this->heartbeat]['transaction_details'] = $this->thank_you_page->get_transaction_details(); |
|
201 | 201 | } |
202 | - if (! isset($response[ $this->heartbeat ]['txn_status'])) { |
|
203 | - $response[ $this->heartbeat ]['txn_status'] = $this->transaction->status_ID(); |
|
202 | + if ( ! isset($response[$this->heartbeat]['txn_status'])) { |
|
203 | + $response[$this->heartbeat]['txn_status'] = $this->transaction->status_ID(); |
|
204 | 204 | } |
205 | 205 | return $response; |
206 | 206 | } |
@@ -221,19 +221,19 @@ discard block |
||
221 | 221 | // then check for payments |
222 | 222 | $payments = $this->thank_you_page->get_txn_payments($since); |
223 | 223 | // has a payment been processed ? |
224 | - if (! empty($payments) || $this->thank_you_page->isOfflinePaymentMethod()) { |
|
224 | + if ( ! empty($payments) || $this->thank_you_page->isOfflinePaymentMethod()) { |
|
225 | 225 | if ($since) { |
226 | - $response[ $this->heartbeat ]['new_payments'] = $this->thank_you_page->get_new_payments($payments); |
|
226 | + $response[$this->heartbeat]['new_payments'] = $this->thank_you_page->get_new_payments($payments); |
|
227 | 227 | $response = $this->setTransactionDetails($response); |
228 | 228 | } else { |
229 | - $response[ $this->heartbeat ]['payment_details'] = $this->thank_you_page->get_payment_details( |
|
229 | + $response[$this->heartbeat]['payment_details'] = $this->thank_you_page->get_payment_details( |
|
230 | 230 | $payments |
231 | 231 | ); |
232 | 232 | } |
233 | 233 | // reset time to check for payments |
234 | - $response[ $this->heartbeat ]['get_payments_since'] = time(); |
|
234 | + $response[$this->heartbeat]['get_payments_since'] = time(); |
|
235 | 235 | } else { |
236 | - $response[ $this->heartbeat ]['get_payments_since'] = $since; |
|
236 | + $response[$this->heartbeat]['get_payments_since'] = $since; |
|
237 | 237 | } |
238 | 238 | return $response; |
239 | 239 | } |
@@ -251,7 +251,7 @@ discard block |
||
251 | 251 | */ |
252 | 252 | private function updateServerWaitTime($thank_you_page_data) |
253 | 253 | { |
254 | - $response[ $this->heartbeat ]['still_waiting'] = isset($thank_you_page_data['initial_access']) |
|
254 | + $response[$this->heartbeat]['still_waiting'] = isset($thank_you_page_data['initial_access']) |
|
255 | 255 | ? time() - $thank_you_page_data['initial_access'] |
256 | 256 | : 0; |
257 | 257 | $response = $this->setTransactionDetails($response, true); |
@@ -17,52 +17,52 @@ |
||
17 | 17 | class WordpressHeartbeat |
18 | 18 | { |
19 | 19 | |
20 | - const RESPONSE_KEY_THANK_YOU_PAGE = 'espresso_thank_you_page'; |
|
20 | + const RESPONSE_KEY_THANK_YOU_PAGE = 'espresso_thank_you_page'; |
|
21 | 21 | |
22 | - /** |
|
23 | - * @var LoaderInterface $loader |
|
24 | - */ |
|
25 | - protected $loader; |
|
22 | + /** |
|
23 | + * @var LoaderInterface $loader |
|
24 | + */ |
|
25 | + protected $loader; |
|
26 | 26 | |
27 | - /** |
|
28 | - * @var RequestInterface $request |
|
29 | - */ |
|
30 | - protected $request; |
|
27 | + /** |
|
28 | + * @var RequestInterface $request |
|
29 | + */ |
|
30 | + protected $request; |
|
31 | 31 | |
32 | 32 | |
33 | - /** |
|
34 | - * WordpressHeartbeat constructor. |
|
35 | - * |
|
36 | - * @param LoaderInterface $loader |
|
37 | - * @param RequestInterface $request |
|
38 | - */ |
|
39 | - public function __construct( |
|
40 | - LoaderInterface $loader, |
|
41 | - RequestInterface $request |
|
42 | - ) { |
|
43 | - $this->loader = $loader; |
|
44 | - $this->request = $request; |
|
45 | - do_action('AHEE__EventEspresso_core_domain_services_admin_ajax_WordpressHeartbeat__constructor', $this); |
|
46 | - add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'resolveRoutes')); |
|
47 | - } |
|
33 | + /** |
|
34 | + * WordpressHeartbeat constructor. |
|
35 | + * |
|
36 | + * @param LoaderInterface $loader |
|
37 | + * @param RequestInterface $request |
|
38 | + */ |
|
39 | + public function __construct( |
|
40 | + LoaderInterface $loader, |
|
41 | + RequestInterface $request |
|
42 | + ) { |
|
43 | + $this->loader = $loader; |
|
44 | + $this->request = $request; |
|
45 | + do_action('AHEE__EventEspresso_core_domain_services_admin_ajax_WordpressHeartbeat__constructor', $this); |
|
46 | + add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'resolveRoutes')); |
|
47 | + } |
|
48 | 48 | |
49 | 49 | |
50 | - /** |
|
51 | - * @since 4.9.76.p |
|
52 | - * @throws InvalidClassException |
|
53 | - */ |
|
54 | - public function resolveRoutes() |
|
55 | - { |
|
56 | - $screenID = $this->request->getRequestParam('screen_id'); |
|
57 | - $heartbeat_data = $this->request->getRequestParam('data', []); |
|
58 | - if ($screenID === 'espresso_events') { |
|
59 | - $this->loader->getShared( |
|
60 | - 'EventEspresso\core\domain\services\admin\ajax\EventEditorHeartbeat' |
|
61 | - ); |
|
62 | - } elseif ($screenID === 'front' && ! empty($heartbeat_data[ self::RESPONSE_KEY_THANK_YOU_PAGE ])) { |
|
63 | - $this->loader->getShared( |
|
64 | - 'EventEspresso\core\domain\services\admin\ajax\ThankYouPageIpnMonitor' |
|
65 | - ); |
|
66 | - } |
|
67 | - } |
|
50 | + /** |
|
51 | + * @since 4.9.76.p |
|
52 | + * @throws InvalidClassException |
|
53 | + */ |
|
54 | + public function resolveRoutes() |
|
55 | + { |
|
56 | + $screenID = $this->request->getRequestParam('screen_id'); |
|
57 | + $heartbeat_data = $this->request->getRequestParam('data', []); |
|
58 | + if ($screenID === 'espresso_events') { |
|
59 | + $this->loader->getShared( |
|
60 | + 'EventEspresso\core\domain\services\admin\ajax\EventEditorHeartbeat' |
|
61 | + ); |
|
62 | + } elseif ($screenID === 'front' && ! empty($heartbeat_data[ self::RESPONSE_KEY_THANK_YOU_PAGE ])) { |
|
63 | + $this->loader->getShared( |
|
64 | + 'EventEspresso\core\domain\services\admin\ajax\ThankYouPageIpnMonitor' |
|
65 | + ); |
|
66 | + } |
|
67 | + } |
|
68 | 68 | } |
@@ -59,7 +59,7 @@ |
||
59 | 59 | $this->loader->getShared( |
60 | 60 | 'EventEspresso\core\domain\services\admin\ajax\EventEditorHeartbeat' |
61 | 61 | ); |
62 | - } elseif ($screenID === 'front' && ! empty($heartbeat_data[ self::RESPONSE_KEY_THANK_YOU_PAGE ])) { |
|
62 | + } elseif ($screenID === 'front' && ! empty($heartbeat_data[self::RESPONSE_KEY_THANK_YOU_PAGE])) { |
|
63 | 63 | $this->loader->getShared( |
64 | 64 | 'EventEspresso\core\domain\services\admin\ajax\ThankYouPageIpnMonitor' |
65 | 65 | ); |