PluginProbe
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards / 5.5.84
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards v5.5.84
5.5.84 5.5.83 5.5.82 5.5.81 5.5.80 5.5.79 5.5.77 5.5.76 5.5.75 5.5.73 5.5.72 5.5.22 5.5.23 5.5.29 5.5.3 5.5.31 5.5.32 5.5.34 5.5.35 5.5.36 5.5.37 5.5.4 5.5.40 5.5.41 5.5.42 All 160 releases
wp-data-access / WPDataProjects / Parent_Child / WPDP_Parent_Form.php

WPDP_Parent_Form.php in WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards 5.5.84, at WPDataProjects/Parent_Child/WPDP_Parent_Form.php

563 lines 17.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Suppress "error - 0 - No summary was found for this file" on phpdoc generation
5 *
6 * @package WPDataProjects\Parent_Child
7 */
8
9 namespace WPDataProjects\Parent_Child {
10
11 use WPDataAccess\Data_Dictionary\WPDA_List_Columns_Cache;
12 use WPDataProjects\Data_Dictionary\WPDP_List_Columns_Cache;
13 use WPDataProjects\Simple_Form\WPDP_Simple_Form;
14
15 /**
16 * Class WPDP_Parent_Form extends WPDP_Simple_Form
17 *
18 * This class presumes the existence of (a) child relationship(s) (1:n or n:m). While the parent is maintained in
19 * the top of the page, child relationship(s) are maintained below the parent. If multiple child relationships are
20 * found, the user can switch between them via tabs.
21 *
22 * @see WPDP_Simple_Form
23 *
24 * @author Peter Schulz
25 * @since 2.0.0
26 */
27 class WPDP_Parent_Form extends WPDP_Simple_Form {
28
29 /**
30 * Possible values: edit and view
31 *
32 * @var string
33 */
34 protected $mode;
35
36 /**
37 * Parent key(s) column names
38 *
39 * @var array
40 */
41 protected $parent_key = array();
42 /**
43 * Parent key(s) values
44 *
45 * @var array
46 */
47 protected $parent_key_value = array();
48
49 /**
50 * Child relationships
51 *
52 * @var array
53 */
54 protected $children = array();
55
56 /**
57 * Tabs (1 for every child)
58 *
59 * @var array
60 */
61 protected $tabs = array();
62
63 /**
64 * Current tab
65 *
66 * @var string
67 */
68 protected $current_tab = null;
69
70 /**
71 * Requested child action
72 *
73 * @var string
74 */
75 protected $child_action;
76
77 /**
78 * Possible values: TRUE and null
79 *
80 * TRUE = request is a child request
81 * All other values (including null) = request is a parent request
82 *
83 * @var mixed
84 */
85 protected $child_request;
86
87 /**
88 * Relationships found for actual parent
89 *
90 * @var array
91 */
92 protected $relations;
93
94 /**
95 * Class used to instantiate edit form
96 *
97 * @var mixed|string
98 */
99 protected $edit_form_class = 'WPDataProjects\\Parent_Child\\WPDP_Child_Form';
100
101 /**
102 * Class used to instantiate list table
103 *
104 * @var mixed|string
105 */
106 protected $list_table_class = 'WPDataProjects\\Parent_Child\\WPDP_Child_List_Table';
107
108 /**
109 * Action value during post (saved because it might change during request processing)
110 *
111 * @var string
112 */
113 protected $action_posted;
114
115 /**
116 * Overwrites WPDP_Parent_Form constructor
117 *
118 * @param string $schema_name Database schema name
119 * @param string $table_name Database table name
120 * @param object $wpda_list_columns Handle to WPDP_List_Columns object
121 * @param array $args Arguments
122 * @param array $relationship Relationships
123 */
124 public function __construct(
125 $schema_name,
126 $table_name,
127 &$wpda_list_columns,
128 $args = array(),
129 $relationship = array()
130 ) {
131 if ( isset( $args['mode'] ) ) {
132 $this->mode = $args['mode'];
133 } else {
134 wp_die( esc_attr__( 'ERROR: Wrong arguments [missing mode]', 'wp-data-access' ) );
135 }
136
137 if ( isset( $args['child_request'] ) ) {
138 $this->child_request = $args['child_request'];
139 } else {
140 wp_die( esc_attr__( 'ERROR: Wrong arguments [missing child_request]', 'wp-data-access' ) );
141 }
142
143 $action = null;
144 if ( isset( $_REQUEST['action'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- already verified
145 // Possible values: "new", "edit" and "view".
146 $action = sanitize_text_field( wp_unslash( $_REQUEST['action'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- already verified
147 $this->action_posted = $action;
148 } elseif ( isset( $args['action'] ) ) {
149 $action = $args['action'];
150 $this->action_posted = $action;
151 }
152
153 $this->relations = $relationship;
154
155 $args['back_to_list_text'] = __( 'Parent List', 'wp-data-access' );
156
157 parent::__construct( $schema_name, $table_name, $wpda_list_columns, $args );
158
159 if ( 'new' !== $action || $this->child_request ) {
160 if ( isset( $this->relations['parent']['key'] ) && is_array( $this->relations['parent']['key'] ) ) {
161 // phpcs:disable WordPress.Security.NonceVerification.Recommended -- already verified
162 foreach ( $this->relations['parent']['key'] as $key ) {
163 if ( isset( $_REQUEST[ 'WPDA_PARENT_KEY*' . $key ] ) ) {
164 array_push( $this->parent_key, $key ); // phpcs:ignore -- 8.1 proof
165 $this->parent_key_value[ $key ] = sanitize_text_field( wp_unslash( $_REQUEST[ 'WPDA_PARENT_KEY*' . $key ] ) ); // input var okay.
166 } elseif ( isset( $_REQUEST[ $key ] ) ) {
167 array_push( $this->parent_key, $key ); // phpcs:ignore -- 8.1 proof
168 $this->parent_key_value[ $key ] = sanitize_text_field( wp_unslash( $_REQUEST[ $key ] ) ); // input var okay.
169 }
170
171 if ( is_array( $this->relations['children'] ) ) {
172 $this->children = $this->relations['children'];
173 }
174 }
175 // phpcs:enable WordPress.Security.NonceVerification.Recommended
176 }
177 }
178
179 $this->set_child_action_member();
180 if ( $this->child_request ) {
181 if ( 'list' === $this->action || '-1' === $this->action ) {
182 $this->action = 'edit';
183 } else {
184 $this->action = 'view';
185 }
186 }
187 if ( 'view' === $this->mode ) {
188 $this->action = 'view';
189 }
190
191 foreach ( $this->children as $child ) {
192 if ( null === $this->current_tab ) {
193 $this->current_tab = $child['table_name'];
194 }
195
196 $this->tabs[ $child['table_name'] ] = $child['tab_label'];
197
198 if ( isset( $child['relation_nm'] ) ) {
199 $this->relations[ $child['table_name'] ]['relation_nm'] = $child['relation_nm'];
200 } elseif ( isset( $child['relation_1n'] ) ) {
201 $this->relations[ $child['table_name'] ]['relation_1n'] = $child['relation_1n'];
202 }
203 }
204
205 if ( isset( $_REQUEST['child_tab'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- verified in parent class
206 if ( isset( $this->tabs[ $_REQUEST['child_tab'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- verified in parent class
207 $this->current_tab = sanitize_text_field( wp_unslash( $_REQUEST['child_tab'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- verified in parent class
208 }
209 }
210
211 if ( isset( $args['edit_form_class'] ) ) {
212 $this->edit_form_class = $args['edit_form_class'];
213 }
214
215 if ( isset( $args['list_form_class'] ) ) {
216 $this->list_table_class = $args['list_form_class'];
217 }
218 }
219
220 /**
221 * Overwrite method to add show less/more functionality
222 *
223 * @param bool $set_back_form_values
224 */
225 protected function prepare_items( $set_back_form_values = false ) {
226 parent::prepare_items( $set_back_form_values );
227
228 foreach ( $this->wpda_list_columns->get_table_columns() as $columns ) {
229 if ( isset( $columns['less'] ) && ! $columns['less'] ) {
230 foreach ( $this->form_items as $item ) {
231 if ( $item->get_item_name() === $columns['column_name'] ) {
232 $item->set_item_class( 'row-show-less-more' );
233 }
234 }
235 }
236 }
237 }
238
239 /**
240 * Determine and set action to be performed on child
241 */
242 protected function set_child_action_member() {
243 if ( $this->child_request ) {
244 if ( '-1' === $this->action ) {
245 $this->child_action = $this->action2;
246 } else {
247 $this->child_action = $this->action;
248 }
249 } else {
250 $this->child_action = 'list';
251 }
252 }
253
254 /**
255 * Overwrite method show
256 *
257 * @param bool $allow_save
258 * @param string $add_param
259 *
260 * @see WPDP_Simple_Form::show()
261 */
262 public function show( $allow_save = true, $add_param = '' ) {
263 if ( $this->child_request ) {
264 parent::show( false, $add_param );
265 } else {
266 parent::show( $allow_save, $add_param );
267 }
268 if ( 'new' === $this->action_posted && 'edit' === parent::get_form_action() ) {
269 // Record successfully inserted: reload page to show tabs
270 ?>
271 <script>
272 jQuery("#wpda_simple_form_0 input[name='wpda_message']").val("<?php esc_html_e( 'Succesfully saved changes to database', 'wp-data-access' ); ?>");
273 jQuery("#wpda_simple_form_0").submit();
274 </script>
275 <?php
276 }
277 $this->add_tabs();
278 foreach ( $this->children as $child ) {
279 if ( $child['table_name'] === $this->current_tab ) {
280 if ( 'edit' === $this->child_action || 'new' === $this->child_action || 'view' === $this->child_action ) {
281 $this->show_child_form( $child['table_name'], $child );
282 } else {
283 $this->show_child_list_table( $child['table_name'], $child );
284 }
285 }
286 }
287 }
288
289 /**
290 * Show child form
291 *
292 * @param string $child_table_name Database table name
293 * @param array $child Child info
294 */
295 protected function show_child_form( $child_table_name, $child ) {
296 if (
297 'edit' === $this->mode &&
298 ( 'new' === $this->child_action || 'edit' === $this->child_action ) &&
299 ( ! ( isset( $_POST['postaction'] ) && 'childlist' === $_POST['postaction'] ) ) // phpcs:ignore WordPress.Security.NonceVerification.Missing -- verified in parent class
300 ) {
301 $this->button_add_new( $child, $child_table_name );
302 echo '<div style="clear:both;"></div>';
303 }
304 $wpda_list_columns = WPDP_List_Columns_Cache::get_list_columns( $this->schema_name, $child_table_name, 'tableform', $this->setname );
305 $wpda_child_form = new $this->edit_form_class(
306 $this->schema_name,
307 $child_table_name,
308 $wpda_list_columns,
309 array(
310 'show_title' => false,
311 'show_back_button' => true,
312 'mode' => $this->mode,
313 'parent' => array(
314 'parent_key' => $this->parent_key,
315 'parent_key_value' => $this->parent_key_value,
316 ),
317 'child' => $child,
318 'back_to_list_text' => __( 'Child List', 'wp-data-access' ),
319 )
320 );
321
322 $wpda_child_form->prepare_form();
323
324 if ( isset( $_POST['postaction'] ) && 'childlist' === $_POST['postaction'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- verified in parent class
325 $this->show_child_list_table( $child_table_name, $child );
326 } else {
327 $wpda_child_form->show();
328 }
329 }
330
331 /**
332 * Show child list table
333 *
334 * @param string $child_table_name Database table name
335 * @param array $child Child info
336 */
337 protected function show_child_list_table( $child_table_name, $child ) {
338 $is_list_table_selection = isset( $_REQUEST['list_table_selection'] ); // phpcs:ignore -- verified in parent class
339 if ( 'edit' === $this->mode ) {
340 $this->button_add_new( $child, $child_table_name );
341 }
342 if ( $is_list_table_selection || 'add' === $this->child_action || 'bulk-add' === $this->child_action ) {
343 $list_table_class = 'WPDataProjects\\Parent_Child\\WPDP_Child_List_Table_Selection';
344 } else {
345 $list_table_class = $this->list_table_class;
346 }
347 $wpda_list_columns = WPDP_List_Columns_Cache::get_list_columns( $this->schema_name, $child_table_name, 'listtable', $this->setname );
348 $wpda_list_table = new $list_table_class(
349 array(
350 'wpdaschema_name' => $this->schema_name,
351 'table_name' => $child_table_name,
352 'wpda_list_columns' => $wpda_list_columns,
353 'mode' => $this->mode,
354 'title' => '',
355 'subtitle' => '',
356 'allow_import' => 'off',
357 'parent' => array(
358 'parent_key' => $this->parent_key,
359 'parent_key_value' => $this->parent_key_value,
360 ),
361 'child' => $child,
362 )
363 );
364 $wpda_list_table->show();
365 }
366
367 /**
368 * Add a tab for every child
369 */
370 protected function add_tabs() {
371 if ( count( $this->children ) > 0 ) { // phpcs:ignore -- 8.1 proof
372 ?>
373 <h2 class="nav-tab-wrapper">
374 <?php
375 $requested_page_number = 1;
376 if ( isset( $_REQUEST['page_number'] ) ) { // phpcs:ignore -- verified in parent class
377 $requested_page_number = sanitize_text_field( wp_unslash( $_REQUEST['page_number'] ) ); // phpcs:ignore -- verified in parent class
378 }
379 foreach ( $this->tabs as $tab => $name ) {
380 $class = ( $tab === $this->current_tab ) ? ' nav-tab-active' : '';
381 $id_from_name = preg_replace( '/[^a-zA-Z0-9]/', '', $name );
382
383 if ( is_admin() ) {
384 $url = "?page={$this->page}";
385 } else {
386 $url = '';
387 }
388 ?>
389 <form action="<?php echo esc_attr( $url ); ?>"
390 method="post"
391 id="form_tab_<?php echo esc_attr( $id_from_name ); ?>"
392 >
393 <a class="nav-tab<?php echo esc_attr( $class ); ?>"
394 href="javascript:void(0)"
395 onclick="jQuery('#form_tab_<?php echo esc_attr( $id_from_name ); ?>').submit()"
396 >
397 <?php echo esc_attr( $name ); ?>
398 <?php $this->add_parent_keys(); ?>
399 <input type="hidden" name="action" value="list">
400 <input type="hidden" name="mode" value="<?php echo esc_attr( $this->mode ); ?>">
401 <input type='hidden' name='child_request' value='TRUE'/>
402 <input type="hidden" name="child_tab" value="<?php echo esc_attr( $tab ); ?>">
403 <input type='hidden' name='page_number'
404 value="<?php echo esc_attr( $requested_page_number ); ?>">
405 </a>
406 </form>
407 <?php
408 }
409 ?>
410 </h2>
411 <?php
412 }
413 }
414
415 /**
416 * Add parent args to child request
417 */
418 protected function add_parent_args() {
419 $child_tab = '';
420 if ( isset( $_REQUEST['child_tab'] ) ) { // phpcs:ignore -- verified in parent class
421 $child_tab = sanitize_text_field( wp_unslash( $_REQUEST['child_tab'] ) ); // phpcs:ignore -- verified in parent class
422 }
423 ?>
424 <input type='hidden' name='child_tab' value='<?php echo esc_attr( $child_tab ); ?>'/>
425 <?php
426 }
427
428 /**
429 * Overwrites method get_url_arguments
430 */
431 protected function get_url_arguments() {
432 // Default behaviour.
433 parent::get_url_arguments();
434
435 // When we are coming from a child we'll need to get our parent key
436 if ( isset( $this->relations['parent']['key'] ) && is_array( $this->relations['parent']['key'] ) ) {
437 foreach ( $this->relations['parent']['key'] as $key ) {
438 if ( isset( $_REQUEST[ 'WPDA_PARENT_KEY*' . $key ] ) ) { // phpcs:ignore -- verified in parent class
439 $this->form_items_new_values[ $key ] = sanitize_text_field( wp_unslash( $_REQUEST[ 'WPDA_PARENT_KEY*' . $key ] ) ); // phpcs:ignore -- verified in parent class
440 }
441 }
442 }
443 }
444
445 /**
446 * Add button new to page top
447 *
448 * @param array $child Child info
449 * @param string $child_table_name Database table name
450 */
451 protected function button_add_new( $child, $child_table_name ) {
452 // Check if table has primary key. If not, disable adding a new record.
453 $check_pk = WPDA_List_Columns_Cache::get_list_columns( $this->schema_name, $child_table_name );
454 $title = 'Add new row';
455
456 if ( is_admin() ) {
457 $url = "?page={$this->page}";
458 } else {
459 $url = '';
460 }
461
462 if ( ! empty( $check_pk->get_table_primary_key() ) ) {
463 ?>
464 <form
465 method="post"
466 action="<?php echo esc_attr( $url ); ?>"
467 style="padding-top:15px;padding-left:5px;float:left;"
468 >
469 <?php $this->add_parent_keys( 'WPDA_PARENT_KEY*' ); ?>
470 <?php echo $this->page_number_item; // phpcs:ignore WordPress.Security.EscapeOutput ?>
471 <input type="hidden" name="mode" value="edit">
472 <input type="hidden" name="child_request" value="TRUE">
473 <input type="hidden" name="child_tab" value="<?php echo esc_attr( $child_table_name ); ?>">
474 <input type="hidden" name="action" value="new">
475 <button type="submit" class="button wpda_tooltip" title="<?php echo esc_attr( $title ); ?>">
476 <i class="fas fa-plus-circle wpda_icon_on_button"></i>
477 <?php esc_html_e( 'Add New', 'wp-data-access' ); ?>
478 </button>
479 </form>
480 <?php
481 }
482 if ( isset( $child['relation_nm'] ) ) {
483 ?>
484 <form
485 method="post"
486 action="<?php echo esc_attr( $url ); ?>"
487 style="padding-top:15px;padding-left:5px;float:left;"
488 >
489 <?php $this->add_parent_keys( 'WPDA_PARENT_KEY*' ); ?>
490 <?php echo $this->page_number_item; // phpcs:ignore WordPress.Security.EscapeOutput ?>
491 <input type="hidden" name="mode" value="edit">
492 <input type="hidden" name="child_request" value="TRUE">
493 <input type="hidden" name="child_tab" value="<?php echo esc_attr( $child_table_name ); ?>">
494 <input type="hidden" name="action" value="add">
495 <button type="submit" class="button wpda_tooltip"
496 title="Add existing row"
497 >
498 <i class="fas fa-plus-circle wpda_icon_on_button"></i>
499 <?php esc_html_e( 'Add Existing', 'wp-data-access' ); ?>
500 </button>
501 </form>
502 <?php
503 }
504 }
505
506 /**
507 * Add parent keys as hidden items
508 *
509 * @param string $name_prefix Added prefix to be flexible
510 */
511 protected function add_parent_keys( $name_prefix = '' ) {
512 foreach ( $this->parent_key as $parent_key ) {
513 ?>
514 <input type="hidden"
515 name="<?php echo esc_attr( $name_prefix ) . esc_attr( $parent_key ); ?>"
516 value="<?php echo esc_attr( $this->parent_key_value[ $parent_key ] ); ?>">
517 <?php
518 }
519 }
520
521 /**
522 * Overwrite method to add show less/more functionality
523 */
524 public function add_form_logic() {
525 if ( 'new' !== $this->action_posted || $this->child_request ) {
526 ?>
527 <input type="button"
528 value="<?php esc_html_e( 'show more', 'wp-data-access' ); ?> &gt;&gt;&gt;"
529 class="button"
530 id="show_more_less_button"
531 style="float:right;display:none;">
532 <script type='text/javascript'>
533 function show_more_less() {
534 jQuery('.row-show-less-more').toggle();
535 if (jQuery('#show_more_less_button').val() === '<?php esc_html_e( 'show more', 'wp-data-access' ); ?> &gt;&gt;&gt;') {
536 jQuery('#show_more_less_button').val('<<< <?php esc_html_e( 'show less', 'wp-data-access' ); ?>');
537 } else {
538 jQuery('#show_more_less_button').val('<?php esc_html_e( 'show more', 'wp-data-access' ); ?> &gt;&gt;&gt;');
539 }
540 }
541
542 if (jQuery('.row-show-less-more').length > 0) {
543 jQuery('#show_more_less_button').show();
544
545 jQuery('#show_more_less_button').on('click', function() {
546 show_more_less();
547 });
548 }
549 </script>
550 <?php
551 } else {
552 ?>
553 <script type='text/javascript'>
554 jQuery('.row-show-less-more').show();
555 </script>
556 <?php
557 }
558 }
559
560 }
561
562 }
563