PluginProbe
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards / 5.5.35
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards v5.5.35
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 5.5.43 All 159 releases
wp-data-access / WPDataAccess / Simple_Form / WPDA_Simple_Form.php

WPDA_Simple_Form.php in WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards 5.5.35, at WPDataAccess/Simple_Form/WPDA_Simple_Form.php

1,637 lines 56.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 WPDataAccess\Simple_Form
7 */
8 namespace WPDataAccess\Simple_Form;
9
10 use WPDataAccess\Data_Dictionary\WPDA_List_Columns;
11 use WPDataAccess\Plugin_Table_Models\WPDA_Media_Model;
12 use WPDataAccess\Plugin_Table_Models\WPDA_Table_Settings_Model;
13 use WPDataAccess\Utilities\WPDA_Message_Box;
14 use WPDataAccess\WPDA;
15 use WPDataAccess\Dashboard\WPDA_Dashboard;
16 /**
17 * Class WPDA_Simple_Form
18 *
19 * Generates a simple dynamic data entry form on request. Data entry form consists of the following components:
20 * + WPDA_Simple_Form (layout management)
21 * + WPDA_Simple_Form_Data (data management)
22 * + WPDA_Simple_Form_Item (data item management)
23 * + WPDA_Simple_Form_Type_Icon (data type icon)
24 *
25 * Simple forms can be generated for tables only. It is not possible to generate simple forms for views.
26 *
27 * Simple forms can be generated for tables with a primary key only. For tables that do not have a primary key it
28 * is not possible to generate a simple form as records in the table cannot be recognized uniquely.
29 *
30 * Primary key fields are disable in update mode. This is to prevent inconsistency. Use method
31 * {@see WPDA_Simple_Form::set_update_keys()} to allow updating primary key items. Make sure you understand to
32 * consequences!!!
33 *
34 * @author Peter Schulz
35 * @since 1.0.0
36 */
37 class WPDA_Simple_Form {
38 /**
39 * Static id to create unique form names on the page
40 *
41 * @var int
42 */
43 protected static $form_id = 0;
44
45 /**
46 * Warning icon
47 */
48 const WARNING_ICON = '<span class="dashicons dashicons-warning"></span> ';
49
50 /**
51 * Form id
52 *
53 * @var int
54 */
55 protected $current_form_id;
56
57 /**
58 * Page title
59 *
60 * @var string
61 */
62 protected $title = null;
63
64 /**
65 * Add action to page title?
66 *
67 * @var string TRUE = add action
68 */
69 protected $add_action_to_title;
70
71 /**
72 * Page subtitle
73 *
74 * @var string
75 */
76 protected $subtitle = '';
77
78 /**
79 * Page fieldset title
80 *
81 * @var string
82 */
83 protected $fieldset_title = '';
84
85 /**
86 * Hides warning update text
87 *
88 * @var string TRUE = hide warning (overwrites plugin settings)
89 */
90 protected $no_warning_update_text = 'FALSE';
91
92 /**
93 * Database schema name
94 *
95 * @var string
96 */
97 protected $schema_name;
98
99 /**
100 * Database table name
101 *
102 * @var string
103 */
104 protected $table_name;
105
106 /**
107 * Handle to data management component
108 *
109 * @var WPDA_Simple_Form_Data
110 */
111 protected $row_data;
112
113 /**
114 * Handle to database record
115 *
116 * @var object
117 */
118 protected $row;
119
120 /**
121 * Handle to WPDA_List_Columns
122 *
123 * @var WPDA_List_Columns
124 */
125 protected $wpda_list_columns;
126
127 /**
128 * Access column names
129 *
130 * @var array
131 */
132 protected $table_columns;
133
134 /**
135 * Access column headers
136 *
137 * @var array
138 */
139 protected $table_column_headers;
140
141 /**
142 * Display column headers
143 *
144 * @var array
145 */
146 protected $table_column_header;
147
148 /**
149 * Column headers (labels, arguments)
150 *
151 * @var array
152 */
153 protected $column_headers;
154
155 /**
156 * Form items
157 *
158 * @var array
159 */
160 protected $form_items = array();
161
162 /**
163 * Form items named array
164 *
165 * Use this array to quickly find an item in the form
166 *
167 * @var array
168 */
169 protected $form_items_named = array();
170
171 /**
172 * Form items old values (if applicable)
173 *
174 * @var array
175 */
176 protected $form_items_old_values = array();
177
178 /**
179 * Form items new values (if applicable)
180 *
181 * @var array
182 */
183 protected $form_items_new_values = array();
184
185 /**
186 * Menu slug current page
187 *
188 * @var string
189 */
190 protected $page;
191
192 /**
193 * Primary page action
194 *
195 * @var string
196 */
197 protected $action;
198
199 /**
200 * Secondary page action
201 *
202 * @var string
203 */
204 protected $action2 = '';
205
206 /**
207 * Auto increment value
208 *
209 * @var int
210 */
211 protected $auto_increment_value = -1;
212
213 /**
214 * Defines it keys are updatable
215 *
216 * @var bool
217 */
218 protected $update_keys_allowed = false;
219
220 /**
221 * Error message number
222 *
223 * @var int
224 */
225 protected $wpda_err = 0;
226
227 /**
228 * Error message text
229 *
230 * @var string
231 */
232 protected $wpda_msg = '';
233
234 /**
235 * Indicates whether the title should be displayed or not
236 *
237 * @var bool
238 */
239 protected $show_title = true;
240
241 /**
242 * Indicates whether the back button should be displayed or not
243 *
244 * @var bool
245 */
246 protected $show_back_button = true;
247
248 /**
249 * Indicates whether the back icon in the title should be displayed or not
250 *
251 * @var bool
252 */
253 protected $show_back_icon = true;
254
255 /**
256 * Indicates whether table type should be checked to display subtitle.
257 *
258 * @var bool
259 */
260 protected $check_table_type = true;
261
262 /**
263 * Page number item name (default 'page_number')
264 *
265 * The name can be changed for pages on multiple levels. This is needed to get back to the right page in
266 * parent-child page.
267 *
268 * @var string
269 */
270 protected $page_number_item_name = 'page_number';
271
272 /**
273 * Real page number
274 *
275 * @var null
276 */
277 protected $page_number_link = '';
278
279 /**
280 * Page number text item
281 *
282 * @var null
283 */
284 protected $page_number_item = '';
285
286 /**
287 * Used to changed button text
288 *
289 * @var string
290 */
291 protected $back_to_list_text = '';
292
293 /**
294 * Table settings (taken from plugin table settings table)
295 *
296 * @var mixed|null
297 */
298 protected $wpda_table_settings = null;
299
300 /**
301 * Show help icon if help url is available
302 *
303 * @var null|string
304 */
305 protected $help_url = null;
306
307 /**
308 * Hide Add New button
309 *
310 * @var null|string
311 */
312 protected $hide_add_new = false;
313
314 /**
315 * Group items into fieldsets
316 *
317 * @var array
318 */
319 protected $fieldsets = array();
320
321 /**
322 * WPDA_Simple_Form constructor
323 *
324 * Performs the following steps:
325 * + Check if requested action is allowed
326 * + Check if table is provided
327 * + Save OLD and NEW request values
328 * + Create WPDA_Simple_Form_Data object
329 *
330 * @param string $schema_name Database schema name.
331 * @param string $table_name Database table name.
332 * @param WPDA_List_Columns $wpda_list_columns Reference to column array.
333 * @param array $args Messages (named array).
334 *
335 * @since 1.0.0
336 *
337 * @see WPDA_Simple_Form_Data
338 */
339 public function __construct(
340 $schema_name,
341 $table_name,
342 &$wpda_list_columns,
343 $args = array()
344 ) {
345 // Get page and handling arguments.
346 if ( isset( $_REQUEST['page'] ) ) {
347 $this->page = sanitize_text_field( wp_unslash( $_REQUEST['page'] ) );
348 // input var okay.
349 } else {
350 wp_die( __( 'ERROR: Wrong arguments [missing page argument]', 'wp-data-access' ) );
351 }
352 if ( isset( $_REQUEST['action'] ) ) {
353 // Possible values: "new", "edit" and "view".
354 $this->action = sanitize_text_field( wp_unslash( $_REQUEST['action'] ) );
355 // input var okay.
356 } else {
357 if ( isset( $args['action'] ) ) {
358 $this->action = $args['action'];
359 } else {
360 wp_die( __( 'ERROR: Wrong arguments [missing action argument]', 'wp-data-access' ) );
361 }
362 }
363 if ( isset( $_REQUEST['action2'] ) ) {
364 $this->action2 = sanitize_text_field( wp_unslash( $_REQUEST['action2'] ) );
365 // input var okay.
366 }
367 $this->schema_name = $schema_name;
368 $this->table_name = $table_name;
369 if ( '' === $this->table_name ) {
370 // Without a table name it makes no sense to continue.
371 wp_die( __( 'ERROR: Wrong arguments [missing table_name argument]' ) );
372 }
373 if ( !WPDA::is_wpda_table( $this->table_name ) ) {
374 // Check access rights for tables that do not belong to the plugin.
375 if ( 'on' !== WPDA::get_option( WPDA::OPTION_BE_ALLOW_INSERT ) && 'new' === $this->action ) {
376 // Insert not allowed.
377 wp_die( __( 'ERROR: Not authorized', 'wp-data-access' ) );
378 }
379 if ( 'on' !== WPDA::get_option( WPDA::OPTION_BE_VIEW_LINK ) && 'view' === $this->action ) {
380 // Viewing not allowed.
381 wp_die( __( 'ERROR: Not authorized', 'wp-data-access' ) );
382 }
383 if ( 'on' !== WPDA::get_option( WPDA::OPTION_BE_ALLOW_UPDATE ) && 'edit' === $this->action ) {
384 // Update not allowed.
385 wp_die( __( 'ERROR: Not authorized', 'wp-data-access' ) );
386 }
387 }
388 // Get columns information.
389 $this->wpda_list_columns = $wpda_list_columns;
390 $this->table_columns = $this->wpda_list_columns->get_table_columns();
391 $this->table_column_headers = $this->wpda_list_columns->get_table_column_headers();
392 // Set page title.
393 if ( isset( $args['title'] ) ) {
394 $this->title = $args['title'];
395 $this->add_action_to_title = true;
396 if ( isset( $args['add_action_to_title'] ) && 'FALSE' === $args['add_action_to_title'] ) {
397 $this->add_action_to_title = false;
398 }
399 }
400 // Set page subtitle.
401 if ( isset( $args['subtitle'] ) ) {
402 $this->subtitle = $args['subtitle'];
403 } else {
404 if ( $this->check_table_type ) {
405 global $wpdb;
406 $wp_tables = $wpdb->tables( 'all', true );
407 if ( isset( $wp_tables[substr( $this->table_name, strlen( $wpdb->prefix ) )] ) ) {
408 $this->subtitle = self::WARNING_ICON . WPDA::get_table_type_text( WPDA::TABLE_TYPE_WP );
409 } elseif ( WPDA::is_wpda_table( $this->table_name ) ) {
410 $this->subtitle = self::WARNING_ICON . WPDA::get_table_type_text( WPDA::TABLE_TYPE_WPDA );
411 }
412 }
413 }
414 if ( isset( $args['no_warning_update_text'] ) ) {
415 $this->no_warning_update_text = $args['no_warning_update_text'];
416 }
417 // Add customizable success and failure messages to support i18n.
418 // This allows to overwrite message in classes extending WPDA_Simple_Form.
419 $args = wp_parse_args( $args, array(
420 'wpda_success_msg' => __( 'Succesfully saved changes to database', 'wp-data-access' ),
421 'wpda_failure_msg' => __( 'Saving changes to database failed', 'wp-data-access' ),
422 'show_title' => true,
423 'show_back_button' => true,
424 'show_back_icon' => true,
425 ) );
426 // Get arguments from URL (old and new values).
427 $this->get_url_arguments();
428 // Add data object for DML.
429 $this->row_data = new WPDA_Simple_Form_Data(
430 $this->schema_name,
431 $this->table_name,
432 $this->wpda_list_columns,
433 $this,
434 $args['wpda_success_msg'],
435 $args['wpda_failure_msg']
436 );
437 $this->current_form_id = 'wpda_simple_form_' . self::$form_id++;
438 if ( isset( $args['show_title'] ) ) {
439 $this->show_title = $args['show_title'];
440 }
441 if ( isset( $args['show_back_button'] ) ) {
442 $this->show_back_button = $args['show_back_button'];
443 }
444 if ( isset( $args['show_back_icon'] ) ) {
445 $this->show_back_icon = $args['show_back_icon'];
446 }
447 // Overwrite column header text if column headers were provided.
448 $this->column_headers = ( isset( $args['column_headers'] ) ? $args['column_headers'] : '' );
449 // Get current page number of list table
450 if ( 'page_number' !== $this->page_number_item_name ) {
451 if ( isset( $_REQUEST['page_number'] ) ) {
452 $requested_page_number = sanitize_text_field( wp_unslash( $_REQUEST['page_number'] ) );
453 // input var okay.
454 $this->page_number_link = '&page_number=' . $requested_page_number;
455 $this->page_number_item = "<input type='hidden' name='page_number' value='{$requested_page_number}'/>";
456 }
457 }
458 if ( isset( $_REQUEST[$this->page_number_item_name] ) ) {
459 $requested_page_number = sanitize_text_field( wp_unslash( $_REQUEST[$this->page_number_item_name] ) );
460 // input var okay.
461 $this->page_number_link .= '&paged=' . $requested_page_number;
462 $this->page_number_item .= "<input type='hidden' name='" . $this->page_number_item_name . "' value='{$requested_page_number}'/>";
463 }
464 // Add search arguments to link to return to same page
465 foreach ( $_REQUEST as $key => $value ) {
466 if ( substr( $key, 0, 19 ) === 'wpda_search_column_' ) {
467 $this->page_number_link .= "&{$key}={$value}";
468 $this->page_number_item .= "<input type='hidden' name='{$key}' value='{$value}' />";
469 }
470 }
471 // Check if button text "back to list" should be changed
472 if ( isset( $args['back_to_list_text'] ) && '' !== $args['back_to_list_text'] ) {
473 $this->back_to_list_text = $args['back_to_list_text'];
474 } else {
475 $this->back_to_list_text = __( 'List', 'wp-data-access' );
476 }
477 // Get table settings
478 $wpda_table_settings = WPDA_Table_Settings_Model::query( $this->table_name, $this->schema_name );
479 if ( isset( $wpda_table_settings[0]['wpda_table_settings'] ) ) {
480 $this->wpda_table_settings = json_decode( $wpda_table_settings[0]['wpda_table_settings'] );
481 }
482 if ( isset( $args['help_url'] ) ) {
483 $this->help_url = $args['help_url'];
484 }
485 if ( isset( $args['hide_add_new'] ) ) {
486 $this->hide_add_new = $args['hide_add_new'];
487 }
488 global $wpda_project_mode;
489 if ( isset( $wpda_project_mode['allow_insert'] ) && 'only' === $wpda_project_mode['allow_insert'] ) {
490 $this->hide_add_new = true;
491 }
492 }
493
494 /**
495 * Get URL arguments.
496 *
497 * @since 1.5.0
498 */
499 protected function get_url_arguments() {
500 // Get OLD and NEW values for all items.
501 foreach ( $this->wpda_list_columns->get_table_columns() as $column ) {
502 if ( isset( $_REQUEST[$column['column_name'] . '_old'] ) ) {
503 $this->form_items_old_values[$column['column_name']] = wp_unslash( $_REQUEST[$column['column_name'] . '_old'] );
504 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
505 }
506 if ( isset( $_REQUEST[$column['column_name']] ) ) {
507 if ( is_array( $_REQUEST[$column['column_name']] ) ) {
508 $column_array = '';
509 foreach ( $_REQUEST[$column['column_name']] as $column_value ) {
510 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
511 $column_array .= wp_unslash( $column_value ) . ',';
512 }
513 if ( '' !== $column_array ) {
514 $this->form_items_new_values[$column['column_name']] = substr( $column_array, 0, strlen( $column_array ) - 1 );
515 }
516 } else {
517 $this->form_items_new_values[$column['column_name']] = wp_unslash( $_REQUEST[$column['column_name']] );
518 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
519 }
520 }
521 }
522 }
523
524 /**
525 * Prepare form items and handle transactions
526 *
527 * Performs the following steps:
528 * + Checks for posted data
529 * + Saves changes if applicable (displays success or failure message)
530 * + Prepares simple form
531 *
532 * @param bool $allow_save
533 */
534 public function prepare_form( $allow_save = true ) {
535 $set_back_form_values = false;
536 if ( $allow_save && ('new' === $this->action || 'edit' === $this->action) && 'save' === $this->action2 ) {
537 // Security check (is action allowed?).
538 $wp_nonce = ( isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : '' );
539 // input var okay.
540 if ( !wp_verify_nonce( $wp_nonce, $this->get_nonce_action() ) ) {
541 wp_die( __( 'ERROR: Not authorized', 'wp-data-access' ) );
542 }
543 if ( 'new' === $this->action ) {
544 // Prepare row and items for validation
545 $this->row = $this->row_data->new_row();
546 $this->prepare_items( true );
547 // Save new record.
548 if ( !$this->validate( true ) ) {
549 $set_back_form_values = true;
550 } else {
551 // Insert record.
552 $add_row_result = $this->row_data->add_row();
553 if ( $add_row_result ) {
554 // Insert succeeded:
555 // (1) save auto_increment value (if applicable)
556 // (2) change action to edit
557 if ( is_numeric( $add_row_result ) ) {
558 // save auto_increment value (1).
559 $this->auto_increment_value = $add_row_result;
560 }
561 // change action to edit (2).
562 $this->action = 'edit';
563 $this->prepare_row();
564 } else {
565 // Insert failed:
566 // (1) set back form items
567 $set_back_form_values = true;
568 }
569 }
570 } else {
571 // Prepare row and items for validation
572 $this->row = $this->row_data->get_row( $this->auto_increment_value, $this->wpda_err );
573 $this->prepare_items( true );
574 // Update existing record.
575 if ( $this->validate() ) {
576 // Update record.
577 $this->row_data->set_row();
578 // Get values updated from database triggers
579 $this->row = $this->row_data->get_row( $this->auto_increment_value, $this->wpda_err );
580 foreach ( $this->form_items_new_values as $key => $value ) {
581 if ( isset( $this->row[0][$key] ) ) {
582 $this->form_items_new_values[$key] = $this->row[0][$key];
583 }
584 }
585 }
586 $this->prepare_row();
587 $set_back_form_values = true;
588 }
589 } else {
590 $this->prepare_row();
591 }
592 $this->prepare_items( $set_back_form_values );
593 if ( '1' === $this->wpda_err && $this->update_keys_allowed && 'edit' === $this->action && 'save' === $this->action2 ) {
594 $keys_have_changed = false;
595 // There was an error! If key updates are allowed, we might have needed to set back the keys to their
596 // original values. We'll inform the user with a message box.
597 foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
598 if ( $this->get_old_value( $pk_column ) !== $this->get_new_value( $pk_column ) ) {
599 $keys_have_changed = true;
600 break;
601 }
602 }
603 if ( $keys_have_changed ) {
604 $msg = new WPDA_Message_Box(array(
605 'message_text' => __( 'Key columns have been reversed to their original values', 'wp-data-access' ),
606 ));
607 $msg->box();
608 }
609 }
610 if ( null === $this->title ) {
611 if ( 'new' === $this->action ) {
612 $action_in_title = __( 'Add new row to', 'wp-data-access' );
613 } else {
614 $action_in_title = ucfirst( $this->action );
615 }
616 $this->title = $action_in_title . ' ' . __( 'table', 'wp-data-access' ) . ' ' . strtoupper( $this->table_name );
617 } else {
618 if ( 'new' === $this->action ) {
619 $title_action = 'Add New ';
620 } else {
621 $title_action = ucfirst( $this->action );
622 }
623 if ( $this->add_action_to_title ) {
624 $this->title = $title_action . ' ' . $this->title;
625 }
626 }
627 if ( is_admin() && ($this->page === \WP_Data_Access_Admin::PAGE_MAIN || substr( $this->page, 0, 13 ) === \WP_Data_Access_Admin::PAGE_EXPLORER) ) {
628 $this->fieldset_title = $this->title;
629 $this->title = 'Data Explorer';
630 }
631 }
632
633 /**
634 * Overwrite to group items into fieldsets
635 */
636 protected function add_fieldsets() {
637 $fields = array();
638 foreach ( $this->form_items as $item ) {
639 $fields[] = $item->get_item_name();
640 }
641 // Add just one default fieldset which contains all fields
642 $this->fieldsets[$this->fieldset_title] = array(
643 'id' => '',
644 'fields' => $fields,
645 );
646 }
647
648 /**
649 * Show simple form
650 *
651 * Performs the following steps:
652 * + Shows simple form for requested table (HTML and Javascript)
653 *
654 * @param boolean $allow_save Allow to save data
655 * @param string $add_param Parameter to be added to form action.
656 *
657 * @since 1.0.0
658 */
659 public function show( $allow_save = true, $add_param = '' ) {
660 $this->add_fieldsets();
661 // Prepare url
662 if ( is_admin() ) {
663 $url = "?page={$this->page}";
664 } else {
665 $url = '';
666 }
667 $url_back = $url;
668 $url .= $add_param;
669 ?>
670 <div class="wrap">
671 <?php
672 if ( $this->show_title ) {
673 ?>
674 <h1 class="wp-heading-inline">
675 <?php
676 if ( is_admin() && $this->show_back_icon ) {
677 ?>
678 <a
679 href="javascript:void(0)"
680 onclick="jQuery('#<?php
681 echo esc_attr( $this->current_form_id );
682 ?>_backbutton').submit()"
683 class="dashicons dashicons-arrow-left-alt2 wpda_tooltip"
684 title="<?php
685 echo esc_attr( $this->back_to_list_text );
686 ?>"
687 ></a>
688 <?php
689 }
690 ?>
691 <?php
692 echo esc_attr( $this->title );
693 ?>
694 <?php
695 if ( substr( $this->page, 0, 13 ) === \WP_Data_Access_Admin::PAGE_EXPLORER || !is_admin() ) {
696 // Button is available on web pages only
697 if ( 'view' !== $this->action && !$this->hide_add_new ) {
698 //phpcs:ignore - 8.1 proof
699 if ( WPDA::is_wpda_table( $this->table_name ) || ('on' === WPDA::get_option( WPDA::OPTION_BE_ALLOW_INSERT ) && count( $this->wpda_list_columns->get_table_primary_key() )) > 0 ) {
700 $title = __( 'Add new row to table', 'wp-data-access' );
701 ?>
702 <form
703 method="post"
704 action="<?php
705 echo esc_attr( $url );
706 ?>"
707 style="display: inline-block; vertical-align: bottom;"
708 >
709 <div>
710 <?php
711 if ( is_admin() ) {
712 // Hide schema and table name on front-end
713 ?>
714 <input type="hidden" name="wpdaschema_name" value="<?php
715 echo esc_attr( $this->schema_name );
716 ?>">
717 <input type="hidden" name="table_name" value="<?php
718 echo esc_attr( $this->table_name );
719 ?>">
720 <?php
721 }
722 ?>
723 <input type="hidden" name="action" value="new">
724 <button type="submit" class="page-title-action wpda_tooltip"
725 title="<?php
726 echo esc_attr( $title );
727 ?>"
728 >
729 <i class="fas fa-plus-circle wpda_icon_on_button"></i>
730 <?php
731 echo __( 'Add New', 'wp-data-access' );
732 ?>
733 </button>
734 </div>
735 </form>
736 <?php
737 }
738 }
739 }
740 ?>
741 </h1>
742 <div class="wpda_subtitle"><strong><?php
743 echo wp_kses( $this->subtitle, array(
744 'span' => array(
745 'class' => array(),
746 ),
747 ) );
748 ?></strong>
749 </div>
750 <?php
751 // Add custom code before the data entry form
752 do_action_ref_array( 'wpda_before_simple_form', array($this) );
753 ?>
754 <p></p>
755 <?php
756 }
757 ?>
758 <form id="<?php
759 echo esc_attr( $this->current_form_id );
760 ?>"
761 method="post" enctype="multipart/form-data"
762 action="<?php
763 echo esc_attr( $url );
764 ?>">
765 <div>
766 <?php
767 $js_code = '';
768 // All column JS code will be stored here and added to the end of the form.
769 foreach ( $this->fieldsets as $fieldset_title => $fieldset ) {
770 if ( isset( $fieldset['id'] ) && '' !== trim( $fieldset['id'] ) ) {
771 $id = trim( $fieldset['id'] );
772 } else {
773 $id = '';
774 }
775 $expandable = ( isset( $fieldset['expandable'] ) && true === $fieldset['expandable'] ? true : false );
776 $expandable_state = ( isset( $_REQUEST["wpda_fieldset_expand_{$id}"] ) ? sanitize_text_field( $_REQUEST["wpda_fieldset_expand_{$id}"] ) : 'off' );
777 $expandable_icons = ( 'on' === $expandable_state ? 'minus-circle' : 'plus-circle' );
778 ?>
779 <fieldset class="wpda_fieldset">
780 <?php
781 if ( '' !== $fieldset_title ) {
782 ?>
783 <legend <?php
784 echo ( '' === $id ? '' : 'id="' . esc_attr( $id ) . '"' );
785 ?>>
786 <?php
787 if ( $expandable && '' !== $id ) {
788 echo '<div class="wpda-fieldset-expand" onclick="expandFieldset(\'' . esc_attr( $id ) . '\')">' . '<i id="wpda_field_expand_' . esc_attr( $id ) . '" class="wpda-fieldset-expand fas fa-' . esc_attr( $expandable_icons ) . '"></i> ' . '<span class="wpda-fieldset-expand">' . esc_html( $fieldset_title ) . '</span>' . '<input type="hidden" id="wpda_fieldset_expand_' . esc_attr( $id ) . '" name="wpda_fieldset_expand_' . esc_attr( $id ) . '" value="' . esc_attr( $expandable_state ) . '" />' . '</div>';
789 } else {
790 echo esc_html( $fieldset_title );
791 }
792 ?>
793 </legend>
794 <?php
795 }
796 ?>
797 <table id="wpda_table_expand_<?php
798 echo esc_attr( $id );
799 ?>"
800 class="wpda_simple_table <?php
801 echo esc_attr( $this->table_name );
802 ?>"
803 <?php
804 echo ( $expandable && 'off' === $expandable_state ? 'style="display: none"' : '' );
805 ?>
806 cellspacing="0"
807 cellpadding="0"
808 >
809 <?php
810 $fieldset_columns = array_flip( $fieldset['fields'] );
811 //phpcs:ignore - 8.1 proof
812 foreach ( $this->form_items as $item ) {
813 if ( isset( $fieldset_columns[$item->get_item_name()] ) ) {
814 $item->show( $this->action, $this->update_keys_allowed );
815 $js_code .= $item->get_item_js();
816 // Add column specific JS code.
817 }
818 }
819 ?>
820 </table>
821 </fieldset>
822 <?php
823 }
824 ?>
825 </div>
826 <div><?php
827 $this->add_form_logic();
828 ?></div>
829 <?php
830 // Add custom code after the data entry form
831 do_action_ref_array( 'wpda_after_simple_form', array($this) );
832 ?>
833 <p></p>
834 <?php
835 if ( is_admin() ) {
836 // Hide schema and table name on front-end
837 ?>
838 <input type="hidden" name="wpdaschema_name" value="<?php
839 echo esc_attr( $this->schema_name );
840 ?>">
841 <input type="hidden" name="table_name" value="<?php
842 echo esc_attr( $this->table_name );
843 ?>">
844 <?php
845 }
846 ?>
847 <input type="hidden" name="action" value="<?php
848 echo esc_attr( $this->action );
849 ?>"/>
850 <input type="hidden" name="action2" value="save"/>
851 <input type="hidden" name="wpda_message" value=""/>
852 <?php
853 if ( 'view' !== $this->action ) {
854 ?>
855 <input type="hidden" name="postaction" id="postaction" value=""/>
856 <?php
857 }
858 ?>
859 <?php
860 $this->add_parent_args();
861 echo $this->page_number_item;
862 // phpcs:ignore WordPress.Security.EscapeOutput
863 echo $this->add_case_sensitive_search();
864 wp_nonce_field( $this->get_nonce_action( false ), '_wpnonce', false );
865 ?>
866 <?php
867 if ( 'view' !== $this->action ) {
868 ?>
869 <button type="submit"
870 class="button button-primary"
871 name="submit_button"
872 onclick="return submit_form(event)">
873 <i class="fas fa-check wpda_icon_on_button"></i>
874 <?php
875 echo __( 'Submit', 'wp-data-access' );
876 ?>
877 </button>
878 <?php
879 if ( $this->show_back_button && $this->show_back_icon ) {
880 ?>
881 <button type="submit"
882 class="button button-secondary"
883 name="submit_button"
884 onclick="return submit_form(event)">
885 <i class="fas fa-check wpda_icon_on_button"></i>
886 <?php
887 echo __( 'Submit', 'wp-data-access' );
888 ?>
889 <i class="fas fa-angle-right wpda_icon_on_button"></i>
890 <?php
891 echo esc_attr( $this->back_to_list_text );
892 ?>
893 </button>
894 <?php
895 }
896 if ( $this->show_back_button ) {
897 ?>
898 <button type="button"
899 onclick="jQuery('#<?php
900 echo esc_attr( $this->current_form_id );
901 ?>_backbutton').submit();"
902 class="button button-secondary">
903 <i class="fas fa-angle-left wpda_icon_on_button"></i>
904 <?php
905 echo esc_attr( $this->back_to_list_text );
906 ?>
907 </button>
908 <?php
909 }
910 ?>
911 <span style="float:right;"><?php
912 $this->add_buttons();
913 ?></span>
914 <?php
915 }
916 ?>
917 <?php
918 if ( 'view' === $this->action ) {
919 ?>
920 <button type="button"
921 onclick="jQuery('#<?php
922 echo esc_attr( $this->current_form_id );
923 ?>_backbutton').submit()"
924 class="button button-secondary">
925 <i class="fas fa-angle-left wpda_icon_on_button"></i>
926 <?php
927 echo esc_attr( $this->back_to_list_text );
928 ?>
929 </button>
930 <?php
931 }
932 ?>
933 </form>
934 <form id="<?php
935 echo esc_attr( $this->current_form_id );
936 ?>_backbutton"
937 method="post" style="display:none"
938 action="<?php
939 echo esc_attr( $url_back );
940 ?>">
941 <?php
942 $this->add_parent_args();
943 echo $this->page_number_item;
944 // phpcs:ignore WordPress.Security.EscapeOutput
945 echo $this->add_case_sensitive_search();
946 ?>
947 <?php
948 if ( is_admin() ) {
949 // Hide schema and table name on front-end
950 ?>
951 <input type="hidden" name="wpdaschema_name" value="<?php
952 echo esc_attr( $this->schema_name );
953 ?>">
954 <input type="hidden" name="table_name" value="<?php
955 echo esc_attr( $this->table_name );
956 ?>">
957 <?php
958 }
959 ?>
960 <input type="hidden" name="action" value="list">
961 </form>
962 </div>
963
964 <script type='text/javascript'>
965 <?php
966 if ( 'view' !== $this->action ) {
967 ?>
968 function submit_form(e) {
969 if (typeof pre_submit_form === "function") {
970 // Perform pre submit
971 pre_submit = pre_submit_form();
972 if (!pre_submit) {
973 return false;
974 }
975 }
976 if (
977 jQuery(e.target).hasClass("button-secondary") ||
978 jQuery(e.target).parent().hasClass("button-secondary")
979 ) {
980 <?php
981 if ( 'child_page_number' === $this->page_number_item_name ) {
982 ?>
983 jQuery("#postaction").val("childlist");
984 <?php
985 } else {
986 ?>
987 jQuery("#postaction").val("list");
988 <?php
989 }
990 ?>
991 } else {
992 jQuery("#postaction").val("");
993 }
994 var failed = false;
995 jQuery('.wpda_not_null').each(function(i, obj) {
996 if (jQuery(obj).val() === '') {
997 objData = jQuery(obj).data();
998 if (objData.dbIsNull===undefined || objData.dbIsNull!==false) {
999 alert(<?php
1000 echo __( '\'Item\'', 'wp-data-access' );
1001 ?> +' ' + jQuery(obj).attr('name') + ' ' + <?php
1002 echo __( '\'must be entered\'', 'wp-data-access' );
1003 ?>);
1004 failed = true;
1005 } else {
1006 element_old = jQuery("input[name=" + jQuery(obj).attr("name") + "_old" + "]");
1007 if (element_old && element_old.val()!=='') {
1008 alert(<?php
1009 echo __( '\'Item\'', 'wp-data-access' );
1010 ?> +' ' + jQuery(obj).attr('name') + ' ' + <?php
1011 echo __( '\'must be entered\'', 'wp-data-access' );
1012 ?>);
1013 failed = true;
1014 }
1015 }
1016 }
1017 });
1018 jQuery('.wpda_input_error').each(function(i, obj) {
1019 alert(<?php
1020 echo __( '\'Column\'', 'wp-data-access' );
1021 ?> +' ' + jQuery(obj).attr('name') + <?php
1022 echo __( '\': max size exceeded\'', 'wp-data-access' );
1023 ?>);
1024 failed = true;
1025 });
1026 jQuery('.wpda_hyperlink').each(function(i, obj) {
1027 hyperlink_name = jQuery(obj).attr('name');
1028 hyperlink_label = jQuery('#' + hyperlink_name + '_label').val();
1029 hyperlink_url = jQuery('#' + hyperlink_name + '_url').val();
1030 hyperlink_target = jQuery('#' + hyperlink_name + '_target').is(':checked') ? '_blank' : '';
1031 hyperlink_update = {
1032 "label" : hyperlink_label,
1033 "url" : hyperlink_url,
1034 "target" : hyperlink_target
1035 };
1036 jQuery(obj).val(JSON.stringify(hyperlink_update));
1037 });
1038 return !failed;
1039 }
1040 <?php
1041 }
1042 ?>
1043 jQuery(function () {
1044 <?php
1045 if ( 'view' === $this->action ) {
1046 ?>
1047 jQuery("#<?php
1048 echo esc_attr( $this->current_form_id );
1049 ?> input").not(':button').prop("readonly", true);
1050 jQuery("#<?php
1051 echo esc_attr( $this->current_form_id );
1052 ?> textarea").prop("readonly", true);
1053 jQuery("#<?php
1054 echo esc_attr( $this->current_form_id );
1055 ?> select").prop("disabled", true);
1056 <?php
1057 }
1058 ?>
1059 <?php
1060 if ( !$this->update_keys_allowed && 'new' !== $this->action ) {
1061 ?>
1062 jQuery("#<?php
1063 echo esc_attr( $this->current_form_id );
1064 ?> input.wpda_primary_key").prop("readonly", true);
1065 jQuery("#<?php
1066 echo esc_attr( $this->current_form_id );
1067 ?> select.wpda_primary_key").prop("disabled", true);
1068 <?php
1069 }
1070 ?>
1071 <?php
1072 if ( 'new' === $this->action ) {
1073 ?>
1074 jQuery("#<?php
1075 echo esc_attr( $this->current_form_id );
1076 ?> input.auto_increment").prop("readonly", true);
1077 <?php
1078 }
1079 ?>
1080 jQuery("#<?php
1081 echo esc_attr( $this->current_form_id );
1082 ?> input.wpda_readonly").prop("readonly", true);
1083 jQuery('.wpda_data_type_number').on('keyup paste', function () {
1084 numberFormat = jQuery(this).data('numberFormat').split(",");
1085 this.value = this.value.replace(/[^\d\-]/g, ''); // Allow only 0-9
1086 if (isNaN(this.value) || (numberFormat[0]!='' && this.value.length>numberFormat[0])) {
1087 jQuery(this).addClass('wpda_input_error');
1088 if (this.value.length>numberFormat[0]) {
1089 jQuery.notify('<?php
1090 echo __( 'Max size exceeded' );
1091 ?>','error');
1092 }
1093 } else {
1094 jQuery(this).removeClass('wpda_input_error');
1095 }
1096 });
1097 jQuery('.wpda_data_type_float').on('keyup paste', function () {
1098 numberFormat = jQuery(this).data('numberFormat').split(",");
1099 maxNumber = Math.pow(10, numberFormat[0] - numberFormat[1]);
1100 this.value = this.value.replace(/[^\d\-\.\,]/g, ''); // Allow only 0-9 . ,
1101 if (isNaN(this.value) || this.value>=maxNumber) {
1102 jQuery(this).addClass('wpda_input_error');
1103 if (this.value>=maxNumber) {
1104 jQuery.notify('<?php
1105 echo __( 'Max size exceeded' );
1106 ?>','error');
1107 }
1108 } else {
1109 jQuery(this).removeClass('wpda_input_error');
1110 }
1111 currentNumber = this.value.split(".");
1112 if (currentNumber.length===1) {
1113 currentNumber = this.value.split(",");
1114 }
1115 if (currentNumber.length===2 && currentNumber[1].length>numberFormat[1]) {
1116 jQuery(this).addClass('wpda_input_error');
1117 jQuery.notify('<?php
1118 echo __( 'Max size exceeded' );
1119 ?>','error');
1120 }
1121 });
1122 jQuery( '.wpda_tooltip' ).tooltip();
1123 // Add toolbar icons
1124 jQuery("#wpda_toolbar_icon_add_row").on("click", function() {
1125 jQuery("#wpda_new_row_table_name").val("<?php
1126 echo esc_attr( $this->table_name );
1127 ?>");
1128 jQuery("#wpda_new_row").submit();
1129 });
1130 });
1131 <?php
1132 echo $js_code;
1133 // phpcs:ignore WordPress.Security.EscapeOutput
1134 ?>
1135 </script>
1136 <?php
1137 }
1138
1139 private function add_case_sensitive_search() {
1140 if ( isset( $_REQUEST['wpda_c'] ) && 'true' === $_REQUEST['wpda_c'] ) {
1141 return '<input type="hidden" name="wpda_c" value="true">';
1142 } else {
1143 return '';
1144 }
1145 }
1146
1147 /**
1148 * Overwrite to add logic to form
1149 *
1150 * @since 2.0.15
1151 */
1152 public function add_form_logic() {
1153 }
1154
1155 /**
1156 * Overwrite to add buttons to right bottom
1157 *
1158 * @since 2.0.15
1159 */
1160 public function add_buttons() {
1161 }
1162
1163 /**
1164 * Creates a wpnonce action
1165 *
1166 * Set wp_nonce action for security check:
1167 * prefix + table name + primary key values
1168 *
1169 * @param boolean $use_old_value TRUE = use old key values, FALSE = use new key values.
1170 *
1171 * @return string wp_nonce action holding: prefix + table name + primary key values.
1172 * @since 1.0.0
1173 */
1174 public function get_nonce_action( $use_old_value = true ) {
1175 // Add prefix + table name to wp_nonce action.
1176 $wp_nonce_action = "wpda-simple-form-{$this->table_name}";
1177 if ( $this->wpda_list_columns->get_table_alternative_keys() ) {
1178 $wp_nonce_action .= '-*';
1179 } else {
1180 foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
1181 // Add primary key value to wp_nonce action.
1182 if ( 'new' === $this->action ) {
1183 // New records have no key values on form startup.
1184 $wp_nonce_action .= '-?';
1185 } else {
1186 // Add primary key value to wp_nonce action.
1187 if ( 'save' === $this->action2 && $use_old_value ) {
1188 // Use old value (in cases where primary key update is allowed).
1189 $wp_nonce_action .= ( isset( $_REQUEST[$pk_column . '_old'] ) ? '-' . sanitize_text_field( wp_unslash( $_REQUEST[$pk_column . '_old'] ) ) : '-?' );
1190 // input var okay.
1191 } else {
1192 if ( isset( $_REQUEST[$pk_column] ) && '' !== sanitize_text_field( wp_unslash( $_REQUEST[$pk_column] ) ) ) {
1193 // input var okay.
1194 // Use new value.
1195 $wp_nonce_action .= '-' . sanitize_text_field( wp_unslash( $_REQUEST[$pk_column] ) );
1196 // input var okay.
1197 } elseif ( -1 !== $this->auto_increment_value ) {
1198 // Use auto increment value (updated wp_nonce action after insert).
1199 $wp_nonce_action .= '-' . $this->auto_increment_value;
1200 } else {
1201 // No value found, let security check handle wrong wp_nonce action.
1202 $wp_nonce_action .= '-?';
1203 }
1204 }
1205 }
1206 }
1207 }
1208 return str_replace( ' ', '_', $wp_nonce_action );
1209 }
1210
1211 /**
1212 * Perform validation check
1213 *
1214 * Called to perform default validation before insert and update.
1215 *
1216 * Extend class WPDA_Simple_Form and override this method if you need validation on insert and/or update or
1217 * if you prefer to change error messages. If you want to handle inserts and updates differently, the
1218 * following information might be helpful:
1219 * + on insert: $this->action = 'new'
1220 * + on update: $this->action = 'edit'
1221 *
1222 * Use set_message to show messages (info as well as error).
1223 *
1224 * @param boolean $pre_insert Do not check auto_increment during pre-insert
1225 *
1226 * @return boolean TRUE = validation succeeded, FALSE = validation failed.
1227 * @since 1.0.0
1228 */
1229 protected function validate( $pre_insert = false ) {
1230 foreach ( $this->form_items as $item ) {
1231 if ( !$item->is_valid( $pre_insert ) ) {
1232 return false;
1233 }
1234 }
1235 return true;
1236 }
1237
1238 /**
1239 * Get current from database table
1240 *
1241 * Handle insert, update and save differently.
1242 *
1243 * @since 1.0.0
1244 */
1245 protected function prepare_row() {
1246 if ( 'edit' === $this->action || 'view' === $this->action || 'save' === $this->action2 ) {
1247 // Get record by primary key, use auto_increment for new records.
1248 $this->row = $this->row_data->get_row( $this->auto_increment_value, $this->wpda_err );
1249 } else {
1250 // There's no record yet.
1251 $this->row = $this->row_data->new_row();
1252 }
1253 }
1254
1255 /**
1256 * Set item attributes
1257 *
1258 * If you want to change the layout of your simple form(s), consider to extend class WPDA_Simple_Form and
1259 * override this method.
1260 *
1261 * @param boolean $set_back_form_values TRUE = set back user entered value, FALSE = set to database value.
1262 *
1263 * @since 1.0.0
1264 */
1265 protected function prepare_items( $set_back_form_values = false ) {
1266 $count_cols = count( $this->table_columns );
1267 //phpcs:ignore - 8.1 proof
1268 for ($i = 0; $i < $count_cols; $i++) {
1269 $column_name = $this->table_columns[$i]['column_name'];
1270 $item_enum = '';
1271 if ( 'enum' === $this->table_columns[$i]['data_type'] || 'set' === $this->table_columns[$i]['data_type'] ) {
1272 $item_enum = $this->table_columns[$i]['column_type'];
1273 }
1274 if ( $set_back_form_values ) {
1275 // Set value to what user entered.
1276 $item_value = $this->get_new_value( $column_name );
1277 } else {
1278 // Get value from database.
1279 $item_value = ( isset( $this->row ) ? $this->row[0][$column_name] : null );
1280 }
1281 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item';
1282 $check_data_type = WPDA::get_type( $this->table_columns[$i]['data_type'] );
1283 if ( 'enum' === $this->table_columns[$i]['data_type'] ) {
1284 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Enum';
1285 } elseif ( 'set' === $this->table_columns[$i]['data_type'] ) {
1286 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Set';
1287 } elseif ( 'date' === $check_data_type || 'time' === $check_data_type ) {
1288 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_DateTime';
1289 // Always initially use database data and time format
1290 $item_value = ( isset( $this->row ) ? $this->row[0][$column_name] : null );
1291 } elseif ( 'tinytext' === $this->table_columns[$i]['data_type'] || 'text' === $this->table_columns[$i]['data_type'] || 'mediumtext' === $this->table_columns[$i]['data_type'] || 'longtext' === $this->table_columns[$i]['data_type'] ) {
1292 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Textarea';
1293 } elseif ( 'tinyint(1)' === $this->table_columns[$i]['column_type'] ) {
1294 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Boolean';
1295 }
1296 // Media support only available to logged-in users
1297 if ( 0 < WPDA::get_current_user_id() ) {
1298 $media_type = WPDA_Media_Model::get_column_media( $this->table_name, $column_name, $this->schema_name );
1299 if ( 'Image' === $media_type ) {
1300 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Image';
1301 } elseif ( 'Attachment' === $media_type ) {
1302 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Media';
1303 } elseif ( 'Hyperlink' === $media_type ) {
1304 if ( !(isset( $this->wpda_table_settings->table_settings->hyperlink_definition ) && 'text' === $this->wpda_table_settings->table_settings->hyperlink_definition) ) {
1305 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Hyperlink';
1306 }
1307 } elseif ( 'Audio' === $media_type ) {
1308 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Audio';
1309 } elseif ( 'Video' === $media_type ) {
1310 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Video';
1311 } elseif ( 'File' === $media_type ) {
1312 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_File';
1313 }
1314 }
1315 $item_label = '';
1316 if ( isset( $this->column_headers[$column_name] ) ) {
1317 $item_label = $this->column_headers[$column_name];
1318 } elseif ( isset( $this->table_column_headers[$column_name] ) ) {
1319 $item_label = $this->table_column_headers[$column_name];
1320 }
1321 $item = new $wpda_simple_form_item_class(array(
1322 'item_name' => $column_name,
1323 'data_type' => $this->table_columns[$i]['data_type'],
1324 'item_label' => $item_label,
1325 'item_value' => $item_value,
1326 'item_default_value' => $this->table_columns[$i]['column_default'],
1327 'item_extra' => $this->table_columns[$i]['extra'],
1328 'item_enum' => $item_enum,
1329 'column_type' => $this->table_columns[$i]['column_type'],
1330 'is_nullable' => $this->table_columns[$i]['is_nullable'],
1331 'user_update' => $set_back_form_values,
1332 'character_maximum_length' => $this->table_columns[$i]['character_maximum_length'],
1333 'numeric_precision' => $this->table_columns[$i]['numeric_precision'],
1334 'numeric_scale' => ( null === $this->table_columns[$i]['numeric_scale'] ? 0 : $this->table_columns[$i]['numeric_scale'] ),
1335 ));
1336 $item->set_is_key_column( $this->is_key_column( $column_name ) );
1337 $this->add_form_item( $i, $item );
1338 }
1339 // Add dynamic hyperlinks (if applicable)
1340 if ( isset( $this->wpda_table_settings->hyperlinks ) ) {
1341 foreach ( $this->wpda_table_settings->hyperlinks as $hyperlink ) {
1342 $hyperlink_label = ( isset( $hyperlink->hyperlink_label ) ? $hyperlink->hyperlink_label : '' );
1343 $hyperlink_form = ( isset( $hyperlink->hyperlink_form ) ? $hyperlink->hyperlink_form : false );
1344 $hyperlink_html = ( isset( $hyperlink->hyperlink_html ) ? $hyperlink->hyperlink_html : '' );
1345 if ( true === $hyperlink_form && $hyperlink_label !== '' && $hyperlink_html !== '' ) {
1346 $hyperlink_target = ( isset( $hyperlink->hyperlink_form ) ? $hyperlink->hyperlink_target : false );
1347 foreach ( $this->form_items as $item ) {
1348 $item_name = $item->get_item_name();
1349 $item_value = $item->get_item_value();
1350 $hyperlink_html = str_replace( "\$\${$item_name}\$\$", $item_value, $hyperlink_html );
1351 }
1352 $item = new WPDA_Simple_Form_Item_Dynamic_Hyperlink(array(
1353 'item_name' => $hyperlink_label,
1354 'data_type' => 'varchar2',
1355 'hyperlink_label' => $hyperlink_label,
1356 'hyperlink_target' => $hyperlink_target,
1357 'hyperlink_html' => $hyperlink_html,
1358 ));
1359 $this->add_form_item( $i++, $item );
1360 }
1361 }
1362 }
1363 }
1364
1365 /**
1366 * Get new value for item
1367 *
1368 * Or empty if no new value available.
1369 *
1370 * @param string $column_name Column name.
1371 *
1372 * @return mixed|string New value for column or empty.
1373 * @since 1.0.0
1374 */
1375 public function get_new_value( $column_name ) {
1376 return ( isset( $this->form_items_new_values[$column_name] ) ? $this->form_items_new_values[$column_name] : null );
1377 }
1378
1379 /**
1380 * Add item to form
1381 *
1382 * @param int $index Item sequence number.
1383 * @param WPDA_Simple_Form_Item $item Reference to simple form item.
1384 *
1385 * @since 1.0.0
1386 *
1387 * @see WPDA_Simple_Form_Item
1388 */
1389 protected function add_form_item( $index, $item ) {
1390 // Add item to form
1391 $this->form_items[$index] = $item;
1392 // Add position to named array for quick access of single items
1393 $item_name = $item->get_item_name();
1394 $this->form_items_named[$item_name] = $index;
1395 }
1396
1397 /**
1398 * Get item position
1399 *
1400 * @param string $item_name Form item name
1401 *
1402 * @return bool|int Position item or false if not found
1403 *
1404 * @since 2.0.15
1405 */
1406 protected function get_item_index( $item_name ) {
1407 if ( isset( $this->form_items_named[$item_name] ) ) {
1408 return $this->form_items_named[$item_name];
1409 } else {
1410 return false;
1411 }
1412 }
1413
1414 /**
1415 * Get old value form item
1416 *
1417 * Or empty if no old value available.
1418 *
1419 * @param string $column_name Column name.
1420 *
1421 * @return mixed|string Old value for column or empty.
1422 * @since 1.0.0
1423 */
1424 public function get_old_value( $column_name ) {
1425 return ( isset( $this->form_items_old_values[$column_name] ) ? $this->form_items_old_values[$column_name] : null );
1426 }
1427
1428 public function revert_column_value( $column_name ) {
1429 @($this->form_items_new_values[$column_name] = $this->form_items_old_values[$column_name]);
1430 }
1431
1432 public function insert_column_default( $column_name, $item_default_value ) {
1433 if ( isset( $this->form_items_old_values ) ) {
1434 @($this->form_items_new_values[$column_name] = $item_default_value);
1435 }
1436 }
1437
1438 /**
1439 * Is column part of primary key?
1440 *
1441 * @param string $column_name Column name.
1442 *
1443 * @return bool TRUE = column is part of primary key, FALSE = column is not part of primary key.
1444 * @since 1.0.0
1445 */
1446 protected function is_key_column( $column_name ) {
1447 foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
1448 if ( $column_name === $pk_column ) {
1449 return true;
1450 }
1451 }
1452 return false;
1453 }
1454
1455 /**
1456 * Get primary form action
1457 *
1458 * @return string Primary page action
1459 * @since 1.0.0
1460 */
1461 public function get_form_action() {
1462 return $this->action;
1463 }
1464
1465 /**
1466 * Get secondary form action
1467 *
1468 * @return string Secondary page action
1469 * @since 1.0.0
1470 */
1471 public function get_form_action2() {
1472 return $this->action2;
1473 }
1474
1475 /**
1476 * Defines whether primary key item can be updated
1477 *
1478 * @param boolean $update_keys_allowed Allow keys to be updated.
1479 *
1480 * @since 1.0.0
1481 */
1482 protected function set_update_keys( $update_keys_allowed ) {
1483 $this->update_keys_allowed = $update_keys_allowed;
1484 }
1485
1486 /**
1487 * Reorder columns
1488 *
1489 * Reorders the column array in the order as defined in argument $columns_ordered.
1490 *
1491 * @param array $columns_ordered Ordered column names.
1492 *
1493 * @since 1.0.0
1494 */
1495 protected function order_and_filter_columns( $columns_ordered ) {
1496 $column_array_ordered = array();
1497 $i = 0;
1498 foreach ( $columns_ordered as $key => $value ) {
1499 $column_array_ordered[$i++] = $this->table_columns[$this->get_column_position( $this->table_columns, $value )];
1500 }
1501 $this->table_columns = $column_array_ordered;
1502 }
1503
1504 /**
1505 * Get column position in column array
1506 *
1507 * @param array $column_array Column array.
1508 * @param string $column_name Column name.
1509 *
1510 * @return int Position of $column_name in $column_array
1511 * @since 1.0.0
1512 */
1513 protected function get_column_position( $column_array, $column_name ) {
1514 if ( !is_array( $column_array ) ) {
1515 return -1;
1516 }
1517 $count_cols = count( $column_array );
1518 //phpcs:ignore - 8.1 proof
1519 for ($i = 0; $i < $count_cols; $i++) {
1520 if ( $column_array[$i]['column_name'] === $column_name ) {
1521 return $i;
1522 }
1523 }
1524 return -1;
1525 }
1526
1527 /**
1528 * Add dummy column to form
1529 *
1530 * @param string $column_name Column name.
1531 *
1532 * @since 1.0.0
1533 */
1534 protected function add_dummy_column( $column_name ) {
1535 $this->table_columns[] = array(
1536 'column_name' => $column_name,
1537 'data_type' => 'varchar',
1538 'extra' => '',
1539 'column_type' => '',
1540 'is_nullable' => 'YES',
1541 'column_default' => '',
1542 );
1543 }
1544
1545 /**
1546 * Set message number and text
1547 *
1548 * Assigns values to $this->wpda_err and $this->wpda_msg.
1549 *
1550 * @param string $wpda_err '0' = INFO, '1' = ERROR.
1551 * @param string $wpda_msg Message to be displayed.
1552 *
1553 * @since 1.0.0
1554 */
1555 protected function set_message( $wpda_err, $wpda_msg ) {
1556 // Wrong values will be handled by message box class.
1557 $this->wpda_err = $wpda_err;
1558 $this->wpda_msg = $wpda_msg;
1559 }
1560
1561 /**
1562 * Use this method to build parent child relationships.
1563 *
1564 * Overwrite this function if you want to use the form as a child form related to some parent
1565 * form. You can add parent arguments to calls to make sure you get back to the right parent.
1566 *
1567 * @since 1.5.0
1568 */
1569 protected function add_parent_args() {
1570 }
1571
1572 /**
1573 * Use this method to build parent child relationships.
1574 *
1575 * Overwrite this function if you want to use the form as a child form related to some parent
1576 * form. You can add parent arguments to calls to make sure you get back to the right parent.
1577 *
1578 * @since 1.6.9
1579 */
1580 protected function add_parent_args_to_back_button() {
1581 }
1582
1583 /**
1584 * Set item labels
1585 *
1586 * @param array $item_labels Named array containing item name/label pairs
1587 *
1588 * @since 2.0.15
1589 */
1590 public function set_labels( $item_labels ) {
1591 if ( is_array( $item_labels ) ) {
1592 foreach ( $item_labels as $key => $label ) {
1593 foreach ( $this->form_items as $form_item ) {
1594 if ( $form_item->get_item_name() === $key ) {
1595 $form_item->set_label( $label );
1596 }
1597 }
1598 }
1599 }
1600 }
1601
1602 /**
1603 * Hide items
1604 *
1605 * @param array $items_to_hide Array contains item names of items to be defined as hidden
1606 *
1607 * @since 2.0.15
1608 */
1609 public function hide_items( $items_to_hide ) {
1610 if ( is_array( $items_to_hide ) ) {
1611 foreach ( $items_to_hide as $column_name ) {
1612 foreach ( $this->form_items as $form_item ) {
1613 if ( $form_item->get_item_name() === $column_name ) {
1614 $form_item->set_hide_item_init( true );
1615 }
1616 }
1617 }
1618 }
1619 }
1620
1621 /**
1622 * Number of items
1623 *
1624 * @return int
1625 *
1626 * @since 2.0.15
1627 */
1628 public function count() {
1629 return count( (array) $this->form_items );
1630 }
1631
1632 public function get_row() {
1633 return $this->row;
1634 }
1635
1636 }
1637