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

WPDA_Repository.php in WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards 5.5.23, at WPDataAccess/Utilities/WPDA_Repository.php

482 lines 14.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\Utilities
7 */
8
9 namespace WPDataAccess\Utilities {
10
11 use WPDataAccess\Data_Dictionary\WPDA_Dictionary_Exist;
12 use WPDataAccess\Plugin_Table_Models\WPDA_Logging_Model;
13 use WPDataAccess\Plugin_Table_Models\WPDA_Media_Model;
14 use WPDataAccess\Plugin_Table_Models\WPDA_Publisher_Model;
15 use WPDataAccess\Plugin_Table_Models\WPDA_Design_Table_Model;
16 use WPDataAccess\Plugin_Table_Models\WPDA_Table_Settings_Model;
17 use WPDataAccess\Plugin_Table_Models\WPDA_User_Menus_Model;
18 use WPDataAccess\Plugin_Table_Models\WPDP_Page_Model;
19 use WPDataAccess\Plugin_Table_Models\WPDP_Project_Model;
20 use WPDataAccess\Plugin_Table_Models\WPDP_Project_Design_Table_Model;
21 use WPDataAccess\WPDA;
22
23 /**
24 * Class WPDA_Repository
25 *
26 * Recreate repository objects.
27 *
28 * @author Peter Schulz
29 * @since 1.0.0
30 */
31 class WPDA_Repository {
32
33 const CREATE_TABLE = array(
34 'wpda_logging' => array(
35 'create_table_logging.sql',
36 ),
37 'wpda_menus' => array(
38 'create_table_menus.sql',
39 ),
40 'wpda_table_settings' => array(
41 'create_table_table_settings.sql',
42 ),
43 'wpda_table_design' => array(
44 'create_table_table_design.sql',
45 'create_table_table_design_alter1.sql',
46 'create_table_table_design_alter3.sql',
47 'create_table_table_design_alter3.sql',
48 ),
49 'wpda_publisher' => array( // Old plugin table name: do NOT change!
50 'create_table_publisher.sql',
51 ),
52 'wpda_media' => array(
53 'create_table_media.sql',
54 ),
55 'wpda_project' => array(
56 'create_table_project.sql',
57 ),
58 'wpda_project_page' => array(
59 'create_table_project_page.sql',
60 ),
61 'wpda_project_table' => array(
62 'create_table_project_table.sql',
63 ),
64 'wpda_csv_uploads' => array(
65 'create_table_csv_uploads.sql',
66 ),
67 'wpda_app' => array(
68 'create_table_app.sql',
69 ),
70 'wpda_app_container' => array(
71 'create_table_app_container.sql',
72 ),
73 'wpda_app_apps' => array(
74 'create_table_app_apps.sql',
75 ),
76 );
77
78 const DROP_TABLE = array(
79 'wpda_logging' => array(
80 'drop_table_logging.sql',
81 ),
82 'wpda_menus' => array(
83 'drop_table_menus.sql',
84 ),
85 'wpda_table_settings' => array(
86 'drop_table_table_settings.sql',
87 ),
88 'wpda_table_design' => array(
89 'drop_table_table_design.sql',
90 ),
91 'wpda_publisher' => array( // Old plugin table name: do NOT change!
92 'drop_table_publisher.sql',
93 ),
94 'wpda_media' => array(
95 'drop_table_media.sql',
96 ),
97 'wpda_project' => array(
98 'drop_table_project.sql',
99 ),
100 'wpda_project_page' => array(
101 'drop_table_project_page.sql',
102 ),
103 'wpda_project_table' => array(
104 'drop_table_project_table.sql',
105 ),
106 'wpda_csv_uploads' => array(
107 'drop_table_csv_uploads.sql',
108 ),
109 'wpda_app' => array(
110 'drop_table_app.sql',
111 ),
112 'wpda_app_container' => array(
113 'drop_table_app_container.sql',
114 ),
115 'wpda_app_apps' => array(
116 'drop_table_app_apps.sql',
117 ),
118 );
119
120 protected $sql_repository_dir = '';
121
122 public function __construct() {
123 $this->sql_repository_dir = plugin_dir_path( dirname( __FILE__ ) ) . '../admin/repository/';
124 }
125
126 /**
127 * Recreate repository (save as much data as possible)
128 *
129 * @since 2.0.11
130 */
131 public function recreate() {
132 global $wpdb;
133
134 $suppress = $wpdb->suppress_errors( true );
135
136 // Remove foreign key constraints on app tables
137 $wpdb->query(
138 "ALTER TABLE {$wpdb->prefix}wpda_app_apps DROP FOREIGN KEY `wp_wpda_app_apps_ibfk_1`"
139 );
140 $wpdb->query(
141 "ALTER TABLE {$wpdb->prefix}wpda_app_apps DROP FOREIGN KEY `wp_wpda_app_apps_ibfk_2`"
142 );
143 $wpdb->query(
144 "AlTER TABLE {$wpdb->prefix}wpda_app_container DROP FOREIGN KEY `wp_wpda_app_container_ibfk_1`"
145 );
146
147 $bck_postfix = WPDA_Restore_Repository::BACKUP_TABLE_EXTENSION . date( 'YmdHis' );
148 foreach ( static::CREATE_TABLE as $key => $value ) {
149 $table_name = $wpdb->prefix . $key;
150
151 // Check if table exists
152 $table_exists = new WPDA_Dictionary_Exist( $wpdb->dbname, $table_name );
153 $table_check = $table_exists->table_exists( false );
154
155 $bck_table_name = null;
156 $same_cols = null;
157
158 if ( $table_check ) {
159 // Create backup table
160 $bck_table_name = $wpdb->prefix . $key . $bck_postfix;
161 $wpdb->query(
162 $wpdb->prepare(
163 'create table `%1s` as select * from `%1s`', // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders
164 array(
165 WPDA::remove_backticks( $bck_table_name ),
166 WPDA::remove_backticks( $table_name ),
167 )
168 )
169 );
170 }
171
172 if ( $table_check ) {
173 // Create temporary table to check for changes
174 if ( $this->run_script( $value[0], '_new' ) ) {
175 // Check if table structure was changed
176 $table_diff = $wpdb->get_row(
177 $wpdb->prepare(
178 'select column_name,ordinal_position,data_type,column_type from (
179 select column_name, ordinal_position, data_type, column_type, count(1) rowcount
180 from information_schema.columns
181 where table_schema = %s
182 and table_name in (%s,%s)
183 group by column_name, ordinal_position, data_type, column_type
184 having count(1) = 1
185 ) A',
186 $wpdb->dbname,
187 $table_name,
188 "{$table_name}_new"
189 )
190 );
191
192 // Drop check table
193 $this->run_script( static::DROP_TABLE[ $key ][0], '_new' );
194
195 if ( $table_diff !== null ) {
196 // Drop old repository table
197 $this->run_script( static::DROP_TABLE[ $key ][0], '' );
198
199 // Create new repository table
200 foreach ( $value as $sql_file ) {
201 $this->run_script( $sql_file );
202 }
203
204 // Get columns matching old and new repository table columns to restore as many values as possible
205 $same_cols = $wpdb->get_results(
206 $wpdb->prepare(
207 'select c1.column_name as column_name
208 from information_schema.columns c1
209 where c1.table_schema = %s
210 and c1.table_name = %s
211 and c1.column_name in (
212 select c2.column_name
213 from information_schema.columns c2
214 where c2.table_schema = %s
215 and c2.table_name = %s
216 )
217 ',
218 $wpdb->dbname,
219 $table_name,
220 $wpdb->dbname,
221 $bck_table_name
222 ),
223 'ARRAY_A'
224 );
225
226 // Restore repository table data
227 $selected_columns = '';
228 foreach ( $same_cols as $same_col ) {
229 $selected_columns .= $same_col['column_name'] . ',';
230 }
231 $selected_columns = substr( $selected_columns, 0, strlen( $selected_columns ) - 1 );
232 $wpdb->query(
233 $wpdb->prepare(
234 'insert into `%1s` (%1s) select %1s from `%1s`', // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders
235 array(
236 WPDA::remove_backticks( $table_name ),
237 $selected_columns,
238 $selected_columns,
239 WPDA::remove_backticks( $bck_table_name ),
240 )
241 )
242 );
243 }
244 }
245 } else {
246 // Create table
247 foreach ( $value as $sql_file ) {
248 $this->run_script( $sql_file );
249 }
250 }
251
252 if ( 'on' !== WPDA::get_option( WPDA::OPTION_MR_KEEP_BACKUP_TABLES ) ) {
253 // Drop backup table
254 $this->run_script( static::DROP_TABLE[ $key ][0], $bck_postfix );
255 }
256 }
257
258 $this->cleanup();
259 $this->remove_old_backups();
260
261 $wpdb->suppress_errors( $suppress );
262 }
263
264 public function remove_old_backups() {
265 if ( 'on' === WPDA::get_option( WPDA::OPTION_MR_KEEP_BACKUP_TABLES ) ) {
266 $backup_tables_kept = WPDA::get_option( WPDA::OPTION_MR_BACKUP_TABLES_KEPT );
267 $base_table_name = WPDA_Publisher_Model::get_base_table_name() . WPDA_Restore_Repository::BACKUP_TABLE_EXTENSION;
268
269 global $wpdb;
270 $rows = $wpdb->get_results(
271 $wpdb->prepare(
272 '
273 select table_name as table_name
274 from information_schema.tables
275 where table_schema = %s
276 and table_name like %s
277 order by 1 desc
278 ',
279 array(
280 $wpdb->dbname,
281 "{$base_table_name}%",
282 )
283 ),
284 'ARRAY_A'
285 );
286
287 for ( $i = $backup_tables_kept; $i < count( $rows ); $i ++ ) {//phpcs:ignore - 8.1 proof
288 $backup_date = substr( $rows[ $i ]['table_name'], strlen( $base_table_name ) );
289 $this->remove_backup( $backup_date );
290 }
291 }
292 }
293
294 public function remove_backup( $backup_date ) {
295 global $wpdb;
296 $backup_date_sanitized = WPDA::remove_backticks( $backup_date );
297
298 $suppress = $wpdb->suppress_errors( true );
299 $extension = WPDA_Restore_Repository::BACKUP_TABLE_EXTENSION;
300 foreach ( self::CREATE_TABLE as $key => $value ) {
301 $wpdb->query(
302 $wpdb->prepare(
303 'drop table `%1s`', // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders
304 array(
305 WPDA::remove_backticks( "{$wpdb->prefix}{$key}{$extension}{$backup_date_sanitized}" ),
306 )
307 )
308 );
309 }
310 $wpdb->suppress_errors( $suppress );
311 }
312
313 /**
314 * Cleanup plugin repository tables
315 */
316 protected function cleanup() {
317 global $wpdb;
318
319 // Remove previous data table list table settings
320 $wpdb->query(
321 "delete from {$wpdb->prefix}usermeta where meta_key like '%columnshidden%' and meta_key like '%wpda_publisher%'"
322 );
323
324 // Remove previous project page list table settings
325 $wpdb->query(
326 "delete from {$wpdb->prefix}usermeta where meta_key like '%columnshidden%' and meta_key like '%wpda_project%'"
327 );
328
329 // Allow column to contain null values
330 $wpdb->query(
331 "alter table {$wpdb->prefix}wpda_project_page modify page_allow_full_export enum('yes','no') null default 'no'"
332 );
333
334 // Remove material sort icons from data tables
335 $wpdb->query(
336 "update {$wpdb->prefix}wpda_publisher set pub_sort_icons = 'default' where pub_sort_icons = 'plugin'"
337 );
338 $wpdb->query(
339 "alter table {$wpdb->prefix}wpda_publisher modify pub_sort_icons enum('default','none')"
340 );
341
342 // Remove plugin configuration settings: wrong values installed with 5.0.0 (needs to be reset on next deployment)
343 delete_option( 'wpda_plugin_navigation' );
344 delete_option( 'wpda_plugin_hide_notices' );
345 }
346
347 /**
348 * Create repository
349 *
350 * @since 1.0.0
351 */
352 public function create() {
353 foreach ( static::CREATE_TABLE as $key => $value ) {
354 foreach ( $value as $sql_file ) {
355 $this->run_script( $sql_file );
356 }
357 }
358 }
359
360 /**
361 * Drop repository
362 *
363 * @since 1.0.0
364 */
365 public function drop() {
366 foreach ( static::DROP_TABLE as $key => $value ) {
367 foreach ( $value as $sql_file ) {
368 $this->run_script( $sql_file );
369 }
370 }
371 }
372
373 /**
374 * Run SQL script file
375 *
376 * @param string $sql_file SQL script file name
377 * @param string $wpda_postfix WPDA postfix
378 *
379 * @return mixed Result of the query taken from the SQL script file
380 *
381 * @since 2.0.11
382 */
383 public function run_script( $sql_file, $wpda_postfix = '' ) {
384 $sql_repository_file = $this->sql_repository_dir . $sql_file;
385 $sql_repository_handle = fopen( $sql_repository_file, 'r' );
386
387 if ( $sql_repository_handle ) {
388 // Read file content and close handle.
389 $sql_repository_file_content = fread( $sql_repository_handle, filesize( $sql_repository_file ) );
390 fclose( $sql_repository_handle );
391
392 global $wpdb;
393
394 // Replace WP prefix and WPDA prefix.
395 $sql_repository_file_content = str_replace( '{wp_prefix}', $wpdb->prefix, $sql_repository_file_content );
396 $sql_repository_file_content = str_replace( '{wpda_prefix}', 'wpda', $sql_repository_file_content ); // for backward compatibility
397 $sql_repository_file_content = str_replace( '{wpda_postfix}', $wpda_postfix, $sql_repository_file_content );
398 $sql_repository_file_content = str_replace( '{wpda_collate}', $wpdb->get_charset_collate(), $sql_repository_file_content );
399
400 // Run script from admin/repository.
401 return $wpdb->query( $sql_repository_file_content ); // phpcs:ignore WordPress.DB.PreparedSQL
402 }
403 }
404
405
406 /**
407 * Inform user if repository is invalid
408 *
409 * @since 1.0.0
410 */
411 public function inform_user() {
412 if ( ! is_admin() ) {
413 return;
414 }
415
416 if ( isset( $_REQUEST['setup_error'] ) && 'off' === $_REQUEST['setup_error'] ) {
417 // Turn off menu management not available message.
418 WPDA::set_option( WPDA::OPTION_WPDA_SETUP_ERROR, 'off' );
419 } else {
420 if ( 'off' !== WPDA::get_option( WPDA::OPTION_WPDA_SETUP_ERROR ) ) {
421 // Check if repository tables exist.
422 if ( ! WPDA_User_Menus_Model::table_exists() ||
423 ! WPDA_Design_Table_Model::table_exists() ||
424 ! WPDP_Project_Design_Table_Model::table_exists() ||
425 ! WPDA_Publisher_Model::table_exists() ||
426 ! WPDA_Logging_Model::table_exists() ||
427 ! WPDA_Media_Model::table_exists() ||
428 ! WPDP_Project_Model::table_exists() ||
429 ! WPDP_Page_Model::table_exists() ||
430 ! WPDA_Table_Settings_Model::table_exists()
431 ) {
432 $msg = new WPDA_Message_Box(
433 array(
434 'message_text' =>
435 __( 'Some features of WP Data Access are currently not available.', 'wp-data-access' ) .
436 ' ' .
437 __( 'ACTION', 'wp-data-access' ) .
438 ': ' .
439 '<a href="?page=wpdataaccess&tab=repository">' . __( 'Recreate repository', 'wp-data-access' ) . '</a>' .
440 ' ' .
441 __( 'to to solve this problem.', 'wp-data-access' ) .
442 ' [' .
443 '<a href="?' . esc_url( sanitize_text_field( wp_unslash( $_SERVER['QUERY_STRING'] ) ) ) . '&setup_error=off">' . __( 'do not show this message again', 'wp-data-access' ) . '</a>' .
444 ']',
445 )
446 );
447
448 $msg->box();
449 }
450 }
451 }
452 }
453
454 public function create_new_backup() {
455 global $wpdb;
456
457 $bck_postfix = WPDA_Restore_Repository::BACKUP_TABLE_EXTENSION . date( 'YmdHis' );
458 foreach ( static::CREATE_TABLE as $key => $value ) {
459 $table_name = $wpdb->prefix . $key;
460
461 // Check if table exists
462 $table_exists = new WPDA_Dictionary_Exist( $wpdb->dbname, $table_name );
463
464 if ( $table_exists->table_exists( false ) ) {
465 // Create backup table
466 $wpdb->query(
467 $wpdb->prepare(
468 'create table `%1s` as select * from `%1s`', // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders
469 array(
470 WPDA::remove_backticks( $wpdb->prefix . $key . $bck_postfix ),
471 WPDA::remove_backticks( $table_name ),
472 )
473 )
474 ); // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.UnquotedComplexPlaceholder
475 }
476 }
477 }
478
479 }
480
481 }
482