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>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
<?php
/**
* Fired during plugin activation
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
*/
/**
* Fired during plugin activation.
*
* This class defines all code necessary to run during the plugin's activation.
*
* @since 1.0.0
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
* @author Raiola Networks <info@raiolanetworks.es>
*/
class Wp_Database_Tools_Activator {
/**
* Short Description. (use period)
*
* Long Description.
*
* @since 1.0.0
*/
public static function activate() {
// schedule cron job.
if ( ! wp_next_scheduled( 'wp_database_tools_scanner_database_daily' ) ) {
wp_schedule_event( time(), 'daily', 'wp_database_tools_scanner_database_daily' );
}
}
}

View File

@@ -0,0 +1,494 @@
<?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_Cronjobs extends Wp_Database_Tools_Database {
/**
* All the information processed from the cronjobs
*
* @since 1.0.0
* @access protected
* @var array $data Cronjobs data.
*/
protected $data;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $size;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $count;
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();
}
/**
* Prepare data to loop over records
*
* @since 1.0.0
*/
private function prepare_data() {
// Custom key.
$this->key = 'cronjobs';
// 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 );
}
/**
* Sets the total number of records
*
* @since 1.0.0
*/
public function check_count() {
$this->count = count( _get_cron_array() );
}
public function check_data() {
// TODO: Better way, loop json encode.
ini_set( 'memory_limit', '-1' );
set_time_limit( 0 );
$this->prepare_data();
// Cronjobs data.
global $wpdb;
$rows = _get_cron_array();
$sum_ids = array_sum( array_keys( $rows ) );
// Pagination.
$rows = array_slice( $rows, $this->data_loop['offset'], $this->limit, true );
$max_loading = count( $rows );
if (
$sum_ids === $this->cache_data['indicators']->ids &&
$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( 'CRONJOBS: 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 = $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'] ) ) {
/*
TODO: The data retrieved from the row as an array is different from what
is currently stored in the cache. A common data must be fetched in order to be able to compare the load.
*/
$sum_ids_cache = array_sum( array_keys( $rows ) );
$sum_ids_cache = ( $this->cache_data['indicators']->ids < $sum_ids ) ? $sum_ids_cache + $this->cache_data['indicators']->ids : $this->cache_data['indicators']->ids;
} else {
$sum_ids_cache = 0;
}
parent::set_cache_indicators( $this->key, $this->api_data['source'], $this->feedback, $sum_ids_cache + $this->cache_data['indicators']->ids );
}
Wp_Database_Tools_Logger::info( 'CRONJOBS: starting to process data' );
// Specific attributes.
$schedules = wp_get_schedules();
// 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 );
// 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( 'CRONJOBS: ending to process data ' . count( $this->cache_data['source'] ) );
// Get source data and calculate finihs size.
$this->data = $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 $timestamp => $events ) {
foreach ( $events as $event_hook => $event_args ) {
foreach ( $event_args as $event ) {
$cronjob = new Wp_Database_Tools_Database_Data_Cronjob( $schedules, $timestamp, $event_hook, $events, $event, $this->feedback );
$key_api_data = false;
// If license is valid.
if ( $this->license_status ) {
// Prepare origin.
if ( null !== $this->api_data['source'] ) {
$key_api_data = array_keys( array_column( (array) $this->api_data['source'], 'name' ), $cronjob->get_name() );
}
// 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 ) {
$cronjob->set_multiple( true );
$cronjob->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, 'cronjobs' );
// 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( $cronjob->get_name() );
$this->full_data['origins'] = $origin->check_choices( $this->full_data['origins'] );
array_push( $cronjob->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
);
$cronjob->origin->set_origin_by_api( $api_data, 'cronjobs' );
$cronjob->origin->set_question( $cronjob->get_name() );
$cronjob->origin->set_status( $this->plugins, $this->themes );
}
} else {
$this->is_multiple = false;
if ( $this->force_execute_scanner == 'NO' ) {
$data_algorithm = $cronjob->get_matching_data( $this->matching, $this->plugins, $this->themes, $cronjob->get_name() );
if ( ! is_null( $data_algorithm ) ) {
$cronjob->set_data_by_algorithm( $data_algorithm );
$cronjob->origin->set_status( $this->plugins, $this->themes );
}
}
}
}
if ( ! $this->is_multiple ) {
$this->full_data['origins'] = $cronjob->origin->check_choices( $this->full_data['origins'] );
// Marketplace.
$marketplace = $cronjob->origin->get_marketplace();
$cronjob->origin->set_marketplace( $marketplace->return_object_vars() );
// Auhor.
$author = $cronjob->origin->get_author();
$cronjob->origin->set_author( $author->return_object_vars() );
// Origin.
$cronjob->set_origin( $cronjob->origin->return_object_vars() );
}
$cronjob_array = $cronjob->return_object_vars( $cronjob );
// Prevent encoding.
if ( ! mb_check_encoding( $cronjob_array ) ) {
Wp_Database_Tools_Logger::error( 'CRONJOBS: error encoding ' . $cronjob_array['name'] );
continue;
}
if ( is_array( $cronjob_array ) ) {
array_push( $this->full_data['data'], $cronjob_array );
} else {
Wp_Database_Tools_Logger::error( 'CRONJOBS: error add ' . $cronjob_array['name'] );
continue;
}
parent::set_status_loading( 'loading', 100 * $this->current_loading / $max_loading, $this->data_loop, false );
$this->current_loading++;
}
}
// Memory optimization.
unset( $events );
}
$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( 'CRONJOBS: error data new cache not found' );
}
if ( ! isset( $current_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'CRONJOBS: error data current cache not found' );
}
if ( mb_check_encoding( $this->full_data ) ) {
Wp_Database_Tools_Logger::info( 'CRONJOBS: 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( 'CRONJOBS: the data cache has not been encoded properly' );
}
if ( $new_cache === null || ! isset( $new_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'CRONJOBS: the data cache has not been encoded properly' );
$new_cache = $this->full_data;
}
}
if ( ! isset( $new_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'CRONJOBS: error data new cache after encoding' );
}
if ( ! isset( $current_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'CRONJOBS: 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( 'CRONJOBS: error merge cronjobs 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( 'CRONJOBS: 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;
}
wp_redirect( $_POST['current-url'] . '&' . WPDBT_PREFIX . 'notice=cronjobs' );
}
/**
* 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 = '';
$hooks_array_successes = array();
$hooks_array_errors = array();
foreach ( $action_keys as $option_key ) {
$cronjob = explode( '↔', $option_key );
$hook = $cronjob[0];
$args = json_decode( html_entity_decode( $cronjob[1] ), true );
$timestamp = $cronjob[2];
$unscheduled = wp_unschedule_event( $timestamp, $hook, $args );
if ( is_wp_error( $unscheduled ) ) {
array_push( $hooks_array_errors, $hook );
} else {
array_push( $hooks_array_successes, $hook );
}
}
if ( ! empty( $hooks_array_successes ) ) {
$successes_messages .= parent::generate_message_success( 'cronjobs', 'hook_names', $hooks_array_successes, __( 'removed', 'wp-database-tools' ) );
set_transient( WPDBT_PREFIX . 'successes', $successes_messages );
}
if ( ! empty( $hooks_array_errors ) ) {
$errors_messages .= parent::generate_message_error( 'cronjobs', 'hook_names', $hooks_array_errors, __( 'removed', 'wp-database-tools' ) );
set_transient( WPDBT_PREFIX . 'errors', $errors_messages );
}
parent::set_cache_indicators( 'cronjobs', 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( 'CRONJOBS: 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_size() {
return $this->size;
}
/**
* The array of data of general database.
*
* @since 1.0.0
* @return array The array of data.
*/
public function get_count() {
return $this->count;
}
}

View File

@@ -0,0 +1,336 @@
<?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_General extends Wp_Database_Tools_Database {
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $data;
public function __construct() {
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wp-database-tools-logger.php';
}
public function check_data( $detail_post ) {
global $wpdb;
$this->data = array();
$detail_page = ( isset( $_GET['details'] ) ) ? $_GET['details'] : null;
if ( $detail_page == null ) {
$detail_page = ( $detail_post != null ) ? $detail_post : null;
}
// REVISIONS
$key = 'revision';
$query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total';
$revisions = parent::execute_simple_query( 'posts', "post_type = 'revision'", $key, 'Revisions', true, $query );
$this->data[ $key ] = $revisions[ $key ];
// Autodrafts
$key = 'autodraft';
$query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total';
$autodrafts = parent::execute_simple_query( 'posts', "post_status = 'auto-draft'", $key, 'Autodrafts', true, $query );
$this->data[ $key ] = $autodrafts[ $key ];
// Trashed posts
$key = 'trash-posts';
$query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total';
$trash_posts = parent::execute_simple_query( 'posts', "post_status = 'trash'", $key, 'Trashed posts', true, $query );
$this->data[ $key ] = $trash_posts[ $key ];
// Pending Comments
$key = 'pending-comments';
$query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total';
$pending_comments = parent::execute_simple_query( 'comments', "comment_approved = '0'", $key, 'Pending Comments', true, $query );
$this->data[ $key ] = $pending_comments[ $key ];
// Spam comments
$key = 'span-comments';
$query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total';
$span_comments = parent::execute_simple_query( 'comments', "comment_approved = 'spam'", $key, 'Spam Comments', true, $query );
$this->data[ $key ] = $span_comments[ $key ];
// Trashed comments
$key = 'trash-comments';
$query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total';
$trash_comments = parent::execute_simple_query( 'comments', "comment_approved = 'trash'", $key, 'Trashed comments', true, $query );
$this->data[ $key ] = $trash_comments[ $key ];
// Pingback comments
$key = 'pingback-comments';
$query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total';
$pingback = parent::execute_simple_query( 'comments', "comment_type = 'pingback'", $key, 'Pingback comments', true, $query );
$this->data[ $key ] = $pingback[ $key ];
// Trackback comments
$key = 'trackback-comments';
$query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total';
$trackback = parent::execute_simple_query( 'comments', "comment_type = 'trackback'", $key, 'Trackback comments', true, $query );
$this->data[ $key ] = $trackback[ $key ];
// Orphaned post meta
$key = 'orphaned-post-meta';
$table = 'postmeta';
$query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total';
// TODO: $wpdb->prepare
$orphaned_post_meta = parent::execute_complex_complex_query(
$table,
$query . ' FROM ' . $wpdb->prefix . $table . " pm LEFT JOIN {$wpdb->prefix}posts p ON p.ID = pm.post_id WHERE p.ID IS NULL",
$key,
'Orphaned post meta',
false,
);
$this->data[ $key ] = $orphaned_post_meta[ $key ];
// Orphaned comment meta
$key = 'orphaned-comment-meta';
$table = 'commentmeta';
$query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total';
// TODO: $wpdb->prepare
$orphaned_comment_meta = parent::execute_complex_complex_query(
$table,
$query . ' FROM ' . $wpdb->prefix . $table . " cm LEFT JOIN {$wpdb->prefix}comments c ON c.comment_id = cm.comment_id WHERE c.comment_id IS NULL",
$key,
'Orphaned comment meta',
false,
);
$this->data[ $key ] = $orphaned_comment_meta[ $key ];
// Orphaned user meta
$key = 'orphaned-user-meta';
$table = 'usermeta';
$query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total';
// TODO: $wpdb->prepare
$orphaned_user_meta = parent::execute_complex_complex_query(
$table,
$query . ' FROM ' . $wpdb->prefix . $table . " WHERE user_id NOT IN (SELECT ID FROM {$wpdb->prefix}users)",
$key,
'Orphaned user meta',
false,
);
$this->data[ $key ] = $orphaned_user_meta[ $key ];
// Orphaned term meta
$key = 'orphaned-term-meta';
$table = 'termmeta';
$table_name = $wpdb->prefix . $table;
$query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total';
// TODO: $wpdb->prepare
$orphaned_term_meta = parent::execute_complex_complex_query(
$table,
$query . ' FROM ' . $wpdb->prefix . $table . " WHERE term_id NOT IN (SELECT term_id FROM {$wpdb->prefix}terms)",
'orphaned-term-meta',
'Orphaned term meta',
false,
);
$this->data[ $key ] = $orphaned_term_meta[ $key ];
// Orphaned relationships
$key = 'orphaned-relationships-meta';
$table = 'term_relationships';
$table_name = $wpdb->prefix . $table;
$query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total';
$sql = $wpdb->prepare( '%1s FROM %1s WHERE term_taxonomy_id = %d AND object_id NOT IN (SELECT id FROM %1s)', $query, $table_name, 1, $wpdb->prefix . 'posts' );
$orphaned_relationships = parent::execute_complex_complex_query(
$table,
$sql,
$key,
'Orphaned relationships meta',
false,
);
$this->data[ $key ] = $orphaned_relationships[ $key ];
// Expired transients
$key = 'expired-transients';
$table = 'options';
$table_name = $wpdb->prefix . $table;
$time = isset( $_SERVER['REQUEST_TIME'] ) ? (int) $_SERVER['REQUEST_TIME'] : time();
$query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total';
$sql = $wpdb->prepare( "%1s FROM %1s WHERE option_name LIKE ('%\_transient_timeout\_%') AND option_value < %s ", $query, $table_name, $time );
$expired_transients = parent::execute_complex_complex_query(
$table,
$sql,
$key,
'Expired transients',
false,
);
$this->data[ $key ] = $expired_transients[ $key ];
}
/**
* 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 'edit':
$this->edit();
break;
case 'delete':
$this->delete();
break;
}
wp_redirect( $_POST['current-url'] . '&' . WPDBT_PREFIX . 'notice=general' );
}
public function loop_delete_data( $detele_array, $table, $is_days, $index_key, $delete_action ) {
$ids_array = array();
$meta_keys_array = array();
foreach ( $detele_array as $key => $row ) {
if ( $delete_action != 'all' ) {
if ( ! parent::can_delete( $is_days, $table, $index_key, $row ) ) {
set_transient( WPDBT_PREFIX . 'warning', true );
continue;
}
}
// Get data to call execute delete
array_push( $ids_array, parent::get_ID( $table, $row ) );
}
return array(
'ids' => $ids_array,
'meta_keys' => $meta_keys_array,
);
}
/**
* 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'];
$details = $_POST['action-is-details'];
$this->check_data( $details );
$action_keys = explode( '↕', $action_keys );
$delete_action = $_POST['action-delete'];
if ( 'no' !== $details ) {
// Prepare data.
$table = $this->data[ $details ]['table'];
$is_days = false;
$index_key = $details;
$array_data = $this->data[ $details ]['data'];
$allowed_keys = $action_keys;
$detele_array = array_intersect_key( $array_data, array_flip( $allowed_keys ) );
// Execute delete.
$info_for_delete = $this->loop_delete_data( $detele_array, $table, $is_days, $index_key, $delete_action );
parent::execute_delete( $table, $info_for_delete['ids'], $info_for_delete['meta_keys'] );
} else {
foreach ( $action_keys as $action_key ) {
$this->check_data( $action_key );
// Prepare data.
$table = $this->data[ $action_key ]['table'];
$is_days = $this->data[ $action_key ]['is-days'];
$index_key = $action_key;
$detele_array = $this->data[ $action_key ]['data'];
// Execute delete.
$info_for_delete = $this->loop_delete_data( $detele_array, $table, $is_days, $index_key, $delete_action );
if ( ! empty( $info_for_delete['ids'] ) ) {
parent::execute_delete( $table, $info_for_delete['ids'], $info_for_delete['meta_keys'] );
}
unset( $action_key );
}
}
}
/**
* 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.
// Save options days keep
$current_options = get_option( WPDBT_PREFIX . 'user_options_general' );
if ( ! $current_options ) {
$current_options = array(); }
// Current days selected.
$current_days_selected = $_POST['action-days'];
// Prepare data.
$action_keys = $_POST['action-keys'];
$action_keys = explode( '↕', $action_keys );
$action_days = $_POST['action-is-days'];
$action_days = explode( '↕', $action_days );
foreach ( $action_keys as $key => $value ) {
if ( $action_days[ $key ] == 'yes' ) {
$current_options[ $value ]['days'] = $current_days_selected;
}
}
update_option( WPDBT_PREFIX . 'user_options_general', $current_options );
}
/**
* The array of data of general database.
*
* @since 1.0.0
* @return array The array of data.
*/
public function get_data() {
return $this->data;
}
}

View File

@@ -0,0 +1,542 @@
<?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;
}
}

View File

