PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.7.0
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.7.0
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
wp-optimize / includes / class-wp-optimize-database-information.php

class-wp-optimize-database-information.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 4.7.0, at includes/class-wp-optimize-database-information.php

806 lines 21.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) die('No direct access allowed');
4
5 class WP_Optimize_Database_Information {
6
7 const UNKNOWN_DB = 'unknown';
8 const MARIA_DB = 'MariaDB';
9 const PERCONA_DB = 'Percona';
10 // for some reason coding standard parser give error here WordPress.DB.RestrictedFunctions.mysql_mysql_db
11 const MYSQL_DB = 'MysqlDB';
12
13 const MYISAM_ENGINE = 'MyISAM';
14 const MEMORY_ENGINE = 'Memory';
15 const INNODB_ENGINE = 'InnoDB';
16 const ARCHIVE_ENGINE = 'ARCHIVE';
17 const CSV_ENGINE = 'CSV';
18 const NDB_ENGINE = 'NDB';
19 const ARIA_ENGINE = 'Aria'; // MariaDB
20 const VIEW = 'VIEW';
21
22 /**
23 * Returns singleton instance object
24 *
25 * @return WP_Optimize_Database_Information Returns `WP_Optimize_Database_Information` object
26 */
27 public static function instance() {
28 static $_instance = null;
29 if (null === $_instance) {
30 $_instance = new self();
31 }
32 return $_instance;
33 }
34
35 /**
36 * Returns server type MySQL or MariaDB if mysql database or Unknown if not mysql.
37 *
38 * @return string
39 */
40 public function get_server_type() {
41 global $wpdb;
42 static $server_type = null;
43
44 if (!$wpdb->is_mysql) return self::UNKNOWN_DB;
45
46 if (null !== $server_type) return $server_type;
47
48 $server_type = self::MYSQL_DB;
49
50 $variables = $wpdb->get_results('SHOW SESSION VARIABLES LIKE "version%"');
51
52 if (!empty($variables)) {
53 foreach ($variables as $variable) {
54 if (preg_match('/mariadb/i', $variable->Value)) {
55 $server_type = self::MARIA_DB;
56 }
57 if (preg_match('/percona/i', $variable->Value)) {
58 $server_type = self::PERCONA_DB;
59 }
60 }
61 }
62
63 return $server_type;
64 }
65
66 /**
67 * Returns database server version
68 *
69 * @return string|bool
70 */
71 public function get_version() {
72 $version = $this->get_option_value('version');
73
74 if (!empty($version)) {
75 if (preg_match('/^(\d+)(\.\d+)+/', $version, $match)) {
76 return $match[0];
77 }
78 }
79
80 return false;
81 }
82
83 /**
84 * Return the table type by $table_name.
85 *
86 * @param string $table_name Database table name.
87 * @param object|null $table_info Optional pre-fetched table status object (e.g. from a bulk fetch), to avoid a redundant lookup.
88 * @return string|boolean - returns false upon failure
89 */
90 public function get_table_type($table_name, $table_info = null) {
91 if (null === $table_info) $table_info = $this->get_table_status($table_name);
92
93 if ($table_info) {
94 if (!$table_info->Engine && $this->is_view($table_name)) return self::VIEW;
95
96 return $table_info->Engine;
97 }
98
99 return false;
100 }
101
102 /**
103 * Returns information about database table.
104 *
105 * @param string $table_name
106 * @param bool $update if true, then force request to database and don't use cached values.
107 * @return mixed
108 */
109 public function get_table_status($table_name, $update = false) {
110 $tables_info = $this->get_show_table_status($update, $table_name);
111
112 foreach ($tables_info as $table_info) {
113 if ($table_name === $table_info->Name) return $table_info;
114 }
115
116 return false;
117 }
118
119 /**
120 * Count the tables in the database
121 *
122 * @param string $prefix The generic prefix of the tables in the database
123 * @param bool $update if true, then force request to database and don't use cached values.
124 * @return int
125 */
126 public function get_table_count($prefix = '', $update = false) {
127 global $wpdb;
128 static $table_counts = array();
129
130 if (!$update && isset($table_counts[$prefix])) return $table_counts[$prefix];
131
132 $table_counts[$prefix] = (int) $wpdb->get_var(
133 $wpdb->prepare(
134 "SELECT COUNT(1)
135 FROM INFORMATION_SCHEMA.TABLES
136 WHERE TABLE_SCHEMA = %s
137 AND TABLE_NAME LIKE %s",
138 DB_NAME,
139 $prefix . '%'
140 )
141 );
142
143 return $table_counts[$prefix];
144 }
145
146 /**
147 * Get all tables names from information_schema
148 *
149 * @param string $prefix The global table prefix
150 * @param int $offset Paginate the result to avoid request timeout for large table counts
151 * @param int $limit Pagination size
152 * @return array
153 */
154 public function get_tables_names($prefix = '', $offset = 0, $limit = null) {
155 global $wpdb;
156
157 $sql = "SELECT *
158 FROM INFORMATION_SCHEMA.TABLES
159 WHERE TABLE_SCHEMA = %s
160 AND TABLE_NAME LIKE %s";
161
162 $params = array(DB_NAME, $prefix . '_%');
163
164 if (null !== $limit) {
165 $sql .= " LIMIT %d, %d";
166 $params[] = (int) $offset;
167 $params[] = (int) $limit;
168 }
169
170 $result = $wpdb->get_results($wpdb->prepare($sql, $params)); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- $sql only contains static text and %s/%d placeholders, passed through $wpdb->prepare()
171
172 $names = array();
173 foreach ($result as $row) {
174 $names[] = $row->TABLE_NAME;
175 }
176
177 return $names;
178 }
179
180 /**
181 * Returns result for query SHOW TABLE STATUS.
182 *
183 * @param bool $update refresh or no cached data
184 * @return array|object|stdClass[]|null
185 */
186 public function get_show_table_status($update = false, $table_name = '') {
187 global $wpdb;
188 static $tables_info = array();
189 static $fetched_all_tables = false;
190
191 if ($fetched_all_tables && !$update) {
192 return $tables_info;
193 }
194
195 // If a table name is provided, and the whole record hasn't been fetched yet, only fetch the information for the current table.
196 // This allows for a big performance gain when using WP-CLI or doing single optimizations.
197 if ($table_name && !$fetched_all_tables) {
198 $tables_info = $wpdb->get_results($wpdb->prepare("SHOW TABLE STATUS LIKE %s", $table_name));
199 } else {
200 if ($update || empty($tables_info) || !is_array($tables_info) || !$fetched_all_tables) {
201 $tables_info = $wpdb->get_results('SHOW TABLE STATUS');
202 $fetched_all_tables = true;
203 foreach ($tables_info as $i => $table) {
204 $rows_count = get_transient('wpo_' . $table->Name . '_count');
205 if (false === $rows_count) break;
206 $tables_info[$i]->Rows = $rows_count;
207 }
208 }
209 }
210
211 // If option innodb_file_per_table is disabled then Data_free column will have summary overhead value for all table.
212 if (!empty($tables_info)) {
213 foreach ($tables_info as $i => $table) {
214 if (self::INNODB_ENGINE == $table->Engine && !$this->is_option_enabled('innodb_file_per_table')) {
215 $tables_info[$i]->Data_free = 0;
216 }
217 }
218 }
219
220 return $tables_info;
221 }
222
223 /**
224 * Whether a table exists
225 *
226 * @param string $table_name Name of the table
227 * @param bool $use_default_prefix Whether to use default prefix
228 * @return boolean
229 */
230 public function table_exists($table_name, $use_default_prefix = true) {
231 global $wpdb;
232 return null !== $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $wpdb->esc_like($use_default_prefix ? $wpdb->prefix.$table_name : $table_name)));
233 }
234
235 /**
236 * Returns result for query SHOW FULL TABLES as associative array [table_name] => table_type.
237 *
238 * @return array
239 */
240 public function get_show_full_tables() {
241 global $wpdb;
242
243 static $tables_info = array();
244
245 if (empty($tables_info) || !is_array($tables_info)) {
246 $_tables_info = $wpdb->get_results('SHOW FULL TABLES', ARRAY_N);
247
248 if (!empty($_tables_info)) {
249 foreach ($_tables_info as $row) {
250 $tables_info[$row[0]] = $row[1];
251 }
252 }
253 }
254
255 return $tables_info;
256 }
257
258 /**
259 * Checks if table is a VIEW.
260 *
261 * @param string $table_name
262 * @return bool
263 */
264 public function is_view($table_name) {
265 $tables_info = $this->get_show_full_tables();
266
267 if (!array_key_exists($table_name, $tables_info)) return false;
268
269 return ('VIEW' === $tables_info[$table_name]);
270 }
271
272 /**
273 * Returns true if DDL supported.
274 *
275 * @return bool
276 */
277 public function has_online_ddl() {
278 if (self::MYSQL_DB === $this->get_server_type()) {
279 if (version_compare($this->get_version(), '5.7', '>=')) {
280 return true;
281 } else {
282 return false;
283 }
284 } elseif (self::MARIA_DB === $this->get_server_type()) {
285 if (version_compare($this->get_version(), '10.0.0', '>=')) {
286 return true;
287 } else {
288 return false;
289 }
290 }
291
292 return false;
293 }
294
295 /**
296 * Returns database option variable
297 *
298 * @param string $option_name Name of database option.
299 * @return mixed|null
300 */
301 public function get_option_value($option_name) {
302 global $wpdb;
303 static $options = array();
304
305 if (array_key_exists($option_name, $options)) return $options[$option_name];
306
307 $option = $wpdb->get_row(
308 $wpdb->prepare('SHOW SESSION VARIABLES LIKE %s', $option_name)
309 );
310
311 if (!empty($option)) {
312 $options[$option_name] = $option->Value;
313 return $option->Value;
314 }
315
316 return null;
317 }
318
319 /**
320 * Returns true if database option $option_name
321 *
322 * @param string $option_name Name of database option name.
323 * @return bool
324 */
325 public function is_option_enabled($option_name) {
326 $option_value = $this->get_option_value($option_name);
327
328 return 'ON' === strtoupper($option_value);
329 }
330
331 /**
332 * Returns true if table $table_name is optimizable
333 *
334 * @param string $table_name Name of database table
335 * @param string|bool $table_type Optional pre-resolved table engine/type, to avoid a redundant lookup.
336 * @return bool
337 */
338 public function is_table_optimizable($table_name, $table_type = null) {
339 $server_type = $this->get_server_type();
340 $server_version = $this->get_version();
341 $table_type = null !== $table_type ? $table_type : $this->get_table_type($table_name);
342
343 // return true if table is MyISAM.
344 if (self::MYISAM_ENGINE === $table_type) return true;
345
346 // return true if table is Archive or Aria.
347 if (self::ARCHIVE_ENGINE === $table_type || self::ARIA_ENGINE === $table_type) return true;
348
349 // if InnoDB then check if we can optimize.
350 if (self::INNODB_ENGINE === $table_type) {
351 // check for MysqlDB.
352 if (self::MYSQL_DB === $server_type && $this->has_online_ddl()) {
353 return true;
354 }
355
356 // check for MariaDB.
357 if (self::MARIA_DB === $server_type) {
358 // if innodb_file_per_table enabled or version not older than 10.1.1 and innodb_defragment enabled.
359 if ($this->is_option_enabled('innodb_file_per_table') || (version_compare($server_version, '10.1.1', '>=') && $this->is_option_enabled('innodb_defragment'))) {
360 return true;
361 }
362 }
363 }
364
365 // otherwise return false.
366 return false;
367 }
368
369 /**
370 * Returns true if the table type is supported for optimization.
371 *
372 * @param string $table_name Name of database table
373 * @param string|bool $table_type Optional pre-resolved table engine/type, to avoid a redundant lookup.
374 * @return bool
375 */
376 public function is_table_type_optimize_supported($table_name, $table_type = null) {
377 $table_type = null !== $table_type ? $table_type : $this->get_table_type($table_name);
378
379 $supported_table_types = array(
380 self::MYISAM_ENGINE,
381 self::INNODB_ENGINE,
382 self::ARCHIVE_ENGINE,
383 self::ARIA_ENGINE,
384 );
385
386 return in_array($table_type, $supported_table_types);
387 }
388
389 /**
390 * Returns true if table type is supported for repair.
391 *
392 * @param string $table_name
393 * @param string|bool $table_type Optional pre-resolved table engine/type, to avoid a redundant lookup.
394 * @return bool
395 */
396 public function is_table_type_repair_supported($table_name, $table_type = null) {
397 $table_type = null !== $table_type ? $table_type : $this->get_table_type($table_name);
398
399 $supported_table_types = array(
400 self::MYISAM_ENGINE,
401 self::ARCHIVE_ENGINE,
402 self::CSV_ENGINE,
403 );
404
405 return in_array($table_type, $supported_table_types);
406 }
407
408 /**
409 * Run CHECK TABLE query and returns statuses for single or list of tables.
410 *
411 * @param array|string $table
412 * @return array
413 */
414 public function check_table($table) {
415 global $wpdb;
416
417 if (is_array($table)) {
418 $table = join('`,`', $table);
419 }
420
421 $result = array();
422
423 if (empty($table)) return $result;
424
425 $query_result = $wpdb->get_results('CHECK TABLE `'. esc_sql($table).'`;');
426
427 if (empty($query_result)) return $result;
428
429 foreach ($query_result as $row) {
430 $table_name_parts = explode('.', rtrim($row->Table, ' .'));
431 $table_name = array_pop($table_name_parts);
432
433 if (!array_key_exists($table_name, $result)) {
434 $result[$table_name] = array(
435 'status' => '',
436 'corrupted' => false,
437 );
438 }
439
440 if ('error' === $row->Msg_type) {
441 $result[$table_name]['status'] = $row->Msg_type;
442
443 if (preg_match('/corrupt/i', $row->Msg_text)) {
444 $result[$table_name]['corrupted'] = true;
445 } else {
446 $result[$table_name]['message'] = $row->Msg_text;
447 }
448 }
449
450 if ('status' === $row->Msg_type) {
451 $result[$table_name]['status'] = $row->Msg_text;
452 }
453 }
454
455 return $result;
456 }
457
458 /**
459 * Check all supported for repair tables and return statuses for them.
460 *
461 * @return array
462 */
463 public function check_all_tables() {
464 static $result = null;
465
466 if (null !== $result) return $result;
467
468 $tables = $this->get_show_table_status();
469 $supported_tables = array();
470
471 foreach ($tables as $table) {
472 if ('' === $table->Engine || $this->is_table_type_repair_supported($table->Name, $table->Engine)) {
473 $supported_tables[] = $table->Name;
474 }
475 }
476
477 $result = $this->check_table($supported_tables);
478
479 return $result;
480 }
481
482 /**
483 * Returns true if table needing repair.
484 *
485 * @param string $table_name Database table name.
486 * @param string|bool $table_type Optional pre-resolved table engine/type, to avoid a redundant lookup.
487 */
488 public function is_table_needing_repair($table_name, $table_type = null) {
489 $table_statuses = $this->check_all_tables();
490
491 if (!$this->is_table_type_repair_supported($table_name, $table_type)) return false;
492
493 return (array_key_exists($table_name, $table_statuses) && $table_statuses[$table_name]['corrupted']);
494 }
495
496 /**
497 * Check if any of plugins from $plugin_names is installed.
498 *
499 * @param array $plugin_names
500 * @return bool
501 */
502 public function is_any_plugin_installed($plugin_names) {
503
504 if (empty($plugin_names)) {
505 return false;
506 }
507
508 // is WordPress core table or using by any of installed plugins then return true.
509 foreach ($plugin_names as $plugin_name) {
510 // $plugin_name is a translatable string, so we compare it with a translated string
511 if (__('WordPress core', 'wp-optimize') === $plugin_name || in_array($plugin_name, $this->get_all_installed_plugins())) {
512 return true;
513 }
514 }
515
516 return false;
517 }
518
519 /**
520 * Get blog_id
521 *
522 * @param string $table_name
523 * @return int
524 */
525 public function get_table_blog_id($table_name) {
526 global $wpdb;
527
528 if (is_multisite()) {
529 $blogs_ids = wp_list_pluck(WP_Optimize()->get_sites(), 'blog_id');
530
531 // if match with base_prefix_(number)_
532 if (preg_match('/^'.$wpdb->base_prefix.'(\d+)_/', $table_name, $match)) {
533 // check if matched number in available sites.
534 if (in_array($match[1], $blogs_ids)) return absint($match[1]);
535 }
536 }
537
538 return 1;
539 }
540
541 /**
542 * Get information about relations between tables and plugins. [ 'table' => ['plugin1', 'plugin2', ...], ... ].
543 *
544 * @return array
545 */
546 private function get_all_plugin_tables_relationship() {
547 static $plugin_tables = array();
548
549 if (!empty($plugin_tables)) return $plugin_tables;
550
551 $wp_core_tables = array(
552 'blogs',
553 'blog_versions',
554 'commentmeta',
555 'comments',
556 'links',
557 'options',
558 'postmeta',
559 'posts',
560 'registration_log',
561 'signups',
562 'term_relationships',
563 'term_taxonomy',
564 'termmeta',
565 'terms',
566 'usermeta',
567 'users',
568 'site',
569 'sitemeta',
570 );
571
572 $plugin_tables_json_file = $this->get_plugin_json_file_path();
573 $fallback_plugin_tables_json_file = WPO_PLUGIN_MAIN_PATH.'plugin.json';
574
575 if (is_file($plugin_tables_json_file) && is_readable($plugin_tables_json_file)) {
576 // get data from plugin.json file.
577 $plugin_tables = json_decode(file_get_contents($plugin_tables_json_file), true);
578 }
579
580 // Fallback to the bundled version if the list is empty
581 if (empty($plugin_tables)) {
582 if (is_file($fallback_plugin_tables_json_file) && is_readable($fallback_plugin_tables_json_file)) {
583 // get data from the bundled plugin.json file.
584 $plugin_tables = json_decode(file_get_contents($fallback_plugin_tables_json_file), true);
585 }
586 }
587
588 foreach ($wp_core_tables as $table) {
589 $plugin_tables[$table][] = __('WordPress core', 'wp-optimize');
590 }
591
592 // add WP-Optimize tables.
593 $wpo = 'wp-optimize';
594 $plugin_tables['tm_taskmeta'] = $plugin_tables['tm_taskmeta'] ?? array();
595 $plugin_tables['tm_tasks'] = $plugin_tables['tm_tasks'] ?? array();
596
597 if (!in_array($wpo, $plugin_tables['tm_taskmeta'], true)) {
598 $plugin_tables['tm_taskmeta'][] = $wpo;
599 }
600
601 if (!in_array($wpo, $plugin_tables['tm_tasks'], true)) {
602 $plugin_tables['tm_tasks'][] = $wpo;
603 }
604
605 return $plugin_tables;
606 }
607
608 /**
609 * Try to get plugin name by table name and return it or return false if plugin is not defined.
610 *
611 * @param string $table
612 * @return array|bool - array with plugin slugs or false.
613 */
614 public function get_table_plugin($table) {
615 global $wpdb;
616
617 $plugins = array();
618 $original_table = $table;
619 // delete table prefix.
620 $table = preg_replace('/^'.$wpdb->prefix.'([0-9]+_)?/', '', $table);
621 $plugins_tables = $this->get_all_plugin_tables_relationship();
622
623 // If a direct match exists.
624 if (array_key_exists($table, $plugins_tables)) {
625 $plugins = $plugins_tables[$table];
626 }
627
628 // if has pro_quiz in name then try to match with learndash tables.
629 if (false !== stripos($original_table, 'pro_quiz')) {
630 $match_learndash_tables_plugin = $this->match_learndash_tables_plugin($original_table);
631
632 if (!empty($match_learndash_tables_plugin)) {
633 $plugins = array_merge($plugins, $match_learndash_tables_plugin);
634 }
635 }
636
637 if (!empty($plugins)) {
638 return array_unique($plugins);
639 }
640
641 return false;
642 }
643
644 /**
645 * Get the path where the updated plugin.json is stored
646 *
647 * @return string
648 */
649 private function get_plugin_json_file_path() {
650 $uploads_dir = wp_upload_dir(null, false);
651 $filtered_path = apply_filters('wpo_get_plugin_json_file_path', trailingslashit($uploads_dir['basedir']).'wpo/wpo-plugins-tables-list.json');
652 return is_string($filtered_path) ? $filtered_path : '';
653 }
654
655 /**
656 * Get all installed plugin slugs.
657 *
658 * @return array
659 */
660 public function get_all_installed_plugins() {
661 static $installed_plugins;
662
663 if (is_array($installed_plugins)) return $installed_plugins;
664
665 $installed_plugins = array();
666
667 if (!function_exists('get_plugins')) include_once(ABSPATH.'wp-admin/includes/plugin.php');
668
669 $plugins = get_plugins();
670
671 foreach ($plugins as $plugin_file => $plugin_data) {
672 if ('' !== $plugin_data['TextDomain']) {
673 $installed_plugins[] = $plugin_data['TextDomain'];
674 } else {
675 $plugin_file_parts = explode('/', $plugin_file);
676 $installed_plugins[]= $plugin_file_parts[0];
677 }
678 }
679
680 return $installed_plugins;
681 }
682
683 /**
684 * Check current plugin status installed/not installed and active/inactive.
685 *
686 * @param string $plugin
687 * @return array - ['installed' => true|false, 'active' => true|false]
688 */
689 public function get_plugin_status($plugin) {
690
691 if (!function_exists('get_plugins')) include_once(ABSPATH.'wp-admin/includes/plugin.php');
692 $plugins = get_plugins();
693
694 // return true for wp-optimize without checking.
695 if ('wp-optimize' === $plugin) {
696 return array(
697 'installed' => true,
698 'active' => true,
699 );
700 }
701
702 $installed = false;
703 $active = false;
704
705 foreach ($plugins as $plugin_file => $plugin_data) {
706 $plugin_file_parts = explode('/', $plugin_file);
707 $plugin_slug = $plugin_file_parts[0] ?? '';
708
709 if ($plugin === $plugin_slug) {
710 $installed = true;
711 $active = is_plugin_active($plugin_file);
712 }
713 }
714
715 return array(
716 'installed' => $installed,
717 'active' => $active,
718 );
719 }
720
721 /**
722 * Update list in plugin.json, if necessary
723 *
724 * @return void
725 */
726 public function update_plugin_json() {
727 // Add the possibility to turn this off.
728 if (!apply_filters('wpo_update_plugin_json', true)) return;
729
730 $update_request = wp_remote_get('https://plugins.svn.wordpress.org/wp-optimize/trunk/plugin.json', array('timeout' => 3000));
731 if (200 !== wp_remote_retrieve_response_code($update_request)) return;
732 $json_content = wp_remote_retrieve_body($update_request);
733 if (json_decode($json_content)) {
734 // phpcs:disable
735 // WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents -- WP_Filesystem not available this early
736 // Generic.PHP.NoSilencedErrors.Discouraged -- suppress PHP warning in case of failure
737 if (false === @file_put_contents($this->get_plugin_json_file_path(), $json_content)) {
738 error_log("WP-Optimize: wpo-plugins-tables-list.json couldn't be updated");
739 return;
740 }
741 // phpcs:enable
742 $this->change_plugin_json_permissions();
743 }
744 }
745
746 /**
747 * Set permissions to 640 for plugin.json
748 *
749 * @return void
750 */
751 public function change_plugin_json_permissions() {
752 $plugin_json_file_path = $this->get_plugin_json_file_path();
753 // phpcs:disable
754 // Generic.PHP.NoSilencedErrors.Discouraged -- suppress PHP warning in case of failure
755 if (is_file($plugin_json_file_path)) {
756 @chmod($plugin_json_file_path, 0640);
757 }
758 // phpcs:enable
759 }
760
761 /**
762 * Cache all table rows count
763 */
764 public function wpo_update_record_count() {
765 global $wpdb;
766 $tables_info = $wpdb->get_results('SHOW TABLE STATUS');
767 foreach ($tables_info as $table) {
768 $rows_count = $wpdb->get_var("SELECT COUNT(*) FROM `" . esc_sql($table->Name) . "`");
769 set_transient('wpo_' . $table->Name . '_count', $rows_count, 24*60*60);
770 }
771 }
772
773 /**
774 * Check if the give table name belongs to a LearnDash plugin table and return the plugin slug.
775 *
776 * @param string $table_name The original table name with prefix to check if it belongs to LearnDash plugin.
777 * @return array
778 */
779 private function match_learndash_tables_plugin($table_name) {
780
781 $table_names = array(
782 'pro_quiz_category',
783 'pro_quiz_form',
784 'pro_quiz_lock',
785 'pro_quiz_prerequisite',
786 'pro_quiz_question',
787 'pro_quiz_statistic',
788 'pro_quiz_statistic_ref',
789 'pro_quiz_template',
790 'pro_quiz_toplist',
791 );
792
793 $learndash_slug = 'sfwd-lms';
794
795 foreach ($table_names as $learndash_table) {
796 $table_suffix = substr($table_name, -strlen($learndash_table));
797
798 if ($table_suffix === $learndash_table) {
799 return array($learndash_slug);
800 }
801 }
802
803 return array();
804 }
805 }
806