PluginProbe
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards / 5.5.83
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards v5.5.83
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 / 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.83, at WPDataAccess/Simple_Form/WPDA_Simple_Form.php

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