@@ -0,0 +1,620 @@
<?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_Tables extends Wp_Database_Tools_Database {
/**
* All the information processed from the tables
*
* @since 1.0.0
* @access protected
* @var array $data Tables data.
*/
protected $data;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $size;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $count;
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();
}
public function check_count() {
global $wpdb;
$num_rows = $wpdb->get_var( "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '" . $wpdb->dbname . "'" );
$this->count = $num_rows;
}
/**
* Prepare data to loop over records
*
* @since 1.0.4
*/
private function prepare_data() {
// Custom key.
$this->key = 'tables';
// 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 );
}
public function check_data() {
// TODO: Better way, loop json encode.
ini_set( 'memory_limit', '-1' );
set_time_limit( 0 );
$this->prepare_data();
// Tables data.
global $wpdb;
$rows = $wpdb->get_results( 'SHOW table STATUS' );
// Loading ajax call.
$max_loading = count( $rows );
$sum_ids = $max_loading;
// Custom atributtes.
$db_size = 0;
if (
$sum_ids === $this->cache_data['indicators']->ids &&
$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'] ) ) {
Wp_Database_Tools_Logger::info( 'TABLES: cache data is ok' );
if ( $this->license_status ) {
Wp_Database_Tools_Logger::info( 'TABLES: license valid' );
// 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 );
// Log cache.
$count_data = is_array( $this->cache_data['source'] ) ? count( $this->cache_data['source']['data'] ) : 'null';
Wp_Database_Tools_Logger::info( 'TABLES: return data cache ' . $count_data );
$this->data = $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.
// In tables we only give a single loop.
$sum_ids_cache = $sum_ids;
parent::set_cache_indicators( $this->key, $this->api_data['source'], $this->feedback, $sum_ids_cache );
}
// 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 );
// 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( 'TABLES: 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_table ) {
$table = new Wp_Database_Tools_Database_Data_Table( $row_table, $this->feedback );
$db_size += $table->get_size();
$key_api_data = false;
// If license is valid.
if ( $this->license_status ) {
// Prepare origin.
if ( null !== $this->api_data['source'] ) {
$key_api_data = array_keys( array_column( $this->api_data['source'], 'name' ), $table->get_name() );
}
// 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;
$this->is_multiple = false;
// Multiples values.
if ( $this->is_multiple ) {
$table->set_multiple( true );
$table->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( $table->get_name() );
$this->full_data['origins'] = $origin->check_choices( $this->full_data['origins'] );
array_push( $table->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
);
$table->origin->set_origin_by_api( $api_data, $this->key );
$table->origin->set_question( $table->get_name() );
$table->origin->set_status( $this->plugins, $this->themes );
}
} else {
$this->is_multiple = false;
if ( 'NO' === $this->force_execute_scanner ) {
$data_algorithm = $table->get_matching_data( $this->matching, $this->plugins, $this->themes, $table->get_name_without_prefix() );
if ( ! is_null( $data_algorithm ) ) {
$table->set_data_by_algorithm( $data_algorithm );
$table->origin->set_status( $this->plugins, $this->themes );
}
}
}
}
if ( ! $this->is_multiple ) {
$this->full_data['origins'] = $table->origin->check_choices( $this->full_data['origins'] );
// Marketplace.
$marketplace = $table->origin->get_marketplace();
$table->origin->set_marketplace( $marketplace->return_object_vars() );
// Auhor.
$author = $table->origin->get_author();
$table->origin->set_author( $author->return_object_vars() );
// Origin.
$table->set_origin( $table->origin->return_object_vars() );
}
// Return object vars.
$table_array = $table->return_object_vars( $table );
// Prevent encoding.
if ( ! mb_check_encoding( $table_array ) ) {
Wp_Database_Tools_Logger::error( 'TABLES: error encoding ' . $table_array['name'] );
continue;
}
if ( is_array( $table_array ) ) {
array_push( $this->full_data['data'], $table_array );
} else {
Wp_Database_Tools_Logger::error( 'TABLES: error add ' . $table_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_table );
}
if ( ! isset( $this->full_data['data'] ) ) {
Wp_Database_Tools_Logger::error( 'TABLES: error tables data empty' );
}
$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( 'TABLES: error data new cache not found' );
}
if ( ! isset( $current_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'TABLES: error data current cache not found' );
}
if ( mb_check_encoding( $new_cache ) ) {
try {
$new_cache = mb_convert_encoding( $this->full_data, 'UTF-8' );
} catch ( Exception $e ) {
$new_cache = $this->full_data;
Wp_Database_Tools_Logger::error( 'TABLES: the data cache has not been encoded properly' );
}
if ( $new_cache === null || ! isset( $new_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'TABLES: the data cache has not been encoded properly' );
$new_cache = $this->full_data;
}
}
if ( ! isset( $new_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'TABLES: error data new cache after encoding' );
}
if ( ! isset( $current_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'TABLES: 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( 'TABLES: error merge tables 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( 'TABLES: error save json' );
}
}
unset( $new_cache );
unset( $current_cache );
// Loading status.
parent::set_status_loading( 'loading', 0, $this->data_loop, false );
}
/**
* 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 'empty':
$this->empty();
break;
case 'optimize':
$this->optimize();
break;
case 'repair':
$this->repair();
break;
}
wp_redirect( $_POST['current-url'] . '&' . WPDBT_PREFIX . 'notice=tables' );
}
/**
* 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.
global $wpdb;
$action_keys = $_POST['action-keys'];
$action_keys = explode( '↕', $action_keys );
$action_prefix = $_POST['action-prefix'];
$action_prefix = explode( '↕', $action_prefix );
$errors_messages = '';
$successes_messages = '';
$tables_array_successes = array();
$tables_array_errors = array();
foreach ( $action_keys as $key => $table_name ) {
if ( $action_prefix[ $key ] == 'true' ) {
$table_name = $wpdb->prefix . $table_name;
}
$sql = $wpdb->prepare( 'DROP TABLE IF EXISTS %1s', $table_name );
$result = $wpdb->query( $sql );
if ( $result === false ) {
array_push( $tables_array_errors, $table_name );
} else {
array_push( $tables_array_successes, $table_name );
}
}
if ( ! empty( $tables_array_successes ) ) {
$successes_messages .= parent::generate_message_success( $this->key, 'names', $tables_array_successes, __( 'removed', 'wp-database-tools' ) );
set_transient( WPDBT_PREFIX . 'successes', $successes_messages );
}
if ( ! empty( $tables_array_errors ) ) {
$errors_messages .= parent::generate_message_error( $this->key, 'names', $tables_array_errors, __( 'removed', 'wp-database-tools' ) );
set_transient( WPDBT_PREFIX . 'errors', $errors_messages );
}
parent::set_cache_indicators( 'tables', 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 empty() {
// TODO: nonce verification.
global $wpdb;
$action_keys = $_POST['action-keys'];
$action_keys = explode( '↕', $action_keys );
$action_prefix = $_POST['action-prefix'];
$action_prefix = explode( '↕', $action_prefix );
$errors_messages = '';
$successes_messages = '';
$tables_array_successes = array();
$tables_array_errors = array();
foreach ( $action_keys as $key => $table_name ) {
if ( $action_prefix[ $key ] == 'true' ) {
$table_name = $wpdb->prefix . $table_name;
}
$sql = $wpdb->prepare( 'TRUNCATE TABLE %1s', $table_name );
$result = $wpdb->query( $sql );
if ( $result === false ) {
array_push( $tables_array_errors, $table_name );
} else {
array_push( $tables_array_successes, $table_name );
}
}
if ( ! empty( $tables_array_successes ) ) {
$successes_messages .= parent::generate_message_success( $this->key, 'names', $tables_array_successes, __( 'emptied', 'wp-database-tools' ) );
set_transient( WPDBT_PREFIX . 'successes', $successes_messages );
}
if ( ! empty( $tables_array_errors ) ) {
$errors_messages .= parent::generate_message_error( $this->key, 'names', $tables_array_errors, __( 'emptied', 'wp-database-tools' ) );
set_transient( WPDBT_PREFIX . 'errors', $errors_messages );
}
parent::set_cache_indicators( 'tables', 0, 0, 0 );
}
public function optimize() {
global $wpdb;
$action_keys = $_POST['action-keys'];
$action_keys = explode( '↕', $action_keys );
$action_prefix = $_POST['action-prefix'];
$action_prefix = explode( '↕', $action_prefix );
$errors_messages = '';
$successes_messages = '';
$tables_array_successes = array();
$tables_array_errors = array();
foreach ( $action_keys as $key => $table_name ) {
if ( $action_prefix[ $key ] == 'true' ) {
$table_name = $wpdb->prefix . $table_name;
}
$sql = $wpdb->prepare( 'OPTIMIZE TABLE %1s', $table_name );
$results = $wpdb->get_results( $sql );
if ( str_contains( json_encode( $results ), 'Operation failed' ) ) {
array_push( $tables_array_errors, $table_name );
} else {
array_push( $tables_array_successes, $table_name );
}
}
if ( ! empty( $tables_array_successes ) ) {
$successes_messages .= parent::generate_message_success( $this->key, 'names', $tables_array_successes, __( 'optimized', 'wp-database-tools' ) );
set_transient( WPDBT_PREFIX . 'successes', $successes_messages );
}
if ( ! empty( $tables_array_errors ) ) {
$errors_messages .= parent::generate_message_error( $this->key, 'names', $tables_array_errors, __( 'optimized', 'wp-database-tools' ) );
set_transient( WPDBT_PREFIX . 'errors', $errors_messages );
}
parent::set_cache_indicators( 'tables', 0, 0, 0 );
}
public function repair() {
global $wpdb;
$action_keys = $_POST['action-keys'];
$action_keys = explode( '↕', $action_keys );
$action_prefix = $_POST['action-prefix'];
$action_prefix = explode( '↕', $action_prefix );
$errors_messages = '';
$successes_messages = '';
$tables_array_successes = array();
$tables_array_errors = array();
foreach ( $action_keys as $key => $table_name ) {
if ( $action_prefix[ $key ] == 'true' ) {
$table_name = $wpdb->prefix . $table_name;
}
$sql = $wpdb->prepare( 'REPAIR TABLE %1s', $table_name );
$results = $wpdb->get_results( $sql );
if ( str_contains( json_encode( $results ), 'Operation failed' ) ) {
array_push( $tables_array_errors, $table_name );
} else {
array_push( $tables_array_successes, $table_name );
}
}
if ( ! empty( $tables_array_successes ) ) {
$successes_messages .= parent::generate_message_success( $this->key, 'names', $tables_array_successes, __( 'repaired', 'wp-database-tools' ) );
set_transient( WPDBT_PREFIX . 'successes', $successes_messages );
}
if ( ! empty( $tables_array_errors ) ) {
$errors_messages .= parent::generate_message_error( $this->key, 'names', $tables_array_errors, __( 'repaired', 'wp-database-tools' ) );
set_transient( WPDBT_PREFIX . 'errors', $errors_messages );
}
parent::set_cache_indicators( 'tables', 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( 'TABLES: 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_size() {
return $this->size;
}
/**
* The array of data of general database.
*
* @since 1.0.0
* @return array The array of data.
*/
public function get_count() {
return $this->count;
}
}

View File

@@ -0,0 +1,606 @@
<?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_Transients 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 LIKE ('%\_transient\_%')" );
$this->count = $num_rows;
}
/**
* Prepare data to loop over records
*
* @since 1.0.4
*/
private function prepare_data() {
// Custom key.
$this->key = 'transients';
// 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 );
}
/**
* Scrolls through the records and assigns the corresponding origins.
*
* @access protected
* @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();
// Transients 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 LIKE ('%\_transient\_%') AND option_name NOT LIKE ('%data_loop%') 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 LIKE %s AND option_name NOT LIKE %s ', 'option_id', $wpdb->prefix . 'options', 'option_name', '%_transient_%', '%data_loop%' );
$sum_ids = $wpdb->get_results( $sql );
$sum_ids = strval( $sum_ids[0]->sum_ids );
if (
$sum_ids === $this->cache_data['indicators']->ids &&
$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( 'TRANSIENTS: 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' ) ) );
$loops = ( ! isset( $this->data_loop['loops'] ) ) ? 0 : $this->data_loop['loops'];
$sum_ids_cache = ( $this->cache_data['indicators']->ids < $sum_ids && $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( 'TRANSIENTS: 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 );
// Si ha finalizado establecesmos la data.
if ( true === $this->data_loop['is_finish'] ) {
Wp_Database_Tools_Logger::info( 'TRANSIENTS: ending to process data ' . count( $this->full_data['data'] ) );
// Get cache.
$this->cache_data['source'] = json_decode( file_get_contents( $cache_path . '_' . $this->key . '.json' ), true );
// 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 ( null !== $this->api_data['source'] ) {
$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( 'TRANSIENTS: 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( 'TRANSIENTS: 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( 'TRANSIENTS: error data new cache not found' );
}
if ( ! isset( $current_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'TRANSIENTS: error data current cache not found' );
}
if ( mb_check_encoding( $this->full_data ) ) {
Wp_Database_Tools_Logger::info( 'TRANSIENTS: 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( 'TRANSIENTS: the data cache has not been encoded properly' );
}
if ( $new_cache === null || ! isset( $new_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'TRANSIENTS: the data cache has not been encoded properly' );
$new_cache = $this->full_data;
}
}
if ( ! isset( $new_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'TRANSIENTS: error data new cache after encoding' );
}
if ( ! isset( $current_cache['data'] ) ) {
Wp_Database_Tools_Logger::error( 'TRANSIENTS: 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( 'TRANSIENTS: error merge transients 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( 'TRANSIENTS: 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();
}
public function remove_all_transients() {
$response = array(
'success' => false,
);
$redirect = admin_url( 'admin.php?page=transients&' ) . WPDBT_PREFIX . 'notice=transients';
global $wpdb;
// $KEY = WPDBT_PREFIX . 'feedback';
$KEY = 'nonce';
if ( ! isset( $_POST[ $KEY ] ) ) {
Wp_Database_Tools_Logger::error( 'Missing error' );
set_transient( WPDBT_PREFIX . 'errors', 'Missing error' );
wp_send_json( wp_json_encode( $redirect ) );
wp_die();
}
if ( ! wp_verify_nonce( sanitize_key( $_POST[ $KEY ] ), 'remove-all-transients' ) ) {
Wp_Database_Tools_Logger::error( 'Nonce error' );
set_transient( WPDBT_PREFIX . 'errors', 'Nonce error' );
wp_send_json( wp_json_encode( $redirect ) );
wp_die();
}
if ( ! isset( $_POST['remove'] ) ) {
Wp_Database_Tools_Logger::error( 'Missing remove' );
set_transient( WPDBT_PREFIX . 'errors', 'Missing remove' );
wp_send_json( wp_json_encode( $redirect ) );
wp_die();
}
if ( empty( $_POST['remove'] ) ) {
Wp_Database_Tools_Logger::error( 'Empty remove' );
set_transient( WPDBT_PREFIX . 'errors', 'Empty remove' );
wp_send_json( wp_json_encode( $redirect ) );
wp_die();
}
if ( $_POST['remove'] != 'REMOVE' ) {
Wp_Database_Tools_Logger::error( 'Not valid remove' );
set_transient( WPDBT_PREFIX . 'errors', 'Not valid remove' );
wp_send_json( wp_json_encode( $redirect ) );
wp_die();
}
// Execute query remove.
global $wpdb;
$results = $wpdb->query( $wpdb->prepare( 'DELETE FROM %1s WHERE option_name LIKE ("%\_transient\_%") AND option_name NOT LIKE ("%wpdbt_successes%") AND option_name NOT LIKE ("%wpdbt_errors%")', $wpdb->prefix . 'options' ) );
if ( $results > 0 && false !== $results ) {
$response['success'] = true;
set_transient( WPDBT_PREFIX . 'successes', 'Eliminados correctamente' );
} else {
$response['success'] = false;
set_transient( WPDBT_PREFIX . 'errors', 'Error al borrar' );
}
wp_send_json( wp_json_encode( $redirect ) );
wp_die();
}
/**
* 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=transients' );
}
/**
* 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( 'transients', 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( 'transients', 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( 'TRANSIENTS: 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;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
<?php
/**
* Fired during plugin deactivation
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
*/
/**
* Fired during plugin deactivation.
*
* This class defines all code necessary to run during the plugin's deactivation.
*
* @since 1.0.0
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
* @author Raiola Networks <info@raiolanetworks.es>
*/
class Wp_Database_Tools_Deactivator {
/**
* Short Description. (use period)
*
* Long Description.
*
* @since 1.0.0
*/
public static function deactivate() {
}
}

View File

@@ -0,0 +1,87 @@
<?php
/**
* Database functions
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
*/
/**
* Manages communication with the API when sending user feedback.
*
* This class contains the methods called from admin-ajax
*
* @since 1.0.0
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
* @author Raiola Networks <info@raiolanetworks.es>
*/
class Wp_Database_Tools_Feedback {
public function save_feedback_user() {
global $wpdb;
// $KEY = WPDBT_PREFIX . 'feedback';
$KEY = 'nonce';
if ( ! isset( $_POST[ $KEY ] ) ) {
Wp_Database_Tools_Logger::error( 'Missing error' );
wp_die( esc_html( __( 'Missing nonce.' ) ) );
}
if ( ! wp_verify_nonce( sanitize_key( $_POST[ $KEY ] ), 'feedback-user' ) ) {
Wp_Database_Tools_Logger::error( 'Nonce error' );
wp_die( esc_html( __( 'Nonce error.' ) ) );
}
$user_id = get_current_user_id();
if ( $user_id ) {
$KEY = WPDBT_PREFIX . 'feedback';
$feedback = get_user_meta( $user_id, $KEY, true );
if ( $feedback == null ) {
$feedback = wp_json_encode( array() );
} else {
$feedback = wp_json_encode( $feedback );
}
$feedback = json_decode( $feedback );
$feedback_array = (array) $feedback;
$all_feedback = array();
$new_feedback = array();
$names = json_decode( stripslashes( $_POST['name'] ) );
$prefixes = json_decode( stripslashes( $_POST['prefix'] ) );
foreach ( $names as $key => $name ) {
if ( $_POST['section'] == 'tables' && $prefixes[ $key ] == 'true' ) {
$name = $wpdb->prefix . $name;
}
$new_feedback[ $_POST['section'] ][ $name ]['vote'] = $_POST['vote'];
$new_feedback[ $_POST['section'] ][ $name ]['type'] = $_POST['type'];
}
// Merge data.
$all_feedback = array_merge_recursive( $feedback_array, $new_feedback );
$updated = update_user_meta( $user_id, $KEY, $all_feedback );
}
// Save feedback user meta data.
wp_send_json( wp_json_encode( $_POST ) );
wp_die();
}
}

View File

@@ -0,0 +1,46 @@
<?php
/**
* Define the internationalization functionality
*
* Loads and defines the internationalization files for this plugin
* so that it is ready for translation.
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
*/
/**
* Define the internationalization functionality.
*
* Loads and defines the internationalization files for this plugin
* so that it is ready for translation.
*
* @since 1.0.0
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
* @author Raiola Networks <info@raiolanetworks.es>
*/
class Wp_Database_Tools_i18n {
/**
* Load the plugin text domain for translation.
*
* @since 1.0.0
*/
public function load_plugin_textdomain() {
load_plugin_textdomain(
'wp-database-tools',
false,
dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/'
);
}
}

View File

@@ -0,0 +1,433 @@
<?php
/**
* License functions
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
*/
/**
* Contains the functionalities related to licence.
*
* This class defines all features of the current license.
*
* @since 1.0.0
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
* @author Raiola Networks <info@raiolanetworks.es>
*/
class Wp_Database_Tools_License {
/**
* The status returned by the EDD api
*
* @since 1.0.0
* @access protected
* @var array $string Content the status license valid|invalid.
*/
protected $status;
/**
* The characteristics returned by an endpoint generated in the
* main installation that returns the values of an ACF
*
* @since 1.0.0
* @access protected
* @var array $features Contains plugin features.
*/
protected $features;
/**
* Collect the plugin prices returned by the EDD API
*
* @since 1.0.0
* @access protected
* @var array $price Content plugin prices.
*/
protected $price;
/**
* The boolean if the license is active.
*
* @since 1.0.0
* @access protected
* @var boolean $is_active license active.
*/
protected $is_active;
/**
* The unique identifier of this plugin.
*
* @since 1.0.0
* @access protected
* @var string $plugin_name The string used to uniquely identify this plugin.
*/
protected $plugin_name;
/**
* The license key that is stored encrypted in the database
*
* @since 1.0.0
* @access protected
* @var string $license_key The string of key license.
*/
protected $license_key;
/**
* The url license plugin.
*
* @since 1.0.0
* @access protected
* @var string $license_url The string of key license.
*/
protected $license_url;
public function __construct( $plugin_name ) {
$this->plugin_name = $plugin_name;
$this->license_url = home_url();
$this->init_license();
}
private function init_license() {
$this->check_status();
$this->check_price();
$this->check_features();
}
/**
* Check current license status.
*
* @since 1.0.0
*/
private function check_status() {
$this->status = get_option( WPDBT_PREFIX . 'edd_license_status' );
if ( $this->status !== false ) {
$license = get_option( WPDBT_PREFIX . 'edd_license_key' );
if ( $license !== false && $license !== '' ) {
$this->license_key = $this->decrypt( $license );
}
}
$this->is_active = ( $this->status == 'valid' );
}
/**
* Getting prices using the EDD API.
*
* @since 1.0.0
*/
private function check_price() {
$TRANSIENT_PRICES_PRO_KEY = WPDBT_PREFIX . 'prices_pro';
if ( get_transient( $TRANSIENT_PRICES_PRO_KEY ) ) {
$this->price = get_transient( $TRANSIENT_PRICES_PRO_KEY );
return;
}
$response = wp_remote_get( WPDBT_EDD_STORE_URL . '/edd-api/v2/products/?product=140' );
if ( is_wp_error( $response ) ) {
return;
}
if ( ! $response['body'] ) {
return;
}
$response = json_decode( $response['body'] );
if ( ! $response ) {
return;
}
if ( ! $response->products[0]->pricing ) {
return;
}
set_transient( $TRANSIENT_PRICES_PRO_KEY, $response->products[0]->pricing, 86400 );
$this->price = $response->products[0]->pricing;
}
/**
* Getting features from a custom enpoint using the WordPress rest API.
*
* @since 1.0.0
*/
private function check_features() {
$TRANSIENT_FEATURES_PRO_KEY = WPDBT_PREFIX . 'features_pro';
if ( get_transient( $TRANSIENT_FEATURES_PRO_KEY ) ) {
$this->features = get_transient( $TRANSIENT_FEATURES_PRO_KEY );
return;
}
$response = wp_remote_get( WPDBT_EDD_STORE_URL . '/wp-json/downloads/v1/acf/140' );
if ( is_wp_error( $response ) ) {
return;
}
$response = json_decode( $response['body'] );
if ( ! $response->success ) {
return;
}
set_transient( $TRANSIENT_FEATURES_PRO_KEY, $response->data, 86400 );
$this->features = $response->data;
}
private function encrypt( $data ) {
$key = WPDBT_ENCRYPTION_KEY;
$plaintext = $data;
$ivlen = openssl_cipher_iv_length( $cipher = WPDBT_ENCRYPTION_METHOD );
$iv = openssl_random_pseudo_bytes( $ivlen );
$ciphertext_raw = openssl_encrypt( $plaintext, $cipher, $key, $options = OPENSSL_RAW_DATA, $iv );
$hmac = hash_hmac( 'sha256', $ciphertext_raw, $key, $as_binary = true );
$ciphertext = base64_encode( $iv . $hmac . $ciphertext_raw );
return $ciphertext;
}
private function decrypt( $data ) {
$key = WPDBT_ENCRYPTION_KEY;
$c = base64_decode( $data );
$ivlen = openssl_cipher_iv_length( $cipher = WPDBT_ENCRYPTION_METHOD );
$iv = substr( $c, 0, $ivlen );
$hmac = substr( $c, $ivlen, $sha2len = 32 );
$ciphertext_raw = substr( $c, $ivlen + $sha2len );
$original_plaintext = openssl_decrypt( $ciphertext_raw, $cipher, $key, $options = OPENSSL_RAW_DATA, $iv );
$calcmac = hash_hmac( 'sha256', $ciphertext_raw, $key, $as_binary = true );
if ( hash_equals( $hmac, $calcmac ) ) {
return $original_plaintext;
}
}
public function form_action_license() {
$retrieved_nonce = $_REQUEST['edd_sample_nonce'];
if ( ! wp_verify_nonce( $retrieved_nonce, 'active_plugin' ) ) {
if ( ! check_admin_referer( 'edd_sample_nonce', 'edd_sample_nonce' ) ) {
return;
}
$license = sanitize_text_field( $_POST['license'] );
// data to send in our API request
$api_params = array(
'edd_action' => 'activate_license',
'license' => $license,
'item_name' => urlencode( WPDBT_EDD_ITEM_NAME ), // the name of our product in EDD
'url' => home_url(),
);
$response = wp_remote_post(
WPDBT_EDD_STORE_URL,
array(
'timeout' => 15,
'sslverify' => false,
'body' => $api_params,
)
);
if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
$message = ( is_wp_error( $response ) && ! empty( $response->get_error_message() ) ) ? $response->get_error_message() : __( 'An error occurred, please try again.' );
} else {
$license_data = json_decode( wp_remote_retrieve_body( $response ) );
if ( false === $license_data->success ) {
switch ( $license_data->error ) {
case 'expired':
$message = sprintf(
__( 'Your license key expired on %s.', WPDBT_SLUG ),
date_i18n( get_option( 'date_format' ), strtotime( $license_data->expires, current_time( 'timestamp' ) ) )
);
break;
case 'revoked':
$message = __( 'Your license key has been disabled', WPDBT_SLUG );
break;
case 'missing':
$message = __( 'Invalid license', WPDBT_SLUG );
break;
case 'invalid':
case 'site_inactive':
$message = __( 'Your license is not active for this URL', WPDBT_SLUG );
break;
case 'item_name_mismatch':
$message = sprintf( __( 'This appears to be an invalid license key for %s.' ), WPDBT_SLUG );
break;
case 'no_activations_left':
$message = __( 'Your license key has reached its activation limit', WPDBT_SLUG );
break;
default:
$message = __( 'An error occurred, please try again', WPDBT_SLUG );
break;
}
}
if ( ! empty( $message ) ) {
$base_url = admin_url( 'admin.php?page=license' );
$redirect = add_query_arg(
array(
WPDBT_PREFIX . 'sl_activation' => 'false',
'message' => urlencode( $message ),
),
$base_url
);
wp_redirect( $redirect );
exit();
}
// SAVE OPTION
$base_url = admin_url( 'admin.php?page=license' );
update_option( WPDBT_PREFIX . 'edd_license_status', $license_data->license );
update_option( WPDBT_PREFIX . 'edd_license_key', $this->encrypt( $license ) );
$redirect = add_query_arg(
array(
WPDBT_PREFIX . 'sl_activation' => 'true',
'message' => urlencode( 'Licencia activada' ),
),
$base_url
);
wp_redirect( $redirect );
exit();
}
} else {
wp_die(
__( 'Invalid nonce specified', $this->plugin_name ),
__( 'Error', $this->plugin_name ),
array(
'response' => 403,
'back_link' => 'admin.php?page=' . $this->plugin_name,
)
);
}
}
/**
* The array of current status license.
*
* @since 1.0.0
* @return array The array of current status license.
*/
public function get_status() {
return $this->status;
}
/**
* The array of features pro license.
*
* @since 1.0.0
* @return array The array of features pro license.
*/
public function get_features() {
return $this->features;
}
/**
* The string of of current price pro license.
*
* @since 1.0.0
* @return string The string of current price pro license.
*/
public function get_price() {
return $this->price;
}
/**
* The boolean of current current license.
*
* @since 1.0.0
* @return boolean The boolean current license status.
*/
public function get_is_active() {
return $this->is_active;
}
/**
* The string of of current price pro license.
*
* @since 1.0.0
* @return string The string of current price pro license.
*/
public function get_license_key() {
return $this->license_key;
}
/**
* Return the license key encrypt.
*
* @since 1.0.0
* @return string The license key encrypt.
*/
public function get_license_key_encrypt() {
return get_option( WPDBT_PREFIX . 'edd_license_key' );
}
/**
* The string of of current price pro license.
*
* @since 1.0.0
* @return string The string of current price pro license.
*/
public function get_license_url() {
return $this->license_url;
}
/**
* Set the license key value.
*
* @param string $value license key value.
* @since 1.0.0
*/
public function set_license_key( $value ) {
update_option( WPDBT_PREFIX . 'edd_license_status', $value );
$this->license_key = $value;
}
}

View File

@@ -0,0 +1,129 @@
<?php
/**
* Register all actions and filters for the plugin
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
*/
/**
* Register all actions and filters for the plugin.
*
* Maintain a list of all hooks that are registered throughout
* the plugin, and register them with the WordPress API. Call the
* run function to execute the list of actions and filters.
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
* @author Raiola Networks <info@raiolanetworks.es>
*/
class Wp_Database_Tools_Loader {
/**
* The array of actions registered with WordPress.
*
* @since 1.0.0
* @access protected
* @var array $actions The actions registered with WordPress to fire when the plugin loads.
*/
protected $actions;
/**
* The array of filters registered with WordPress.
*
* @since 1.0.0
* @access protected
* @var array $filters The filters registered with WordPress to fire when the plugin loads.
*/
protected $filters;
/**
* Initialize the collections used to maintain the actions and filters.
*
* @since 1.0.0
*/
public function __construct() {
$this->actions = array();
$this->filters = array();
}
/**
* Add a new action to the collection to be registered with WordPress.
*
* @since 1.0.0
* @param string $hook The name of the WordPress action that is being registered.
* @param object $component A reference to the instance of the object on which the action is defined.
* @param string $callback The name of the function definition on the $component.
* @param int $priority Optional. The priority at which the function should be fired. Default is 10.
* @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1.
*/
public function add_action( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
$this->actions = $this->add( $this->actions, $hook, $component, $callback, $priority, $accepted_args );
}
/**
* Add a new filter to the collection to be registered with WordPress.
*
* @since 1.0.0
* @param string $hook The name of the WordPress filter that is being registered.
* @param object $component A reference to the instance of the object on which the filter is defined.
* @param string $callback The name of the function definition on the $component.
* @param int $priority Optional. The priority at which the function should be fired. Default is 10.
* @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1
*/
public function add_filter( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
$this->filters = $this->add( $this->filters, $hook, $component, $callback, $priority, $accepted_args );
}
/**
* A utility function that is used to register the actions and hooks into a single
* collection.
*
* @since 1.0.0
* @access private
* @param array $hooks The collection of hooks that is being registered (that is, actions or filters).
* @param string $hook The name of the WordPress filter that is being registered.
* @param object $component A reference to the instance of the object on which the filter is defined.
* @param string $callback The name of the function definition on the $component.
* @param int $priority The priority at which the function should be fired.
* @param int $accepted_args The number of arguments that should be passed to the $callback.
* @return array The collection of actions and filters registered with WordPress.
*/
private function add( $hooks, $hook, $component, $callback, $priority, $accepted_args ) {
$hooks[] = array(
'hook' => $hook,
'component' => $component,
'callback' => $callback,
'priority' => $priority,
'accepted_args' => $accepted_args
);
return $hooks;
}
/**
* Register the filters and actions with WordPress.
*
* @since 1.0.0
*/
public function run() {
foreach ( $this->filters as $hook ) {
add_filter( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
}
foreach ( $this->actions as $hook ) {
add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
}
}
}

View File

@@ -0,0 +1,350 @@
<?php
/**
* @author advename
* @since October 27, 2019
* @link https://github.com/advename/Simple-PHP-Logger
* @license MIT
* @version 1.0.0
*
* Description:
* The simple php logger is a single-file logwriter with the features of:
* - single file
* - singleton pattern
* - six log levels (info, notice, debug, warning, error, fatal)
* - logs the line where the Logger method is executed (good for troubleshooting)
* - logs the relative filepath of the source file, not the required one (good for troubleshooting)
*/
class Wp_Database_Tools_Logger {
/**
* $log_file - path and log file name
*
* @var string
*/
protected static $log_file;
/**
* $file - file
*
* @var string
*/
protected static $file;
/**
* $options - settable options
*
* @var array $dateFormat of the format used for the log.txt file; $logFormat used for the time of a single log event
*/
protected static $options = array(
'dateFormat' => 'd-M-Y',
'logFormat' => 'H:i:s d-M-Y',
);
private static $instance;
/**
* Create the log file
*
* @param string $log_file - path and filename of log
* @param array $params - settable options
*/
public static function createLogFile() {
$time = date( static::$options['dateFormat'] );
static::$log_file = plugin_dir_path( dirname( __FILE__ ) ) . "/logs/log-{$time}.txt";
// Check if directory /logs exists
if ( ! file_exists( plugin_dir_path( dirname( __FILE__ ) ) . '/logs' ) ) {
mkdir( plugin_dir_path( dirname( __FILE__ ) ) . '/logs', 0777, true );
}
// Create log file if it doesn't exist.
if ( ! file_exists( static::$log_file ) ) {
fopen( static::$log_file, 'w' ) or exit( "Can't create {static::log_file}!" );
}
// Check permissions of file.
if ( ! is_writable( static::$log_file ) ) {
// throw exception if not writable
throw new Exception( 'ERROR: Unable to write to file!', 1 );
}
}
/**
* Set logging options (optional)
*
* @param array $options Array of settable options
*
* Options:
* [
* 'dateFormat' => 'value of the date format the .txt file should be saved int'
* 'logFormat' => 'value of the date format each log event should be saved int'
* ]
*/
public static function setOptions( $options = array() ) {
static::$options = array_merge( static::$options, $options );
}
/**
* Info method (write info message)
*
* Used for e.g.: "The user example123 has created a post".
*
* @param string $message Descriptive text of the debug
* @param string $context Array to expend the message's meaning
* @return void
*/
public static function info( $message, array $context = array() ) {
// grab the line and file path where the log method has been executed ( for troubleshooting )
$bt = debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, 1 );
// execute the writeLog method with passing the arguments
static::writeLog(
array(
'message' => $message,
'bt' => $bt,
'severity' => 'INFO',
'context' => $context,
)
);
}
/**
* Notice method (write notice message)
*
* Used for e.g.: "The user example123 has created a post".
*
* @param string $message Descriptive text of the debug
* @param string $context Array to expend the message's meaning
* @return void
*/
public static function notice( $message, array $context = array() ) {
// grab the line and file path where the log method has been executed ( for troubleshooting )
$bt = debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, 1 );
// execute the writeLog method with passing the arguments
static::writeLog(
array(
'message' => $message,
'bt' => $bt,
'severity' => 'NOTICE',
'context' => $context,
)
);
}
/**
* Debug method (write debug message)
*
* Used for debugging, could be used instead of echo'ing values
*
* @param string $message Descriptive text of the debug
* @param string $context Array to expend the message's meaning
* @return void
*/
public static function debug( $message, array $context = array() ) {
// grab the line and file path where the log method has been executed ( for troubleshooting )
$bt = debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, 1 );
// execute the writeLog method with passing the arguments
static::writeLog(
array(
'message' => $message,
'bt' => $bt,
'severity' => 'DEBUG',
'context' => $context,
)
);
}
/**
* Warning method (write warning message)
*
* Used for warnings which is not fatal to the current operation
*
* @param string $message Descriptive text of the warning
* @param string $context Array to expend the message's meaning
* @return void
*/
public static function warning( $message, array $context = array() ) {
// grab the line and file path where the log method has been executed ( for troubleshooting )
$bt = debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, 1 );
// execute the writeLog method with passing the arguments
static::writeLog(
array(
'message' => $message,
'bt' => $bt,
'severity' => 'WARNING',
'context' => $context,
)
);
}
/**
* Error method (write error message)
*
* Used for e.g. file not found,...
*
* @param string $message Descriptive text of the error
* @param string $context Array to expend the message's meaning
* @return void
*/
public static function error( $message, array $context = array() ) {
// grab the line and file path where the log method has been executed ( for troubleshooting )
$bt = debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, 1 );
// execute the writeLog method with passing the arguments
static::writeLog(
array(
'message' => $message,
'bt' => $bt,
'severity' => 'ERROR',
'context' => $context,
)
);
}
/**
* Fatal method (write fatal message)
*
* Used for e.g. database unavailable, system shutdown
*
* @param string $message Descriptive text of the error
* @param string $context Array to expend the message's meaning
* @return void
*/
public static function fatal( $message, array $context = array() ) {
// grab the line and file path where the log method has been executed ( for troubleshooting )
$bt = debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, 1 );
// execute the writeLog method with passing the arguments
static::writeLog(
array(
'message' => $message,
'bt' => $bt,
'severity' => 'FATAL',
'context' => $context,
)
);
}
/**
* Write to log file
*
* @param array $args Array of message (for log file), line (of log method execution), severity (for log file) and displayMessage (to display on frontend for the used)
* @return void
*/
// public function writeLog($message, $line = null, $displayMessage = null, $severity)
public static function writeLog( $args = array() ) {
if ( WPDBT_LOG ) {
// Create the log file
static::createLogFile();
// open log file
if ( ! is_resource( static::$file ) ) {
static::openLog();
}
// // grab the url path
// $path = $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
// Grab time - based on the time format
$time = date( static::$options['logFormat'] );
// Convert context to json
$context = json_encode( $args['context'] );
$caller = array_shift( $args['bt'] );
$btLine = $caller['line'];
$btPath = $caller['file'];
// Convert absolute path to relative path (using UNIX directory seperators)
$path = static::absToRelPath( $btPath );
// Create log variable = value pairs
$timeLog = is_null( $time ) ? '[N/A] ' : "[{$time}] ";
$pathLog = is_null( $path ) ? '[N/A] ' : "[{$path}] ";
$lineLog = is_null( $btLine ) ? '[N/A] ' : "[{$btLine}] ";
$severityLog = is_null( $args['severity'] ) ? '[N/A]' : "[{$args['severity']}]";
$messageLog = is_null( $args['message'] ) ? 'N/A' : "{$args['message']}";
$contextLog = empty( $args['context'] ) ? '' : "{$context}";
// Write time, url, & message to end of file
fwrite( static::$file, "{$timeLog}{$severityLog}" . PHP_EOL . "{$pathLog}{$lineLog}" . PHP_EOL . "{$messageLog} {$contextLog}" . PHP_EOL );
// Close file stream
static::closeFile();
}
}
/**
* Open log file
*
* @return void
*/
private static function openLog() {
$openFile = static::$log_file;
// 'a' option = place pointer at end of file
static::$file = fopen( $openFile, 'a' ) or exit( "Can't open $openFile!" );
}
/**
* Close file stream
*/
public static function closeFile() {
if ( static::$file ) {
fclose( static::$file );
}
}
/**
* Convert absolute path to relative url (using UNIX directory seperators)
*
* E.g.:
* Input: D:\development\htdocs\public\todo-list\index.php
* Output: localhost/todo-list/index.php
*
* @param string Absolute directory/path of file which should be converted to a relative (url) path
* @return string Relative path
*/
public static function absToRelPath( $pathToConvert ) {
$pathAbs = str_replace( array( '/', '\\' ), '/', $pathToConvert );
$documentRoot = str_replace( array( '/', '\\' ), '/', $_SERVER['DOCUMENT_ROOT'] );
return $_SERVER['SERVER_NAME'] . str_replace( $documentRoot, '', $pathAbs );
}
/**
* The Singleton's constructor should always be private to prevent direct
* construction calls with the `new` operator.
*/
protected function __construct() { }
/**
* Singletons should not be cloneable.
*/
protected function __clone() { }
/**
* Singletons should not be restorable from strings.
*/
public function __wakeup() {
throw new \Exception( 'Cannot unserialize a singleton.' );
}
public static function getInstance() {
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* The Singleton's constructor should always be private to prevent direct
* construction calls with the `new` operator.
*/
private function __destruct() { }
}

View File

@@ -0,0 +1,474 @@
<?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 find match.
*
* This class defines all features of the matching algorith.
*
* @since 1.0.0
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
* @author Raiola Networks <info@raiolanetworks.es>
*/
class Wp_Database_Tools_Matching {
/**
* The information of the plugins formatted
*
* @since 1.0.0
* @access protected
* @var array $plugins The plugins data.
*/
protected $plugins;
/**
* The information of the themes formatted
*
* @since 1.0.0
* @access protected
* @var array $themes The themes data.
*/
protected $themes;
/**
* Constructor
*
* Create the instance of a Matching.
*
* @access public
* @since 1.0.0
*
* @param Wp_Database_Tools_Plugins $plugins Plugin Obj.
* @param Wp_Database_Tools_Themes $themes Theme Obj.
*/
public function __construct( $plugins, $themes ) {
$this->plugins = $plugins->get_plugins();
$this->themes = $themes->get_themes();
}
/**
* Searches for possible matches of origins and returns matches
* sorted by the level of probability of a match.
*
* @access public
* @since 1.0.0
*
* @param String $type Values plugin|theme.
* @param String $source_name Name of the source.
* @param String $source_value Value of the source.
*
* @return Array match found.
*/
public function find_match( $type, $source_name, $source_value ) {
$MATCHING_LVL = 100;
if ( 'plugin' === $type ) {
$search_origin = $this->plugins;
$search_text_domain = true;
}
if ( 'theme' === $type ) {
$search_origin = $this->themes;
$search_text_domain = false;
}
$concidences_slugs = array();
// We go through all possible sources (plugins or themes) looking for matches.
foreach ( $search_origin as $key => $origin ) {
// Porcent match.
$match_results = array();
// Text Domain.
if ( $search_text_domain === true ) {
$text_domain = $origin['text_domain'];
$match = $this->search_by_text_domain( $text_domain, $source_name );
array_push( $match_results, $match );
}
// Slugs.
$slug = $origin['slug'];
$name = $origin['name'];
if ( $source_value !== null ) {
if ( str_contains( $source_name, 'edd_' ) ) {
$match = $this->search_by_value( $slug, $name, $source_value );
array_push( $match_results, $match );
}
}
$match = $this->search_by_text_slug( $slug, $source_name );
array_push( $match_results, $match );
// Initials.
$initials = $origin['initials'];
if ( strlen( $initials ) >= 3 && strlen( $initials ) <= 5 ) {
$match = $this->search_by_starts_initials( $initials, $source_name );
array_push( $match_results, $match );
if ( str_contains( $slug, 'premium' ) || str_contains( $slug, 'pro' ) ) {
if ( substr( $initials, -1 ) == 'p' ) {
$match = $this->search_by_starts_initials_without_last( $initials, $source_name );
array_push( $match_results, $match );
}
}
$match = $this->search_by_starts_initials_similar( $initials, $source_name );
array_push( $match_results, $match );
}
$match = $this->search_by_similar_slug( $slug, $source_name );
array_push( $match_results, $match );
// Search main file.
if ( isset( $origin['path'] ) ) {
$path = $origin['path'];
$match = $this->search_main_file( $path, $source_name, $initials );
array_push( $match_results, $match );
}
// Order array.
asort( $match_results );
$concidences_slugs[ $slug ] = end( $match_results );
unset( $origin );
}
// Order array.
asort( $concidences_slugs );
// Get value if the match if hightest.
if ( end( $concidences_slugs ) >= $MATCHING_LVL ) {
$data_return = array(
'slug' => array_key_last( $concidences_slugs ),
'match' => end( $concidences_slugs ),
);
return $data_return;
}
return null;
}
/**
* Return longest char match between two strings
*
* @access protected
* @since 1.0.0
*
* @param String $str1 First string to compare.
* @param String $str2 Second string to compare.
*
* @return int longest match.
*/
protected function get_longest_matching_substring( $str1, $str2 ) {
$len_1 = strlen( $str1 );
$longest = '';
for ( $i = 0; $i < $len_1; $i++ ) {
for ( $j = $len_1 - $i; $j > 0; $j-- ) {
$sub = substr( $str1, $i, $j );
if ( strpos( $str2, $sub ) !== false && strlen( $sub ) > strlen( $longest ) ) {
$longest = $sub;
break;
}
}
}
return strlen( $longest );
}
/**
* Compare the slug of the plugin or theme with the name of the source
* (options, cronjobs...) to find a match.
*
* The comparison is done by looking for an exact match of the same string
* at its beginning.
*
* @access protected
* @since 1.0.0
*
* @param String $slug Slug of origin.
* @param String $source_name Name of the source.
*
* @return int longest match.
*/
protected function search_by_similar_slug( $slug, $source_name ) {
$slug_name = preg_split( '/-|_/', $slug );
$source_name = str_replace( array( '_', '-' ), '_', $source_name );
$match = 0;
foreach ( $slug_name as $key => $slug ) {
if ( $key == 0 ) {
$slug_search = $slug_name[0] . '_';
}
if ( $key == 1 ) {
$slug_search = $slug_name[0] . '_' . $slug_name[1] . '_';
}
if ( $key == 2 ) {
$slug_search = $slug_name[0] . '_' . $slug_name[1] . '_' . $slug_name[2] . '_';
}
$slug_length = strlen( $slug_search );
if ( str_starts_with( $source_name, $slug_search ) && $slug_length > 3 ) {
$match += $slug_length + 100;
}
}
return $match;
}
/**
* Compare the slug of the plugin or theme with the name of the source
* (options, cronjobs...) to find a match.
*
* The comparison is made on the basis of the highest coincidence between
* the achievement of their chars.
*
* @access protected
* @since 1.0.0
*
* @param String $slug Slug of origin.
* @param String $source_name Name of the source.
*
* @return int longest match.
*/
protected function search_by_text_slug( $slug, $source_name ) {
$slug = str_replace( array( '_', '-' ), '', $slug );
$source_name = str_replace( array( '_', '-' ), '', $source_name );
$slug = strtolower( $slug );
$source_name = strtolower( $source_name );
$slug_length = strlen( $slug );
$result = $this->get_longest_matching_substring( $slug, $source_name );
$match = ( $result * 100 ) / $slug_length;
$match += $slug_length;
return $match;
}
/**
* Compare text_domain slug of the plugin or theme with the name of the source
* (options, cronjobs...) to find a match.
*
* The comparison is made on the basis of the highest coincidence between
* the achievement of their chars.
*
* @access protected
* @since 1.0.0
*
* @param String $text_domain Slug of origin.
* @param String $source_name Name of the source.
*
* @return int match.
*/
protected function search_by_text_domain( $text_domain, $source_name ) {
$text_domain = str_replace( array( '_', '-' ), '', $text_domain );
$source_name = str_replace( array( '_', '-' ), '', $source_name );
$text_domain = strtolower( $text_domain );
$source_name = strtolower( $source_name );
$text_domain_length = strlen( $text_domain );
$result = $this->get_longest_matching_substring( $text_domain, $source_name );
$match = ( $result * 100 ) / $text_domain_length;
$match += $text_domain_length;
return $match;
}
/**
* Compare initials of the plugin or theme with the name of the source
* (options, cronjobs...) to find a match.
*
* @access protected
* @since 1.0.0
*
* @param String $initials Initials of origin.
* @param String $source_name Name of the source.
*
* @return int match.
*/
protected function search_by_starts_initials( $initials, $source_name ) {
$source_name = preg_split( '/-|_/', $source_name );
if ( count( $source_name ) > 1 ) {
$start_name = $source_name[0];
$match = ( $start_name === $initials ) ? 100 : 0;
return $match;
}
return 0;
}
/**
* Compare initials of the plugin or theme with the name of the source
* (options, cronjobs...) to find a match.
*
* We search by initials omitting the last character.
* This is checked to avoid comparisons with words
* like "pro" or "lite" at the end.
*
* @access protected
* @since 1.0.0
*
* @param String $initials Initials of origin.
* @param String $source_name Name of the source.
*
* @return int match.
*/
protected function search_by_starts_initials_without_last( $initials, $source_name ) {
$source_name = preg_split( '/-|_/', $source_name );
if ( count( $source_name ) > 1 ) {
$start_name = $source_name[0];
$match = ( $start_name == substr_replace( $initials, '', -1 ) ) ? 100 : 0;
return $match;
}
return 0;
}
/**
* Compare initials of the plugin or theme with the name of the source
* (options, cronjobs...) to find a match.
*
* We compare the similarity of the initials
*
* @access protected
* @since 1.0.0
*
* @param String $initials Initials of origin.
* @param String $source_name Name of the source.
*
* @return int match.
*/
protected function search_by_starts_initials_similar( $initials, $source_name ) {
$initials = strtolower( $initials );
$source_name = strtolower( $source_name );
$source_name = preg_split( '/-|_/', $source_name );
if ( count( $source_name ) > 1 ) {
$start_name = $source_name[0];
similar_text( $initials, $start_name, $match );
return $match;
}
return 0;
}
/**
* We look for matches in the value of the origins (options,tables,cronjobs)
* by comparing with the slug and name of the source (themes,plugins).
*
* @access protected
* @since 1.0.0
*
* @param String $slug Initials of origin.
* @param String $name Name of the source.
* @param String $source_value Name of the source.
*
* @return int match.
*/
protected function search_by_value( $slug, $name, $source_value ) {
$content = strtolower( $source_value );
if ( str_contains( $content, strtolower( $slug ) ) ) {
return 100;
}
if ( str_contains( $content, strtolower( $name ) ) ) {
return 100;
}
return 0;
}
/**
* We look for matches in the origins file (themes,plugins)
* comparing with the value of the sources (cronjobs,options,tables).
*
* @access protected
* @since 1.0.0
*
* @param String $path The file path.
* @param String $source_name Name of the source.
* @param String $initials Initials of the source.
*
* @return int match.
*/
protected function search_main_file( $path, $source_name, $initials ) {
$prefix_source = preg_split( '/-|_/', $source_name );
if ( count( $prefix_source ) > 1 ) {
if ( $prefix_source[0] != 'edd' ) {
if ( strlen( $prefix_source[0] ) >= 3 ) {
$content = strtolower( file_get_contents( WP_PLUGIN_DIR . '/' . $path ) );
$regex = '/("|\')' . $prefix_source[0] . '(_|-)/i';
// Search on main file.
preg_match( $regex, $content, $concidences );
if ( count( $concidences ) > 0 ) {
similar_text( $concidences[0], $prefix_source[0], $percent );
if ( $percent >= 80 ) {
return intval( $percent );
}
similar_text( $concidences[0], $initials, $percent );
if ( $percent >= 80 ) {
return intval( $percent );
}
return 0;
}
}
}
}
return 0;
}
}

View File

@@ -0,0 +1,149 @@
<?php
/**
* Database functions
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
*/
/**
* Detects current plugins in the installation
* *
*
* @since 1.0.0
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
* @author Patricia Alvarez <patricia@raiolanetworks.es>
*/
class Wp_Database_Tools_Plugins {
/**
* Plugins in the installation.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $plugins;
public function __construct() {
$this->init();
}
protected function init() {
$this->format_plugins();
}
protected function format_plugins() {
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$plugins_data = array();
foreach ( get_plugins() as $key => $plugin ) {
// Check marketplace
$marketplace = 'unknown';
if ( str_contains( $plugin['AuthorURI'], 'codecanyon' ) || str_contains( $plugin['PluginURI'], 'codecanyon' ) ) {
$marketplace = 'https://codecanyon.net';
}
if ( str_contains( $plugin['AuthorURI'], 'themeforest' ) || str_contains( $plugin['PluginURI'], 'themeforest' ) ) {
$marketplace = 'https://themeforest.net';
}
if ( str_contains( $plugin['AuthorURI'], 'wordpress.org' ) || str_contains( $plugin['PluginURI'], 'wordpress.org' ) ) {
$marketplace = 'https://wordpress.org';
}
// Format plugins data
$plugins_data[ $key ]['name'] = $plugin['Name'];
$plugins_data[ $key ]['marketplace'] = $marketplace;
$plugins_data[ $key ]['status'] = $this->get_plugin_status( $key );
$plugins_data[ $key ]['initials'] = $this->get_initials( $key );
$plugins_data[ $key ]['description'] = $plugin['Description'];
$plugins_data[ $key ]['text_domain'] = $plugin['TextDomain'];
$plugins_data[ $key ]['slug'] = explode( '/', $key )[0];
$plugins_data[ $key ]['version'] = $plugin['Version'];
$plugins_data[ $key ]['author'] = $plugin['Author'];
$plugins_data[ $key ]['author_name'] = $plugin['AuthorName'];
$plugins_data[ $key ]['author_url'] = $plugin['AuthorURI'];
$plugins_data[ $key ]['name'] = $plugin['Name'];
$plugins_data[ $key ]['path'] = $key;
}
$this->plugins = $plugins_data;
}
/**
* Get's the activation status for a plugin.
*
* @since 5.5.0
*
* @param string $plugin The plugin file to check.
* @return string 'active' . 'inactive' or 'uninstalled'.
* @author Patricia Alvarez <patricia@raiolanetworks.es>
*/
protected function get_plugin_status( $plugin ) {
// Check if exist path
if ( ! file_exists( WP_PLUGIN_DIR . '/' . $plugin ) ) {
return 'uninstalled';
}
// Check if exist is active
if ( is_plugin_active( $plugin ) ) {
return 'active';
}
// Check if exist is inactive
if ( is_plugin_inactive( $plugin ) ) {
return 'inactive';
}
// // Check if exist is active
// if ( is_plugin_active_for_network( $plugin ) ) {
// return 'network-active';
// }
}
public function get_initials( $input ) {
$words = preg_split( '/[\s,_-]+/', $input );
$initials = '';
foreach ( $words as $input => $word ) {
$initials .= substr( $word, 0, 1 );
}
return $initials;
}
/**
* Get's the activation status for a plugin.
*
* @since 1.0.0
*
* @param string $plugin The plugin file to check.
* @return string 'active' . 'inactive' or 'uninstalled'.
* @author Patricia Alvarez <patricia@raiolanetworks.es>
*/
public function get_plugins() {
return $this->plugins;
}
}

View File

@@ -0,0 +1,305 @@
<?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_Scanner {
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $path;
/**
* The license manager.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $license;
/**
* The license manager.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $plugins;
/**
* The license manager.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $themes;
public function __construct( $license, $plugins, $themes ) {
include_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wp-database-tools-logger.php';
$this->license = $license;
$this->plugins = $plugins->get_plugins();
$this->themes = $themes->get_themes();
}
/**
* Saves the current status of the scanner in a transient.
*
* @param string $status Current status of scanner error|active|success.
* @param string $message Message to return on sidebar.
* @since 1.0.0
*/
public function set_status_scanner( $status, $message ) {
$scanner_status_data = array(
'status' => $status,
'message' => $message,
'time' => date( 'Y-m-d H:i:s' ),
);
set_transient( WPDBT_PREFIX . 'scanner_last_status', wp_json_encode( $scanner_status_data ) );
set_transient( WPDBT_PREFIX . 'scanner_status', wp_json_encode( $scanner_status_data ) );
}
/**
* We check the global variables and create a request to wp-cron
* to check if it is working correctly.
*
* @since 1.0.1
*/
public function wpdt_test_cron_spawn() {
global $wp_version;
$cron_check = get_transient( WPDBT_PREFIX . 'cron_check' );
if ( 'success' === $cron_check || 'error' === $cron_check || 'warning' === $cron_check ) {
return true;
}
if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) {
$message = esc_html__( 'DISABLE_WP_CRON is disabled, the cron is not active', 'wp-database-tools' );
set_transient( WPDBT_PREFIX . 'cron_check', 'error', 600 );
set_transient( WPDBT_PREFIX . 'cron_check_date', gmdate( 'Y-m-d H:i:s' ), 600 );
set_transient( WPDBT_PREFIX . 'cron_check_message', $message, 600 );
}
if ( defined( 'ALTERNATE_WP_CRON' ) && ALTERNATE_WP_CRON ) {
$message = esc_html__( 'ALTERNATE_WP_CRON is enabled, we cannot determine the functioning of the cron', 'wp-database-tools' );
set_transient( WPDBT_PREFIX . 'cron_check', 'warning', 600 );
set_transient( WPDBT_PREFIX . 'cron_check_date', gmdate( 'Y-m-d H:i:s' ), 600 );
set_transient( WPDBT_PREFIX . 'cron_check_message', $message, 600 );
}
$sslverify = version_compare( $wp_version, '4.0', '<' );
$doing_wp_cron = sprintf( '%.22F', microtime( true ) );
$cron_request = apply_filters(
'cron_request',
array(
'url' => site_url( 'wp-cron.php?doing_wp_cron=' . $doing_wp_cron ),
'key' => $doing_wp_cron,
'args' => array(
'timeout' => 3,
'blocking' => true,
'sslverify' => apply_filters( 'https_local_ssl_verify', $sslverify ),
),
)
);
$cron_request['args']['blocking'] = true;
$result = wp_remote_post( $cron_request['url'], $cron_request['args'] );
if ( wp_remote_retrieve_response_code( $result ) >= 300 ) {
Wp_Database_Tools_Logger::error( 'Error execute cronjob response code ' . wp_remote_retrieve_response_code( $result ) );
$message = sprintf( __( 'Error execute cronjob response code %s', 'wp-database-tools' ), wp_remote_retrieve_response_code( $result ) );
set_transient( WPDBT_PREFIX . 'cron_check', 'error', 600 );
set_transient( WPDBT_PREFIX . 'cron_check_date', gmdate( 'Y-m-d H:i:s' ), 600 );
set_transient( WPDBT_PREFIX . 'cron_check_message', $message, 600 );
} else {
Wp_Database_Tools_Logger::info( 'Success execute cronjob response' . json_encode( $result ) );
$message = esc_html__( 'The cronjob is working correctly', 'wp-database-tools' );
set_transient( WPDBT_PREFIX . 'cron_check', 'success', 1000 );
set_transient( WPDBT_PREFIX . 'cron_check_date', gmdate( 'Y-m-d H:i:s' ), 1000 );
set_transient( WPDBT_PREFIX . 'cron_check_message', $message, 1000 );
}
return true;
}
/**
* Method executed from WordPress cron.
*
* @since 1.0.0
* @author Patricia Álvarez <patriciaaf@raiolanetworks.es>
*/
public function cron_scanner( $tables, $options, $cronjobs, $transients ) {
Wp_Database_Tools_Logger::info( 'CRON SCANNER: start send data API' );
if ( $this->plugins == null ) {
Wp_Database_Tools_Logger::error( 'CRON SCANNER: plugins data null' );
}
if ( $this->themes == null ) {
Wp_Database_Tools_Logger::error( 'CRON SCANNER: themes data null' );
}
$this->set_status_scanner( 'active', __( 'Performing scanner', 'wp-database-tools' ) );
$tables = $tables['data'];
if ( null === $tables ) {
Wp_Database_Tools_Logger::error( 'CRON SCANNER: tables data null' );
} else {
$count_data = is_array( $tables ) ? count( $tables ) : 'null';
Wp_Database_Tools_Logger::info( 'CRON SCANNER: tables data ' . $count_data );
}
$options = $options['data'];
if ( null === $options ) {
Wp_Database_Tools_Logger::error( 'CRON SCANNER: options data null' );
} else {
$count_data = is_array( $options ) ? count( $options ) : 'null';
Wp_Database_Tools_Logger::info( 'CRON SCANNER: options data ' . $count_data );
}
$transients = $transients['data'];
if ( null === $transients ) {
Wp_Database_Tools_Logger::error( 'CRON SCANNER: transients data null' );
} else {
$count_data = is_array( $transients ) ? count( $transients ) : 'null';
Wp_Database_Tools_Logger::info( 'CRON SCANNER: transients data ' . $count_data );
}
$cronjobs = $cronjobs['data'];
if ( null === $cronjobs ) {
Wp_Database_Tools_Logger::error( 'CRON SCANNER: cronjobs data null' );
} else {
$count_data = is_array( $cronjobs ) ? count( $cronjobs ) : 'null';
Wp_Database_Tools_Logger::info( 'CRON SCANNER: cronjobs data ' . $count_data );
}
$domain = ( WPDBT_ENV === 'DEV' ) ? WPDBT_DEV_DOMAIN : WPDBT_PROD_DOMAIN;
$url = $domain . '/api/v2/scanner';
$args = array(
'timeout' => 1800,
'headers' => array(
'content-type' => 'application/json',
),
'body' => wp_json_encode(
array(
'tables' => wp_json_encode( $tables ),
'options' => wp_json_encode( $options ),
'transients' => wp_json_encode( $transients ),
'cronjobs' => wp_json_encode( $cronjobs ),
'plugins' => wp_json_encode( $this->plugins ),
'themes' => wp_json_encode( $this->themes ),
'license' => $this->license->get_license_key_encrypt() ?? 'invalid',
'license_url' => $this->license->get_license_url(),
'comercial' => 'true',
'version' => WPDBT_VERSION,
'force_execute_scanner' => get_option( WPDBT_PREFIX . 'force_execute_scanner' ) ?? 'NO',
)
),
);
$this->set_status_scanner( 'active', __( 'Getting results', 'wp-database-tools' ) );
$response = wp_remote_post( $url, $args );
$code = wp_remote_retrieve_response_code( $response );
// Error check.
if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
$this->set_status_scanner( 'error', $response->get_error_message() );
Wp_Database_Tools_Logger::error( 'SCANNER: something went wrong: ' . $error_message );
} else {
// format response.
$response_data = wp_remote_retrieve_body( $response );
$response_data = json_decode( $response_data, true );
$PATH_API_DATA = plugin_dir_path( __DIR__ ) . 'data/api/';
$KEYS = array( 'tables', 'options', 'cronjobs', 'plugins', 'themes', 'cores', 'marketplaces', 'authors', 'transients' );
if ( isset( $response_data['license'] ) && $code == 200 ) {
// update the execute scanner to NO.
update_option( WPDBT_PREFIX . 'force_execute_scanner', 'NO' );
if ( $response_data['license'] === 'valid' ) {
$this->license->set_license_key( $response_data['license'] );
foreach ( $KEYS as $KEY ) {
if ( $response_data['data'][ $KEY ] ) {
file_put_contents( $PATH_API_DATA . $KEY . '.json', wp_json_encode( mb_convert_encoding( $response_data['data'][ $KEY ], 'UTF-8' ) ) );
}
}
$this->set_status_scanner( 'success', __( 'Scanner finished', 'wp-database-tools' ) );
} else {
// Set data empty for invalid license.
$this->license->set_license_key( $response_data['license'] );
// Save empty data.
foreach ( $KEYS as $KEY ) {
if ( $response_data['data'][ $KEY ] ) {
file_put_contents( $PATH_API_DATA . $KEY . '.json', '' );
}
}
Wp_Database_Tools_Logger::error( 'SCANNER: licencia no válida' );
$this->set_status_scanner( 'error', __( 'Invalid license', 'wp-database-tools' ) );
}
} else {
$error_message = __( 'Scanner fault', 'wp-database-tools' );
if ( isset( $response_data['message'] ) ) {
$error_message = $response_data['message'];
} elseif ( isset( $response['response']['message'] ) ) {
$error_message = $response['response']['message'];
}
Wp_Database_Tools_Logger::error( json_encode( $response ) );
$this->set_status_scanner( 'error', $error_message );
}
}
}
}

View File

@@ -0,0 +1,129 @@
<?php
/**
* Database functions
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
*/
/**
* Detects current plugins in the installation
* *
*
* @since 1.0.0
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
* @author Patricia Alvarez <patricia@raiolanetworks.es>
*/
class Wp_Database_Tools_Themes {
/**
* Plugins in the installation.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $themes;
public function __construct() {
$this->init();
}
protected function init() {
$this->format_themes();
}
protected function format_themes() {
$themes_data = array();
foreach ( wp_get_themes() as $key => $theme ) {
// Check marketplace.
$marketplace = 'unknown';
if ( str_contains( $theme['AuthorURI'], 'codecanyon' ) || str_contains( $theme['ThemeURI'], 'codecanyon' ) ) {
$marketplace = 'https://codecanyon.net';
}
if ( str_contains( $theme['AuthorURI'], 'themeforest' ) || str_contains( $theme['ThemeURI'], 'themeforest' ) ) {
$marketplace = 'https://themeforest.net';
}
if ( str_contains( $theme['AuthorURI'], 'wordpress.org' ) || str_contains( $theme['ThemeURI'], 'wordpress.org' ) ) {
$marketplace = 'https://wordpress.org';
}
$themes_data[ $key ]['name'] = $theme->get( 'Name' ) ?? $key;
$themes_data[ $key ]['marketplace'] = $marketplace;
$themes_data[ $key ]['slug'] = $key;
$themes_data[ $key ]['initials'] = $this->get_initials( $key );
$themes_data[ $key ]['status'] = $this->get_theme_status( $key );
$themes_data[ $key ]['author'] = $theme->get( 'Author' ) ?? null;
$themes_data[ $key ]['author_name'] = $theme->get( 'Author' ) ?? null;
$themes_data[ $key ]['author_url'] = $theme->get( 'ThemeURI' ) ?? null;
$themes_data[ $key ]['version'] = $theme['Version'] ?? null;
}
$this->themes = $themes_data;
}
/**
* Get's the activation status for a plugin.
*
* @since 5.5.0
*
* @param string $plugin The plugin file to check.
* @return string 'active' . 'inactive' or 'uninstalled'.
* @author Patricia Alvarez <patricia@raiolanetworks.es>
*/
protected function get_theme_status( $theme ) {
if ( $theme === get_option( 'template' ) ) {
return 'active';
} elseif ( file_exists( get_theme_root() . '/' . $theme ) ) {
return 'inactive';
}
}
/**
* Get's the initials.
*
* @since 1.0.0
*
* @param string $plugin The plugin file to check.
* @return string 'active' . 'inactive' or 'uninstalled'.
* @author Patricia Alvarez <patricia@raiolanetworks.es>
*/
public function get_initials( $input ) {
$words = preg_split( '/[\s,_-]+/', $input );
$initials = '';
foreach ( $words as $input => $word ) {
$initials .= substr( $word, 0, 1 );
}
return $initials;
}
/**
* Get's the activation status for a plugin.
*
* @since 5.5.0
*
* @return string 'active' . 'inactive' or 'uninstalled'.
* @author Patricia Alvarez <patricia@raiolanetworks.es>
*/
public function get_themes() {
return $this->themes;
}
}

View File

