PluginProbe ʕ •ᴥ•ʔ
JetFormBuilder — Dynamic Blocks Form Builder / 3.0.0
JetFormBuilder — Dynamic Blocks Form Builder v3.0.0
3.6.5.1 3.6.5 3.6.4.2 3.6.4.1 3.6.4 3.6.3.1 3.6.3 3.6.2.2 3.6.2.1 3.6.2 3.6.1.1 3.6.1 3.6.0.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.1.0 2.1.1 2.1.10 2.1.11 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 3.0.0 3.0.0.1 3.0.0.2 3.0.0.3 3.0.1 3.0.1.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.0.1 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.3.2 3.3.3 3.3.3.1 3.3.4 3.3.4.1 3.3.4.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.5.1 3.4.5.2 3.4.6 3.4.7 3.4.7.1 3.5.0 3.5.1 3.5.1.1 3.5.1.2 3.5.2 3.5.2.1 3.5.3 3.5.4 3.5.5 3.5.6 3.5.6.1 3.5.6.2 3.5.6.3 3.6.0
jetformbuilder / includes / actions / action-handler.php
jetformbuilder / includes / actions Last commit date
conditions 3 years ago events 3 years ago methods 3 years ago types 3 years ago action-handler.php 3 years ago action-localize.php 3 years ago actions-tools.php 3 years ago events-list.php 3 years ago events-manager.php 3 years ago manager.php 3 years ago
action-handler.php
601 lines
1 <?php
2
3 namespace Jet_Form_Builder\Actions;
4
5 // If this file is called directly, abort.
6 use Jet_Form_Builder\Actions\Events\Base_Executor;
7 use Jet_Form_Builder\Actions\Types\Base;
8 use Jet_Form_Builder\Classes\Macros_Parser;
9 use Jet_Form_Builder\Exceptions\Action_Exception;
10 use Jet_Form_Builder\Exceptions\Condition_Exception;
11 use Jet_Form_Builder\Exceptions\Handler_Exception;
12 use Jet_Form_Builder\Exceptions\Repository_Exception;
13 use Jet_Form_Builder\Plugin;
14 use Jet_Form_Builder\Actions\Conditions\Condition_Manager;
15
16 if ( ! defined( 'WPINC' ) ) {
17 die;
18 }
19
20 /**
21 * Define Actions handler class class
22 */
23 class Action_Handler {
24
25 public $form_id = null;
26 public $request_data = array();
27 public $form_actions = array();
28 public $is_ajax = false;
29 private $form_conditions = array();
30 private $form_events = array();
31
32 /**
33 * Data for actions
34 */
35 public $size_all;
36 public $response_data = array();
37
38 public $context = array();
39
40 /** @var bool|int Current Action ID */
41 public $current_position = false;
42
43 /** @var string */
44 public $current_flow_handler = '';
45
46 /**
47 * @var array Action IDs that were executed without errors
48 */
49 protected $passed = array();
50
51 /**
52 * @var array Action IDs that were skipped due to a condition not matching
53 */
54 protected $skipped = array();
55
56 /**
57 * Hidden actions
58 *
59 * @var array<string, bool>
60 */
61 private $hidden = array();
62
63 public function get_form_id() {
64 return (int) $this->form_id;
65 }
66
67 /**
68 * @param $form_id
69 *
70 * @return Action_Handler
71 */
72 public function set_form_id( $form_id ) {
73 if ( ! $form_id || $form_id === $this->form_id ) {
74 return $this;
75 }
76 $this->form_id = $form_id;
77 $this->set_form_actions();
78
79 return $this;
80 }
81
82 public function add_request( $request ): Action_Handler {
83 if ( ! $this->in_loop() ) {
84 $this->request_data = array_merge( $this->request_data, $request );
85
86 return $this;
87 }
88
89 foreach ( $request as $field_name => $value ) {
90 $field_name = $this->get_unique_field_id( $field_name );
91
92 $this->request_data[ $field_name ] = $value;
93 }
94
95 return $this;
96 }
97
98 /**
99 * Set form actions,
100 * which were saved in form meta
101 *
102 * @return Action_Handler
103 */
104 public function set_form_actions() {
105 $form_actions = Plugin::instance()->post_type->get_actions( $this->form_id );
106
107 foreach ( $form_actions as $form_action ) {
108 try {
109 $this->save_form_action( $form_action )->on_register_in_flow();
110 } catch ( Repository_Exception $exception ) {
111 continue;
112 }
113 }
114
115 return $this;
116 }
117
118 /**
119 * @param $form_action
120 *
121 * @return Base
122 * @throws Repository_Exception
123 */
124 private function save_form_action( $form_action ): Base {
125 $type = $form_action['type'];
126
127 if ( ! ( $form_action['is_execute'] ?? true ) ) {
128 throw new Repository_Exception( 'This action is turned off' );
129 }
130
131 $action = jet_form_builder()->actions->get_action_clone( $type );
132
133 $id = $form_action['id'];
134 $settings = $form_action['settings'][ $type ] ?? $form_action['settings'];
135
136 /**
137 * Save action settings to the class field,
138 * it allows to not send action settings
139 * in action hook
140 */
141 $action->_id = $id;
142 $action->settings = $settings;
143
144 $this->save_action( $action, $form_action );
145
146 return $action;
147 }
148
149 /**
150 * Doesn't throw an exception if there are no actions
151 *
152 * Don't call manually.
153 * Use jet_fb_events()->execute() instead.
154 *
155 * @param Base_Executor $executor
156 *
157 * @return $this
158 * @throws Action_Exception
159 */
160 public function soft_run_actions( Base_Executor $executor ): Action_Handler {
161 if ( ! count( $executor ) ) {
162 return $this;
163 }
164 $this->run_actions( $executor );
165
166 return $this;
167 }
168
169 /**
170 * Don't call manually.
171 * Use jet_fb_events()->execute() instead.
172 *
173 * @param Base_Executor $executor
174 *
175 * @throws Action_Exception
176 */
177 public function run_actions( Base_Executor $executor ) {
178 if ( ! count( $executor ) ) {
179 throw new Action_Exception( 'failed', 'Empty actions' );
180 }
181
182 foreach ( $executor as $action ) {
183 $this->process_single_action( $action );
184 }
185
186 /**
187 * End the cycle
188 */
189 $this->set_current_action( false );
190 }
191
192 public function process_single_action( Base $action ) {
193 /**
194 * Start the cycle
195 *
196 * @var int current_position
197 */
198 $this->set_current_action( $action->_id );
199
200 try {
201 /**
202 * Check conditions for action
203 */
204 $this->get_current_condition_manager()->check_all();
205 } catch ( Condition_Exception $exception ) {
206 /**
207 * We save the ID of the current action,
208 * for possible logging of form entries
209 */
210 $this->skipping_current();
211
212 return;
213 }
214
215 /**
216 * Process single action
217 */
218 $action->do_action( $this->request_data, $this );
219
220 /**
221 * We save the ID of the current action,
222 * for possible logging of form entries
223 */
224 $this->passing_current();
225 }
226
227 /**
228 * Unregister notification by id
229 *
230 * @param $key
231 *
232 * @return Action_Handler [description]
233 */
234 public function unregister_action( $key ) {
235 if ( is_numeric( $key ) && isset( $this->form_actions[ $key ] ) ) {
236 unset( $this->form_actions[ $key ] );
237 unset( $this->form_conditions[ $key ] );
238 unset( $this->form_events[ $key ] );
239
240 return $this;
241 }
242 foreach ( $this->form_actions as $index => $action ) {
243 if ( $key === $action->get_id() ) {
244 unset( $this->form_actions[ $index ] );
245 unset( $this->form_conditions[ $index ] );
246 unset( $this->form_events[ $index ] );
247
248 return $this;
249 }
250 }
251
252 return $this;
253 }
254
255 /**
256 * Returns all registered notifications
257 *
258 * @return Base[] [description]
259 */
260 public function get_all() {
261 return $this->form_actions;
262 }
263
264 public function get_inserted_post_id( $action_id = 0 ) {
265 $default_post_id = absint( $this->response_data['inserted_post_id'] ?? 0 );
266
267 if ( ! $action_id ) {
268 return $default_post_id;
269 }
270
271 $action_id = absint( $action_id );
272
273 if ( empty( $this->response_data['inserted_posts'] ) ) {
274 return $default_post_id;
275 }
276
277 foreach ( $this->response_data['inserted_posts'] as $posts ) {
278 if ( $action_id === $posts['action_id'] ) {
279 return $posts['post_id'];
280 }
281 }
282
283 return $default_post_id;
284 }
285
286 public function add_response( $values ) {
287 Plugin::instance()->form_handler->add_response_data( $values );
288 }
289
290 public function get_context( $action_slug, $property = '' ) {
291 $context = $this->context[ $action_slug ] ?? array();
292
293 return $property ? $context[ $property ] ?? false : $context;
294 }
295
296 public function add_context( $action_slug, $context ) {
297 $this->context[ $action_slug ] = array_merge( $this->get_context( $action_slug ), $context );
298
299 return $this;
300 }
301
302 public function add_context_once( string $action_slug, array $context ) {
303 $action_context = $this->get_context( $action_slug );
304
305 if ( ! $action_context ) {
306 $this->add_context( $action_slug, $context );
307
308 return $this;
309 }
310
311 foreach ( $context as $name => $value ) {
312 if ( isset( $action_context[ $name ] ) ) {
313 unset( $context[ $name ] );
314 }
315 }
316 $this->add_context( $action_slug, $context );
317
318 return $this;
319 }
320
321 public function in_loop(): bool {
322 return ( 0 < (int) $this->current_position );
323 }
324
325 public function in_loop_or_die() {
326 if ( $this->in_loop() ) {
327 return;
328 }
329
330 wp_die(
331 esc_html( 'The action loop has not been started, see ' . self::class . '::run_actions()' ),
332 __METHOD__,
333 '1.4.0'
334 );
335 }
336
337 public function get_current_action(): Base {
338 $this->in_loop_or_die();
339
340 return $this->get_action( $this->get_position() );
341 }
342
343 public function get_current_condition_manager(): Condition_Manager {
344 $this->in_loop_or_die();
345
346 return $this->get_condition_by_id( $this->get_position() );
347 }
348
349 /**
350 * @param $id
351 *
352 * @return false|Base
353 * @deprecated since 3.0.0
354 * Use \Jet_Form_Builder\Actions\Action_Handler::get_action instead
355 */
356 public function get_action_by_id( $id ) {
357 return $this->get_action( $id );
358 }
359
360 /**
361 * @param $id
362 *
363 * @return false|Condition_Manager
364 */
365 public function get_condition_by_id( $id ) {
366 return $this->form_conditions[ $id ] ?? false;
367 }
368
369 /**
370 * @param $id
371 *
372 * @return false|Events_List
373 */
374 public function get_events_by_id( $id ) {
375 return $this->form_events[ $id ] ?? false;
376 }
377
378 /**
379 * For fix backward compatibility
380 *
381 * @param array $form_events
382 *
383 * @return array
384 */
385 public function merge_events( array $form_events ): array {
386 foreach ( $form_events as $action_id => $event_list ) {
387 $this->form_events[ $action_id ] = $event_list;
388 }
389
390 return $this->form_events;
391 }
392
393 /**
394 * @param $slug
395 *
396 * @return false|Base
397 * @deprecated since 3.0.0
398 * Use \Jet_Form_Builder\Actions\Action_Handler::get_action instead
399 */
400 public function get_action_by_slug( $slug ) {
401 return $this->get_action( $slug );
402 }
403
404 /**
405 * @param int|string $class_slug_or_id
406 *
407 * @return false|Base
408 */
409 public function get_action( $class_slug_or_id ) {
410 $is_number = is_numeric( $class_slug_or_id );
411 $is_class = ! $is_number && class_exists( $class_slug_or_id );
412
413 if ( $is_number ) {
414 return $this->form_actions[ $class_slug_or_id ] ?? false;
415 }
416
417 foreach ( $this->form_actions as $action ) {
418 /** @var Base $action */
419
420 if ( $is_class && is_a( $action, $class_slug_or_id ) ) {
421 return $action;
422 } else if ( $is_class ) {
423 continue;
424 }
425
426 if ( $action->get_id() !== $class_slug_or_id ) {
427 continue;
428 }
429
430 return $action;
431 }
432
433 return false;
434 }
435
436 /**
437 * Use jet_fb_handler()->refer
438 * @return mixed|string
439 * @deprecated 2.1.3
440 *
441 */
442 public function get_refer() {
443 return $this->request_data['__refer'] ?? '';
444 }
445
446 public function get_passed_actions(): array {
447 return $this->passed;
448 }
449
450 public function get_skipped_actions(): array {
451 return $this->skipped;
452 }
453
454 public function passing_current() {
455 $this->passing_action( $this->get_position() );
456 }
457
458 public function passing_action( int $action_id ) {
459 $this->passed[] = $action_id;
460
461 return $this;
462 }
463
464 public function skipping_current() {
465 $this->skipping_action( $this->get_position() );
466 }
467
468 public function skipping_action( int $action_id ) {
469 $this->skipped[] = $action_id;
470
471 return $this;
472 }
473
474 /**
475 * @param int|bool $action_id
476 *
477 * @return $this
478 */
479 public function set_current_action( $action_id ) {
480 $this->current_position = (int) $action_id;
481
482 return $this;
483 }
484
485 public function get_position(): int {
486 return $this->current_position;
487 }
488
489 public function start_flow( string $flow_handler ) {
490 $this->current_flow_handler = $flow_handler;
491
492 return $this;
493 }
494
495 public function end_flow() {
496 $this->current_flow_handler = '';
497
498 return $this;
499 }
500
501 /**
502 * @param string $action_class
503 * @param array $props
504 *
505 * @return false|Base
506 * False if action not founded or already added as hidden
507 */
508 public function add_hidden( string $action_class, array $props = array() ) {
509 try {
510 $action = jet_form_builder()->actions->get_action( $action_class );
511 } catch ( Repository_Exception $exception ) {
512 return false;
513 }
514
515 if ( array_key_exists( $action->get_id(), $this->hidden ) ) {
516 return false;
517 }
518 $clone_action = clone $action;
519
520 $clone_action->_id = $this->get_unique_action_id();
521
522 $this->save_action( $clone_action, $props );
523 $this->hidden[ $clone_action->get_id() ] = $clone_action->_id;
524
525 return $clone_action;
526 }
527
528 public function remove_hidden( $action_slug ) {
529 $id = $this->hidden[ $action_slug ] ?? false;
530
531 if ( false === $id ) {
532 return;
533 }
534
535 unset( $this->form_actions[ $id ] );
536 unset( $this->hidden[ $action_slug ] );
537 }
538
539 public function isset_hidden( $action_slug ): bool {
540 return isset( $this->hidden[ $action_slug ] );
541 }
542
543 private function save_action( Base $action, array $props ) {
544 $conditions = $props['conditions'] ?? array();
545 $operator = $props['condition_operator'] ?? 'and';
546 $events = $props['events'] ?? array();
547
548 $condition = new Condition_Manager();
549 $condition->set_conditions( $conditions );
550 $condition->set_condition_operator( $operator );
551
552 $this->form_conditions[ $action->_id ] = $condition;
553 $this->form_actions[ $action->_id ] = $action;
554 $this->form_events[ $action->_id ] = Events_List::create(
555 array_merge( $events, $action->get_required_events() )
556 );
557 }
558
559
560 public function sort_hidden_actions() {
561 /**
562 * @var Base $action
563 */
564 foreach ( $this->form_actions as $action ) {
565 $this->remove_hidden( $action->get_id() );
566 }
567
568 $action_ids = array_values( $this->hidden );
569 $hidden = array();
570
571 foreach ( $action_ids as $id ) {
572 $hidden[ $id ] = $this->get_action( $id );
573 unset( $this->form_actions[ $id ] );
574 }
575
576 $this->form_actions = $hidden + $this->form_actions;
577 }
578
579 public function get_unique_action_id( int $start_from = 1 ): int {
580 if ( ! array_key_exists( $start_from, $this->form_actions ) ) {
581 return $start_from;
582 }
583
584 return $this->get_unique_action_id( ++ $start_from );
585 }
586
587 public function get_unique_field_id( string $computed_field ): string {
588 if (
589 ! array_key_exists( $computed_field, $this->request_data ) ||
590 ! $this->in_loop()
591 ) {
592 return $computed_field;
593 }
594
595 $computed_field .= '_' . $this->get_current_action()->_id;
596
597 return $computed_field;
598 }
599
600 }
601