Files
roi-theme/wp-content/plugins/wp-database-tools/includes/class-wp-database-tools-database-options.php
root a22573bf0b Commit inicial - WordPress Análisis de Precios Unitarios
- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 21:04:30 -06:00

543 lines
17 KiB
PHP
Executable File

<?php
/**
* Database functions
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
*/
/**
* Contains the functionalities related to database management.
*
* This class defines all code necessary to manage the database functionalities.
*
* @since 1.0.0
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
* @author Raiola Networks <info@raiolanetworks.es>
*/
class Wp_Database_Tools_Database_Options extends Wp_Database_Tools_Database {
/**
* All the information processed from the options
*
* @since 1.0.0
* @access protected
* @var array $data Options data.
*/
protected $data;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $count;
/**
* Initialize the class.
*
* @since 1.0.0
*
* @param array $plugins Values plugins.
* @param array $themes Values themes.
* @param String $matching Value of the source.
* @param String $license_status Value of the source.
*/
public function __construct( $plugins, $themes, $matching, $license_status ) {
$this->plugins = $plugins;
$this->themes = $themes;
$this->matching = $matching;
$this->license_status = $license_status;
// Set total count.
$this->check_count();
}
/**
* Sets the total number of records
*
* @since 1.0.0
*/
public function check_count() {
global $wpdb;
$num_rows = $wpdb->get_var( 'SELECT COUNT(option_id) FROM ' . $wpdb->prefix . "options WHERE option_name NOT LIKE ('%\_transient\_%')" );
$this->count = $num_rows;
}
/**
* Prepare data to loop over records
*
* @since 1.0.0
*/
private function prepare_data() {
// Custom key.
$this->key = 'options';
// Limit to query.
$this->limit = 1000;
// Multiples origins.
$this->is_multiple = false;
// Loading ajax call.
$this->current_loading = 0;
// Prepare data.
$this->full_data = parent::init_full_data();
// API data.
$this->api_data = parent::get_api_data( $this->key );
// Data loop transient.
$this->data_loop = parent::get_data_loop( $this->key );
// Feedback.
$this->feedback = parent::get_user_feedback( $this->key );
// Cache files.
$this->cache_data = parent::get_data_cache_indicator( $this->key );
// Force scanner active.
$this->force_execute_scanner = get_option( WPDBT_PREFIX . 'force_execute_scanner' );
// Load dependencies.
parent::load_dependencies_child( $this->key );
// Set transient loading.
parent::set_status_loading( 'loading', $this->current_loading, $this->data_loop, false );
}
/**
* Prepares the database data and applies the detection algorithm
*
* @since 1.0.0
*/
public function check_data() {
// TODO: Better way, loop json encode.
ini_set( 'memory_limit', '-1' );
set_time_limit( 0 );
$this->prepare_data();
// Options data.
global $wpdb;
$rows = $wpdb->get_results( 'SELECT *, LENGTH(option_id) + LENGTH(option_value) + LENGTH(option_name) + LENGTH(autoload) as size FROM ' . $wpdb->prefix . "options WHERE option_name NOT LIKE ('%\_transient\_%') LIMIT " . $this->limit . ' OFFSET ' . $this->data_loop['offset'] );
// Loading ajax call.
$max_loading = count( $rows );
// Count for cache.
$sql = $wpdb->prepare( 'SELECT SUM(%1s) AS sum_ids FROM %1s WHERE %1s NOT LIKE %s', 'option_id', $wpdb->prefix . 'options', 'option_name', '%_transient_%' );
$sum_ids = $wpdb->get_results( $sql );
$sum_ids = strval( $sum_ids[0]->sum_ids );
// Count ids from cache.
$sum_ids_cache = strval( array_sum( array_column( (array) $this->cache_data['source']['data'], 'id' ) ) );
if (
$sum_ids === $sum_ids_cache &&
$this->cache_data['indicators']->api === strlen( wp_json_encode( $this->api_data['source'] ) ) &&
$this->cache_data['indicators']->status === strlen( wp_json_encode( array( $this->feedback, $this->license_status ) ) )
) {
if ( ! empty( $this->cache_data['source'] ) && ! is_null( $this->cache_data['source'] ) ) {
if ( $this->license_status ) {
Wp_Database_Tools_Logger::info( 'OPTIONS: load data by cache' );
// Set data loop (total).
parent::set_data_loop( $this->limit, $this->data_loop['offset'], $this->count, $this->key );
$this->data_loop = parent::get_data_loop( $this->key );
$this->data = parent::calculate_data_source_size( $this->cache_data['source'] );
// Set status loading.
parent::set_status_loading( 'success', 100, $this->data_loop, true );
return;
}
}
} elseif ( false === $this->data_loop['is_finish'] ) {
// Count ids from cache.
if ( isset( $this->cache_data['source']['data'] ) ) {
$sum_ids_cache = strval( array_sum( array_column( $this->cache_data['source']['data'], 'id' ) ) );
$sum_ids_cache = ( $this->cache_data['indicators']->ids < $sum_ids && $this->data_loop['loops'] !== 1 ) ? $sum_ids_cache + $this->cache_data['indicators']->ids : $sum_ids_cache;
} elseif ( $this->cache_data['indicators']->ids > $sum_ids ) {
$sum_ids_cache = 0;
}
parent::set_cache_indicators( $this->key, $this->api_data['source'], $this->feedback, $sum_ids_cache );
}
Wp_Database_Tools_Logger::info( 'OPTIONS: starting to process data' );
// TODO: Pass cache management to other class
$cache_path = plugin_dir_path( __DIR__ ) . 'data/cache/' . WPDBT_PREFIX . $this->key;
// IF first loop reset cache file.
if ( 0 === $this->data_loop['offset'] ) {
$success_cache = file_put_contents( $cache_path . '_' . $this->key . '.json', wp_json_encode( mb_convert_encoding( array(), 'UTF-8' ) ) );
}
// Set data loop.
parent::set_data_loop( $this->limit, $this->data_loop['offset'], $this->count, $this->key );
// Get if finish.
$this->data_loop = parent::get_data_loop( $this->key );
Wp_Database_Tools_Logger::info( 'OPTIONS: ' . json_encode( $this->data_loop ) );
// Si ha finalizado establecesmos la data.
if ( true === $this->data_loop['is_finish'] ) {
// Get cache.
$this->cache_data['source'] = json_decode( file_get_contents( $cache_path . '_' . $this->key . '.json' ), true );
Wp_Database_Tools_Logger::info( 'OPTIONS: ending to process data ' . count( $this->cache_data['source'] ) );
// Get source data and calculate finihs size.
$this->data = parent::calculate_data_source_size( $this->cache_data['source'] );
// Set status loading.
parent::set_status_loading( 'success', 100, $this->data_loop, false );
// Reset values loop.
parent::remove_data_loop( $this->key );
return;
}
foreach ( $rows as $row_option ) {
$option = new Wp_Database_Tools_Database_Data_Option( $row_option, $this->feedback );
// sum size.
$this->full_data['size']['total']['value'] += $option->get_size();
if ( $option->get_autoload() == 'yes' ) {
$this->full_data['size']['autoload']['value'] += $option->get_size();
}
$key_api_data = false;
// If license is valid.
if ( $this->license_status ) {
// Prepare origin.
if ( $this->api_data['source'] != null ) {
$search_term = ( $option->get_regex() !== false )
? $option->get_regex()
: $option->get_name();
$key_api_data = array_keys( array_column( (array) $this->api_data['source'], 'name' ), $search_term );
}
// If key found.
if ( false !== $key_api_data && ! empty( $key_api_data ) ) {
// Check multiple only for verified registers.
$key_api_data_verified = $key_api_data;
foreach ( $key_api_data_verified as $index => $key ) {
if ( $this->api_data['source'][ $key ]->verified !== 1 ) {
unset( $key_api_data_verified[ $index ] );
}
}
$this->is_multiple = count( $key_api_data_verified ) > 1;
// Multiples values.
if ( $this->is_multiple ) {
$option->set_multiple( true );
$option->origin = array();
foreach ( $key_api_data_verified as $key ) {
$api_data = parent::set_data_api(
$this->api_data['source'][ $key ],
$this->api_data['plugins'],
$this->api_data['themes'],
$this->api_data['cores'],
$this->api_data['marketplaces'],
$this->api_data['authors'],
$this->key
);
$origin = new Wp_Database_Tools_Database_Data_Origin();
$origin->set_origin_by_api( $api_data, $this->key );
// Marketplace.
$marketplace = $origin->get_marketplace();
$origin->set_marketplace( $marketplace->return_object_vars() );
// Auhor.
$author = $origin->get_author();
$origin->set_author( $author->return_object_vars() );
// Origin.
$origin->set_status( $this->plugins, $this->themes );
$origin->set_question( $option->get_name() );
$this->full_data['origins'] = $origin->check_choices( $this->full_data['origins'] );
array_push( $option->origin, $origin->return_object_vars() );
}
// Simple values.
} else {
$this->is_multiple = false;
$key_api_data = $key_api_data[0];
$api_data = parent::set_data_api(
$this->api_data['source'][ $key_api_data ],
$this->api_data['plugins'],
$this->api_data['themes'],
$this->api_data['cores'],
$this->api_data['marketplaces'],
$this->api_data['authors'],
$this->key
);
$option->origin->set_origin_by_api( $api_data, $this->key );
$option->origin->set_question( $option->get_name() );
$option->origin->set_status( $this->plugins, $this->themes );
}
} else {
$this->is_multiple = false;
if ( 'NO' === $this->force_execute_scanner && false === $option->get_regex() ) {
$data_algorithm = $option->get_matching_data( $this->matching, $this->plugins, $this->themes, $option->get_name() );
if ( ! is_null( $data_algorithm ) ) {
$option->set_data_by_algorithm( $data_algorithm );
$option->origin->set_status( $this->plugins, $this->themes );
}
}
}
}
if ( ! $this->is_multiple ) {
$this->full_data['origins'] = $option->origin->check_choices( $this->full_data['origins'] );
// Marketplace.
$marketplace = $option->origin->get_marketplace();
$option->origin->set_marketplace( $marketplace->return_object_vars() );
// Auhor.
$author = $option->origin->get_author();
$option->origin->set_author( $author->return_object_vars() );
// Origin.
$option->set_origin( $option->origin->return_object_vars() );
}
$option_array = $option->return_object_vars( $option );
// Prevent encoding.
if ( ! mb_check_encoding( $option_array ) ) {
Wp_Database_Tools_Logger::error( 'OPTIONS: error encoding ' . $option_array['name'] );
continue;
}
if ( is_array( $option_array ) ) {
array_push( $this->full_data['data'], $option_array );
} else {
Wp_Database_Tools_Logger::error( 'OPTIONS: error add ' . $option_array['name'] );
continue;
}
parent::set_status_loading( 'loading', 100 * $this->current_loading / $max_loading, $this->data_loop, false );
$this->current_loading++;
// Memory optimization.
unset( $row_option );
}
$this->full_data['plugins'] = $this->plugins;
$this->full_data['themes'] = $this->themes;
// If it is finished we establish the data.
if ( false === $this->data_loop['is_finish'] ) {
// Get cache data.
$current_cache = json_decode( file_get_contents( $cache_path . '_' . $this->key . '.json' ), true );
// Encoding current data.
$new_cache = $this->full_data;
if ( ! isset( $new_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'OPTIONS: error data new cache not found' );
}
if ( ! isset( $current_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'OPTIONS: error data current cache not found' );
}
if ( mb_check_encoding( $this->full_data ) ) {
Wp_Database_Tools_Logger::info( 'OPTIONS: available encoding' );
try {
$new_cache = mb_convert_encoding( $this->full_data, 'UTF-8' );
} catch ( Exception $e ) {
$new_cache = $this->full_data;
Wp_Database_Tools_Logger::error( 'OPTIONS: the data cache has not been encoded properly' );
}
if ( $new_cache === null || ! isset( $new_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'OPTIONS: the data cache has not been encoded properly' );
$new_cache = $this->full_data;
}
}
if ( ! isset( $new_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'OPTIONS: error data new cache after encoding' );
}
if ( ! isset( $current_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'OPTIONS: error data current cache after encoding' );
}
// Merge data.
$current_cache = array_merge_recursive( $current_cache, $new_cache );
if ( ! isset( $current_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'OPTIONS: error merge options data' );
}
// Save data cache.
$current_cache = wp_json_encode( $current_cache );
$save_cache = file_put_contents( $cache_path . '_' . $this->key . '.json', $current_cache );
if ( false === $save_cache ) {
Wp_Database_Tools_Logger::error( 'OPTIONS: error save json' );
}
}
// Loading status.
parent::set_status_loading( 'loading', 0, $this->data_loop, false );
// Memory optimization.
unset( $this->full_data );
unset( $this->api_data );
unset( $this->cache_data );
unset( $new_cache );
unset( $current_cache );
gc_collect_cycles();
}
/**
* Call a specific method depending on the action to be performed.
*
* @since 1.0.0
*/
public function action_form() {
// TODO: nonce verification.
switch ( $_POST['action-type'] ) {
case 'delete':
$this->delete();
break;
case 'edit':
$this->edit();
break;
}
wp_redirect( $_POST['current-url'] . '&' . WPDBT_PREFIX . 'notice=options' );
}
/**
* Deletes the records that are indicated in $POST through keys.
* These keys are used in a query. The result is stored in a transient,
* which is then returned as a warning to the user..
*
* @since 1.0.0
*/
public function delete() {
// TODO: nonce verification.
$action_keys = $_POST['action-keys'];
$action_keys = explode( '↕', $action_keys );
$errors_messages = '';
$successes_messages = '';
$options_array_successes = array();
$options_array_errors = array();
foreach ( $action_keys as $option_key ) {
$option_delete = delete_option( $option_key );
if ( $option_delete === true ) {
array_push( $options_array_successes, $option_key );
} else {
array_push( $options_array_errors, $option_key );
}
}
if ( ! empty( $options_array_successes ) ) {
$successes_messages .= parent::generate_message_success( 'options', 'option_names', $options_array_successes, __( 'removed', 'wp-database-tools' ) );
set_transient( WPDBT_PREFIX . 'successes', $successes_messages );
}
if ( ! empty( $options_array_errors ) ) {
$errors_messages .= parent::generate_message_error( 'options', 'option_names', $options_array_errors, __( 'removed', 'wp-database-tools' ) );
set_transient( WPDBT_PREFIX . 'errors', $errors_messages );
}
parent::set_cache_indicators( 'options', 0, 0, 0 );
}
/**
* Edit the records that are indicated in $POST through keys.
* These keys are used in a query. The result is stored in a transient,
* which is then returned as a warning to the user..
*
* @since 1.0.0
*/
public function edit() {
// TODO: nonce verification.
$action_keys = $_POST['action-keys'];
$action_keys = explode( '↕', $action_keys );
$autoload = $_POST['autoload'];
$errors_messages = '';
$successes_messages = '';
$options_array_successes = array();
$options_array_errors = array();
foreach ( $action_keys as $option_key ) {
global $wpdb;
$table_name = $wpdb->prefix . 'options';
$sql = $wpdb->prepare( 'UPDATE %1s SET autoload = %s WHERE option_name LIKE %s', $table_name, $autoload, $option_key );
$resuls = $wpdb->get_results( $sql );
if ( ! empty( $resuls ) ) {
array_push( $options_array_errors, $option_key );
} else {
array_push( $options_array_successes, $option_key );
}
}
if ( ! empty( $options_array_successes ) ) {
$successes_messages .= parent::generate_message_success( 'options', 'option_names', $options_array_successes, __( 'edited', 'wp-database-tools' ) );
set_transient( WPDBT_PREFIX . 'successes', $successes_messages );
}
if ( ! empty( $options_array_errors ) ) {
$errors_messages .= parent::generate_message_error( 'options', 'option_names', $options_array_errors, __( 'edited', 'wp-database-tools' ) );
set_transient( WPDBT_PREFIX . 'errors', $errors_messages );
}
parent::set_cache_indicators( 'options', 0, 0, 0 );
}
/**
* The array of data of general database.
*
* @since 1.0.0
* @return array The array of data.
*/
public function get_data() {
$count_data = is_array( $this->data ) ? count( $this->data['data'] ) : 'null';
Wp_Database_Tools_Logger::info( 'OPTIONS: return data ' . $count_data );
return $this->data;
}
/**
* The array of data of general database.
*
* @since 1.0.0
* @return array The array of data.
*/
public function get_count() {
return $this->count;
}
}