@@ -0,0 +1,764 @@
<?php
/**
* The file that defines the core plugin class
*
* A class definition that includes attributes and functions used across both the
* public-facing side of the site and the admin area.
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Allows plugins to use their own update API.
*
* @author Easy Digital Downloads
* @version 1.9.2
*/
class Wp_Database_Tools_Updater {
/**
* The URL pointing to the custom API endpoint.
*
* @since 1.0.0
* @access protected
* @var String $api_url The URL pointing to the custom API endpoint.
*/
private $api_url = '';
/**
* Optional data to send with API calls.
*
* @since 1.0.0
* @access protected
* @var Array $api_data Optional data to send with API calls.
*/
private $api_data = array();
/**
* Path to the plugin file.
*
* @since 1.0.0
* @access protected
* @var String $plugin_file Path to the plugin file.
*/
private $plugin_file = '';
/**
* Path to the plugin file.
*
* @since 1.0.0
* @access protected
* @var String $name Path to the plugin file.
*/
private $name = '';
/**
* Path to the plugin file.
*
* @since 1.0.0
* @access protected
* @var String $slug Path to the plugin file.
*/
private $slug = '';
/**
* Slug of the current plugin.
*
* @since 1.0.0
* @access protected
* @var String $version Slug of the current plugin.
*/
private $version = '';
/**
* Override
*
* @since 1.0.0
* @access protected
* @var Boolean $wp_override Override
*/
private $wp_override = false;
/**
* Indicate if is a beta.
*
* @since 1.0.0
* @access protected
* @var Boolean $beta Indicate if is a beta.
*/
private $beta = false;
/**
* Request cache key.
*
* @since 1.0.0
* @access protected
* @var String $failed_request_cache_key Request cache key.
*/
private $failed_request_cache_key;
/**
* Class constructor.
*
* @uses plugin_basename()
* @uses hook()
*
* @param string $_api_url The URL pointing to the custom API endpoint.
* @param string $_plugin_file Path to the plugin file.
* @param array $_api_data Optional data to send with API calls.
*/
public function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
global $edd_plugin_data;
$this->api_url = trailingslashit( $_api_url );
$this->api_data = $_api_data;
$this->plugin_file = $_plugin_file;
$this->name = plugin_basename( $_plugin_file );
$this->slug = basename( $_plugin_file, '.php' );
$this->version = $_api_data['version'];
$this->wp_override = isset( $_api_data['wp_override'] ) ? (bool) $_api_data['wp_override'] : false;
$this->beta = ! empty( $this->api_data['beta'] ) ? true : false;
$this->failed_request_cache_key = 'edd_sl_failed_http_' . md5( $this->api_url );
$edd_plugin_data[ $this->slug ] = $this->api_data;
/**
* Fires after the $edd_plugin_data is setup.
*
* @since x.x.x
*
* @param array $edd_plugin_data Array of EDD SL plugin data.
*/
do_action( 'post_edd_sl_plugin_updater_setup', $edd_plugin_data );
// Set up hooks.
$this->init();
}
/**
* Set up WordPress filters to hook into WP's update process.
*
* @uses add_filter()
*
* @return void
*/
public function init() {
add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
add_action( 'after_plugin_row', array( $this, 'show_update_notification' ), 10, 2 );
add_action( 'admin_init', array( $this, 'show_changelog' ) );
}
/**
* Check for Updates at the defined API endpoint and modify the update array.
*
* This function dives into the update API just when WordPress creates its update array,
* then adds a custom API call and injects the custom plugin data retrieved from the API.
* It is reassembled from parts of the native WordPress plugin update code.
* See wp-includes/update.php line 121 for the original wp_update_plugins() function.
*
* @uses api_request()
*
* @param array $_transient_data Update array build by WordPress.
* @return array Modified update array with custom plugin data.
*/
public function check_update( $_transient_data ) {
global $pagenow;
if ( ! is_object( $_transient_data ) ) {
$_transient_data = new stdClass();
}
if ( ! empty( $_transient_data->response ) && ! empty( $_transient_data->response[ $this->name ] ) && false === $this->wp_override ) {
return $_transient_data;
}
$current = $this->get_repo_api_data();
if ( false !== $current && is_object( $current ) && isset( $current->new_version ) ) {
if ( version_compare( $this->version, $current->new_version, '<' ) ) {
$_transient_data->response[ $this->name ] = $current;
} else {
// Populating the no_update information is required to support auto-updates in WordPress 5.5.
$_transient_data->no_update[ $this->name ] = $current;
}
}
$_transient_data->last_checked = time();
$_transient_data->checked[ $this->name ] = $this->version;
return $_transient_data;
}
/**
* Get repo API data from store.
* Save to cache.
*
* @return \stdClass
*/
public function get_repo_api_data() {
$version_info = $this->get_cached_version_info();
$version_info = false; // Force no cache.
if ( false === $version_info ) {
$version_info = $this->api_request(
'plugin_latest_version',
array(
'slug' => $this->slug,
'beta' => $this->beta,
)
);
if ( ! $version_info ) {
return false;
}
// This is required for your plugin to support auto-updates in WordPress 5.5.
$version_info->plugin = $this->name;
$version_info->id = $this->name;
$version_info->tested = $this->get_tested_version( $version_info );
$this->set_version_info_cache( $version_info );
}
return $version_info;
}
/**
* Gets the plugin's tested version.
*
* @since 1.9.2
* @param Object $version_info Gets the plugin's tested version.
* @return null|string
*/
private function get_tested_version( $version_info ) {
// There is no tested version.
if ( empty( $version_info->tested ) ) {
return null;
}
// Strip off extra version data so the result is x.y or x.y.z.
list( $current_wp_version ) = explode( '-', get_bloginfo( 'version' ) );
// The tested version is greater than or equal to the current WP version, no need to do anything.
if ( version_compare( $version_info->tested, $current_wp_version, '>=' ) ) {
return $version_info->tested;
}
$current_version_parts = explode( '.', $current_wp_version );
$tested_parts = explode( '.', $version_info->tested );
// The current WordPress version is x.y.z, so update the tested version to match it.
if ( isset( $current_version_parts[2] ) && $current_version_parts[0] === $tested_parts[0] && $current_version_parts[1] === $tested_parts[1] ) {
$tested_parts[2] = $current_version_parts[2];
}
return implode( '.', $tested_parts );
}
/**
* Show the update notification on multisite subsites.
*
* @param string $file Plugin file.
* @param array $plugin Plugin.
*/
public function show_update_notification( $file, $plugin ) {
// Return early if in the network admin, or if this is not a multisite install.
if ( is_network_admin() || ! is_multisite() ) {
return;
}
// Allow single site admins to see that an update is available.
if ( ! current_user_can( 'activate_plugins' ) ) {
return;
}
if ( 'wp-database-tools/wp-database-tools.php' !== $file ) {
return;
}
if ( $this->name !== $file ) {
return;
}
// Do not print any message if update does not exist.
$update_cache = get_site_transient( 'update_plugins' );
if ( ! isset( $update_cache->response[ $this->name ] ) ) {
if ( ! is_object( $update_cache ) ) {
$update_cache = new stdClass();
}
$update_cache->response[ $this->name ] = $this->get_repo_api_data();
}
// Return early if this plugin isn't in the transient->response or if the site is running the current or newer version of the plugin.
if ( empty( $update_cache->response[ $this->name ] ) || version_compare( $this->version, $update_cache->response[ $this->name ]->new_version, '>=' ) ) {
return;
}
printf(
'<tr class="plugin-update-tr %3$s" id="%1$s-update" data-slug="%1$s" data-plugin="%2$s">',
// '<tr class="plugin-update-tr active" id="%1$s-update" data-slug="%1$s" data-plugin="%2$s">',
$this->slug,
$file,
in_array( $this->name, $this->get_active_plugins(), true ) ? 'active' : 'inactive'
);
echo '<td colspan="4" class="plugin-update colspanchange">';
echo '<div class="update-message notice inline notice-warning notice-alt"><p>';
$changelog_link = '';
if ( ! empty( $update_cache->response[ $this->name ]->sections->changelog ) ) {
$changelog_link = add_query_arg(
array(
'edd_sl_action' => 'view_plugin_changelog',
'plugin' => urlencode( $this->name ),
'slug' => urlencode( $this->slug ),
'TB_iframe' => 'true',
'width' => 77,
'height' => 911,
),
self_admin_url( 'index.php' )
);
}
$update_link = add_query_arg(
array(
'action' => 'upgrade-plugin',
'plugin' => urlencode( $this->name ),
),
self_admin_url( 'update.php' )
);
printf(
/* translators: the plugin name. */
esc_html__( 'There is a new version of %1$s available.', 'easy-digital-downloads' ),
esc_html( $plugin['Name'] )
);
if ( ! current_user_can( 'update_plugins' ) ) {
echo ' ';
esc_html_e( 'Contact your network administrator to install the update.', 'easy-digital-downloads' );
} elseif ( empty( $update_cache->response[ $this->name ]->package ) && ! empty( $changelog_link ) ) {
echo ' ';
printf(
/* translators: 1. opening anchor tag, do not translate 2. the new plugin version 3. closing anchor tag, do not translate. */
__( '%1$sView version %2$s details%3$s.', 'easy-digital-downloads' ),
'<a target="_blank" class="thickbox open-plugin-details-modal" href="' . esc_url( $changelog_link ) . '">',
esc_html( $update_cache->response[ $this->name ]->new_version ),
'</a>'
);
} elseif ( ! empty( $changelog_link ) ) {
echo ' ';
printf(
__( '%1$sView version %2$s details%3$s or %4$supdate now%5$s.', 'easy-digital-downloads' ),
'<a target="_blank" class="thickbox open-plugin-details-modal" href="' . esc_url( $changelog_link ) . '">',
esc_html( $update_cache->response[ $this->name ]->new_version ),
'</a>',
'<a target="_blank" class="update-link" href="' . esc_url( wp_nonce_url( $update_link, 'upgrade-plugin_' . $file ) ) . '">',
'</a>'
);
} else {
printf(
' %1$s%2$s%3$s',
'<a target="_blank" class="update-link" href="' . esc_url( wp_nonce_url( $update_link, 'upgrade-plugin_' . $file ) ) . '">',
esc_html__( 'Update now.', 'easy-digital-downloads' ),
'</a>'
);
}
do_action( "in_plugin_update_message-{$file}", $plugin, $plugin );
echo '</p></div></td></tr>';
}
/**
* Gets the plugins active in a multisite network.
*
* @return array
*/
private function get_active_plugins() {
$active_plugins = (array) get_option( 'active_plugins' );
$active_network_plugins = (array) get_site_option( 'active_sitewide_plugins' );
return array_merge( $active_plugins, array_keys( $active_network_plugins ) );
}
/**
* Updates information on the "View version x.x details" page with custom data.
*
* @uses api_request()
*
* @param mixed $_data Data.
* @param string $_action Action.
* @param object $_args Args.
* @return object $_data Data.
*/
public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
if ( 'plugin_information' !== $_action ) {
return $_data;
}
if ( ! isset( $_args->slug ) || ( $_args->slug !== $this->slug ) ) {
return $_data;
}
$to_send = array(
'slug' => $this->slug,
'is_ssl' => is_ssl(),
'fields' => array(
'banners' => array(),
'reviews' => false,
'icons' => array(),
),
);
// Get the transient where we store the api request for this plugin for 24 hours.
$edd_api_request_transient = $this->get_cached_version_info();
// If we have no transient-saved value, run the API, set a fresh transient with the API value, and return that value too right now.
if ( empty( $edd_api_request_transient ) ) {
$api_response = $this->api_request( 'plugin_information', $to_send );
// Expires in 3 hours.
$this->set_version_info_cache( $api_response );
if ( false !== $api_response ) {
$_data = $api_response;
}
} else {
$_data = $edd_api_request_transient;
}
// Convert sections into an associative array, since we're getting an object, but Core expects an array.
if ( isset( $_data->sections ) && ! is_array( $_data->sections ) ) {
$_data->sections = $this->convert_object_to_array( $_data->sections );
}
// Convert banners into an associative array, since we're getting an object, but Core expects an array.
if ( isset( $_data->banners ) && ! is_array( $_data->banners ) ) {
$_data->banners = $this->convert_object_to_array( $_data->banners );
}
// Convert icons into an associative array, since we're getting an object, but Core expects an array.
if ( isset( $_data->icons ) && ! is_array( $_data->icons ) ) {
$_data->icons = $this->convert_object_to_array( $_data->icons );
}
// Convert contributors into an associative array, since we're getting an object, but Core expects an array.
if ( isset( $_data->contributors ) && ! is_array( $_data->contributors ) ) {
$_data->contributors = $this->convert_object_to_array( $_data->contributors );
}
if ( ! isset( $_data->plugin ) ) {
$_data->plugin = $this->name;
}
return $_data;
}
/**
* Convert some objects to arrays when injecting data into the update API
*
* Some data like sections, banners, and icons are expected to be an associative array, however due to the JSON
* decoding, they are objects. This method allows us to pass in the object and return an associative array.
*
* @since 3.6.5
*
* @param stdClass $data Data.
*
* @return array
*/
private function convert_object_to_array( $data ) {
if ( ! is_array( $data ) && ! is_object( $data ) ) {
return array();
}
$new_data = array();
foreach ( $data as $key => $value ) {
$new_data[ $key ] = is_object( $value ) ? $this->convert_object_to_array( $value ) : $value;
}
return $new_data;
}
/**
* Disable SSL verification in order to prevent download update failures
*
* @param array $args Args.
* @param string $url Url.
* @return object $array Array.
*/
public function http_request_args( $args, $url ) {
if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
$args['sslverify'] = $this->verify_ssl();
}
return $args;
}
/**
* Calls the API and, if successfull, returns the object delivered by the API.
*
* @uses get_bloginfo()
* @uses wp_remote_post()
* @uses is_wp_error()
*
* @param string $_action The requested action.
* @param array $_data Parameters for the API action.
* @return false|object|void
*/
private function api_request( $_action, $_data ) {
$data = array_merge( $this->api_data, $_data );
if ( $data['slug'] !== $this->slug ) {
return;
}
// Don't allow a plugin to ping itself.
if ( trailingslashit( home_url() ) === $this->api_url ) {
return false;
}
if ( $this->request_recently_failed() ) {
return false;
}
return $this->get_version_from_remote();
}
/**
* Determines if a request has recently failed.
*
* @since 1.9.1
*
* @return bool
*/
private function request_recently_failed() {
$failed_request_details = get_option( $this->failed_request_cache_key );
// Request has never failed.
if ( empty( $failed_request_details ) || ! is_numeric( $failed_request_details ) ) {
return false;
}
/*
* Request previously failed, but the timeout has expired.
* This means we're allowed to try again.
*/
if ( time() > $failed_request_details ) {
delete_option( $this->failed_request_cache_key );
return false;
}
return true;
}
/**
* Logs a failed HTTP request for this API URL.
* We set a timestamp for 1 hour from now. This prevents future API requests from being
* made to this domain for 1 hour. Once the timestamp is in the past, API requests
* will be allowed again. This way if the site is down for some reason we don't bombard
* it with failed API requests.
*
* @see EDD_SL_Plugin_Updater::request_recently_failed
*
* @since 1.9.1
*/
private function log_failed_request() {
update_option( $this->failed_request_cache_key, strtotime( '+1 hour' ) );
}
/**
* If available, show the changelog for sites in a multisite install.
*/
public function show_changelog() {
if ( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' !== $_REQUEST['edd_sl_action'] ) {
return;
}
if ( empty( $_REQUEST['plugin'] ) ) {
return;
}
if ( empty( $_REQUEST['slug'] ) || $this->slug !== $_REQUEST['slug'] ) {
return;
}
if ( ! current_user_can( 'update_plugins' ) ) {
wp_die( esc_html__( 'You do not have permission to install plugin updates', 'easy-digital-downloads' ), esc_html__( 'Error', 'easy-digital-downloads' ), array( 'response' => 403 ) );
}
$version_info = $this->get_repo_api_data();
if ( isset( $version_info->sections ) ) {
$sections = $this->convert_object_to_array( $version_info->sections );
if ( ! empty( $sections['changelog'] ) ) {
echo '<div style="background:#fff;padding:10px;">' . wp_kses_post( $sections['changelog'] ) . '</div>';
}
}
exit;
}
/**
* Gets the current version information from the remote site.
*
* @return array|false
*/
private function get_version_from_remote() {
$api_params = array(
'edd_action' => 'get_version',
'license' => ! empty( $this->api_data['license'] ) ? $this->api_data['license'] : '',
'item_name' => isset( $this->api_data['item_name'] ) ? $this->api_data['item_name'] : false,
'item_id' => isset( $this->api_data['item_id'] ) ? $this->api_data['item_id'] : false,
'version' => isset( $this->api_data['version'] ) ? $this->api_data['version'] : false,
'slug' => $this->slug,
'author' => $this->api_data['author'],
'url' => home_url(),
'beta' => $this->beta,
'php_version' => phpversion(),
'wp_version' => get_bloginfo( 'version' ),
);
/**
* Filters the parameters sent in the API request.
*
* @param array $api_params The array of data sent in the request.
* @param array $this->api_data The array of data set up in the class constructor.
* @param string $this->plugin_file The full path and filename of the file.
*/
$api_params = apply_filters( 'edd_sl_plugin_updater_api_params', $api_params, $this->api_data, $this->plugin_file );
$request = wp_remote_post(
$this->api_url,
array(
'timeout' => 15,
'sslverify' => $this->verify_ssl(),
'body' => $api_params,
)
);
if ( is_wp_error( $request ) || ( 200 !== wp_remote_retrieve_response_code( $request ) ) ) {
$this->log_failed_request();
return false;
}
$request = json_decode( wp_remote_retrieve_body( $request ) );
if ( $request && isset( $request->sections ) ) {
$request->sections = maybe_unserialize( $request->sections );
} else {
$request = false;
}
if ( $request && isset( $request->banners ) ) {
$request->banners = maybe_unserialize( $request->banners );
}
if ( $request && isset( $request->icons ) ) {
$request->icons = maybe_unserialize( $request->icons );
}
if ( ! empty( $request->sections ) ) {
foreach ( $request->sections as $key => $section ) {
$request->$key = (array) $section;
}
}
return $request;
}
/**
* Get the version info from the cache, if it exists.
*
* @param string $cache_key Key of cache.
* @return object
*/
public function get_cached_version_info( $cache_key = '' ) {
if ( empty( $cache_key ) ) {
$cache_key = $this->get_cache_key();
}
$cache = get_option( $cache_key );
// Cache is expired.
if ( empty( $cache['timeout'] ) || time() > $cache['timeout'] ) {
return false;
}
// We need to turn the icons into an array, thanks to WP Core forcing these into an object at some point.
$cache['value'] = json_decode( $cache['value'] );
if ( ! empty( $cache['value']->icons ) ) {
$cache['value']->icons = (array) $cache['value']->icons;
}
return $cache['value'];
}
/**
* Adds the plugin version information to the database.
*
* @param string $value Value cache.
* @param string $cache_key Key of cache.
*/
public function set_version_info_cache( $value = '', $cache_key = '' ) {
if ( empty( $cache_key ) ) {
$cache_key = $this->get_cache_key();
}
$data = array(
'timeout' => strtotime( '+3 hours', time() ),
'value' => wp_json_encode( $value ),
);
update_option( $cache_key, $data, 'no' );
// Delete the duplicate option.
delete_option( 'edd_api_request_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) ) );
}
/**
* Returns if the SSL of the store should be verified.
*
* @since 1.6.13
* @return bool
*/
private function verify_ssl() {
return (bool) apply_filters( 'edd_sl_api_request_verify_ssl', true, $this );
}
/**
* Gets the unique key (option name) for a plugin.
*
* @since 1.9.0
* @return string
*/
private function get_cache_key() {
$string = $this->slug . $this->api_data['license'] . $this->beta;
return 'edd_sl_' . md5( serialize( $string ) );
}
}

View File

