File: /var/www/html/owlcrmlanding/wp-content/plugins/go-live-update-urls/src/Database.php
<?php
namespace Go_Live_Update_Urls;
use Go_Live_Update_Urls\Traits\Singleton;
/**
* Database manipulation.
*
* @author OnPoint Plugins
* @since 6.0.0
*/
class Database {
use Singleton;
/**
* Get list of tables we treat as serialized when updating
*
* @since 5.0.0
*
* @return array<string, string> - array( %table_name% => %table_column% )
*/
public function get_serialized_tables() {
global $wpdb;
// Default tables with serialized data.
$serialized_tables = [
$wpdb->options => 'option_value',
$wpdb->postmeta => 'meta_value',
$wpdb->commentmeta => 'meta_value',
$wpdb->signups => 'meta',
$wpdb->termmeta => 'meta_value',
$wpdb->usermeta => 'meta_value',
];
// We are not going to update site meta if we are not on the main blog.
if ( is_multisite() ) {
$serialized_tables[ $wpdb->sitemeta ] = 'meta_value';
$serialized_tables[ $wpdb->blogmeta ] = 'meta_value';
}
return apply_filters( 'go-live-update-urls/database/serialized-tables', $serialized_tables );
}
/**
* Get the list of tables that were not create by WP core
*
* @return string[]
*/
public function get_custom_plugin_tables(): array {
$core_tables = $this->get_core_tables();
$all_tables = $this->get_all_table_names();
$all_tables = \array_flip( $all_tables );
foreach ( $core_tables as $_table ) {
unset( $all_tables[ $_table ] );
}
return (array) apply_filters( 'go-live-update-urls/database/plugin-tables', \array_keys( $all_tables ) );
}
/**
* Get the list of WP core tables
*
* @since 4.0.0
*
* @return string[]
*/
public function get_core_tables() {
global $wpdb;
$tables = [
$wpdb->posts,
$wpdb->comments,
$wpdb->options,
$wpdb->postmeta,
$wpdb->terms,
$wpdb->term_taxonomy,
$wpdb->term_relationships,
$wpdb->termmeta,
$wpdb->commentmeta,
$wpdb->users,
$wpdb->usermeta,
];
if ( isset( $wpdb->links ) ) {
$tables[] = $wpdb->links;
}
if ( is_multisite() ) {
$tables[] = $wpdb->blogs;
$tables[] = $wpdb->signups;
$tables[] = $wpdb->site;
$tables[] = $wpdb->sitemeta;
$tables[] = $wpdb->sitecategories;
$tables[] = $wpdb->registration_log;
// WP 5.0.0+.
if ( isset( $wpdb->blogmeta ) ) {
$tables[] = $wpdb->blogmeta;
}
}
return (array) apply_filters( 'go-live-update-urls/database/core-tables', $tables );
}
/**
* Get types of MySQL fields which may contain URLS.
*
* Only fields of these types will be updated.
*
* @since 6.1.0
*
* @return string[]
*/
public function get_column_types(): array {
$types = [
'char',
'longtext',
'longtext',
'mediumtext',
'text',
'tinytext',
'varchar',
];
return (array) apply_filters( 'go-live-update-urls/database/column-types', $types, $this );
}
/**
* Get the names of every table in this blog
* If we are multisite, we also get the global tables.
*
* @since 5.0.1
*
* @return string[]
*/
public function get_all_table_names() {
global $wpdb;
$query = "SELECT TABLE_NAME as TableName FROM information_schema.TABLES WHERE TABLE_SCHEMA='" . $wpdb->dbname . "' AND TABLE_NAME LIKE '" . $wpdb->esc_like( $wpdb->prefix ) . "%'";
// Site 1's 'LIKE wp_%' will return all tables in the database,
// so we exclude all possible sub sites (e.g., wp_2, wp_3 up to 9).
$not_like = '';
if ( 1 === (int) $wpdb->blogid && is_multisite() ) {
for ( $i = 1; $i <= 9; $i ++ ) {
$not_like .= $wpdb->prepare( '%s,', $wpdb->prefix . $i );
}
$query .= ' AND SUBSTRING(TABLE_NAME,1,4) NOT IN (' . substr( $not_like, 0, - 1 ) . ')';
}
return $wpdb->get_col( $query );
}
/**
* Make the actual changes to the database
*
* @since 5.0.0
*
* @param string $old_url - the old URL.
* @param string $new_url - the new URL.
* @param string[] $tables - the tables we are going to update.
*
* @return array<string, int>
*/
public function update_the_database( $old_url, $new_url, array $tables ): array {
do_action( 'go-live-update-urls/database/before-update', $old_url, $new_url, $tables, $this );
$tables = apply_filters( 'go-live-update-urls/database/update-tables', $tables, $this );
$updates = Updates::factory( $old_url, $new_url, $tables );
$counts = $updates->update_serialized_values();
foreach ( (array) $tables as $_table ) {
if ( ! \array_key_exists( $_table, $counts ) ) {
$counts[ $_table ] = 0;
}
$counts[ $_table ] += $updates->update_table_columns( $_table );
}
$counts = apply_filters( 'go-live-update-urls/database/updated/counts', $counts, $old_url, $new_url, $tables, $this );
do_action( 'go-live-update-urls/database/after-update', $old_url, $new_url, $tables, $this );
return $counts;
}
/**
* Count all occurrences of the old URL within a provided
* list of tables.
*
* @since 5.0.0
*
* @param string $old_url - the old URL.
* @param string $new_url - the new URL.
* @param string[] $tables - the tables we are going to update.
*
* @return int[]
*/
public function count_database_urls( string $old_url, string $new_url, array $tables ): array {
do_action( 'go-live-update-urls/database/before-counting', $old_url, $new_url, $tables, $this );
$tables = apply_filters( 'go-live-update-urls/database/update-tables', $tables, $this );
$updates = Updates::factory( $old_url, $new_url, $tables );
$counts = [];
foreach ( (array) $tables as $_table ) {
$counts[ $_table ] = $updates->count_table_urls( $_table );
}
$counts = (array) apply_filters( 'go-live-update-urls/database/counted/counts', $counts, $old_url, $new_url, $tables, $this );
do_action( 'go-live-update-urls/database/after-counting', $old_url, $new_url, $tables, $this );
return $counts;
}
/**
* Update an individual table's column.
*
* @since 5.3.0
*
* @param string $table - Table to update.
* @param string $column - Column to update.
* @param string $old_url - Old URL.
* @param string $new_url - New URL.
*
* @return int
*/
public function update_column( $table, $column, $old_url, $new_url ): int {
global $wpdb;
$count = $this->count_column_urls( $table, $column, $old_url );
$update_query = 'UPDATE ' . $table . ' SET `' . $column . '` = replace(`' . $column . '`, %s, %s)';
if ( $this->supports_skipping( $table ) ) {
$skip = esc_sql( implode( ',', (array) Skip_Rows::instance()->get_skipped( $table ) ) );
$primary = esc_sql( (string) Skip_Rows::instance()->get_primary_key( $table ) );
$update_query .= " WHERE `{$primary}` NOT IN ({$skip})";
}
$wpdb->query( $wpdb->prepare( $update_query, [ $old_url, $new_url ] ) );
return $count;
}
/**
* Count of number of rows in a table which contain the old URL.
*
* When updating, the serialized data is updated first and this
* counts the leftovers.
*
* During dry-run counting, this will count all occurrences in the
* database.
*
* @since 6.1.0
*
* @param string $table - Table to update.
* @param string $column - Column to update.
* @param string $old_url - Old URL.
*
* @return int
*/
public function count_column_urls( $table, $column, $old_url ): int {
global $wpdb;
$query = "SELECT SUM( ROUND( ( LENGTH( `{$column}` ) - LENGTH( REPLACE( `{$column}`, %s, '' ) ) ) / LENGTH( %s ) ) ) from `{$table}`";
return (int) $wpdb->get_var( $wpdb->prepare( $query, [ $old_url, $old_url ] ) );
}
/**
* Does this table support skipping rows?
*
* 1. Does it have rows to skip?
* 2. Does the filter allow skipping?
*
* @since 6.5.0
*
* @param string $table - Database table.
*
* @return bool
*/
protected function supports_skipping( $table ) {
if ( null === Skip_Rows::instance()->get_skipped( $table ) || null === Skip_Rows::instance()->get_primary_key( $table ) ) {
return false;
}
return (bool) apply_filters( 'go-live-update-urls-pro/database/supports-skipping', true, $table, $this );
}
}