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

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

1,648 lines 58.2 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 global $wpda_project_mode;
546 if ( 'on' !== WPDA::get_option( WPDA::OPTION_BE_ALLOW_INSERT ) || isset( $wpda_project_mode['allow_insert'] ) && ('off' === $wpda_project_mode['allow_insert'] || 'only' === $wpda_project_mode['allow_insert']) ) {
547 wp_die( esc_attr__( 'ERROR: Not authorized', 'wp-data-access' ) );
548 }
549 // Prepare row and items for validation
550 $this->row = $this->row_data->new_row();
551 $this->prepare_items( true );
552 // Save new record.
553 if ( !$this->validate( true ) ) {
554 $set_back_form_values = true;
555 } else {
556 // Insert record.
557 $add_row_result = $this->row_data->add_row();
558 if ( $add_row_result ) {
559 // Insert succeeded:
560 // (1) save auto_increment value (if applicable)
561 // (2) change action to edit
562 if ( is_numeric( $add_row_result ) ) {
563 // save auto_increment value (1).
564 $this->auto_increment_value = $add_row_result;
565 }
566 // change action to edit (2).
567 $this->action = 'edit';
568 $this->prepare_row();
569 } else {
570 // Insert failed:
571 // (1) set back form items
572 $set_back_form_values = true;
573 }
574 }
575 } else {
576 global $wpda_project_mode;
577 if ( 'on' !== WPDA::get_option( WPDA::OPTION_BE_ALLOW_UPDATE ) && (isset( $wpda_project_mode['mode'] ) && 'edit' === $wpda_project_mode['mode']) ) {
578 wp_die( esc_attr__( 'ERROR: Not authorized', 'wp-data-access' ) );
579 }
580 // Prepare row and items for validation
581 $this->row = $this->row_data->get_row( $this->auto_increment_value, $this->wpda_err );
582 $this->prepare_items( true );
583 // Update existing record.
584 if ( $this->validate() ) {
585 // Update record.
586 $this->row_data->set_row();
587 // Get values updated from database triggers
588 $this->row = $this->row_data->get_row( $this->auto_increment_value, $this->wpda_err );
589 foreach ( $this->form_items_new_values as $key => $value ) {
590 if ( isset( $this->row[0][$key] ) ) {
591 $this->form_items_new_values[$key] = $this->row[0][$key];
592 }
593 }
594 }
595 $this->prepare_row();
596 $set_back_form_values = true;
597 }
598 } else {
599 $this->prepare_row();
600 }
601 $this->prepare_items( $set_back_form_values );
602 if ( '1' === $this->wpda_err && $this->update_keys_allowed && 'edit' === $this->action && 'save' === $this->action2 ) {
603 $keys_have_changed = false;
604 // There was an error! If key updates are allowed, we might have needed to set back the keys to their
605 // original values. We'll inform the user with a message box.
606 foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
607 if ( $this->get_old_value( $pk_column ) !== $this->get_new_value( $pk_column ) ) {
608 $keys_have_changed = true;
609 break;
610 }
611 }
612 if ( $keys_have_changed ) {
613 $msg = new WPDA_Message_Box(array(
614 'message_text' => __( 'Key columns have been reversed to their original values', 'wp-data-access' ),
615 ));
616 $msg->box();
617 }
618 }
619 if ( null === $this->title ) {
620 if ( 'new' === $this->action ) {
621 $action_in_title = __( 'Add new row to', 'wp-data-access' );
622 } else {
623 $action_in_title = ucfirst( $this->action );
624 }
625 $this->title = $action_in_title . ' ' . __( 'table', 'wp-data-access' ) . ' ' . strtoupper( $this->table_name );
626 } else {
627 if ( 'new' === $this->action ) {
628 $title_action = 'Add New ';
629 } else {
630 $title_action = ucfirst( $this->action );
631 }
632 if ( $this->add_action_to_title ) {
633 $this->title = $title_action . ' ' . $this->title;
634 }
635 }
636 if ( is_admin() && ($this->page === \WP_Data_Access_Admin::PAGE_MAIN || substr( $this->page, 0, 13 ) === \WP_Data_Access_Admin::PAGE_EXPLORER) ) {
637 $this->fieldset_title = $this->title;
638 $this->title = 'Data Explorer';
639 }
640 }
641
642 /**
643 * Overwrite to group items into fieldsets
644 */
645 protected function add_fieldsets() {
646 $fields = array();
647 foreach ( $this->form_items as $item ) {
648 $fields[] = $item->get_item_name();
649 }
650 // Add just one default fieldset which contains all fields
651 $this->fieldsets[$this->fieldset_title] = array(
652 'id' => '',
653 'fields' => $fields,
654 );
655 }
656
657 /**
658 * Show simple form
659 *
660 * Performs the following steps:
661 * + Shows simple form for requested table (HTML and Javascript)
662 *
663 * @param boolean $allow_save Allow to save data
664 * @param string $add_param Parameter to be added to form action.
665 *
666 * @since 1.0.0
667 */
668 public function show( $allow_save = true, $add_param = '' ) {
669 $this->add_fieldsets();
670 // Prepare url
671 if ( is_admin() ) {
672 $url = "?page={$this->page}";
673 } else {
674 $url = '';
675 }
676 $url_back = $url;
677 $url .= $add_param;
678 ?>
679 <div class="wrap">
680 <?php
681 if ( $this->show_title ) {
682 ?>
683 <h1 class="wp-heading-inline">
684 <?php
685 if ( is_admin() && $this->show_back_icon ) {
686 ?>
687 <a
688 href="javascript:void(0)"
689 onclick="jQuery('#<?php
690 echo esc_attr( $this->current_form_id );
691 ?>_backbutton').submit()"
692 class="dashicons dashicons-arrow-left-alt2 wpda_tooltip"
693 title="<?php
694 echo esc_attr( $this->back_to_list_text );
695 ?>"
696 ></a>
697 <?php
698 }
699 ?>
700 <?php
701 echo esc_attr( $this->title );
702 ?>
703 <?php
704 if ( substr( $this->page, 0, 13 ) === \WP_Data_Access_Admin::PAGE_EXPLORER || !is_admin() ) {
705 // Button is available on web pages only
706 if ( 'view' !== $this->action && !$this->hide_add_new ) {
707 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 ) {
708 $title = __( 'Add new row to table', 'wp-data-access' );
709 ?>
710 <form
711 method="post"
712 action="<?php
713 echo esc_attr( $url );
714 ?>"
715 style="display: inline-block; vertical-align: bottom;"
716 >
717 <div>
718 <?php
719 if ( is_admin() ) {
720 // Hide schema and table name on front-end
721 ?>
722 <input type="hidden" name="wpdaschema_name" value="<?php
723 echo esc_attr( $this->schema_name );
724 ?>">
725 <input type="hidden" name="table_name" value="<?php
726 echo esc_attr( $this->table_name );
727 ?>">
728 <?php
729 }
730 ?>
731 <input type="hidden" name="action" value="new">
732 <button type="submit" class="page-title-action wpda_tooltip"
733 title="<?php
734 echo esc_attr( $title );
735 ?>"
736 >
737 <i class="fas fa-plus-circle wpda_icon_on_button"></i>
738 <?php
739 esc_html_e( 'Add New', 'wp-data-access' );
740 ?>
741 </button>
742 </div>
743 </form>
744 <?php
745 }
746 }
747 }
748 ?>
749 </h1>
750 <div class="wpda_subtitle"><strong><?php
751 echo wp_kses( $this->subtitle, array(
752 'span' => array(
753 'class' => array(),
754 ),
755 ) );
756 ?></strong>
757 </div>
758 <?php
759 // Add custom code before the data entry form
760 do_action_ref_array( 'wpda_before_simple_form', array($this) );
761 ?>
762 <p></p>
763 <?php
764 }
765 ?>
766 <form id="<?php
767 echo esc_attr( $this->current_form_id );
768 ?>"
769 method="post" enctype="multipart/form-data"
770 action="<?php
771 echo esc_attr( $url );
772 ?>">
773 <div>
774 <?php
775 $js_code = '';
776 // All column JS code will be stored here and added to the end of the form.
777 foreach ( $this->fieldsets as $fieldset_title => $fieldset ) {
778 if ( isset( $fieldset['id'] ) && '' !== trim( $fieldset['id'] ) ) {
779 $id = trim( $fieldset['id'] );
780 } else {
781 $id = '';
782 }
783 $expandable = ( isset( $fieldset['expandable'] ) && true === $fieldset['expandable'] ? true : false );
784 // phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash
785 $expandable_state = ( isset( $_REQUEST["wpda_fieldset_expand_{$id}"] ) ? sanitize_text_field( $_REQUEST["wpda_fieldset_expand_{$id}"] ) : 'off' );
786 // phpcs:enable WordPress.Security.ValidatedSanitizedInput.MissingUnslash
787 $expandable_icons = ( 'on' === $expandable_state ? 'minus-circle' : 'plus-circle' );
788 ?>
789 <fieldset class="wpda_fieldset">
790 <?php
791 if ( '' !== $fieldset_title ) {
792 ?>
793 <legend <?php
794 echo ( '' === $id ? '' : 'id="' . esc_attr( $id ) . '"' );
795 ?>>
796 <?php
797 if ( $expandable && '' !== $id ) {
798 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>';
799 } else {
800 echo esc_html( $fieldset_title );
801 }
802 ?>
803 </legend>
804 <?php
805 }
806 ?>
807 <table id="wpda_table_expand_<?php
808 echo esc_attr( $id );
809 ?>"
810 class="wpda_simple_table <?php
811 echo esc_attr( $this->table_name );
812 ?>"
813 <?php
814 echo ( $expandable && 'off' === $expandable_state ? 'style="display: none"' : '' );
815 ?>
816 cellspacing="0"
817 cellpadding="0"
818 >
819 <?php
820 $fieldset_columns = array_flip( $fieldset['fields'] );
821 foreach ( $this->form_items as $item ) {
822 if ( isset( $fieldset_columns[$item->get_item_name()] ) ) {
823 $item->show( $this->action, $this->update_keys_allowed );
824 $js_code .= $item->get_item_js();
825 // Add column specific JS code.
826 }
827 }
828 ?>
829 </table>
830 </fieldset>
831 <?php
832 }
833 ?>
834 </div>
835 <div><?php
836 $this->add_form_logic();
837 ?></div>
838 <?php
839 // Add custom code after the data entry form
840 do_action_ref_array( 'wpda_after_simple_form', array($this) );
841 ?>
842 <p></p>
843 <?php
844 if ( is_admin() ) {
845 // Hide schema and table name on front-end
846 ?>
847 <input type="hidden" name="wpdaschema_name" value="<?php
848 echo esc_attr( $this->schema_name );
849 ?>">
850 <input type="hidden" name="table_name" value="<?php
851 echo esc_attr( $this->table_name );
852 ?>">
853 <?php
854 }
855 ?>
856 <input type="hidden" name="action" value="<?php
857 echo esc_attr( $this->action );
858 ?>"/>
859 <input type="hidden" name="action2" value="save"/>
860 <input type="hidden" name="wpda_message" value=""/>
861 <?php
862 if ( 'view' !== $this->action ) {
863 ?>
864 <input type="hidden" name="postaction" id="postaction" value=""/>
865 <?php
866 }
867 ?>
868 <?php
869 $this->add_parent_args();
870 // phpcs:disable WordPress.Security.EscapeOutput
871 echo $this->page_number_item;
872 echo $this->add_case_sensitive_search();
873 // phpcs:enable WordPress.Security.EscapeOutput
874 wp_nonce_field( $this->get_nonce_action( false ), '_wpnonce', false );
875 ?>
876 <?php
877 if ( 'view' !== $this->action ) {
878 ?>
879 <button type="submit"
880 class="button button-primary"
881 name="submit_button"
882 onclick="return submit_form(event)">
883 <i class="fas fa-check wpda_icon_on_button"></i>
884 <?php
885 esc_html_e( 'Submit', 'wp-data-access' );
886 ?>
887 </button>
888 <?php
889 if ( $this->show_back_button && $this->show_back_icon ) {
890 ?>
891 <button type="submit"
892 class="button button-secondary"
893 name="submit_button"
894 onclick="return submit_form(event)">
895 <i class="fas fa-check wpda_icon_on_button"></i>
896 <?php
897 esc_html_e( 'Submit', 'wp-data-access' );
898 ?>
899 <i class="fas fa-angle-right wpda_icon_on_button"></i>
900 <?php
901 echo esc_attr( $this->back_to_list_text );
902 ?>
903 </button>
904 <?php
905 }
906 if ( $this->show_back_button ) {
907 ?>
908 <button type="button"
909 onclick="jQuery('#<?php
910 echo esc_attr( $this->current_form_id );
911 ?>_backbutton').submit();"
912 class="button button-secondary">
913 <i class="fas fa-angle-left wpda_icon_on_button"></i>
914 <?php
915 echo esc_attr( $this->back_to_list_text );
916 ?>
917 </button>
918 <?php
919 }
920 ?>
921 <span style="float:right;"><?php
922 $this->add_buttons();
923 ?></span>
924 <?php
925 }
926 ?>
927 <?php
928 if ( 'view' === $this->action ) {
929 ?>
930 <button type="button"
931 onclick="jQuery('#<?php
932 echo esc_attr( $this->current_form_id );
933 ?>_backbutton').submit()"
934 class="button button-secondary">
935 <i class="fas fa-angle-left wpda_icon_on_button"></i>
936 <?php
937 echo esc_attr( $this->back_to_list_text );
938 ?>
939 </button>
940 <?php
941 }
942 ?>
943 </form>
944 <form id="<?php
945 echo esc_attr( $this->current_form_id );
946 ?>_backbutton"
947 method="post" style="display:none"
948 action="<?php
949 echo esc_attr( $url_back );
950 ?>">
951 <?php
952 $this->add_parent_args();
953 // phpcs:disable WordPress.Security.EscapeOutput
954 echo $this->page_number_item;
955 echo $this->add_case_sensitive_search();
956 // phpcs:enable WordPress.Security.EscapeOutput
957 ?>
958 <?php
959 if ( is_admin() ) {
960 // Hide schema and table name on front-end
961 ?>
962 <input type="hidden" name="wpdaschema_name" value="<?php
963 echo esc_attr( $this->schema_name );
964 ?>">
965 <input type="hidden" name="table_name" value="<?php
966 echo esc_attr( $this->table_name );
967 ?>">
968 <?php
969 }
970 ?>
971 <input type="hidden" name="action" value="list">
972 </form>
973 </div>
974
975 <script type='text/javascript'>
976 <?php
977 if ( 'view' !== $this->action ) {
978 ?>
979 function submit_form(e) {
980 if (typeof pre_submit_form === "function") {
981 // Perform pre submit
982 pre_submit = pre_submit_form();
983 if (!pre_submit) {
984 return false;
985 }
986 }
987 if (
988 jQuery(e.target).hasClass("button-secondary") ||
989 jQuery(e.target).parent().hasClass("button-secondary")
990 ) {
991 <?php
992 if ( 'child_page_number' === $this->page_number_item_name ) {
993 ?>
994 jQuery("#postaction").val("childlist");
995 <?php
996 } else {
997 ?>
998 jQuery("#postaction").val("list");
999 <?php
1000 }
1001 ?>
1002 } else {
1003 jQuery("#postaction").val("");
1004 }
1005 var failed = false;
1006 jQuery('.wpda_not_null').each(function(i, obj) {
1007 if (jQuery(obj).val() === '') {
1008 objData = jQuery(obj).data();
1009 if (objData.dbIsNull===undefined || objData.dbIsNull!==false) {
1010 alert(<?php
1011 echo "'" . esc_attr__( 'Item', 'wp-data-access' ) . "'";
1012 ?> + ' ' + jQuery(obj).attr('name') + ' ' + <?php
1013 echo "'" . esc_attr__( 'must be entered', 'wp-data-access' ) . "'";
1014 ?>);
1015 failed = true;
1016 } else {
1017 element_old = jQuery("input[name=" + jQuery(obj).attr("name") + "_old" + "]");
1018 if (element_old && element_old.val()!=='') {
1019 alert(<?php
1020 echo "'" . esc_attr__( 'Item', 'wp-data-access' ) . "'";
1021 ?> +' ' + jQuery(obj).attr('name') + ' ' + <?php
1022 echo "'" . esc_attr__( 'must be entered', 'wp-data-access' ) . "'";
1023 ?>);
1024 failed = true;
1025 }
1026 }
1027 }
1028 });
1029 jQuery('.wpda_input_error').each(function(i, obj) {
1030 alert(<?php
1031 echo "'" . esc_attr__( 'Column', 'wp-data-access' ) . "'";
1032 ?> + ' ' + jQuery(obj).attr('name') + <?php
1033 echo "'" . esc_attr__( ': max size exceeded', 'wp-data-access' ) . "'";
1034 ?>);
1035 failed = true;
1036 });
1037 jQuery('.wpda_hyperlink').each(function(i, obj) {
1038 hyperlink_name = jQuery(obj).attr('name');
1039 hyperlink_label = jQuery('#' + hyperlink_name + '_label').val();
1040 hyperlink_url = jQuery('#' + hyperlink_name + '_url').val();
1041 hyperlink_target = jQuery('#' + hyperlink_name + '_target').is(':checked') ? '_blank' : '';
1042 hyperlink_update = {
1043 "label" : hyperlink_label,
1044 "url" : hyperlink_url,
1045 "target" : hyperlink_target
1046 };
1047 jQuery(obj).val(JSON.stringify(hyperlink_update));
1048 });
1049 return !failed;
1050 }
1051 <?php
1052 }
1053 ?>
1054 jQuery(function () {
1055 <?php
1056 if ( 'view' === $this->action ) {
1057 ?>
1058 jQuery("#<?php
1059 echo esc_attr( $this->current_form_id );
1060 ?> input").not(':button').prop("readonly", true);
1061 jQuery("#<?php
1062 echo esc_attr( $this->current_form_id );
1063 ?> textarea").prop("readonly", true);
1064 jQuery("#<?php
1065 echo esc_attr( $this->current_form_id );
1066 ?> select").prop("disabled", true);
1067 <?php
1068 }
1069 ?>
1070 <?php
1071 if ( !$this->update_keys_allowed && 'new' !== $this->action ) {
1072 ?>
1073 jQuery("#<?php
1074 echo esc_attr( $this->current_form_id );
1075 ?> input.wpda_primary_key").prop("readonly", true);
1076 jQuery("#<?php
1077 echo esc_attr( $this->current_form_id );
1078 ?> select.wpda_primary_key").prop("disabled", true);
1079 <?php
1080 }
1081 ?>
1082 <?php
1083 if ( 'new' === $this->action ) {
1084 ?>
1085 jQuery("#<?php
1086 echo esc_attr( $this->current_form_id );
1087 ?> input.auto_increment").prop("readonly", true);
1088 <?php
1089 }
1090 ?>
1091 jQuery("#<?php
1092 echo esc_attr( $this->current_form_id );
1093 ?> input.wpda_readonly").prop("readonly", true);
1094 jQuery('.wpda_data_type_number').on('keyup paste', function () {
1095 numberFormat = jQuery(this).data('numberFormat').split(",");
1096 this.value = this.value.replace(/[^\d\-]/g, ''); // Allow only 0-9
1097 if (isNaN(this.value) || (numberFormat[0]!='' && this.value.length>numberFormat[0])) {
1098 jQuery(this).addClass('wpda_input_error');
1099 if (this.value.length>numberFormat[0]) {
1100 jQuery.notify('<?php
1101 esc_html_e( 'Max size exceeded', 'wp-data-access' );
1102 ?>','error');
1103 }
1104 } else {
1105 jQuery(this).removeClass('wpda_input_error');
1106 }
1107 });
1108 jQuery('.wpda_data_type_float').on('keyup paste', function () {
1109 numberFormat = jQuery(this).data('numberFormat').split(",");
1110 maxNumber = Math.pow(10, numberFormat[0] - numberFormat[1]);
1111 this.value = this.value.replace(/[^\d\-\.\,]/g, ''); // Allow only 0-9 . ,
1112 if (isNaN(this.value) || this.value>=maxNumber) {
1113 jQuery(this).addClass('wpda_input_error');
1114 if (this.value>=maxNumber) {
1115 jQuery.notify('<?php
1116 esc_html_e( 'Max size exceeded', 'wp-data-access' );
1117 ?>','error');
1118 }
1119 } else {
1120 jQuery(this).removeClass('wpda_input_error');
1121 }
1122 currentNumber = this.value.split(".");
1123 if (currentNumber.length===1) {
1124 currentNumber = this.value.split(",");
1125 }
1126 if (currentNumber.length===2 && currentNumber[1].length>numberFormat[1]) {
1127 jQuery(this).addClass('wpda_input_error');
1128 jQuery.notify('<?php
1129 esc_html_e( 'Max size exceeded', 'wp-data-access' );
1130 ?>','error');
1131 }
1132 });
1133 jQuery( '.wpda_tooltip' ).tooltip();
1134 // Add toolbar icons
1135 jQuery("#wpda_toolbar_icon_add_row").on("click", function() {
1136 jQuery("#wpda_new_row_table_name").val("<?php
1137 echo esc_attr( $this->table_name );
1138 ?>");
1139 jQuery("#wpda_new_row").submit();
1140 });
1141 });
1142 <?php
1143 // phpcs:disable WordPress.Security.EscapeOutput
1144 echo $js_code;
1145 // phpcs:enable WordPress.Security.EscapeOutput
1146 ?>
1147 </script>
1148 <?php
1149 }
1150
1151 private function add_case_sensitive_search() {
1152 if ( isset( $_REQUEST['wpda_c'] ) && 'true' === $_REQUEST['wpda_c'] ) {
1153 return '<input type="hidden" name="wpda_c" value="true">';
1154 } else {
1155 return '';
1156 }
1157 }
1158
1159 /**
1160 * Overwrite to add logic to form
1161 *
1162 * @since 2.0.15
1163 */
1164 public function add_form_logic() {
1165 }
1166
1167 /**
1168 * Overwrite to add buttons to right bottom
1169 *
1170 * @since 2.0.15
1171 */
1172 public function add_buttons() {
1173 }
1174
1175 /**
1176 * Creates a wpnonce action
1177 *
1178 * Set wp_nonce action for security check:
1179 * prefix + table name + primary key values
1180 *
1181 * @param boolean $use_old_value TRUE = use old key values, FALSE = use new key values.
1182 *
1183 * @return string wp_nonce action holding: prefix + table name + primary key values.
1184 * @since 1.0.0
1185 */
1186 public function get_nonce_action( $use_old_value = true ) {
1187 // Add prefix + table name to wp_nonce action.
1188 $wp_nonce_action = "wpda-simple-form-{$this->table_name}";
1189 if ( $this->wpda_list_columns->get_table_alternative_keys() ) {
1190 $wp_nonce_action .= '-*';
1191 } else {
1192 foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
1193 // Add primary key value to wp_nonce action.
1194 if ( 'new' === $this->action ) {
1195 // New records have no key values on form startup.
1196 $wp_nonce_action .= '-?';
1197 } else {
1198 // Add primary key value to wp_nonce action.
1199 if ( 'save' === $this->action2 && $use_old_value ) {
1200 // Use old value (in cases where primary key update is allowed).
1201 $wp_nonce_action .= ( isset( $_REQUEST[$pk_column . '_old'] ) ? '-' . sanitize_text_field( wp_unslash( $_REQUEST[$pk_column . '_old'] ) ) : '-?' );
1202 // input var okay.
1203 } else {
1204 if ( isset( $_REQUEST[$pk_column] ) && '' !== sanitize_text_field( wp_unslash( $_REQUEST[$pk_column] ) ) ) {
1205 // input var okay.
1206 // Use new value.
1207 $wp_nonce_action .= '-' . sanitize_text_field( wp_unslash( $_REQUEST[$pk_column] ) );
1208 // input var okay.
1209 } elseif ( -1 !== $this->auto_increment_value ) {
1210 // Use auto increment value (updated wp_nonce action after insert).
1211 $wp_nonce_action .= '-' . $this->auto_increment_value;
1212 } else {
1213 // No value found, let security check handle wrong wp_nonce action.
1214 $wp_nonce_action .= '-?';
1215 }
1216 }
1217 }
1218 }
1219 }
1220 return str_replace( ' ', '_', $wp_nonce_action );
1221 }
1222
1223 /**
1224 * Perform validation check
1225 *
1226 * Called to perform default validation before insert and update.
1227 *
1228 * Extend class WPDA_Simple_Form and override this method if you need validation on insert and/or update or
1229 * if you prefer to change error messages. If you want to handle inserts and updates differently, the
1230 * following information might be helpful:
1231 * + on insert: $this->action = 'new'
1232 * + on update: $this->action = 'edit'
1233 *
1234 * Use set_message to show messages (info as well as error).
1235 *
1236 * @param boolean $pre_insert Do not check auto_increment during pre-insert
1237 *
1238 * @return boolean TRUE = validation succeeded, FALSE = validation failed.
1239 * @since 1.0.0
1240 */
1241 protected function validate( $pre_insert = false ) {
1242 foreach ( $this->form_items as $item ) {
1243 if ( !$item->is_valid( $pre_insert ) ) {
1244 return false;
1245 }
1246 }
1247 return true;
1248 }
1249
1250 /**
1251 * Get current from database table
1252 *
1253 * Handle insert, update and save differently.
1254 *
1255 * @since 1.0.0
1256 */
1257 protected function prepare_row() {
1258 if ( 'edit' === $this->action || 'view' === $this->action || 'save' === $this->action2 ) {
1259 // Get record by primary key, use auto_increment for new records.
1260 $this->row = $this->row_data->get_row( $this->auto_increment_value, $this->wpda_err );
1261 } else {
1262 // There's no record yet.
1263 $this->row = $this->row_data->new_row();
1264 }
1265 }
1266
1267 /**
1268 * Set item attributes
1269 *
1270 * If you want to change the layout of your simple form(s), consider to extend class WPDA_Simple_Form and
1271 * override this method.
1272 *
1273 * @param boolean $set_back_form_values TRUE = set back user entered value, FALSE = set to database value.
1274 *
1275 * @since 1.0.0
1276 */
1277 protected function prepare_items( $set_back_form_values = false ) {
1278 $count_cols = count( $this->table_columns );
1279 for ($i = 0; $i < $count_cols; $i++) {
1280 $column_name = $this->table_columns[$i]['column_name'];
1281 $item_enum = '';
1282 if ( 'enum' === $this->table_columns[$i]['data_type'] || 'set' === $this->table_columns[$i]['data_type'] ) {
1283 $item_enum = $this->table_columns[$i]['column_type'];
1284 }
1285 if ( $set_back_form_values ) {
1286 // Set value to what user entered.
1287 $item_value = $this->get_new_value( $column_name );
1288 } else {
1289 // Get value from database.
1290 $item_value = ( isset( $this->row ) ? $this->row[0][$column_name] : null );
1291 }
1292 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item';
1293 $check_data_type = WPDA::get_type( $this->table_columns[$i]['data_type'] );
1294 if ( 'enum' === $this->table_columns[$i]['data_type'] ) {
1295 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Enum';
1296 } elseif ( 'set' === $this->table_columns[$i]['data_type'] ) {
1297 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Set';
1298 } elseif ( 'date' === $check_data_type || 'time' === $check_data_type ) {
1299 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_DateTime';
1300 // Always initially use database data and time format
1301 $item_value = ( isset( $this->row ) ? $this->row[0][$column_name] : null );
1302 } 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'] ) {
1303 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Textarea';
1304 } elseif ( 'tinyint(1)' === $this->table_columns[$i]['column_type'] ) {
1305 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Boolean';
1306 }
1307 // Media support only available to logged-in users
1308 if ( 0 < WPDA::get_current_user_id() ) {
1309 $media_type = WPDA_Media_Model::get_column_media( $this->table_name, $column_name, $this->schema_name );
1310 if ( 'Image' === $media_type ) {
1311 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Image';
1312 } elseif ( 'Attachment' === $media_type ) {
1313 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Media';
1314 } elseif ( 'Hyperlink' === $media_type ) {
1315 if ( !(isset( $this->wpda_table_settings->table_settings->hyperlink_definition ) && 'text' === $this->wpda_table_settings->table_settings->hyperlink_definition) ) {
1316 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Hyperlink';
1317 }
1318 } elseif ( 'Audio' === $media_type ) {
1319 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Audio';
1320 } elseif ( 'Video' === $media_type ) {
1321 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Video';
1322 } elseif ( 'File' === $media_type ) {
1323 $wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_File';
1324 }
1325 }
1326 $item_label = '';
1327 if ( isset( $this->column_headers[$column_name] ) ) {
1328 $item_label = $this->column_headers[$column_name];
1329 } elseif ( isset( $this->table_column_headers[$column_name] ) ) {
1330 $item_label = $this->table_column_headers[$column_name];
1331 }
1332 $item = new $wpda_simple_form_item_class(array(
1333 'item_name' => $column_name,
1334 'data_type' => $this->table_columns[$i]['data_type'],
1335 'item_label' => $item_label,
1336 'item_value' => $item_value,
1337 'item_default_value' => $this->table_columns[$i]['column_default'],
1338 'item_extra' => $this->table_columns[$i]['extra'],
1339 'item_enum' => $item_enum,
1340 'column_type' => $this->table_columns[$i]['column_type'],
1341 'is_nullable' => $this->table_columns[$i]['is_nullable'],
1342 'user_update' => $set_back_form_values,
1343 'character_maximum_length' => $this->table_columns[$i]['character_maximum_length'],
1344 'numeric_precision' => $this->table_columns[$i]['numeric_precision'],
1345 'numeric_scale' => ( null === $this->table_columns[$i]['numeric_scale'] ? 0 : $this->table_columns[$i]['numeric_scale'] ),
1346 ));
1347 $item->set_is_key_column( $this->is_key_column( $column_name ) );
1348 $this->add_form_item( $i, $item );
1349 }
1350 // Add dynamic hyperlinks (if applicable)
1351 if ( isset( $this->wpda_table_settings->hyperlinks ) ) {
1352 foreach ( $this->wpda_table_settings->hyperlinks as $hyperlink ) {
1353 $hyperlink_label = ( isset( $hyperlink->hyperlink_label ) ? $hyperlink->hyperlink_label : '' );
1354 $hyperlink_form = ( isset( $hyperlink->hyperlink_form ) ? $hyperlink->hyperlink_form : false );
1355 $hyperlink_html = ( isset( $hyperlink->hyperlink_html ) ? $hyperlink->hyperlink_html : '' );
1356 if ( true === $hyperlink_form && $hyperlink_label !== '' && $hyperlink_html !== '' ) {
1357 $hyperlink_target = ( isset( $hyperlink->hyperlink_form ) ? $hyperlink->hyperlink_target : false );
1358 foreach ( $this->form_items as $item ) {
1359 $item_name = $item->get_item_name();
1360 $item_value = $item->get_item_value();
1361 $hyperlink_html = str_replace( "\$\${$item_name}\$\$", $item_value, $hyperlink_html );
1362 }
1363 $item = new WPDA_Simple_Form_Item_Dynamic_Hyperlink(array(
1364 'item_name' => $hyperlink_label,
1365 'data_type' => 'varchar2',
1366 'hyperlink_label' => $hyperlink_label,
1367 'hyperlink_target' => $hyperlink_target,
1368 'hyperlink_html' => $hyperlink_html,
1369 ));
1370 $this->add_form_item( $i++, $item );
1371 }
1372 }
1373 }
1374 }
1375
1376 /**
1377 * Get new value for item
1378 *
1379 * Or empty if no new value available.
1380 *
1381 * @param string $column_name Column name.
1382 *
1383 * @return mixed|string New value for column or empty.
1384 * @since 1.0.0
1385 */
1386 public function get_new_value( $column_name ) {
1387 return ( isset( $this->form_items_new_values[$column_name] ) ? $this->form_items_new_values[$column_name] : null );
1388 }
1389
1390 /**
1391 * Add item to form
1392 *
1393 * @param int $index Item sequence number.
1394 * @param WPDA_Simple_Form_Item $item Reference to simple form item.
1395 *
1396 * @since 1.0.0
1397 *
1398 * @see WPDA_Simple_Form_Item
1399 */
1400 protected function add_form_item( $index, $item ) {
1401 // Add item to form
1402 $this->form_items[$index] = $item;
1403 // Add position to named array for quick access of single items
1404 $item_name = $item->get_item_name();
1405 $this->form_items_named[$item_name] = $index;
1406 }
1407
1408 /**
1409 * Get item position
1410 *
1411 * @param string $item_name Form item name
1412 *
1413 * @return bool|int Position item or false if not found
1414 *
1415 * @since 2.0.15
1416 */
1417 protected function get_item_index( $item_name ) {
1418 if ( isset( $this->form_items_named[$item_name] ) ) {
1419 return $this->form_items_named[$item_name];
1420 } else {
1421 return false;
1422 }
1423 }
1424
1425 /**
1426 * Get old value form item
1427 *
1428 * Or empty if no old value available.
1429 *
1430 * @param string $column_name Column name.
1431 *
1432 * @return mixed|string Old value for column or empty.
1433 * @since 1.0.0
1434 */
1435 public function get_old_value( $column_name ) {
1436 return ( isset( $this->form_items_old_values[$column_name] ) ? $this->form_items_old_values[$column_name] : null );
1437 }
1438
1439 public function revert_column_value( $column_name ) {
1440 @($this->form_items_new_values[$column_name] = $this->form_items_old_values[$column_name]);
1441 }
1442
1443 public function insert_column_default( $column_name, $item_default_value ) {
1444 if ( isset( $this->form_items_old_values ) ) {
1445 @($this->form_items_new_values[$column_name] = $item_default_value);
1446 }
1447 }
1448
1449 /**
1450 * Is column part of primary key?
1451 *
1452 * @param string $column_name Column name.
1453 *
1454 * @return bool TRUE = column is part of primary key, FALSE = column is not part of primary key.
1455 * @since 1.0.0
1456 */
1457 protected function is_key_column( $column_name ) {
1458 foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
1459 if ( $column_name === $pk_column ) {
1460 return true;
1461 }
1462 }
1463 return false;
1464 }
1465
1466 /**
1467 * Get primary form action
1468 *
1469 * @return string Primary page action
1470 * @since 1.0.0
1471 */
1472 public function get_form_action() {
1473 return $this->action;
1474 }
1475
1476 /**
1477 * Get secondary form action
1478 *
1479 * @return string Secondary page action
1480 * @since 1.0.0
1481 */
1482 public function get_form_action2() {
1483 return $this->action2;
1484 }
1485
1486 /**
1487 * Defines whether primary key item can be updated
1488 *
1489 * @param boolean $update_keys_allowed Allow keys to be updated.
1490 *
1491 * @since 1.0.0
1492 */
1493 protected function set_update_keys( $update_keys_allowed ) {
1494 $this->update_keys_allowed = $update_keys_allowed;
1495 }
1496
1497 /**
1498 * Reorder columns
1499 *
1500 * Reorders the column array in the order as defined in argument $columns_ordered.
1501 *
1502 * @param array $columns_ordered Ordered column names.
1503 *
1504 * @since 1.0.0
1505 */
1506 protected function order_and_filter_columns( $columns_ordered ) {
1507 $column_array_ordered = array();
1508 $i = 0;
1509 foreach ( $columns_ordered as $key => $value ) {
1510 $column_array_ordered[$i++] = $this->table_columns[$this->get_column_position( $this->table_columns, $value )];
1511 }
1512 $this->table_columns = $column_array_ordered;
1513 }
1514
1515 /**
1516 * Get column position in column array
1517 *
1518 * @param array $column_array Column array.
1519 * @param string $column_name Column name.
1520 *
1521 * @return int Position of $column_name in $column_array
1522 * @since 1.0.0
1523 */
1524 protected function get_column_position( $column_array, $column_name ) {
1525 if ( !is_array( $column_array ) ) {
1526 return -1;
1527 }
1528 $count_cols = count( $column_array );
1529 for ($i = 0; $i < $count_cols; $i++) {
1530 if ( $column_array[$i]['column_name'] === $column_name ) {
1531 return $i;
1532 }
1533 }
1534 return -1;
1535 }
1536
1537 /**
1538 * Add dummy column to form
1539 *
1540 * @param string $column_name Column name.
1541 *
1542 * @since 1.0.0
1543 */
1544 protected function add_dummy_column( $column_name ) {
1545 $this->table_columns[] = array(
1546 'column_name' => $column_name,
1547 'data_type' => 'varchar',
1548 'extra' => '',
1549 'column_type' => '',
1550 'is_nullable' => 'YES',
1551 'column_default' => '',
1552 );
1553 }
1554
1555 /**
1556 * Set message number and text
1557 *
1558 * Assigns values to $this->wpda_err and $this->wpda_msg.
1559 *
1560 * @param string $wpda_err '0' = INFO, '1' = ERROR.
1561 * @param string $wpda_msg Message to be displayed.
1562 *
1563 * @since 1.0.0
1564 */
1565 protected function set_message( $wpda_err, $wpda_msg ) {
1566 // Wrong values will be handled by message box class.
1567 $this->wpda_err = $wpda_err;
1568 $this->wpda_msg = $wpda_msg;
1569 }
1570
1571 /**
1572 * Use this method to build parent child relationships.
1573 *
1574 * Overwrite this function if you want to use the form as a child form related to some parent
1575 * form. You can add parent arguments to calls to make sure you get back to the right parent.
1576 *
1577 * @since 1.5.0
1578 */
1579 protected function add_parent_args() {
1580 }
1581
1582 /**
1583 * Use this method to build parent child relationships.
1584 *
1585 * Overwrite this function if you want to use the form as a child form related to some parent
1586 * form. You can add parent arguments to calls to make sure you get back to the right parent.
1587 *
1588 * @since 1.6.9
1589 */
1590 protected function add_parent_args_to_back_button() {
1591 }
1592
1593 /**
1594 * Set item labels
1595 *
1596 * @param array $item_labels Named array containing item name/label pairs
1597 *
1598 * @since 2.0.15
1599 */
1600 public function set_labels( $item_labels ) {
1601 if ( is_array( $item_labels ) ) {
1602 foreach ( $item_labels as $key => $label ) {
1603 foreach ( $this->form_items as $form_item ) {
1604 if ( $form_item->get_item_name() === $key ) {
1605 $form_item->set_label( $label );
1606 }
1607 }
1608 }
1609 }
1610 }
1611
1612 /**
1613 * Hide items
1614 *
1615 * @param array $items_to_hide Array contains item names of items to be defined as hidden
1616 *
1617 * @since 2.0.15
1618 */
1619 public function hide_items( $items_to_hide ) {
1620 if ( is_array( $items_to_hide ) ) {
1621 foreach ( $items_to_hide as $column_name ) {
1622 foreach ( $this->form_items as $form_item ) {
1623 if ( $form_item->get_item_name() === $column_name ) {
1624 $form_item->set_hide_item_init( true );
1625 }
1626 }
1627 }
1628 }
1629 }
1630
1631 /**
1632 * Number of items
1633 *
1634 * @return int
1635 *
1636 * @since 2.0.15
1637 */
1638 public function count() {
1639 return count( (array) $this->form_items );
1640 }
1641
1642 public function get_row() {
1643 return $this->row;
1644 }
1645
1646 }
1647
1648 // phpcs:enable WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing