PluginProbe
JetFormBuilder — Dynamic Blocks Form Builder / 1.5.2
JetFormBuilder — Dynamic Blocks Form Builder v1.5.2
3.6.5.2 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 All 130 releases
jetformbuilder / includes / actions / methods / abstract-modifier.php
abstract-modifier.php
331 lines 8.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 /**
37 * @throws Action_Exception
38 */
39 public function run() {
40 $this->attach_items();
41 $this->do_action();
42 $this->after_action_externals();
43 }
44
45 public function get_action() {
46 return $this->action;
47 }
48
49 /**
50 * @param string $action
51 *
52 * @return Abstract_Modifier
53 * @throws Silence_Exception
54 */
55 public function set_action( string $action ) {
56 $actions = $this->get_actions();
57
58 if ( isset( $actions[ $action ]['action'] ) && is_callable( $actions[ $action ]['action'] ) ) {
59 $this->action = $action;
60
61 return $this;
62 }
63
64 throw new Silence_Exception(
65 'Undefined action',
66 array(
67 $action,
68 array_keys( $this->get_actions() )
69 )
70 );
71 }
72
73 /**
74 * @throws Action_Exception
75 */
76 public function do_action() {
77 $action = $this->get_actions()[ $this->get_action() ] ?? array();
78 $action_callback = $action['action'] ?? false;
79 $after_callback = $action['after'] ?? false;
80
81 if ( ! is_callable( $action_callback ) ) {
82 throw new Action_Exception( 'internal_error' );
83 }
84
85 call_user_func( $action_callback, $this );
86
87 if ( ! is_callable( $after_callback ) ) {
88 return;
89 }
90
91 call_user_func( $after_callback, $this );
92 }
93
94 public function attach_items() {
95 $this->fields_map = array_filter( $this->fields_map );
96
97 foreach ( $this->request as $key => $value ) {
98 try {
99 $this->current_prop = $key;
100 $this->current_value = $value;
101
102 $this->attach_item();
103 } catch ( Modifier_Exclude_Property $exception ) {
104 $this->exclude_current_prop();
105
106 } catch ( Silence_Exception $exception ) {
107 continue;
108 }
109 }
110 }
111
112 /**
113 * @throws Silence_Exception
114 */
115 public function attach_item() {
116 $this->current_prop = $this->get_current_prop_from_fields_map();
117
118 if ( in_array( $this->current_prop, $this->excluded_props, true ) ) {
119 throw new Silence_Exception( "Prop '{$this->current_prop}' is excluded" );
120 }
121
122 $this->before_attach();
123
124 $this->source_arr[ $this->current_prop ] = $this->current_value;
125 }
126
127 /**
128 * @param string $field_name
129 *
130 * @return string
131 * @throws Silence_Exception
132 */
133 public function get_prop_by_field_name( string $field_name ) {
134 /**
135 * At this moment $this->current_prop
136 * store the `field_name`
137 */
138 if ( empty( $this->fields_map[ $field_name ] ) ) {
139 throw new Silence_Exception( 'Field is not used.' );
140 }
141
142 /**
143 * And here we returning the post property
144 * Ex: 'post_content' | 'post_status' | 'jet_tax__slug' | 'custom_meta_key'
145 */
146 return Tools::sanitize_text_field( $this->fields_map[ $field_name ] );
147 }
148
149 public function replace_field_by_prop( string $prop_name, $value ) {
150 $field_name = $this->get_field_name_by_prop( $prop_name );
151
152 if ( false === $field_name ) {
153 $field_name = $this->unique_slug( $prop_name );
154
155 $this->fields_map[ $field_name ] = $prop_name;
156 }
157
158 $this->set_request( array(
159 $field_name => $value
160 ) );
161
162 return $this;
163 }
164
165 /**
166 * @return string
167 * @throws Silence_Exception
168 */
169 public function get_current_prop_from_fields_map() {
170 return $this->get_prop_by_field_name( $this->current_prop );
171 }
172
173 public function get_value_by_prop( string $prop ) {
174 $field_name = $this->get_field_name_by_prop( $prop );
175
176 return $this->request[ $field_name ] ?? false;
177 }
178
179 public function get_field_name_by_prop( string $search_prop ) {
180 foreach ( $this->fields_map as $field_name => $prop ) {
181 if ( $search_prop === $prop ) {
182 return $field_name;
183 }
184 }
185
186 return false;
187 }
188
189
190 /**
191 * @throws Silence_Exception
192 */
193 public function before_attach() {
194 $property_callback = $this->get_object_fields()[ $this->current_prop ]['before_cb'] ?? false;
195
196 if ( is_callable( $property_callback ) ) {
197 call_user_func( $property_callback, $this );
198
199 return;
200 }
201
202 if ( ! $this->is_reserved_property( $this->current_prop ) ) {
203 call_user_func( array( $this, 'custom_before_attach' ), $this );
204
205 throw new Silence_Exception( 'Property not need to attach' );
206 }
207 }
208
209 /**
210 * @throws Silence_Exception
211 */
212 public function custom_before_attach() {
213 /**
214 * We make the array in reverse order,
215 * in order to check external: meta last,
216 * since it does not have a check ( 'condition_cb' )
217 */
218 $externals = array_reverse( $this->get_external_properties() );
219
220 if ( empty( $externals ) ) {
221 return;
222 }
223
224 foreach ( $externals as $external_key => $external_value ) {
225 $this->current_external = $external_key;
226 $condition_cb = $external_value['condition_cb'] ?? false;
227
228 if ( empty( $condition_cb ) || (
229 is_callable( $condition_cb ) && ! call_user_func( $condition_cb, $this )
230 ) ) {
231 continue;
232 }
233
234 $match_cb = $external_value['match_cb'] ?? false;
235 if ( ! is_callable( $match_cb ) ) {
236 throw new Silence_Exception( "'match_cb' is not callable in {$external_key}" );
237 }
238
239 call_user_func( $match_cb, $this );
240 break;
241 }
242 }
243
244 public function is_reserved_property( $prop ) {
245 $fields = $this->get_object_fields();
246
247 return isset( $fields[ $prop ] ) || in_array( $prop, $fields, true );
248 }
249
250 public function after_action_externals() {
251 $externals = $this->get_external_properties();
252
253 foreach ( $externals as $external_key => $external_value ) {
254 $this->current_external = $external_key;
255 $condition_cb = $external_value['after_action'] ?? false;
256
257 if ( is_callable( $condition_cb ) ) {
258 call_user_func( $condition_cb, $this );
259 }
260 }
261 }
262
263 public function unique_slug( $suffix ) {
264 $form_id = jet_form_builder()->form_handler->form_id ?? 0;
265 $prefix = static::class;
266
267 return "{$prefix}_{$form_id}__{$suffix}";
268 }
269
270 public function set_fields_map( $fields_map ) {
271 $this->fields_map = $fields_map;
272
273 return $this;
274 }
275
276 public function set_external( string $key, array $data ) {
277 if ( ! isset( $this->external_data[ $key ] ) || ! is_array( $this->external_data[ $key ] ) ) {
278 $this->external_data[ $key ] = array();
279 }
280 $this->external_data[ $key ] = array_merge( $this->external_data[ $key ], $data );
281
282 return $this;
283 }
284
285 public function get_external( string $key ) {
286 return $this->external_data[ $key ] ?? array();
287 }
288
289 public function set_current_external( array $data ) {
290 return $this->set_external( $this->current_external, $data );
291 }
292
293 public function get_current_external() {
294 return $this->get_external( (string) $this->current_external );
295 }
296
297 public function set_request( $request ) {
298 $this->request = array_merge( $this->request, $request );
299
300 return $this;
301 }
302
303 public function exclude_current_prop() {
304 $this->exclude_prop( $this->current_prop );
305 }
306
307 /**
308 * @throws Modifier_Exclude_Property
309 */
310 public function exclude_current() {
311 throw new Modifier_Exclude_Property( "Excluding: {$this->current_prop}" );
312 }
313
314 public function exclude_prop( string $prop ) {
315 if ( ! in_array( $prop, $this->excluded_props, true ) ) {
316 $this->excluded_props[] = $prop;
317 }
318
319 unset( $this->source_arr[ $prop ] );
320 }
321
322 /**
323 * @throws Silence_Exception
324 */
325 public function throw_if_empty() {
326 if ( empty( $this->current_value ) ) {
327 throw new Silence_Exception( 'Current field is empty' );
328 }
329 }
330
331 }