get_var( "SELECT TABLE_COLLATION FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = '{$wpdb->posts}' LIMIT 1" ); if (empty($collation) && !empty($wpdb->collate)) { $collation = $wpdb->collate; } if (empty($collation)) { $collation = 'utf8mb4_unicode_ci'; } return ($memo = $collation); } } if (!function_exists('aieo_get_wp_charset')) { function aieo_get_wp_charset() { global $wpdb; static $memo = null; if ($memo !== null) { return $memo; } $charset = $wpdb->get_var( "SELECT CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = '{$wpdb->posts}' AND COLUMN_NAME = 'post_title' LIMIT 1" ); if (empty($charset) && !empty($wpdb->charset)) { $charset = $wpdb->charset; } if (empty($charset)) { $charset = 'utf8mb4'; } $memo = $charset; return $charset; } } if (!function_exists('aieo_analytics_target_collation')) { function aieo_analytics_target_collation() { $collation = (string) aieo_get_wp_collation(); return 0 === strpos($collation, 'utf8mb4_') ? $collation : 'utf8mb4_unicode_ci'; } } if (!function_exists('aieo_analytics_collation')) { function aieo_analytics_collation($refresh = false) { global $wpdb; static $memo = null; if ($memo !== null && !$refresh) { return $memo; } $collation = (string) $wpdb->get_var($wpdb->prepare( 'SELECT TABLE_COLLATION FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s', $wpdb->prefix . 'aieo_order_stats' )); if ('' === $collation) { $collation = aieo_analytics_target_collation(); } return ($memo = 0 === strpos($collation, 'utf8mb4_') ? $collation : 'utf8mb4_unicode_ci'); } } if (!function_exists('aieo_column_charset_collate')) { function aieo_column_charset_collate($table, $column) { global $wpdb; static $memo = array(); $key = $table . '.' . $column; if (isset($memo[$key])) { return $memo[$key]; } $row = $wpdb->get_row($wpdb->prepare( 'SELECT CHARACTER_SET_NAME AS cs, COLLATION_NAME AS co FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s AND COLUMN_NAME = %s', $table, $column )); $ok = $row && preg_match('/^\w+$/', (string) $row->cs) && preg_match('/^\w+$/', (string) $row->co); return ($memo[$key] = $ok ? "CHARACTER SET {$row->cs} COLLATE {$row->co}" : ''); } } if (!function_exists('aieo_db_supports_analytics')) { function aieo_db_supports_analytics() { global $wpdb; static $memo = null; if ($memo !== null) { return $memo; } $version = (string) $wpdb->get_var('SELECT VERSION()'); $number = preg_match('/(\d+\.\d+\.\d+)/', $version, $m) ? $m[1] : '0.0.0'; return ($memo = version_compare($number, false !== stripos($version, 'mariadb') ? '10.3.0' : '8.0.21', '>=')); } } if (!function_exists('aieo_get_charset_collate')) { function aieo_get_charset_collate() { $charset = aieo_get_wp_charset(); $collate = aieo_get_wp_collation(); $charset_collate = ''; if (!empty($charset)) { $charset_collate = "DEFAULT CHARACTER SET {$charset}"; } if (!empty($collate)) { $charset_collate .= " COLLATE {$collate}"; } return $charset_collate; } } if (!function_exists('aieo_dbdelta')) { function aieo_dbdelta($sql) { if (!function_exists('dbDelta')) { require_once ABSPATH . 'wp-admin/includes/upgrade.php'; } $clean = array(); foreach (preg_split('/\r\n|\r|\n/', (string) $sql) as $line) { $line = preg_replace('/(^|\s)--(\s.*)?$/', '', $line); if (trim($line) === '') { continue; } $clean[] = rtrim($line); } $sql = implode("\n", $clean); if (preg_match('/^\s*CREATE\s+TABLE\s+IF\s+NOT\s+EXISTS\s+`?([^\s`(]+)`?/i', $sql, $m)) { global $wpdb; if ((int) $wpdb->get_var($wpdb->prepare('SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s', $m[1]))) { return array(); } $wpdb->query($sql); return '' === $wpdb->last_error ? array($m[1] => 'Created table ' . $m[1]) : array(); } return dbDelta($sql); } } if (!function_exists('aieo_boot_schema_should_run')) { function aieo_boot_schema_should_run($key) { if (!is_admin() && !(defined('WP_CLI') && WP_CLI) && !wp_doing_cron()) { return false; } $version = defined('AIEO_VERSION') ? AIEO_VERSION : '0'; return get_option('aieo_boot_schema_' . $key) !== $version && AIEO_Schema_Lock::acquire('aieo_boot_schema_' . $key); } } if (!function_exists('aieo_boot_schema_done')) { function aieo_boot_schema_done($key) { update_option('aieo_boot_schema_' . $key, defined('AIEO_VERSION') ? AIEO_VERSION : '0', true); } } if (!function_exists('aieo_dmm_forget_known_tables')) { function aieo_dmm_forget_known_tables() { delete_option('aieo_known_tables'); } } if (!function_exists('aieo_dmm_table_exists')) { function aieo_dmm_table_exists($table_name) { global $wpdb; static $known = null; $version = defined('AIEO_VERSION') ? AIEO_VERSION : '0'; if (null === $known) { $stored = get_option('aieo_known_tables'); $known = (is_array($stored) && isset($stored['v'], $stored['t']) && $stored['v'] === $version && is_array($stored['t'])) ? $stored['t'] : array(); } $key = (string) $table_name; if (isset($known[$key])) { return true; } $found = $wpdb->get_var($wpdb->prepare( "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s", $table_name )); $exists = ((int) $found) > 0; if ($exists) { $known[$key] = true; update_option('aieo_known_tables', array('v' => $version, 't' => $known), true); } return $exists; } } if (!function_exists('aieo_dmm_table_is_empty')) { function aieo_dmm_table_is_empty($table_name) { global $wpdb; if (!aieo_dmm_table_exists($table_name)) { return true; } $count = $wpdb->get_var("SELECT COUNT(*) FROM {$table_name}"); return ((int) $count) === 0; } } if (!function_exists('aieo_dmm_sanitize_role_column')) { function aieo_dmm_sanitize_role_column($role) { $clean = strtolower(preg_replace('/[^a-z0-9_]/', '_', $role)); if ($clean === '') { return 'role_r'; } if (preg_match('/^[0-9]/', $clean)) { $clean = 'r_' . $clean; } return 'role_' . $clean; } } require_once dirname(__FILE__) . '/../dmm/sql/dmm-schema.php'; function aieo_call_sproc( $sql, $installer, $method = 'query' ) { global $wpdb; $allowed = array( 'query', 'get_results', 'get_row', 'get_var', 'get_col' ); if ( ! in_array( $method, $allowed, true ) ) { $method = 'query'; } $prev_suppress = $wpdb->suppress_errors( true ); $wpdb->last_error = ''; $out = $wpdb->{$method}( $sql ); $err = (string) $wpdb->last_error; if ( '' === $err || false === stripos( $err, 'does not exist' ) ) { $wpdb->suppress_errors( $prev_suppress ); aieo_drain_sproc_results(); if ( '' !== $err ) { $wpdb->print_error( $err ); } return $out; } if ( ! is_callable( $installer ) ) { $wpdb->suppress_errors( $prev_suppress ); aieo_drain_sproc_results(); return $out; } if ( function_exists( 'aieo_debug_log' ) ) { aieo_debug_log( 'AIEO: stored routine missing (' . $err . ') — reinstalling and retrying once.' ); } call_user_func( $installer ); $wpdb->suppress_errors( $prev_suppress ); $wpdb->last_error = ''; $out = $wpdb->{$method}( $sql ); aieo_drain_sproc_results(); return $out; } function aieo_install_sproc_drain_guard() { static $installed = false; if ( $installed || ! function_exists( 'add_filter' ) ) { return; } $installed = true; add_filter( 'query', function ( $sql ) { $n = aieo_drain_sproc_results(); if ( $n > 0 ) { static $warned = false; if ( ! $warned ) { $warned = true; if ( function_exists( 'aieo_debug_log' ) ) { aieo_debug_log( sprintf( 'AIEO: drained %d abandoned result set(s) before a query — a stored-procedure CALL ' . 'bypassed aieo_call_sproc(). Next statement was: %s', $n, substr( (string) $sql, 0, 200 ) ) ); } } } return $sql; }, 0 ); } function aieo_drain_sproc_results() { global $wpdb; $dbh = isset( $wpdb->dbh ) ? $wpdb->dbh : null; if ( ! ( $dbh instanceof mysqli ) ) { return 0; } $n = 0; while ( $n < 100 && $dbh->more_results() ) { if ( ! $dbh->next_result() ) { if ( $dbh->errno ) { global $EZSQL_ERROR; $wpdb->last_error = $dbh->error; $EZSQL_ERROR[] = array( 'query' => $wpdb->last_query, 'error_str' => $dbh->error ); if ( function_exists( 'aieo_debug_log' ) ) { aieo_debug_log( 'AIEO: a stored procedure failed after its first result set: ' . $dbh->error . ' (' . substr( (string) $wpdb->last_query, 0, 200 ) . ')' ); } } break; } $r = $dbh->store_result(); if ( $r instanceof mysqli_result ) { $r->free(); } $n++; } return $n; } function aieo_sql_error_mark() { global $EZSQL_ERROR; return is_array( $EZSQL_ERROR ) ? count( $EZSQL_ERROR ) : 0; } function aieo_sql_errors_since( $mark ) { global $EZSQL_ERROR; if ( ! is_array( $EZSQL_ERROR ) ) { return array(); } return array_values( array_map( static function ( $e ) { return (string) ( is_array( $e ) && isset( $e['error_str'] ) ? $e['error_str'] : '' ); }, array_slice( $EZSQL_ERROR, (int) $mark ) ) ); } if (!function_exists('aieo_schema_version_satisfied')) { function aieo_schema_version_satisfied($installed, $target) { if (is_numeric($installed) && is_numeric($target)) { return (float) $installed >= (float) $target; } return (string) $installed === (string) $target; } } if (!function_exists('aieo_install_schema_once')) { function aieo_install_schema_once($option, $target, $installer, $lock_timeout = 5) { if (aieo_schema_version_satisfied(get_option($option, 0), $target)) { return false; } if (!AIEO_Schema_Lock::acquire($option, $lock_timeout)) { return false; } try { if (false === call_user_func($installer)) { return false; } update_option($option, $target, false); return true; } finally { AIEO_Schema_Lock::release($option); } } }