PluginProbe
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards / 2.0.13
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards v2.0.13
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 5.5.41 All 161 releases
← All changes | WPDataAccess/Simple_Form/WPDA_Simple_Form_Data.php +461 -451 5.5.42.0.13 View file →
@@ -1,472 +1,482 @@
1 1 <?php
2 -
3 2 /**
4 3 * Suppress "error - 0 - No summary was found for this file" on phpdoc generation
5 4 *
6 5 * @package WPDataAccess\Simple_Form
7 6 */
8 -namespace WPDataAccess\Simple_Form;
9 7
10 -use WPDataAccess\Connection\WPDADB;
11 -use WPDataAccess\Data_Dictionary\WPDA_Dictionary_Exist;
12 -use WPDataAccess\Data_Dictionary\WPDA_List_Columns;
13 -use WPDataAccess\Plugin_Table_Models\WPDA_Table_Settings_Model;
14 -use WPDataAccess\Utilities\WPDA_Message_Box;
15 -use WPDataAccess\WPDA;
16 -/**
17 - * Class WPDA_Simple_Form_Data
18 - *
19 - * WPDA_Simple_Form_Data is responsible for data management. It queries the database, adds new records to tables
20 - * and updates table data. Simple validations are performed based on information retrieved from the data dictionary.
21 - *
22 - * @author Peter Schulz
23 - * @since 1.0.0
24 - */
25 -class WPDA_Simple_Form_Data {
26 - /**
27 - * Database schema name
28 - *
29 - * @var string
30 - */
31 - protected $schema_name;
8 +namespace WPDataAccess\Simple_Form {
32 9
33 - /**
34 - * Database table name
35 - *
36 - * @var string
37 - */
38 - protected $table_name;
10 + use WPDataAccess\Data_Dictionary\WPDA_Dictionary_Exist;
11 + use WPDataAccess\Data_Dictionary\WPDA_List_Columns;
12 + use WPDataAccess\Utilities\WPDA_Message_Box;
13 + use WPDataAccess\WPDA;
39 14
40 - /**
41 - * Reference to calling form
42 - *
43 - * @var WPDA_Simple_Form
44 - */
45 - protected $calling_form;
15 + /**
16 + * Class WPDA_Simple_Form_Data
17 + *
18 + * WPDA_Simple_Form_Data is responsible for data management. It queries the database, adds new records to tables
19 + * and updates table data. Simple validations are performed based on information retrieved from the data dictionary.
20 + *
21 + * @package WPDataAccess\Simple_Form
22 + * @author Peter Schulz
23 + * @since 1.0.0
24 + */
25 + class WPDA_Simple_Form_Data {
46 26
47 - /**
48 - * Reference to column list
49 - *
50 - * @var WPDA_List_Columns
51 - */
52 - protected $wpda_list_columns;
27 + /**
28 + * Database schema name
29 + *
30 + * @var string
31 + */
32 + protected $schema_name;
53 33
54 - /**
55 - * Default success message
56 - *
57 - * Is set in the constructor to support internationalization.
58 - *
59 - * @var string
60 - */
61 - protected $wpda_success_msg;
34 + /**
35 + * Database table name
36 + *
37 + * @var string
38 + */
39 + protected $table_name;
62 40
63 - /**
64 - * Default failure message
65 - *
66 - * Is set in the constructor to support internationalization.
67 - *
68 - * @var string
69 - */
70 - protected $wpda_failure_msg;
41 + /**
42 + * Reference to calling form
43 + *
44 + * @var WPDA_Simple_Form
45 + */
46 + protected $calling_form;
71 47
72 - /**
73 - * Handle to data dictionary object
74 - *
75 - * @var WPDA_Dictionary_Exist
76 - */
77 - protected $wpda_data_dictionary;
48 + /**
49 + * Reference to column list
50 + *
51 + * @var WPDA_List_Columns
52 + */
53 + protected $wpda_list_columns;
78 54
79 - /**
80 - * WPDA_Simple_Form_Data constructor
81 - *
82 - * Check if table exists and access is granted.
83 - *
84 - * @param string $schema_name Database schema name.
85 - * @param string $table_name Database table name.
86 - * @param WPDA_List_Columns $wpda_list_columns Reference to column array.
87 - * @param WPDA_Simple_Form $calling_form Reference to calling form.
88 - * @param string $wpda_success_msg Message shown on success.
89 - * @param string $wpda_failure_msg Message shown on failure.
90 - *
91 - * @since 1.0.0
92 - */
93 - public function __construct(
94 - $schema_name,
95 - $table_name,
96 - &$wpda_list_columns,
97 - &$calling_form,
98 - $wpda_success_msg,
99 - $wpda_failure_msg
100 - ) {
101 - $this->schema_name = $schema_name;
102 - $this->table_name = $table_name;
103 - // Table must exist and user must be authorized.
104 - $this->wpda_data_dictionary = new WPDA_Dictionary_Exist($this->schema_name, $this->table_name);
105 - if ( !$this->wpda_data_dictionary->table_exists() ) {
106 - wp_die( __( 'ERROR: Invalid table name or not authorized' ) );
107 - }
108 - $this->calling_form = $calling_form;
109 - $this->wpda_list_columns = $wpda_list_columns;
110 - $this->wpda_success_msg = $wpda_success_msg;
111 - $this->wpda_failure_msg = $wpda_failure_msg;
112 - }
55 + /**
56 + * Default succes message
57 + *
58 + * Is set in the constructor to support internationalization.
59 + *
60 + * @var string
61 + */
62 + protected $wpda_success_msg;
113 63
114 - /**
115 - * Create new record
116 - *
117 - * Nothing to do!
118 - *
119 - * @return null
120 - * @since 1.0.0
121 - */
122 - public function new_row() {
123 - return null;
124 - }
64 + /**
65 + * Default failure message
66 + *
67 + * Is set in the constructor to support internationalization.
68 + *
69 + * @var string
70 + */
71 + protected $wpda_failure_msg;
125 72
126 - /**
127 - * Add records to database table
128 - *
129 - * @return bool TRUE = record successfully added to table
130 - * @since 1.0.0
131 - */
132 - public function add_row() {
133 - $column_values_to_be_inserted = null;
134 - foreach ( $this->wpda_list_columns->get_table_columns() as $column ) {
135 - if ( isset( $column['readonly'], $column['default'] ) ) {
136 - $this->calling_form->insert_column_default( $column['column_name'], WPDA::convert_default_value( $column['default'] ) );
137 - }
138 - if ( $column['column_name'] === $this->wpda_list_columns->get_auto_increment_column_name() ) {
139 - // Auto increment column is not added
140 - } else {
141 - if ( null === $this->calling_form->get_new_value( $column['column_name'] ) || '' === $this->calling_form->get_new_value( $column['column_name'] ) ) {
142 - // Skip empty columns
143 - } elseif ( 'date' === WPDA::get_type( $column['data_type'] ) || 'time' === WPDA::get_type( $column['data_type'] ) ) {
144 - // Convert date and time values
145 - $column_values_to_be_inserted[$column['column_name']] = self::convert_datetime( $column['data_type'], $this->calling_form->get_new_value( $column['column_name'] ) );
146 - } else {
147 - // Add value
148 - $column_values_to_be_inserted[$column['column_name']] = $this->calling_form->get_new_value( $column['column_name'] );
149 - }
150 - }
151 - }
152 - $wpdadb = WPDADB::get_db_connection( $this->schema_name );
153 - if ( null === $wpdadb ) {
154 - wp_die( sprintf( __( 'ERROR - Remote database %s not available', 'wp-data-access' ), esc_attr( $this->schema_name ) ) );
155 - }
156 - $result = $wpdadb->insert( $this->table_name, $column_values_to_be_inserted );
157 - // db call ok; no-cache ok.
158 - if ( 1 === $result ) {
159 - $msg = new WPDA_Message_Box(array(
160 - 'message_text' => $this->wpda_success_msg,
161 - ));
162 - $msg->box();
163 - // If inserted record contains an auto_increment column: return value.
164 - if ( false !== $this->wpda_list_columns->get_auto_increment_column_name() ) {
165 - return $wpdadb->insert_id;
166 - // Return auto_increment value.
167 - } else {
168 - return true;
169 - // Return true = transaction succeeded.
170 - }
171 - } else {
172 - // An error occurred.
173 - $msg = new WPDA_Message_Box(array(
174 - 'message_text' => ( '' === $wpdadb->last_error ? $this->wpda_failure_msg : $this->wpda_failure_msg . ' [' . $wpdadb->last_error . ']' ),
175 - 'message_type' => 'error',
176 - 'message_is_dismissible' => false,
177 - ));
178 - $msg->box();
179 - return false;
180 - // Return false = transaction failed.
181 - }
182 - }
73 + /**
74 + * Handle to data dictionary object
75 + *
76 + * @var WPDA_Dictionary_Exist
77 + */
78 + protected $wpda_data_dictionary;
183 79
184 - /**
185 - * Get record from database table
186 - *
187 - * @param int $auto_increment_value Auto increment number (returned if provided by dbms).
188 - * @param string $wpda_err Error message to be shown on failure.
189 - *
190 - * @return mixed
191 - * @since 1.0.0
192 - */
193 - public function get_row( $auto_increment_value, $wpda_err ) {
194 - $settings_db = WPDA_Table_Settings_Model::query( $this->table_name, $this->schema_name );
195 - if ( isset( $settings_db[0]['wpda_table_settings'] ) ) {
196 - $settings_db_custom = json_decode( $settings_db[0]['wpda_table_settings'] );
197 - if ( isset( $settings_db_custom->table_settings->row_level_security ) && 'true' === $settings_db_custom->table_settings->row_level_security ) {
198 - // Check access
199 - $wp_nonce = ( isset( $_REQUEST['rownonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['rownonce'] ) ) : '' );
200 - // input var okay.
201 - $keys = '';
202 - foreach ( $this->wpda_list_columns->get_table_primary_key() as $key ) {
203 - $keys .= "-{$key}-" . $this->calling_form->get_new_value( $key );
204 - }
205 - // Check action from list table
206 - if ( !wp_verify_nonce( $wp_nonce, "wpda-row-level-security-{$this->table_name}{$keys}" ) ) {
207 - // Check action from data entry form (standard behaviour)
208 - $wp_nonce = ( isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : '' );
209 - // input var okay.
210 - if ( !wp_verify_nonce( $wp_nonce, $this->calling_form->get_nonce_action() ) ) {
211 - wp_die( __( 'ERROR: Not authorized', 'wp-data-access' ) );
212 - }
213 - }
214 - }
215 - }
216 - $wpdadb = WPDADB::get_db_connection( $this->schema_name );
217 - if ( null === $wpdadb ) {
218 - wp_die( sprintf( __( 'ERROR - Remote database %s not available', 'wp-data-access' ), esc_attr( $this->schema_name ) ) );
219 - }
220 - $table_columns = array();
221 - // Get all table columns.
222 - foreach ( $this->wpda_list_columns->get_table_columns() as $column ) {
223 - $table_columns[$column['column_name']] = $column['data_type'];
224 - }
225 - $where = '';
226 - // Compose where clause.
227 - $use_primary_key = true;
228 - if ( $auto_increment_value < 1 ) {
229 - foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
230 - if ( '' === $this->calling_form->get_new_value( $pk_column ) ) {
231 - $use_primary_key = false;
232 - }
233 - }
234 - }
235 - if ( isset( $_REQUEST['child_request'] ) && 'TRUE' === $_REQUEST['child_request'] && $auto_increment_value > -1 ) {
236 - // Special case:
237 - // - parent-child relation based on non-primary key parent column
238 - // - parent primary key is auto increment
239 - // - child primary key is auto increment
240 - // - insert record
241 - $use_primary_key = true;
242 - }
243 - if ( $use_primary_key ) {
244 - foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
245 - $where_current = ( '' === $where ? ' where ' : ' and ' );
246 - if ( WPDA::get_type( $table_columns[$pk_column] ) === 'number' ) {
247 - // Column data type is numeric:
248 - // For numeric columns we need to omit quotes. All numeric values will be handled as float. MySQL
249 - // will automatically convert them if necessary. Values supplied in a wrong format will be handed
250 - // over to MySQL as is and might result in unpredictable results. For our simple form we rely on
251 - // the user's judgement.
252 - $where_current .= " `{$pk_column}` = %d";
253 - } else {
254 - // Column data type is string:
255 - // Quotes will be added to all non-numeric values. We might have issues with date and time fields.
256 - // For our simple form we'll accept that limitation (at least for now).
257 - $where_current .= " `{$pk_column}` = %s";
258 - }
259 - if ( $auto_increment_value > -1 && $pk_column === $this->wpda_list_columns->get_auto_increment_column_name() ) {
260 - // For inserts with auto_increment columns use $wpdadb->insert_id.
261 - $pkvalue = $auto_increment_value;
262 - } else {
263 - if ( 0 === $wpda_err ) {
264 - // No errors: use new value.
265 - if ( $this->calling_form->get_new_value( $pk_column ) === '' ) {
266 - wp_die( __( 'ERROR: Wrong arguments [missing primary key value]', 'wp-data-access' ) );
267 - }
268 - $pkvalue = $this->calling_form->get_new_value( $pk_column );
269 - } else {
270 - // There are errors: use old values (in case a key value was changed).
271 - if ( $this->calling_form->get_old_value( $pk_column ) === '' ) {
272 - wp_die( __( 'ERROR: Wrong arguments [missing primary key value]', 'wp-data-access' ) );
273 - }
274 - $pkvalue = $this->calling_form->get_old_value( $pk_column );
275 - }
276 - }
277 - if ( WPDA::get_type( $table_columns[$pk_column] ) === 'date' || WPDA::get_type( $table_columns[$pk_column] ) === 'time' ) {
278 - // Convert date and time values
279 - $pkvalue = self::convert_datetime( $table_columns[$pk_column], $pkvalue, $pkvalue );
280 - }
281 - $where .= $wpdadb->prepare( $where_current, $pkvalue );
282 - // phpcs:ignore Standard.Category.SniffName.ErrorCode
283 - }
284 - } else {
285 - $alternative_key_found = false;
286 - // Check for alternative keys
287 - foreach ( $this->wpda_list_columns->get_table_alternative_keys() as $alternative_keys ) {
288 - foreach ( $alternative_keys as $alternative_key ) {
289 - $alternative_keys_found = 0;
290 - if ( $this->calling_form->get_new_value( $alternative_key ) !== '' ) {
291 - $where_current = ( '' === $where ? ' where ' : ' and ' );
292 - if ( WPDA::get_type( $table_columns[$alternative_key] ) === 'number' ) {
293 - $where_current .= " `{$alternative_key}` = %f";
294 - } else {
295 - $where_current .= " `{$alternative_key}` = %s";
296 - }
297 - $pkvalue = $this->calling_form->get_new_value( $alternative_key );
298 - $alternative_keys_found++;
299 - }
300 - }
301 - if ( $alternative_keys_found === count( $alternative_keys ) ) {
302 - //phpcs:ignore - 8.1 proof
303 - $alternative_key_found = true;
304 - }
305 - }
306 - if ( !$alternative_key_found ) {
307 - wp_die( __( 'ERROR: Wrong arguments [missing key value]', 'wp-data-access' ) );
308 - }
309 - $where .= $wpdadb->prepare( $where_current, $pkvalue );
310 - // phpcs:ignore Standard.Category.SniffName.ErrorCode
311 - }
312 - if ( '' === $this->schema_name ) {
313 - $query = "\n\t\t\t\t\tselect *\n\t\t\t\t\tfrom `{$this->table_name}`\n\t\t\t\t\t{$where}\n\t\t\t\t";
314 - } else {
315 - $query = "\n\t\t\t\t\tselect *\n\t\t\t\t\tfrom `{$wpdadb->dbname}`.`{$this->table_name}`\n\t\t\t\t\t{$where}\n\t\t\t\t";
316 - }
317 - $result = $wpdadb->get_results( $query, 'ARRAY_A' );
318 - // phpcs:ignore Standard.Category.SniffName.ErrorCode
319 - if ( 1 === $wpdadb->num_rows ) {
320 - return $result;
321 - } else {
322 - wp_die( __( 'ERROR: Wrong arguments [no data found]', 'wp-data-access' ) );
323 - }
324 - }
80 + /**
81 + * WPDA_Simple_Form_Data constructor
82 + *
83 + * Check if table exists and access is granted.
84 + *
85 + * @since 1.0.0
86 + *
87 + * @param string $schema_name Database schema name.
88 + * @param string $table_name Database table name.
89 + * @param WPDA_List_Columns $wpda_list_columns Reference to column array.
90 + * @param WPDA_Simple_Form $calling_form Reference to calling form.
91 + * @param string $wpda_success_msg Message shown on success.
92 + * @param string $wpda_failure_msg Message shown on failure.
93 + */
94 + public function __construct(
95 + $schema_name,
96 + $table_name,
97 + &$wpda_list_columns,
98 + &$calling_form,
99 + $wpda_success_msg,
100 + $wpda_failure_msg
101 + ) {
325 102
326 - /**
327 - * Update current record (write changes to database)
328 - *
329 - * @since 1.0.0
330 - */
331 - public function set_row() {
332 - $wpdadb = WPDADB::get_db_connection( $this->schema_name );
333 - if ( null === $wpdadb ) {
334 - wp_die( sprintf( __( 'ERROR - Remote database %s not available', 'wp-data-access' ), esc_attr( $this->schema_name ) ) );
335 - }
336 - $column_values_to_be_updated = null;
337 - foreach ( $this->wpda_list_columns->get_table_columns() as $column ) {
338 - if ( isset( $column['readonly'] ) ) {
339 - $this->calling_form->revert_column_value( $column['column_name'] );
340 - continue;
341 - }
342 - if ( $this->calling_form->get_old_value( $column['column_name'] ) !== $this->calling_form->get_new_value( $column['column_name'] ) ) {
343 - if ( 'number' === WPDA::get_type( $column['data_type'] ) && '' === $this->calling_form->get_new_value( $column['column_name'] ) ) {
344 - // Convert empty numeric value to null
345 - $column_values_to_be_updated[$column['column_name']] = null;
346 - } else {
347 - if ( 'time' === WPDA::get_type( $column['data_type'] ) || 'date' === WPDA::get_type( $column['data_type'] ) ) {
348 - // Convert date and time values
349 - $column_values_to_be_updated[$column['column_name']] = self::convert_datetime( $column['data_type'], $this->calling_form->get_new_value( $column['column_name'] ) );
350 - } else {
351 - $new_value = $this->calling_form->get_new_value( $column['column_name'] );
352 - if ( '' !== $new_value ) {
353 - $column_values_to_be_updated[$column['column_name']] = $this->calling_form->get_new_value( $column['column_name'] );
354 - } else {
355 - if ( isset( $column['is_nullable'] ) && 'YES' === $column['is_nullable'] ) {
356 - $column_values_to_be_updated[$column['column_name']] = null;
357 - } else {
358 - $column_values_to_be_updated[$column['column_name']] = $this->calling_form->get_new_value( $column['column_name'] );
359 - }
360 - }
361 - }
362 - }
363 - }
364 - }
365 - if ( null === $column_values_to_be_updated ) {
366 - // Nothing to update.
367 - if ( $_REQUEST['wpda_message'] && '' !== $_REQUEST['wpda_message'] ) {
368 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
369 - // Happens when inserting new row on parent child page
370 - $msgtxt = sanitize_text_field( wp_unslash( $_REQUEST['wpda_message'] ) );
371 - // input var okay.
372 - } else {
373 - $msgtxt = __( 'Nothing to save', 'wp-data-access' );
374 - }
375 - $msg = new WPDA_Message_Box(array(
376 - 'message_text' => $msgtxt,
377 - ));
378 - $msg->box();
379 - } else {
380 - // Write changes to database.
381 - $where = array();
382 - foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
383 - $action = $this->calling_form->get_form_action();
384 - $action2 = $this->calling_form->get_form_action2();
385 - if ( 'edit' === $action && 'save' === $action2 ) {
386 - // Form was submitted after update: use old key value to build where clause.
387 - if ( '' === $this->calling_form->get_old_value( $pk_column ) ) {
388 - wp_die( __( 'ERROR: Wrong arguments [missing primary key value]', 'wp-data-access' ) );
389 - }
390 - $where[$pk_column] = $this->calling_form->get_old_value( $pk_column );
391 - // Set primary keys value(s).
392 - $data_type = $this->wpda_list_columns->get_column_data_type( $pk_column );
393 - if ( 'time' === $data_type || 'date' === $data_type ) {
394 - // Convert date and time values
395 - $where[$pk_column] = self::convert_datetime( $data_type, $where[$pk_column] );
396 - }
397 - } else {
398 - // Form submitted a new record: use new value (no old value available).
399 - if ( $this->calling_form->get_new_value( $pk_column ) === '' ) {
400 - wp_die( __( 'ERROR: Wrong arguments [missing primary key value]', 'wp-data-access' ) );
401 - }
402 - $where[$pk_column] = $this->calling_form->get_new_value( $pk_column );
403 - // Set primary keys value(s).
404 - }
405 - }
406 - // var_dump($column_values_to_be_updated);
407 - $result = $wpdadb->update( $this->table_name, $column_values_to_be_updated, $where );
408 - // db call ok; no-cache ok.
409 - if ( 1 === $result ) {
410 - // Since we are updating by key, result must be exactly 1 record.
411 - $msg = new WPDA_Message_Box(array(
412 - 'message_text' => $this->wpda_success_msg,
413 - ));
414 - $msg->box();
415 - } else {
416 - if ( 0 === $result && '' === $wpdadb->last_error ) {
417 - $table_info = WPDA::get_table_values( $this->schema_name, $this->table_name );
418 - if ( 1 === count( $table_info ) && 'connect' === strtolower( $table_info[0]['engine'] ) ) {
419 - //phpcs:ignore - 8.1 proof
420 - // Connect engine does not return number of rows updated
421 - // Presuming update was successful when no error message was returned
422 - $msg = new WPDA_Message_Box(array(
423 - 'message_text' => $this->wpda_success_msg,
424 - ));
425 - $msg->box();
426 - return;
427 - }
428 - // Nothing to update.
429 - $msg = new WPDA_Message_Box(array(
430 - 'message_text' => __( 'Nothing to save', 'wp-data-access' ),
431 - ));
432 - $msg->box();
433 - } else {
434 - // An error occurred.
435 - $msg = new WPDA_Message_Box(array(
436 - 'message_text' => ( '' === $wpdadb->last_error ? $this->wpda_failure_msg : $this->wpda_failure_msg . ' [' . $wpdadb->last_error . ']' ),
437 - 'message_type' => 'error',
438 - 'message_is_dismissible' => false,
439 - ));
440 - $msg->box();
441 - }
442 - }
443 - }
444 - }
103 + $this->schema_name = $schema_name;
104 + $this->table_name = $table_name;
445 105
446 - public static function convert_datetime( $column_type, $column_value, $error_value = null ) {
447 - if ( null === $column_value || '' === $column_value ) {
448 - return null;
449 - }
450 - switch ( $column_type ) {
451 - case 'time':
452 - $date_format = WPDA::get_option( WPDA::OPTION_PLUGIN_TIME_FORMAT );
453 - $db_format = WPDA::DB_TIME_FORMAT;
454 - break;
455 - case 'date':
456 - $date_format = WPDA::get_option( WPDA::OPTION_PLUGIN_DATE_FORMAT );
457 - $db_format = WPDA::DB_DATE_FORMAT;
458 - break;
459 - default:
460 - $date_format = WPDA::get_option( WPDA::OPTION_PLUGIN_DATE_FORMAT ) . ' ' . WPDA::get_option( WPDA::OPTION_PLUGIN_TIME_FORMAT );
461 - $db_format = WPDA::DB_DATETIME_FORMAT;
462 - }
463 - $convert_date = \DateTime::createFromFormat( $date_format, $column_value );
464 - if ( false !== $convert_date ) {
465 - $converted_value = $convert_date->format( $db_format );
466 - } else {
467 - $converted_value = $error_value;
468 - }
469 - return $converted_value;
470 - }
106 + // Table must exist and user must be authorized.
107 + $this->wpda_data_dictionary = new WPDA_Dictionary_Exist( $this->schema_name, $this->table_name );
108 + if ( ! $this->wpda_data_dictionary->table_exists() ) {
109 + wp_die( esc_html__( 'ERROR: Invalid table name or not authorized' ) );
110 + }
111 +
112 + $this->calling_form = $calling_form;
113 +
114 + $this->wpda_list_columns = $wpda_list_columns;
115 +
116 + $this->wpda_success_msg = $wpda_success_msg;
117 + $this->wpda_failure_msg = $wpda_failure_msg;
118 +
119 + }
120 +
121 + /**
122 + * Is data valid?
123 + *
124 + * @since 1.0.0
125 + *
126 + * @return bool TRUE = data is valid (as far as validation is possible)
127 + */
128 + public function is_valid() {
129 +
130 + $no_errors = true;
131 + $auto_increment_column_name = $this->wpda_list_columns->get_auto_increment_column_name();
132 +
133 + foreach ( $this->wpda_list_columns->get_table_columns() as $column ) {
134 +
135 + if ( $column['column_name'] !== $auto_increment_column_name ) {
136 + // Get column value.
137 + $column_value = $this->calling_form->get_new_value( $column['column_name'] );
138 +
139 + // Check if null value is allowed.
140 + if ( 'NO' === $column['is_nullable'] ) {
141 + // Null values are not allowed for this column: check value.
142 + if ( '' === $column_value ) {
143 + // No value: inform user and set validation to failed.
144 + $msg = new WPDA_Message_Box(
145 + [
146 + 'message_text' => ucfirst( str_replace( '_', ' ', $column['column_name'] ) ) .
147 + ' ' . __( 'must be entered', 'wp-data-access' ),
148 + 'message_type' => 'error',
149 + 'message_is_dismissible' => false,
150 + ]
151 + );
152 + $msg->box();
153 + $no_errors = false;
154 + }
155 + }
156 +
157 + // Check if value matches data type (as far as possible).
158 + switch ( WPDA::get_type( $column['data_type'] ) ) {
159 + case 'number':
160 + // Check if input is numeric: also JS checked in form.
161 + if ( '' !== $column_value && ! is_numeric( $column_value ) ) {
162 + // Value is not numeric: inform user and set validation to failed.
163 + $msg = new WPDA_Message_Box(
164 + [
165 + 'message_text' => ucfirst( str_replace( '_', ' ', $column['column_name'] ) ) .
166 + ' ' . __( 'must be numeric', 'wp-data-access' ),
167 + 'message_type' => 'error',
168 + 'message_is_dismissible' => false,
169 + ]
170 + );
171 + $msg->box();
172 + $no_errors = false;
173 + }
174 + break;
175 + case 'date':
176 + // Too many formats for a simple dynamic solution.
177 + // TODO : Add generic date validation to the next release.
178 + break;
179 + case 'time':
180 + // Too many formats for a simple dynamic solution.
181 + // TODO : Add generic time validation to the next release.
182 + break;
183 + case 'enum':
184 + // Check if value in enum: also JS checked in form.
185 + // Get enum from MySQL table.
186 + $allowed_values = explode(
187 + ',',
188 + str_replace(
189 + '\'',
190 + '',
191 + substr( substr( $column['column_type'], 5 ), 0, -1 )
192 + )
193 + );
194 + $value_found = false;
195 + // Check if value is in enum.
196 + foreach ( $allowed_values as $allowed_value ) {
197 + if ( $allowed_value === $column_value ) {
198 + $value_found = true; // Value allowed.
199 + }
200 + }
201 + if ( ! $value_found ) {
202 + // Value not in enum: inform user and set validation to failed.
203 + $msg = new WPDA_Message_Box(
204 + [
205 + 'message_text' => 'Value for ' .
206 + str_replace( '_', ' ', $column['column_name'] ) .
207 + ' ' . __( 'not allowed', 'wp-data-access' ),
208 + 'message_type' => 'error',
209 + 'message_is_dismissible' => false,
210 + ]
211 + );
212 + $msg->box();
213 + $no_errors = false;
214 + }
215 + break;
216 + default: // string.
217 + // No check needed.
218 + }
219 + }
220 + }
221 +
222 + return $no_errors;
223 +
224 + }
225 +
226 + /**
227 + * Create new record
228 + *
229 + * Nothing to do!
230 + *
231 + * @since 1.0.0
232 + *
233 + * @return null
234 + */
235 + public function new_row() {
236 +
237 + return null;
238 +
239 + }
240 +
241 + /**
242 + * Add records to database table
243 + *
244 + * @since 1.0.0
245 + *
246 + * @return bool TRUE = record successfully added to table
247 + */
248 + public function add_row() {
249 +
250 + global $wpdb;
251 +
252 + $column_values_to_be_inserted = null;
253 + foreach ( $this->wpda_list_columns->get_table_columns() as $column ) {
254 +
255 + $column_values_to_be_inserted[ $column['column_name'] ] =
256 + $this->calling_form->get_new_value( $column['column_name'] );
257 +
258 + }
259 +
260 + if ( '' === $this->schema_name || $wpdb->dbname === $this->schema_name ) {
261 + // Table is located in WordPress schema.
262 + $result = $wpdb->insert(
263 + $this->table_name,
264 + $column_values_to_be_inserted
265 + ); // db call ok; no-cache ok.
266 + } else {
267 + // Table is located in another schema.
268 + $db = new \wpdb( DB_USER, DB_PASSWORD, $this->schema_name, DB_HOST );
269 + $result = $db->insert(
270 + $this->table_name,
271 + $column_values_to_be_inserted
272 + ); // db call ok; no-cache ok.
273 + $db->close();
274 + }
275 +
276 + if ( 1 === $result ) {
277 + $msg = new WPDA_Message_Box(
278 + [
279 + 'message_text' => $this->wpda_success_msg,
280 + ]
281 + );
282 + $msg->box();
283 +
284 + // If inserted record contains an auto_increment column: return value.
285 + if ( $this->wpda_list_columns->get_auto_increment_column_name() ) {
286 + return $wpdb->insert_id; // Return auto_increment value.
287 + } else {
288 + return true; // Return true = transaction succeeded.
289 + }
290 + } else {
291 + // An error occured.
292 + $msg = new WPDA_Message_Box(
293 + [
294 + 'message_text' => $this->wpda_failure_msg,
295 + 'message_type' => 'error',
296 + 'message_is_dismissible' => false,
297 + ]
298 + );
299 + $msg->box();
300 +
301 + return false; // Return false = transaction failed.
302 + }
303 +
304 + }
305 +
306 + /**
307 + * Get record from database table
308 + *
309 + * @since 1.0.0
310 + *
311 + * @param int $auto_increment_value Auto increment number (returned if provided by dbms).
312 + * @param string $wpda_err Error message to be shown on failure.
313 + * @return mixed
314 + */
315 + public function get_row( $auto_increment_value, $wpda_err ) {
316 +
317 + global $wpdb;
318 +
319 + $table_columns = []; // Get all table columns.
320 + foreach ( $this->wpda_list_columns->get_table_columns() as $column ) {
321 + $table_columns[ $column['column_name'] ] = $column['data_type'];
322 + }
323 +
324 + $where = ''; // Compose where clause.
325 + foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
326 + $where_current = '' === $where ? ' where ' : ' and ';
327 + if ( WPDA::get_type( $table_columns[ $pk_column ] ) === 'number' ) {
328 + // Column data type is numeric:
329 + // For numeric columns we need to omit quotes. All numeric values will be handled as float. MySQL
330 + // will automatically convert them if necessarry. Values supplied in a wrong format will be handed
331 + // over to MySQL as is and might result in unpredictable results. For our simple form we rely on
332 + // the users judgement.
333 + $where_current .= " `$pk_column` = %f";
334 + } else {
335 + // Column data type is string:
336 + // Quotes will be added to all non numeric values. We might have issues with date and time fields.
337 + // For our simple form we'll accept that limitation (at least for now).
338 + $where_current .= " `$pk_column` = %s";
339 + }
340 +
341 + if ( $auto_increment_value > -1 ) {
342 + // For inserts with auto_increment columns use $wpdb->insert_id.
343 + $pkvalue = $auto_increment_value;
344 + } else {
345 + if ( 0 === $wpda_err ) {
346 + // No errors: use new value.
347 + if ( $this->calling_form->get_new_value( $pk_column ) === '' ) {
348 + wp_die( esc_html__( 'ERROR: Wrong arguments', 'wp-data-access' ) );
349 + }
350 + $pkvalue = $this->calling_form->get_new_value( $pk_column );
351 + } else {
352 + // There are errors: use old values (in case a key value was changed).
353 + if ( $this->calling_form->get_old_value( $pk_column ) === '' ) {
354 + wp_die( esc_html__( 'ERROR: Wrong arguments', 'wp-data-access' ) );
355 + }
356 + $pkvalue = $this->calling_form->get_old_value( $pk_column );
357 + }
358 + }
359 +
360 + $where .= $wpdb->prepare( $where_current, $pkvalue ); // WPCS: unprepared SQL OK.
361 + }
362 +
363 + if ( '' === $this->schema_name ) {
364 + $query = "
365 + select *
366 + from `{$this->table_name}`
367 + $where
368 + ";
369 + } else {
370 + $query = "
371 + select *
372 + from `{$this->schema_name}`.`{$this->table_name}`
373 + $where
374 + ";
375 + }
376 + $result = $wpdb->get_results( $query, 'ARRAY_A' ); // WPCS: unprepared SQL OK; db call ok; no-cache ok.
377 +
378 + if ( 1 === $wpdb->num_rows ) {
379 + return $result;
380 + } else {
381 + wp_die( esc_html__( 'ERROR: Wrong arguments', 'wp-data-access' ) );
382 + }
383 +
384 + }
385 +
386 + /**
387 + * Update current record (write changes to database)
388 + *
389 + * @since 1.0.0
390 + */
391 + public function set_row() {
392 +
393 + global $wpdb;
394 +
395 + $column_values_to_be_updated = null;
396 + foreach ( $this->wpda_list_columns->get_table_columns() as $column ) {
397 + if ( $this->calling_form->get_old_value( $column['column_name'] ) !==
398 + $this->calling_form->get_new_value( $column['column_name'] )
399 + ) {
400 + $column_values_to_be_updated[ $column['column_name'] ] =
401 + $this->calling_form->get_new_value( $column['column_name'] );
402 + }
403 + }
404 +
405 + if ( null === $column_values_to_be_updated ) {
406 + // Nothing to update.
407 + $msg = new WPDA_Message_Box(
408 + [
409 + 'message_text' => __( 'Nothing to save', 'wp-data-access' ),
410 + ]
411 + );
412 + $msg->box();
413 + } else {
414 + // Write changes to database.
415 + $where = [];
416 + foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
417 + $action = $this->calling_form->get_form_action();
418 + $action2 = $this->calling_form->get_form_action2();
419 +
420 + if ( 'edit' === $action && 'save' === $action2 ) {
421 + // Form was submitted after update: use old key value to build where clause.
422 + if ( '' === $this->calling_form->get_old_value( $pk_column ) ) {
423 +
424 + wp_die( esc_html__( 'ERROR: Wrong arguments', 'wp-data-access' ) );
425 +
426 + }
427 + $where[ $pk_column ] = $this->calling_form->get_old_value( $pk_column ); // Set primary keys value(s).
428 + } else {
429 + // Form submitted a new record: use new value (no old value available).
430 + if ( $this->calling_form->get_new_value( $pk_column ) === '' ) {
431 + wp_die( esc_html__( 'ERROR: Wrong arguments', 'wp-data-access' ) );
432 + }
433 + $where[ $pk_column ] = $this->calling_form->get_new_value( $pk_column ); // Set primary keys value(s).
434 + }
435 + }
436 +
437 + if ( '' === $this->schema_name || $wpdb->dbname === $this->schema_name ) {
438 + // Table is located in WordPress schema.
439 + $result = $wpdb->update(
440 + $this->table_name,
441 + $column_values_to_be_updated,
442 + $where
443 + ); // db call ok; no-cache ok.
444 + } else {
445 + // Table is located in another schema.
446 + $db = new \wpdb( DB_USER, DB_PASSWORD, $this->schema_name, DB_HOST );
447 + $result = $db->update(
448 + $this->table_name,
449 + $column_values_to_be_updated,
450 + $where
451 + ); // db call ok; no-cache ok.
452 + $db->close();
453 + }
454 +
455 + if ( 1 === $result ) {
456 + // Since we are updating by key, result must be exactly 1 record.
457 + $msg = new WPDA_Message_Box(
458 + [
459 + 'message_text' => $this->wpda_success_msg,
460 + ]
461 + );
462 + $msg->box();
463 + } else {
464 + $wpdb->show_errors();
465 +
466 + // An error occured.
467 + $msg = new WPDA_Message_Box(
468 + [
469 + 'message_text' => $this->wpda_failure_msg,
470 + 'message_type' => 'error',
471 + 'message_is_dismissible' => false,
472 + ]
473 + );
474 + $msg->box();
475 + }
476 + }
477 +
478 + }
479 +
480 + }
471 481
472 482 }