@@ -0,0 +1,511 @@
<?php
/**
* The file that defines the core plugin class
*
* A class definition that includes attributes and functions used across both the
* public-facing side of the site and the admin area.
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
*/
/**
* The core plugin class.
*
* This is used to define internationalization, admin-specific hooks, and
* public-facing site hooks.
*
* Also maintains the unique identifier of this plugin as well as the current
* version of the plugin.
*
* @since 1.0.0
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes
* @author Raiola Networks <info@raiolanetworks.es>
*/
class Wp_Database_Tools {
/**
* The loader that's responsible for maintaining and registering all hooks that power
* the plugin.
*
* @since 1.0.0
* @access protected
* @var Wp_Database_Tools_Loader $loader Maintains and registers all hooks for the plugin.
*/
protected $loader;
/**
* The class responsible for logic database manage.
*
* @since 1.0.0
* @access protected
* @var Wp_Database_Tools_Database $loader Maintains and registers all hooks for the plugin.
*/
protected $database;
/**
* The class responsible for logic of manage license.
*
* @since 1.0.0
* @access protected
* @var Wp_Database_Tools_License $license Manage the license functionalities.
*/
protected $license;
/**
* The class responsible for logic of manage license.
*
* @since 1.0.0
* @access protected
* @var Wp_Database_Tools_Cronjobs $cronjobs Manage the license functionalities.
*/
protected $cronjobs;
/**
* The class responsible for logic of manage license.
*
* @since 1.0.0
* @access protected
* @var Wp_Database_Tools_Scanner $license Manage the license functionalities.
*/
protected $scanner;
/**
* The class responsible for logic of manage license.
*
* @since 1.0.0
* @access protected
* @var Wp_Database_Tools_Updater $updater Manage the license functionalities.
*/
protected $updater;
/**
* The class responsible for logic of manage user feedback.
*
* @since 1.0.0
* @access protected
* @var Wp_Database_Tools_Feedback $feedback Manage the license functionalities.
*/
protected $feedback;
/**
* The unique identifier of this plugin.
*
* @since 1.0.0
* @access protected
* @var string $plugin_name The string used to uniquely identify this plugin.
*/
protected $plugin_name;
/**
* The current version of the plugin.
*
* @since 1.0.0
* @access protected
* @var string $version The current version of the plugin.
*/
protected $version;
/**
* The current version of the plugin.
*
* @since 1.0.0
* @access protected
* @var string $version The current version of the plugin.
*/
protected $plugins;
/**
* The current version of the plugin.
*
* @since 1.0.0
* @access protected
* @var string $version The current version of the plugin.
*/
protected $themes;
/**
* The current version of the plugin.
*
* @since 1.0.0
* @access protected
* @var string $version The current version of the plugin.
*/
protected $matching;
/**
* Define the core functionality of the plugin.
*
* Set the plugin name and the plugin version that can be used throughout the plugin.
* Load the dependencies, define the locale, and set the hooks for the admin area and
* the public-facing side of the site.
*
* @since 1.0.0
*/
public function __construct() {
if ( defined( 'WPDBT_VERSION' ) ) {
$this->version = WPDBT_VERSION;
} else {
$this->version = '1.0.0';
}
$this->plugin_name = 'wp-database-tools';
$this->load_dependencies();
$this->set_locale();
$this->define_admin_hooks();
}
/**
* Load the required dependencies for this plugin.
*
* Include the following files that make up the plugin:
*
* - Wp_Database_Tools_Loader. Orchestrates the hooks of the plugin.
* - Wp_Database_Tools_i18n. Defines internationalization functionality.
* - Wp_Database_Tools_Admin. Defines all hooks for the admin area.
*
* Create an instance of the loader which will be used to register the hooks
* with WordPress.
*
* @since 1.0.0
* @access private
*/
private function load_dependencies() {
/**
* The class responsible for orchestrating the actions and filters of the
* core plugin.
*/
include_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wp-database-tools-loader.php';
/**
* The class responsible for logic of database functions
*/
include_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wp-database-tools-database.php';
/**
* The class responsible for features of current license
*/
include_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wp-database-tools-license.php';
/**
* The class responsible for features of scanner database
*/
include_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wp-database-tools-scanner.php';
/**
* The class responsible for defining internationalization functionality
* of the plugin.
*/
include_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wp-database-tools-i18n.php';
/**
* The class responsible for updated
*/
include_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wp-database-tools-updater.php';
/**
* The class responsible for defining all actions that occur in the admin area.
*/
include_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-wp-database-tools-admin.php';
/**
* The class responsible for plugins
*/
include_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wp-database-tools-plugins.php';
/**
* The class responsible for themes
*/
include_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wp-database-tools-themes.php';
/**
* The class responsible for themes
*/
include_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wp-database-tools-matching.php';
/**
* The class responsible for themes
*/
include_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wp-database-tools-feedback.php';
$this->loader = new Wp_Database_Tools_Loader();
$this->plugins = new Wp_Database_Tools_Plugins();
$this->themes = new Wp_Database_Tools_Themes();
$this->matching = new Wp_Database_Tools_Matching( $this->plugins, $this->themes );
$this->license = new Wp_Database_Tools_License( $this->plugin_name );
$this->database = new Wp_Database_Tools_Database( $this->plugins, $this->themes, $this->matching, $this->license->get_is_active() );
$this->scanner = new Wp_Database_Tools_Scanner( $this->license, $this->plugins, $this->themes );
$this->feedback = new Wp_Database_Tools_Feedback();
if ( $this->license->get_is_active() ) {
$this->updater = new Wp_Database_Tools_Updater(
WPDBT_EDD_STORE_URL,
'wp-database-tools/wp-database-tools.php',
array(
'version' => $this->version,
'license' => $this->license->get_license_key(),
'item_id' => WPDBT_EDD_ITEM_ID,
'author' => 'Raiola Networks',
'beta' => false,
)
);
}
}
/**
* Define the locale for this plugin for internationalization.
*
* Uses the Wp_Database_Tools_i18n class in order to set the domain and to register the hook
* with WordPress.
*
* @since 1.0.0
* @access private
*/
private function set_locale() {
$plugin_i18n = new Wp_Database_Tools_i18n();
$this->loader->add_action( 'plugins_loaded', $plugin_i18n, 'load_plugin_textdomain' );
}
/**
* Register all of the hooks related to the admin area functionality
* of the plugin.
*
* @since 1.0.0
* @access private
*/
private function define_admin_hooks() {
$plugin_admin = new Wp_Database_Tools_Admin(
$this->get_plugin_name(),
$this->get_version(),
$this->get_database(),
$this->get_license(),
$this->get_scanner(),
$this->get_cronjobs(),
$this->get_feedback(),
);
// Load styles.
$this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' );
// Load scripts.
$this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
// Load menu.
$this->loader->add_action( 'admin_menu', $plugin_admin, 'add_admin_menu' );
// License.
$this->loader->add_action( 'admin_post_active_plugin', $plugin_admin, 'active_plugin' );
// Action forms.
$this->loader->add_action( 'admin_post_process_general', $plugin_admin, 'process_general' );
$this->loader->add_action( 'admin_post_process_tables', $plugin_admin, 'process_tables' );
$this->loader->add_action( 'admin_post_process_options', $plugin_admin, 'process_options' );
$this->loader->add_action( 'admin_post_process_transients', $plugin_admin, 'process_transients' );
$this->loader->add_action( 'admin_post_process_cronjobs', $plugin_admin, 'process_cronjobs' );
// Notices return.
$this->loader->add_action( 'admin_notices', $plugin_admin, 'custom_notices' );
// Scanner cronjob.
$this->loader->add_filter( 'wp_database_tools_scanner_database_daily', $plugin_admin, 'cron_scanner' );
$this->loader->add_filter( 'wp_database_tools_scanner_database_single', $plugin_admin, 'cron_scanner' );
// Scanner ajax call.
$this->loader->add_action( 'wp_ajax_nopriv_init_scanner', $plugin_admin, 'init_scanner' );
$this->loader->add_action( 'wp_ajax_init_scanner', $plugin_admin, 'init_scanner' );
// Scanner ajax feedbck.
$this->loader->add_action( 'wp_ajax_nopriv_save_feedback_user', $this->get_feedback(), 'save_feedback_user' );
$this->loader->add_action( 'wp_ajax_save_feedback_user', $this->get_feedback(), 'save_feedback_user' );
$this->loader->add_action( 'wp_ajax_load_data', $plugin_admin, 'load_data' );
$this->loader->add_action( 'wp_ajax_load_data_status', $plugin_admin, 'load_data_status' );
$this->loader->add_action( 'wp_ajax_check_force_scanner', $plugin_admin, 'check_force_scanner' );
// Remove all transients.
$this->loader->add_action( 'wp_ajax_nopriv_remove_all_transients', $this->database->get_transients_obj(), 'remove_all_transients' );
$this->loader->add_action( 'wp_ajax_remove_all_transients', $this->database->get_transients_obj(), 'remove_all_transients' );
// Scanner class.
$this->loader->add_action( 'init', $this->get_scanner(), 'wpdt_test_cron_spawn' );
// Admin load.
$this->loader->add_action( 'admin_init', $this->get_database(), 'remove_data_loop' );
}
/**
* Run the loader to execute all of the hooks with WordPress.
*
* @since 1.0.0
*/
public function run() {
$this->loader->run();
}
/**
* Run the scanner if the option did not exist or the data
* returned by the API is empty.
*
* @since 1.1.0
*/
public function run_force_execute_scanner() {
$this->check_exist_execute_scanner();
$this->check_data_execute_scanner();
$force_execute_scanner = get_option( WPDBT_PREFIX . 'force_execute_scanner' );
if ( 'YES' === $force_execute_scanner ) {
// schedule cron job.
if ( ! wp_next_scheduled( 'wp_database_tools_scanner_database_single' ) ) {
wp_schedule_single_event( time() - 3600, 'wp_database_tools_scanner_database_single' );
}
}
}
/**
* If the json returned by the api is empty set the option to "YES".
*
* @since 1.1.2
* @access private
*/
private function check_data_execute_scanner() {
$api_data_source = json_decode( file_get_contents( plugin_dir_path( __DIR__ ) . 'data/api/tables.json' ) );
if ( ( is_null( $api_data_source ) || empty( $api_data_source ) ) && $this->license->get_is_active() === true ) {
update_option( WPDBT_PREFIX . 'force_execute_scanner', 'YES' );
} else {
update_option( WPDBT_PREFIX . 'force_execute_scanner', 'NO' );
}
}
/**
* If the option does not exist, set the scanner execution to "YES".
*
* @since 1.1.2
* @access private
*/
private function check_exist_execute_scanner() {
$force_execute_scanner = get_option( WPDBT_PREFIX . 'force_execute_scanner' );
if ( false === $force_execute_scanner ) {
update_option( WPDBT_PREFIX . 'force_execute_scanner', 'YES' );
}
}
/**
* The name of the plugin used to uniquely identify it within the context of
* WordPress and to define internationalization functionality.
*
* @since 1.0.0
* @return string The name of the plugin.
*/
public function get_plugin_name() {
return $this->plugin_name;
}
/**
* The reference to the class that orchestrates the hooks with the plugin.
*
* @since 1.0.0
* @return Wp_Database_Tools_Loader Orchestrates the hooks of the plugin.
*/
public function get_loader() {
return $this->loader;
}
/**
* The class responsible for logic of database functions.
*
* @since 1.0.0
* @return Wp_Database_Tools_Database Manage database functionalities.
*/
public function get_database() {
return $this->database;
}
/**
* The class responsible for all features of the current license.
*
* @since 1.0.0
* @return Wp_Database_Tools_License Defines all features of the current license.
*/
public function get_license() {
return $this->license;
}
/**
* The class responsible for all features of the current license.
*
* @since 1.0.0
* @return Wp_Database_Tools_Cronjobs Defines all features of the current cronjobs.
*/
public function get_cronjobs() {
return $this->cronjobs;
}
/**
* The class responsible for all features of the current scanner.
*
* @since 1.0.0
* @return Wp_Database_Tools_Scanner Defines all features of the current scanner.
*/
public function get_scanner() {
return $this->scanner;
}
/**
* The class responsible for all features of the current plugins.
*
* @since 1.0.0
* @return Wp_Database_Tools_Plugins Defines all features of the current plugins.
*/
public function get_plugins() {
return $this->plugins;
}
/**
* The class responsible for all features of the user feedback.
*
* @since 1.0.0
* @return Wp_Database_Tools_Feedback Defines features of feedback.
*/
public function get_feedback() {
return $this->feedback;
}
/**
* Retrieve the version number of the plugin.
*
* @since 1.0.0
* @return string The version number of the plugin.
*/
public function get_version() {
return $this->version;
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* Author class file
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes/data
*/
/**
* Author.
*
* This class defines all code necessary to manage the Author.
*
* @since 1.0.0
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes/data
* @author Raiola Networks <info@raiolanetworks.es>
*/
class Wp_Database_Tools_Database_Data_Author {
/**
* The id of the Author.
*
* @since 1.0.0
* @access protected
* @var string $id The id of the Author.
*/
protected $id;
/**
* The name of the Author.
*
* @since 1.0.0
* @access protected
* @var string $name The name of the Author.
*/
protected $name;
/**
* The url of the Author.
*
* @since 1.0.0
* @access protected
* @var string $url The name of the Author.
*/
protected $url;
/**
* Constructor
*
* Create the instance of a Author.
*
* @access public
* @since 1.0.0
*/
public function __construct() {
$this->id = str_shuffle( 'abcdefABCDEF' ) . '-' . rand( 1000, 2000 );
$this->name = 'Unknown';
$this->url = null;
}
/**
* Set object attributes via API information
*
* @access public
* @since 1.0.0
*
* @param Object $api_data Object obtained from API information.
*/
public function set_author_by_api( $api_data ) {
$this->id = $api_data->id;
$this->name = $api_data->author ?? $api_data->user_nicname ?? null;
$this->url = $api_data->profile ?? $api_data->author_url ?? null;
}
/**
* Set object attributes via algorithm
*
* @access public
* @since 1.0.0
*
* @param Array $algorithm_data Array returning the identification algorithm.
*/
public function set_author_by_algorithm( $algorithm_data ) {
$this->name = $data_algorithm['author'] ?? $data_algorithm['author_name'] ?? null;
$this->url = $data_algorithm['author_url'] ?? null;
}
/**
* Return attributes as an array
*
* @access public
* @since 1.0.0
*
* @return Array Array attributes.
*/
public function return_object_vars() {
return get_object_vars( $this );
}
}

View File

@@ -0,0 +1,153 @@
<?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_Data_Cronjob extends Wp_Database_Tools_Database_Data {
/**
* The schedule of cronjob.
*
* @since 1.0.0
* @access protected
* @var array $schedule The schedule of cronjob.
*/
protected $schedule;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $display The general data of database.
*/
protected $display;
/**
* The args of cronjob.
*
* @since 1.0.0
* @access protected
* @var array $args The args of cronjob.
*/
protected $args;
/**
* The interval of cronjob.
*
* @since 1.0.0
* @access protected
* @var array $interval The interval of cronjob.
*/
protected $interval;
/**
* Next run of cronjob.
*
* @since 1.0.0
* @access protected
* @var array $next_run Next run of cronjob.
*/
protected $next_run;
/**
* The timestamp of cronjob.
*
* @since 1.0.0
* @access protected
* @var array $timestamp The timestamp of cronjob.
*/
protected $timestamp;
/**
* Constructor
*
* Create the instance of a Marketplace.
*
* @access public
* @since 1.0.0
*
* @param Array $schedules Schedules.
* @param int $timestamp Timestamp.
* @param string $event_hook Event_hook name.
* @param Array $events Events.
* @param Object $event Event.
* @param Array $feedback Feedback info.
*/
public function __construct( $schedules, $timestamp, $event_hook, $events, $event, $feedback ) {
parent::__construct();
$args_value = '';
foreach ( $event['args'] as $key => $arg ) {
$args_value .= $arg . ' ';
}
// Cronjob data.
$this->schedule = empty( $event['schedule'] ) ? '-' : $event['schedule'];
$this->display = $schedules[ $event['schedule'] ]['display'] ?? '';
$this->args_array = ( ! empty( $args_value ) ) ? $event['args'] : '';
$this->args = $args_value;
$this->interval = isset( $event['interval'] ) ? $event['interval'] : 0;
$this->next_run = ( $timestamp ) ? date( 'Y-m-d H:i:s', $timestamp ) : '-';
$this->timestamp = ( $timestamp ) ? $timestamp : 0;
$this->section = 'cronjobs';
// Common data.
$this->id = trim( $event_hook . '↔' . htmlspecialchars( json_encode( $event['args'] ) ) . '↔' . $timestamp );
$this->name = $event_hook;
$this->set_feedback( $feedback );
$this->check_regex();
}
/**
* Set true the regex attribute
*
* @access public
* @since 1.0.0
*/
public function check_regex() {
// Parent method.
$this->set_regex( false );
}
/**
* Set true the multiple attribute
*
* @access public
* @since 1.0.0
*/
public function set_multiple() {
$this->multiple = true;
}
/**
* Return attributes as an array
*
* @access public
* @since 1.0.0
*
* @return Array Array attributes.
*/
public function return_object_vars() {
return get_object_vars( $this );
}
}

View File

@@ -0,0 +1,126 @@
<?php
/**
* Marketplace class file
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes/data
*/
/**
* Marketplace.
*
* This class defines all code necessary to manage the Marketplace.
*
* @since 1.0.0
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes/data
* @author Raiola Networks <info@raiolanetworks.es>
*/
class Wp_Database_Tools_Database_Data_Marketplace {
/**
* The id of the marketplace.
*
* @since 1.0.0
* @access protected
* @var string $id Id of the marketplace.
*/
protected $id;
/**
* The name of the marketplace.
*
* @since 1.0.0
* @access protected
* @var string $name The name of the marketplace.
*/
protected $name;
/**
* The slug of the marketplace.
*
* @since 1.0.0
* @access protected
* @var string $slug The slug of the marketplace.
*/
protected $slug;
/**
* The url of marketplace.
*
* @since 1.0.0
* @access protected
* @var string $homepage The url of marketplace.
*/
protected $homepage;
/**
* The image of marketplace.
*
* @since 1.0.0
* @access protected
* @var string $image The image of marketplace.
*/
protected $image;
/**
* Constructor
*
* Create the instance of a Marketplace.
*
* @access public
* @since 1.0.0
*/
public function __construct() {
$this->id = str_shuffle( 'abcdefABCDEF' ) . '-' . rand( 1000, 2000 );
$this->name = 'Unknown';
$this->slug = 'unknown-marketplace';
$this->homepage = null;
$this->image = null;
}
/**
* Set object attributes via API information
*
* @access public
* @since 1.0.0
*
* @param Object $api_data Object obtained from API information.
*/
public function set_marketplace_by_api( $api_data ) {
$this->id = $api_data->id ?? $this->id;
$this->name = $api_data->name ?? $this->name;
$this->slug = $api_data->slug;
$this->homepage = $api_data->homepage;
$this->image = $api_data->image;
}
/**
* Set object attributes via algorithm
*
* @access public
* @since 1.0.0
*
* @param Array $algorithm_data Array returning the identification algorithm.
*/
public function set_marketplace_by_algorithm( $algorithm_data ) {
$this->name = $data_algorithm['marketplace'] ?? 'Unknown';
$this->url = sanitize_title( $algorithm_data['marketplace'] ) ?? 'unknown-marketplace';
}
/**
* Return attributes as an array
*
* @access public
* @since 1.0.0
*
* @return Array Array attributes.
*/
public function return_object_vars() {
return get_object_vars( $this );
}
}

View File

@@ -0,0 +1,210 @@
<?php
/**
* Option class file
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes/data
*/
/**
* Option.
*
* This class defines all code necessary to manage the Option.
*
* @since 1.0.0
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes/data
* @author Raiola Networks <info@raiolanetworks.es>
*/
class Wp_Database_Tools_Database_Data_Option extends Wp_Database_Tools_Database_Data {
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $autoload The general data of database.
*/
protected $autoload;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $extract The general data of database.
*/
protected $extract;
/**
* Constructor
*
* Create the instance of a Option.
*
* @access public
* @since 1.0.0
*
* @param Obj $option Option row data.
* @param Array $feedback Feedback array content by user meta.
*/
public function __construct( $option, $feedback ) {
parent::__construct();
// Option data.
$this->autoload = $option->autoload;
$this->extract = $this->set_extract( $option->option_value );
$this->value = htmlentities( $option->option_value );
// Common data.
$this->id = $option->option_id;
$this->name = $option->option_name;
$this->section = 'options';
$this->size = $option->size;
$this->format_size = $this->get_file_size_info( $this->size );
$this->format_size = $this->format_size['size'] . '' . $this->format_size['type'];
$this->set_feedback( $feedback );
$this->check_regex();
}
/**
* Determine whether to display the integer value or an extract in
* case the length is greater than a certain number
*
* @access public
* @since 1.0.0
*
* @param String $value The option value.
*/
public function set_extract( $value ) {
return ( strlen( $value ) > 16 )
? substr( esc_attr( wp_strip_all_tags( $value ) ), 0, 16 ) . '...'
: '';
}
/**
* Converts bit size to a readable format
*
* @access public
* @since 1.0.0
*
* @param int $file_size The size option.
*/
public function get_file_size_info( $file_size ) {
$bytes = array( 'B', 'KB', 'MB', 'GB', 'TB' );
if ( $file_size < 1024 ) {
$file_size = 1;
}
for ( $i = 0; $file_size > 1024; $i++ ) {
$file_size /= 1024;
}
$db_size_info['size'] = round( $file_size, 2 );
$db_size_info['type'] = $bytes[ $i ];
return $db_size_info;
}
/**
* Adds the size of a record
*
* @access public
* @since 1.0.0
*
* @param Obj $option Option row data.
*/
public function sum_size( $option ) {
if ( isset( $option->Data_length ) && isset( $option->Index_length ) ) {
$sum = $option->Data_length + $option->Index_length;
} else {
$sum = 0;
}
return $sum;
}
/**
* Set true the multiple attribute
*
* @access public
* @since 1.0.0
*/
public function set_multiple() {
$this->multiple = true;
}
/**
* We found that the option does not conform to certain patterns.
* If it does meet a pattern we set the regex property.
* This is done so that no such records are stored in the database,
* but the regex is simply stored as a string.
*
* @access public
* @since 1.0.0
*/
public function check_regex() {
$this->set_regex( false );
// Regex wpseo.
if ( str_starts_with( $this->name, 'wpseo_sitemap_' ) ) {
$pattern = '/wpseo_sitemap_([0-9]+)_cache_validator/i';
if ( preg_match( $pattern, $this->name ) ) {
$this->set_regex( 'wpseo_sitemap_{regex}_cache_validator' );
}
}
// Regex updraft_lock_.
if ( str_starts_with( $this->name, 'updraft_lock_' ) ) {
$pattern = '/updraft_lock_([a-z0-9]{12})/i';
if ( preg_match( $pattern, $this->name ) ) {
$this->set_regex( 'updraft_lock_{regex}' );
}
}
// Regex jetpack_nonce_.
if ( str_starts_with( $this->name, 'jetpack_nonce_' ) ) {
$pattern = '/jetpack_nonce_([0-9]{10})_([a-z0-9]{10})/i';
if ( preg_match( $pattern, $this->name ) ) {
$this->set_regex( 'jetpack_nonce_{regex}_{regex}' );
}
}
}
/**
* Return the autoload attribute.
*
* @access public
* @since 1.0.0
*
* @return string this->autoload The autoload attribute.
*/
public function get_autoload() {
return $this->autoload;
}
/**
* Return attributes as an array
*
* @access public
* @since 1.0.0
*
* @return Array Array attributes.
*/
public function return_object_vars() {
return get_object_vars( $this );
}
}

View File

@@ -0,0 +1,511 @@
<?php
/**
* Option class file
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes/data
*/
/**
* Origin.
*
* This class defines all code necessary to manage the Origin.
*
* @since 1.0.0
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes/data
* @author Raiola Networks <info@raiolanetworks.es>
*/
class Wp_Database_Tools_Database_Data_Origin {
/**
* The id of Origin.
*
* @since 1.0.0
* @access protected
* @var string $id The id of Origin.
*/
protected $id;
/**
* The name of Origin.
*
* @since 1.0.0
* @access protected
* @var string $name The name of Origin.
*/
protected $name;
/**
* The type of Origin.
*
* @since 1.0.0
* @access protected
* @var string $type uncategorized|plugin|theme.
*/
protected $type;
/**
* The search term of Origin.
*
* @since 1.0.0
* @access protected
* @var string $search The search term of Origin.
*/
protected $search;
/**
* The slug term of Origin.
*
* @since 1.0.0
* @access protected
* @var string $slug The slug term of Origin.
*/
protected $slug;
/**
* The warning of Origin.
*
* When an origin is detected by the algorithm the warning attribute is set to yes.
*
* @since 1.0.0
* @access protected
* @var string $warning yes|no.
*/
protected $warning;
/**
* The homepage of Origin.
*
* @since 1.0.0
* @access protected
* @var string $homepage The website of the Origin.
*/
protected $homepage;
/**
* The download url of Origin.
*
* @since 1.0.0
* @access protected
* @var string $download_link The download url of Origin.
*/
protected $download_link;
/**
* The rating of Origin.
*
* @since 1.0.0
* @access protected
* @var string $rating The rating of Origin.
*/
protected $rating;
/**
* The status of Origin.
*
* @since 1.0.0
* @access protected
* @var string $status active|inactive|uninstall|unknown.
*/
protected $status;
/**
* The current version of Origin.
*
* @since 1.0.0
* @access protected
* @var string $version The current version of Origin.
*/
protected $version;
/**
* The reliability of Origin.
*
* @since 1.0.0
* @access protected
* @var int $reliability The reliability of Origin.
*/
protected $reliability;
/**
* The reliability level of Origin.
*
* @since 1.0.0
* @access protected
* @var int $reliability_level low|medium|hight.
*/
protected $reliability_level;
/**
* The question feedback origin.
*
* @since 1.0.0
* @access protected
* @var array $question The question feedback origin.
*/
protected $question;
/**
* The total likes.
*
* @since 1.0.0
* @access protected
* @var int $likes The total likes.
*/
protected $likes;
/**
* The total dislikes.
*
* @since 1.0.0
* @access protected
* @var int $dislikes The total dislikes.
*/
protected $dislikes;
/**
* The author of Origin.
*
* @since 1.0.0
* @access protected
* @var Wp_Database_Tools_Database_Data_Author $author The author of Origin.
*/
protected $author;
/**
* The Marketplace of Origin.
*
* @since 1.0.0
* @access protected
* @var Wp_Database_Tools_Database_Data_Marketplace $marketplace The Marketplace of Origin.
*/
protected $marketplace;
/**
* Constructor
*
* Create the instance of a Origin.
*
* @access public
* @since 1.0.0
*/
public function __construct() {
$this->id = 'uncategorized';
$this->search = 'Uncategorized';
$this->name = 'Uncategorized';
$this->type = 'uncategorized';
$this->status = 'unknown';
$this->slug = '-';
$this->rating = '-';
$this->download_link = '';
$this->homepage = '';
$this->dislikes = 0;
$this->likes = 0;
$this->author = new Wp_Database_Tools_Database_Data_Author();
$this->marketplace = new Wp_Database_Tools_Database_Data_Marketplace();
}
/**
* Set object attributes via API information
*
* @access public
* @since 1.0.0
*
* @param Object $api_data Object obtained from API information.
* @param string $section The section of data.
*/
public function set_origin_by_api( $api_data, $section ) {
// Dynamic access property.
if ( 'tables' === $section ) {
$morph = 'tableable';
}
if ( 'options' === $section ) {
$morph = 'optionable';
}
if ( 'transients' === $section ) {
$morph = 'transientable';
}
if ( 'cronjobs' === $section ) {
$morph = 'cronable';
}
$source = $api_data['source'];
$origin = $api_data['origin'];
// Set the origin fields.
$this->type = $source->{$morph . '_type'} ?? $this->type;
if ( 'uncategorized' !== $this->type ) {
$this->type = strtolower( str_replace( 'App\Models\\', '', $this->type ) );
}
$this->id = ( 'core' === $this->type ) ? 'wordpress-core' : $origin->slug ?? $this->id;
$this->name = ( 'core' === $this->type ) ? __( 'WordPress Core', 'wp-database-tools' ) : $origin->custom_name ?? $origin->name ?? $this->slug;
$this->search = ( 'core' === $this->type ) ? 'WordPress Core' : $origin->slug ?? $this->slug;
$this->homepage = ( 'core' === $this->type ) ? 'https://es.wordpress.org/' : $origin->homepage ?? $this->homepage;
$this->download_link = ( 'core' === $this->type ) ? 'https://wordpress.org/latest.zip' : $origin->download_link ?? $this->download_link;
$this->slug = ( 'core' === $this->type ) ? '-' : $origin->slug ?? $this->slug;
$this->warning = 'no';
$this->rating = $origin->rating ?? $this->rating;
$this->reliability = $source->reliability ?? $this->reliability;
$this->reliability_level = $this->calculate_reliability_level( $this->reliability );
$this->dislikes = $source->dislikes;
$this->likes = $source->likes;
$this->author->set_author_by_api( $api_data['author'] );
$this->marketplace->set_marketplace_by_api( $api_data['marketplace'] );
}
/**
* Set object attributes via algorithm
*
* @access public
* @since 1.0.0
*
* @param Array $data_algorithm Array returning the identification algorithm.
*/
public function set_origin_by_algorithm( $data_algorithm ) {
// Set origin fields.
$this->id = $data_algorithm['origin']['slug'] ?? $data_algorithm['origin']['name'];
$this->version = $data_algorithm['origin']['version'];
$this->name = $data_algorithm['origin']['name'];
$this->search = $data_algorithm['origin']['slug'];
$this->slug = $data_algorithm['origin']['slug'];
$this->type = $data_algorithm['type'];
$this->warning = 'yes';
$this->reliability = $this->calculate_match_porcent( $data_algorithm['length'], $data_algorithm['match'] );
$this->reliability_level = $this->calculate_reliability_level( $this->reliability );
$this->author->set_author_by_algorithm( $data_algorithm['origin'] );
$this->marketplace->set_marketplace_by_algorithm( $data_algorithm['origin'] );
}
/**
* Set the selection of origins in the frontend (choices) by passing
* the data through admin ajax.
*
* @access public
* @since 1.0.0
*
* @param Array $choices Array returning choices.
*/
public function check_choices( $choices ) {
if ( 'uncategorized' !== $this->type && 'core' !== $this->type ) {
$index = ( 'plugin' === $this->type ) ? 1 : 2;
$value = $this->name . '$' . $this->type . '$' . $this->warning;
$label = ( 'no' === $this->warning )
? $this->name
: '<div class="d-flex-start"><img class="mr-5" width="15px" src="' . WPDBT_ADMIN_URL . 'img/warning.svg">' . $this->name . '</div>';
$key = array_search( $value, array_column( $choices[ $index ]['choices'], 'value' ) );
if ( false === $key ) {
$data = array(
'value' => $value,
'label' => $label,
'selected' => false,
);
array_push( $choices[ $index ]['choices'], $data );
}
}
return $choices;
}
/**
* Set the selection of origins in the frontend (choices) by passing
* the data through admin ajax.
*
* @access public
* @since 1.0.0
*
* @param Array $plugins Array with all plugins.
* @param Array $themes Array with all themes.
*/
public function set_status( $plugins, $themes ) {
if ( 'plugin' === $this->type ) {
$key = array_search(
$this->slug,
array_filter(
array_combine(
array_keys( $plugins ),
array_column(
$plugins,
'slug'
)
)
)
);
if ( false === $key ) {
$this->status = 'uninstalled';
return;
}
$this->status = $plugins[ $key ]['status'];
return;
}
if ( 'theme' === $this->type ) {
if ( isset( $themes[ $this->slug ] ) ) {
$this->status = $themes[ $this->slug ]['status'];
return;
}
$this->status = 'uninstalled';
return;
}
if ( 'core' === $this->type ) {
$this->status = 'active';
return;
}
$this->status = 'unknown';
}
/**
* Calculate the match porcent.
*
* @access public
* @since 1.0.0
*
* @param string $length length.
* @param string $match match.
*/
protected function calculate_match_porcent( $length, $match ) {
if ( $match > $length ) {
return 90;
}
return ( $match * 100 ) / 25;
}
/**
* Return the level string.
*
* @access public
* @since 1.0.0
*
* @param int $level the puntuation of reliability.
*
* @return string The string indicates by level.
*/
protected function calculate_reliability_level( $level ) {
if ( $level < 50 ) {
return 'low';
}
if ( $level >= 50 && $level <= 70 ) {
return 'medium';
}
if ( $level > 70 ) {
return 'hight';
}
}
/**
* Return the author of Origin.
*
* @access public
* @since 1.0.0
*
* @return Wp_Database_Tools_Database_Data_Author $author The author of Origin.
*/
public function get_author() {
return $this->author;
}
/**
* Return the marketplace of Origin.
*
* @access public
* @since 1.0.0
*
* @return Wp_Database_Tools_Database_Data_Marketplace $marketplace The marketplace of Origin.
*/
public function get_marketplace() {
return $this->marketplace;
}
/**
* Return the type of Origin.
*
* @access public
* @since 1.0.0
*
* @return string $type The type of Origin.
*/
public function get_type() {
return $this->type;
}
/**
* Set the question attribute
*
* @access public
* @since 1.0.0
*
* @param string $name the name of source.
*/
public function set_question( $name ) {
$quote = str_contains( strtolower( WPDBT_CURRENT_LANG ), 'es' ) ? '¿' : '';
$this->question = $quote . '<strong>' . $name . '</strong> ' . __( 'belongs to this', 'wp-database-tools' ) . ' ' . $this->get_type() . '?';
}
/**
* Set the question attribute
*
* @access public
* @since 1.0.0
*
* @param Wp_Database_Tools_Database_Data_Author $value The author.
*/
public function set_author( $value ) {
$this->author = $value;
}
/**
* Set the question attribute
*
* @access public
* @since 1.0.0
*
* @param Wp_Database_Tools_Database_Data_Marketplace $value The marketplace.
*/
public function set_marketplace( $value ) {
$this->marketplace = $value;
}
/**
* Return attributes as an array
*
* @access public
* @since 1.0.0
*
* @return Array Array attributes.
*/
public function return_object_vars() {
return get_object_vars( $this );
}
}

View File

@@ -0,0 +1,113 @@
<?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_Data_Table extends Wp_Database_Tools_Database_Data
{
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var int $data The general data of database.
*/
protected $row;
/**
* Indicates if the table is prefixed or not
*
* @since 1.0.0
* @access protected
* @var boolean $prefix Table has prefix.
*/
protected $prefix;
/**
* Table name without prefix
*
* @since 1.0.0
* @access protected
* @var string $name_without_prefix Table name without prefix.
*/
protected $name_without_prefix;
public function __construct($table, $feedback)
{
parent::__construct();
global $wpdb;
// table data
$this->row = $table->Rows;
// Common data
$this->name = $table->Name;
$this->id = $this->name;
$this->section = 'tables';
$this->size = $this->sum_size($table);
$this->format_size = $this->get_file_size_info( $this->size );
$this->format_size = $this->format_size['size'] . '' . $this->format_size['type'];
$this->set_feedback($feedback);
$this->check_regex();
$this->set_prefix($table->Name, $wpdb->prefix);
}
public function check_regex(){
$this->set_regex(false);
}
public function set_multiple($value){
$this->multiple = true;
}
public function return_object_vars(){
return get_object_vars($this);
}
public function set_prefix($name, $prefix){
if (str_starts_with($name, $prefix)) {
$this->name_without_prefix = substr($name, strlen($prefix));
}else{
$this->name_without_prefix = $name;
}
$this->prefix = ($prefix . $this->name_without_prefix == $name);
}
public function get_name()
{
return ($this->prefix) ? $this->name_without_prefix : $this->name;
}
public function get_name_without_prefix()
{
return $this->name_without_prefix;
}
}

View File

@@ -0,0 +1,219 @@
<?php
/**
* transient class file
*
* @link https://raiolanetworks.es
* @since 1.0.0
*
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes/data
*/
/**
* transient.
*
* This class defines all code necessary to manage the transient.
*
* @since 1.0.0
* @package Wp_Database_Tools
* @subpackage Wp_Database_Tools/includes/data
* @author Raiola Networks <info@raiolanetworks.es>
*/
class Wp_Database_Tools_Database_Data_Transient extends Wp_Database_Tools_Database_Data {
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $autoload The general data of database.
*/
protected $expired;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $autoload The general data of database.
*/
protected $autoload;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $extract The general data of database.
*/
protected $extract;
/**
* Constructor
*
* Create the instance of a transient.
*
* @access public
* @since 1.0.0
*
* @param Obj $transient Transient row data.
* @param Array $feedback Feedback array content by user meta.
*/
public function __construct( $transient, $feedback ) {
parent::__construct();
// transient data.
$this->autoload = $transient->autoload;
$this->extract = $this->set_extract( $transient->transient_value );
$this->value = htmlentities( $transient->transient_value );
// Common data.
$this->id = $transient->transient_id;
$this->name = $transient->transient_name;
$this->section = 'transients';
$this->size = $transient->size;
$this->format_size = $this->get_file_size_info( $this->size );
$this->format_size = $this->format_size['size'] . '' . $this->format_size['type'];
$this->set_feedback( $feedback );
$this->check_regex();
}
/**
* Determine whether to display the integer value or an extract in
* case the length is greater than a certain number
*
* @access public
* @since 1.0.0
*
* @param String $value The transient value.
*/
public function set_extract( $value ) {
return ( strlen( $value ) > 16 )
? substr( esc_attr( wp_strip_all_tags( $value ) ), 0, 16 ) . '...'
: '';
}
/**
* Converts bit size to a readable format
*
* @access public
* @since 1.0.0
*
* @param int $file_size The size transient.
*/
public function get_file_size_info( $file_size ) {
$bytes = array( 'B', 'KB', 'MB', 'GB', 'TB' );
if ( $file_size < 1024 ) {
$file_size = 1;
}
for ( $i = 0; $file_size > 1024; $i++ ) {
$file_size /= 1024;
}
$db_size_info['size'] = round( $file_size, 2 );
$db_size_info['type'] = $bytes[ $i ];
return $db_size_info;
}
/**
* Adds the size of a record
*
* @access public
* @since 1.0.0
*
* @param Obj $transient transient row data.
*/
public function sum_size( $transient ) {
if ( isset( $transient->Data_length ) && isset( $transient->Index_length ) ) {
$sum = $transient->Data_length + $transient->Index_length;
} else {
$sum = 0;
}
return $sum;
}
/**
* Set true the multiple attribute
*
* @access public
* @since 1.0.0
*/
public function set_multiple() {
$this->multiple = true;
}
/**
* We found that the transient does not conform to certain patterns.
* If it does meet a pattern we set the regex property.
* This is done so that no such records are stored in the database,
* but the regex is simply stored as a string.
*
* @access public
* @since 1.0.0
*/
public function check_regex() {
$this->set_regex( false );
// Regex wpseo.
if ( str_starts_with( $this->name, 'wpseo_sitemap_' ) ) {
$pattern = '/wpseo_sitemap_([0-9]+)_cache_validator/i';
if ( preg_match( $pattern, $this->name ) ) {
$this->set_regex( 'wpseo_sitemap_{regex}_cache_validator' );
}
}
// Regex updraft_lock_.
if ( str_starts_with( $this->name, 'updraft_lock_' ) ) {
$pattern = '/updraft_lock_([a-z0-9]{12})/i';
if ( preg_match( $pattern, $this->name ) ) {
$this->set_regex( 'updraft_lock_{regex}' );
}
}
// Regex jetpack_nonce_.
if ( str_starts_with( $this->name, 'jetpack_nonce_' ) ) {
$pattern = '/jetpack_nonce_([0-9]{10})_([a-z0-9]{10})/i';
if ( preg_match( $pattern, $this->name ) ) {
$this->set_regex( 'jetpack_nonce_{regex}_{regex}' );
}
}
}
/**
* Return the autoload attribute.
*
* @access public
* @since 1.0.0
*
* @return string this->autoload The autoload attribute.
*/
public function get_autoload() {
return $this->autoload;
}
/**
* Return attributes as an array
*
* @access public
* @since 1.0.0
*
* @return Array Array attributes.
*/
public function return_object_vars() {
return get_object_vars( $this );
}
}

View File

@@ -0,0 +1,260 @@
<?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_Data {
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var int $likes The general data of database.
*/
protected $id;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var int $likes The general data of database.
*/
protected $name;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var int $dislikes The general data of database.
*/
protected $feedback;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $multiple;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var Wp_Database_Tools_Database_Data_Origin $origin The general data of database.
*/
public $origin;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $check;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $size;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $format_size;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $section;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $regex;
/**
* The general data of database.
*
* @since 1.0.0
* @access protected
* @var array $data The general data of database.
*/
protected $value;
public function __construct() {
$admin_url = plugin_dir_url( __DIR__ ) . 'admin/';
$this->origin = new Wp_Database_Tools_Database_Data_Origin();
$this->multiple = false;
$this->reliability = '-';
$this->check = false;
}
public function get_matching_data( $matching, $plugins, $themes, $name ) {
$data_value = null;
if ( $this->section == 'options' ) {
$data_value = ( $this->value == '' ) ? null : $this->value;
}
$slug_concidence_plugins = $matching->find_match( 'plugin', $name, $data_value );
$slug_concidence_themes = $matching->find_match( 'theme', $name, $data_value );
$concidence = false;
if ( ! empty( $slug_concidence_plugins ) && ! empty( $slug_concidence_themes ) ) {
// Set the better coincidence
$type = ( $slug_concidence_plugins['match'] >= $slug_concidence_themes['match'] ) ? 'plugin' : 'theme';
$coincidence_data = ( $type == 'plugin' ) ? $slug_concidence_plugins : $slug_concidence_themes;
$concidence = true;
} elseif ( ! empty( $slug_concidence_plugins ) ) {
$type = 'plugin';
$coincidence_data = $slug_concidence_plugins;
$concidence = true;
} elseif ( ! empty( $slug_concidence_themes ) ) {
$type = 'theme';
$coincidence_data = $slug_concidence_themes;
$concidence = true;
}
if ( $concidence == true ) {
if ( $type == 'plugin' ) {
$key = array_search( $coincidence_data['slug'], array_column( $plugins, 'slug' ) );
$data['origin'] = $plugins[ array_keys( $plugins )[ $key ] ];
}
if ( $type == 'theme' ) {
$key = array_search( $coincidence_data['slug'], array_column( $themes, 'slug' ) );
$data['origin'] = $themes[ array_keys( $themes )[ $key ] ];
}
if ( is_null( $data['origin'] ) ) {
return null;
}
$data['type'] = $type;
$data['length'] = strlen( $coincidence_data['slug'] );
$data['match'] = $coincidence_data['match'];
return $data;
} else {
return null;
}
}
public function set_feedback( $feedback ) {
if ( isset( $feedback ) ) {
$feedback = (array) $feedback;
$this->feedback = isset( $feedback[ $this->name ] );
} else {
$this->feedback = false;
}
}
public function set_data_by_algorithm( $data_algorithm ) {
$this->origin->set_origin_by_algorithm( $data_algorithm );
}
public function sum_size( $row ) {
if ( isset( $row->Data_length ) && isset( $row->Index_length ) ) {
$sum = $row->Data_length + $row->Index_length;
} else {
$sum = 0;
}
return $sum;
}
public function get_file_size_info( $file_size ) {
$bytes = array( 'B', 'KB', 'MB', 'GB', 'TB' );
if ( $file_size < 1024 ) {
$file_size = 1;
}
for ( $i = 0; $file_size > 1024; $i++ ) {
$file_size /= 1024;
}
$db_size_info['size'] = round( $file_size, 2 );
$db_size_info['type'] = $bytes[ $i ];
return $db_size_info;
}
public function get_name() {
return $this->name;
}
public function get_size() {
return $this->size;
}
public function get_origin() {
return $this->origin;
}
public function get_regex() {
return $this->regex;
}
public function set_origin( $value ) {
$this->origin = $value;
}
public function set_regex( $value ) {
$this->regex = $value;
}
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden