PluginProbe ʕ •ᴥ•ʔ
JetFormBuilder — Dynamic Blocks Form Builder / 2.0.4
JetFormBuilder — Dynamic Blocks Form Builder v2.0.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 / methods / abstract-modifier.php
jetformbuilder / includes / actions / methods Last commit date
exceptions 4 years ago form-record 4 years ago post-modification 4 years ago update-user 4 years ago abstract-modifier.php 4 years ago
abstract-modifier.php
367 lines
1 <?php
2
3 namespace Jet_Form_Builder\Actions\Methods;
4
5 use Jet_Form_Builder\Actions\Methods\Exceptions\Modifier_Exclude_Property;
6 use Jet_Form_Builder\Classes\Tools;
7 use Jet_Form_Builder\Exceptions\Action_Exception;
8 use Jet_Form_Builder\Exceptions\Silence_Exception;
9
10 abstract class Abstract_Modifier {
11
12 public $source_arr = array();
13 protected $current_prop = '';
14 protected $current_value;
15 protected $request = array();
16 protected $excluded_props = array();
17 protected $current_external;
18 protected $external_data = array();
19 protected $fields_map = array();
20
21 protected $action;
22
23 /**
24 * Return object fields
25 *
26 * @return string[] [type] [description]
27 */
28 abstract public function get_object_fields();
29
30 abstract public function get_actions();
31
32 public function get_external_properties() {
33 return array();
34 }
35
36 public function get_required_fields() {
37 return array();
38 }
39
40 /**
41 * @throws Action_Exception
42 */
43 public function run() {
44 $this->attach_items();
45 $this->attach_required_fields();
46 $this->do_action();
47 $this->after_action_externals();
48 }
49
50 public function get_action() {
51 return $this->action;
52 }
53
54 /**
55 * @param string $action
56 *
57 * @return Abstract_Modifier
58 * @throws Silence_Exception
59 */
60 public function set_action( string $action ) {
61 $actions = $this->get_actions();
62
63 if ( isset( $actions[ $action ]['action'] ) && is_callable( $actions[ $action ]['action'] ) ) {
64 $this->action = $action;
65
66 return $this;
67 }
68
69 throw new Silence_Exception(
70 'Undefined action',
71 array(
72 $action,
73 array_keys( $this->get_actions() ),
74 )
75 );
76 }
77
78 /**
79 * @throws Action_Exception
80 */
81 public function do_action() {
82 $action = $this->get_actions()[ $this->get_action() ] ?? array();
83 $action_callback = $action['action'] ?? false;
84 $after_callback = $action['after'] ?? false;
85
86 if ( ! is_callable( $action_callback ) ) {
87 throw new Action_Exception( 'internal_error' );
88 }
89
90 call_user_func( $action_callback, $this );
91
92 if ( ! is_callable( $after_callback ) ) {
93 return;
94 }
95
96 call_user_func( $after_callback, $this );
97 }
98
99 public function attach_items() {
100 $this->fields_map = array_filter( $this->fields_map );
101
102 foreach ( $this->request as $key => $value ) {
103 try {
104 $this->current_prop = $key;
105 $this->current_value = $value;
106
107 $this->attach_item();
108 } catch ( Modifier_Exclude_Property $exception ) {
109 $this->exclude_current_prop();
110
111 } catch ( Silence_Exception $exception ) {
112 continue;
113 }
114 }
115 }
116
117 public function attach_required_fields() {
118 foreach ( $this->get_required_fields() as $name => $options ) {
119 try {
120 $this->current_prop = $name;
121 $this->is_isset_current_prop( $options );
122
123 } catch ( Silence_Exception $exception ) {
124 continue;
125 }
126 }
127 }
128
129 /**
130 * @param array $options
131 *
132 * @throws Silence_Exception
133 */
134 public function is_isset_current_prop( array $options ) {
135 if ( isset( $options['callback'] ) && is_callable( $options['callback'] ) ) {
136 call_user_func( $options['callback'], $options );
137
138 return;
139 }
140 if ( isset( $this->source_arr[ $this->current_prop ] ) ) {
141 throw new Silence_Exception( "{$this->current_prop} is not set." );
142 }
143 }
144
145 /**
146 * @throws Silence_Exception
147 */
148 public function attach_item() {
149 $this->current_prop = $this->get_current_prop_from_fields_map();
150
151 if ( in_array( $this->current_prop, $this->excluded_props, true ) ) {
152 throw new Silence_Exception( "Prop '{$this->current_prop}' is excluded" );
153 }
154
155 $this->before_attach();
156
157 $this->source_arr[ $this->current_prop ] = $this->current_value;
158 }
159
160 /**
161 * @param string $field_name
162 *
163 * @return string
164 * @throws Silence_Exception
165 */
166 public function get_prop_by_field_name( string $field_name ) {
167 /**
168 * At this moment $this->current_prop
169 * store the `field_name`
170 */
171 if ( empty( $this->fields_map[ $field_name ] ) ) {
172 throw new Silence_Exception( 'Field is not used.' );
173 }
174
175 /**
176 * And here we returning the post property
177 * Ex: 'post_content' | 'post_status' | 'jet_tax__slug' | 'custom_meta_key'
178 */
179 return Tools::sanitize_text_field( $this->fields_map[ $field_name ] );
180 }
181
182 public function replace_field_by_prop( string $prop_name, $value ) {
183 $field_name = $this->get_field_name_by_prop( $prop_name );
184
185 if ( false === $field_name ) {
186 $field_name = $this->unique_slug( $prop_name );
187
188 $this->fields_map[ $field_name ] = $prop_name;
189 }
190
191 $this->set_request(
192 array(
193 $field_name => $value,
194 )
195 );
196
197 return $this;
198 }
199
200 /**
201 * @return string
202 * @throws Silence_Exception
203 */
204 public function get_current_prop_from_fields_map() {
205 return $this->get_prop_by_field_name( $this->current_prop );
206 }
207
208 public function get_value_by_prop( string $prop ) {
209 $field_name = $this->get_field_name_by_prop( $prop );
210
211 return $this->request[ $field_name ] ?? false;
212 }
213
214 public function get_field_name_by_prop( string $search_prop ) {
215 foreach ( $this->fields_map as $field_name => $prop ) {
216 if ( $search_prop === $prop ) {
217 return $field_name;
218 }
219 }
220
221 return false;
222 }
223
224
225 /**
226 * @throws Silence_Exception
227 */
228 public function before_attach() {
229 $property_callback = $this->get_object_fields()[ $this->current_prop ]['before_cb'] ?? false;
230
231 if ( is_callable( $property_callback ) ) {
232 call_user_func( $property_callback, $this );
233
234 return;
235 }
236
237 if ( ! $this->is_reserved_property( $this->current_prop ) ) {
238 call_user_func( array( $this, 'custom_before_attach' ), $this );
239
240 throw new Silence_Exception( 'Property not need to attach' );
241 }
242 }
243
244 /**
245 * @throws Silence_Exception
246 */
247 public function custom_before_attach() {
248 /**
249 * We make the array in reverse order,
250 * in order to check external: meta last,
251 * since it does not have a check ( 'condition_cb' )
252 */
253 $externals = array_reverse( $this->get_external_properties() );
254
255 if ( empty( $externals ) ) {
256 return;
257 }
258
259 foreach ( $externals as $external_key => $external_value ) {
260 $this->current_external = $external_key;
261 $condition_cb = $external_value['condition_cb'] ?? false;
262
263 if ( empty( $condition_cb ) || (
264 is_callable( $condition_cb ) && ! call_user_func( $condition_cb, $this )
265 ) ) {
266 continue;
267 }
268
269 $match_cb = $external_value['match_cb'] ?? false;
270 if ( ! is_callable( $match_cb ) ) {
271 throw new Silence_Exception( "'match_cb' is not callable in {$external_key}" );
272 }
273
274 call_user_func( $match_cb, $this );
275 break;
276 }
277 }
278
279 public function is_reserved_property( $prop ) {
280 $fields = $this->get_object_fields();
281
282 return isset( $fields[ $prop ] ) || in_array( $prop, $fields, true );
283 }
284
285 public function after_action_externals() {
286 $externals = $this->get_external_properties();
287
288 foreach ( $externals as $external_key => $external_value ) {
289 $this->current_external = $external_key;
290 $condition_cb = $external_value['after_action'] ?? false;
291
292 if ( is_callable( $condition_cb ) ) {
293 call_user_func( $condition_cb, $this );
294 }
295 }
296 }
297
298 public function unique_slug( $suffix ) {
299 $form_id = jet_form_builder()->form_handler->form_id ?? 0;
300 $prefix = static::class;
301
302 return "{$prefix}_{$form_id}__{$suffix}";
303 }
304
305 public function set_fields_map( $fields_map ) {
306 $this->fields_map = $fields_map;
307
308 return $this;
309 }
310
311 public function set_external( string $key, array $data ) {
312 if ( ! isset( $this->external_data[ $key ] ) || ! is_array( $this->external_data[ $key ] ) ) {
313 $this->external_data[ $key ] = array();
314 }
315 $this->external_data[ $key ] = array_merge( $this->external_data[ $key ], $data );
316
317 return $this;
318 }
319
320 public function get_external( string $key ) {
321 return $this->external_data[ $key ] ?? array();
322 }
323
324 public function set_current_external( array $data ) {
325 return $this->set_external( $this->current_external, $data );
326 }
327
328 public function get_current_external() {
329 return $this->get_external( (string) $this->current_external );
330 }
331
332 public function set_request( $request ) {
333 $this->request = array_merge( $this->request, $request );
334
335 return $this;
336 }
337
338 public function exclude_current_prop() {
339 $this->exclude_prop( $this->current_prop );
340 }
341
342 /**
343 * @throws Modifier_Exclude_Property
344 */
345 public function exclude_current() {
346 throw new Modifier_Exclude_Property( "Excluding: {$this->current_prop}" );
347 }
348
349 public function exclude_prop( string $prop ) {
350 if ( ! in_array( $prop, $this->excluded_props, true ) ) {
351 $this->excluded_props[] = $prop;
352 }
353
354 unset( $this->source_arr[ $prop ] );
355 }
356
357 /**
358 * @throws Silence_Exception
359 */
360 public function throw_if_empty() {
361 if ( empty( $this->current_value ) ) {
362 throw new Silence_Exception( 'Current field is empty' );
363 }
364 }
365
366 }
367