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,75 @@
<?php
namespace WPDRMS\ASP\Core;
use WPDRMS\ASP\Asset\AssetInterface;
use WPDRMS\ASP\BlockEditor\ASPBlock;
use WPDRMS\ASP\BlockEditor\BlockEditorAssets;
use WPDRMS\ASP\BlockEditor\BlockInterface;
use WPDRMS\ASP\Integration\Imagely\NextGenGallery;
use WPDRMS\ASP\Options\OptionAssets;
use WPDRMS\ASP\Options\Routes\DirectoriesRoute;
use WPDRMS\ASP\Options\Routes\IndexTableOptionsRoute;
use WPDRMS\ASP\Options\Routes\SearchOptionsRoute;
use WPDRMS\ASP\Options\Routes\TaxonomyTermsRoute;
use WPDRMS\ASP\Patterns\SingletonTrait;
use WPDRMS\ASP\Rest\RestInterface;
use WPDRMS\ASP\Rest\TimedModalRoutes;
/**
* Returns all class instances for a given interface name
*
* @see .phpstorm.meta.php for corrected type hints
*/
class Factory {
use SingletonTrait;
const SUPPORTED_INTERFACES = array(
'Rest' => array(
TimedModalRoutes::class,
DirectoriesRoute::class,
TaxonomyTermsRoute::class,
SearchOptionsRoute::class,
IndexTableOptionsRoute::class,
),
'Asset' => array(
OptionAssets::class,
),
'Block' => array(
ASPBlock::class,
),
'Integration' => array(
NextGenGallery::class,
),
);
/**
* Get all the objects array for a given interface
*
* @param key-of<self::SUPPORTED_INTERFACES> $interface_name
* @param mixed[] $args
*/
public function get( string $interface_name, ?array $args = null ): array {
if ( !isset(self::SUPPORTED_INTERFACES[ $interface_name ]) ) {
return array();
}
$classes = self::SUPPORTED_INTERFACES[ $interface_name ];
return array_map(
function ( $class_name ) use ( $args ) {
if ( method_exists($class_name, 'instance') ) {
if ( is_array($args) ) {
return $class_name::instance(...$args);
} else {
return $class_name::instance();
}
}
if ( is_array($args) ) {
return new $class_name(...$args); // @phpstan-ignore-line
} else {
return new $class_name(); // @phpstan-ignore-line
}
},
$classes
);
}
}

View File

@@ -0,0 +1,176 @@
<?php
namespace WPDRMS\ASP\Core;
if (!defined('ABSPATH')) die('-1');
class Globals {
/**
* The plugin options and defaults
*
* @var array
*/
public $options;
/**
* The plugin options and defaults (shorthand)
*
* @var array
*/
public $o;
/**
* Instance of the init class
*
* @var Init
*/
public $init;
/**
* Instance of the instances class
*
* @var Instances
*/
public $instances;
/**
* Instance of the instances class
*
* @var \WPDRMS\ASP\Misc\PriorityGroups
*/
public $priority_groups;
/**
* Instance of the updates manager
*
* @var \asp_updates
*/
public $updates;
/**
* Instance of the database manager
*
* @var \WPDRMS\ASP\Database\Manager
*/
public $db;
/**
* Instance of the REST API manager
*
* @var \WPDRMS\ASP\API\REST0\Rest
*/
public $rest_api;
/**
* Instance of the manager
*
* @var Manager
*/
public $manager;
/**
* Instance of the manager
*
* @var WPDRMS\ASP\Frontend\FiltersManager
*/
public $front_filters;
/**
* Instance of the manager
*
* @var \WD_ASP_Instant
*/
public $instant;
/**
* Instance of the scripts manager
*
* @var \WPDRMS\ASP\Asset\Script\Manager
*/
public $script_manager;
/**
* Instance of the scripts manager
*
* @var \WPDRMS\ASP\Asset\Css\Manager
*/
public $css_manager;
/**
* Instance of the legacy scripts manager
*
* @var ScriptsLegacy
*/
public $scripts_legacy;
/**
* Array of ASP tables
*
* @var array
*/
public $tables;
/**
* Holds the correct table prefix for ASP tables
*
* @var string
*/
public $_prefix;
/**
* The upload directory for the plugin
*
* @var string
*/
public $upload_dir = "asp_upload";
/**
* The upload directory for the BFI thumb library
*
* @var string
*/
public $bfi_dir = "bfi_thumb";
/**
* The upload path
*
* @var string
*/
public $upload_path;
/**
* The BFI lib upload path
*
* @var string
*/
public $bfi_path;
/**
* The upload URL
*
* @var string
*/
public $upload_url;
/**
* Cache subdirectory name for CSS/JS assets
*
* @var string
*/
public $global_cache_path;
/**
* Cache path for CSS/JS assets
*
* @var string
*/
public $cache_path;
/**
* Cache url for CSS/JS assets
*
* @var string
*/
public $cache_url;
}

View File

@@ -0,0 +1,570 @@
<?php
namespace WPDRMS\ASP\Core;
use WPDRMS\ASP\Asset\Script;
use WPDRMS\ASP\Cache\TextCache;
use WPDRMS\ASP\Database;
use WPDRMS\ASP\Hooks\Ajax\DeleteCache;
use WPDRMS\ASP\Patterns\SingletonTrait;
use WPDRMS\ASP\Utils\FileManager;
use WPDRMS\ASP\Utils\Plugin;
defined('ABSPATH') or die("You can't access this file directly.");
/**
* Class aspInit
*
* AJAX SEARCH PRO initializator Class
*/
class Init {
use SingletonTrait;
private static $new_install = false;
private function __construct() {
wd_asp()->db = Database\Manager::getInstance();
// Before the ASP_Helpers::previousVersion is ever executed, _asp_version option does not exist
if ( get_option('_asp_version', false) === false ) {
self::$new_install = true;
}
}
/**
* Runs on activation OR if this->safety_check() detects a silent change
*/
public function activate() {
// Includes the index table creation as well
Database\Manager::getInstance()->create();
$this->activation_only_backwards_compatibility_fixes();
FileManager::instance()->createRequiredDirectories();
DeleteCache::getInstance()->handle(false);
// Was the plugin previously installed, and updated?
if ( Plugin::previousVersion(ASP_CURR_VER_STRING, '<') ) {
update_option('asp_recently_updated', 1);
}
set_transient('asp_just_activated', 1);
// Add functions to asp_scheduled_activation_events to schedule background process events to the activation hook
wp_schedule_single_event( time() + 15, 'asp_scheduled_activation_events' );
}
/**
* Checks if the user correctly updated the plugin and fixes if not
*/
public function safety_check() {
// Run the re-activation actions if this is actually a newer version
if ( Plugin::previousVersion(ASP_CURR_VER_STRING, '<', true) ) {
$this->activate();
// Run a backwards compatibility check
$this->backwards_compatibility_fixes();
wd_asp()->css_manager->generator->generate();
// Take a note on the recent update
update_option('asp_recently_updated', 1);
} else {
// Was the plugin just activated, without version change?
if ( get_transient('asp_just_activated') !== false ) {
// Check the folders, they might have been deleted by accident
FileManager::instance()->createRequiredDirectories();
// Run a backwards compatibility check
$this->backwards_compatibility_fixes();
wd_asp()->css_manager->generator->generate();
delete_transient('asp_just_activated');
}
}
}
/**
* Fix known backwards incompatibilities, only running at plugin activation
*/
public function activation_only_backwards_compatibility_fixes() {
// Turn off the jquery script versions
$comp = wd_asp()->o['asp_compatibility'];
if ( !self::$new_install ) {
if ( $comp['js_source'] == 'min' || $comp['js_source'] == 'min-scoped' ) {
wd_asp()->o['asp_compatibility']['js_source'] = 'jqueryless-min';
} elseif ( $comp['js_source'] == 'nomin' || $comp['js_source'] == 'nomin-scoped' ) {
wd_asp()->o['asp_compatibility']['js_source'] = 'jqueryless-nomin';
}
asp_save_option('asp_compatibility');
}
// Old way of reatining the browser back button to new one
if ( isset($comp['js_retain_popstate']) && $comp['js_retain_popstate'] == 1 ) {
foreach ( wd_asp()->instances->get() as $si ) {
$id = $si['id'];
$sd = $si['data'];
$sd['trigger_update_href'] = 1;
wd_asp()->instances->update($id, $sd);
}
unset($comp['js_retain_popstate']);
wd_asp()->o['asp_compatibility'] = $comp;
asp_save_option('asp_compatibility');
}
}
/**
* Fix known backwards incompatibilities
*/
public function backwards_compatibility_fixes() {
// Index table option fixes
$ito = wd_asp()->o['asp_it_options'];
if ( isset($ito['it_post_types']) && !is_array($ito['it_post_types']) ) {
$ito['it_post_types'] = explode('|', $ito['it_post_types']);
foreach ( $ito['it_post_types'] as $ck => $ct ) {
if ( $ct == '' ) {
unset($ito['it_post_types'][ $ck ]);
}
}
wd_asp()->o['asp_it_options']['it_post_types'] = $ito['it_post_types'];
asp_save_option('asp_it_options');
}
$ana = wd_asp()->o['asp_analytics'];
// Analytics Options fixes 4.18
if ( isset($ana['analytics']) && ( $ana['analytics'] == 1 || $ana['analytics'] == 'pageview' ) ) {
wd_asp()->o['asp_analytics']['analytics'] = 'event';
asp_save_option('asp_analytics');
}
// 4.18.6 Pool sizes no longer slow down page load on index table options
delete_option('_asp_it_pool_sizes');
// 4.22.6 - These were removed at the same time
$comp = wd_asp()->o['asp_compatibility'];
if ( isset($comp['forceinlinestyles']) ) {
if ( $comp['forceinlinestyles'] ) {
$comp['css_loading_method'] = 'inline';
}
unset($comp['forceinlinestyles']);
unset($comp['css_async_load']);
unset($comp['load_in_footer']);
unset($comp['load_mcustom_js']);
wd_asp()->o['asp_compatibility'] = $comp;
asp_save_option('asp_compatibility');
}
/*
* Search instance option fixes
*
* - Get instances
* - Check options
* - Transition to new options based on old ones
* - Save instances
*/
foreach ( wd_asp()->instances->get() as $si ) {
$id = $si['id'];
$sd = $si['data'];
// -------------------------- 4.10 ------------------------------
// Primary and secondary fields
$values = array( '-1', '0', '1', '2', 'c__f' );
$adv_fields = array(
'primary_titlefield',
'secondary_titlefield',
'primary_descriptionfield',
'secondary_descriptionfield',
);
foreach ( $adv_fields as $field ) {
// Force string conversion for proper comparision
if ( !in_array($sd[ $field ] . '', $values) ) {
// Custom field value is selected
$sd[ $field . '_cf' ] = $sd[ $field ];
$sd[ $field ] = 'c__f';
}
}
// -------------------------- 4.10 ------------------------------
// ------------------------- 4.10.4 -----------------------------
// Autocomplete aggreagated to one option only.
if ( isset($sd['autocomplete_mobile']) ) {
if ( $sd['autocomplete_mobile'] == 1 && $sd['autocomplete'] == 1 ) {
$sd['autocomplete'] = 1;
} elseif ( $sd['autocomplete_mobile'] == 1 ) {
$sd['autocomplete'] = 3;
} elseif ( $sd['autocomplete'] == 1 ) {
$sd['autocomplete'] = 2;
} else {
$sd['autocomplete'] = 0;
}
unset($sd['autocomplete_mobile']);
}
// ------------------------- 4.10.4 -----------------------------
// ------------------------- 4.11 -------------------------------
// Autocomplete aggreagated to one option only.
if ( !isset($sd['frontend_fields']['unselected']) ) {
$sd['frontend_fields']['unselected'] = array();
}
if ( isset($sd['showexactmatches'], $sd['exactmatchestext']) ) {
$sd['frontend_fields']['labels']['exact'] = $sd['exactmatchestext'];
if ( $sd['showexactmatches'] == 0 ) {
$sd['frontend_fields']['unselected'][] = 'exact';
$sd['frontend_fields']['selected'] =
array_diff( $sd['frontend_fields']['selected'], array( 'exact' ) );
}
}
if ( isset($sd['showsearchintitle'], $sd['searchintitletext']) ) {
$sd['frontend_fields']['labels']['title'] = $sd['searchintitletext'];
if ( $sd['showsearchintitle'] == 0 ) {
$sd['frontend_fields']['unselected'][] = 'title';
$sd['frontend_fields']['selected'] =
array_diff( $sd['frontend_fields']['selected'], array( 'title' ) );
}
}
if ( isset($sd['showsearchincontent'], $sd['searchincontenttext']) ) {
$sd['frontend_fields']['labels']['content'] = $sd['searchincontenttext'];
if ( $sd['showsearchincontent'] == 0 ) {
$sd['frontend_fields']['unselected'][] = 'content';
$sd['frontend_fields']['selected'] =
array_diff( $sd['frontend_fields']['selected'], array( 'content' ) );
}
}
if ( isset($sd['showsearchinexcerpt'], $sd['searchinexcerpttext']) ) {
$sd['frontend_fields']['labels']['excerpt'] = $sd['searchinexcerpttext'];
if ( $sd['showsearchinexcerpt'] == 0 ) {
$sd['frontend_fields']['unselected'][] = 'excerpt';
$sd['frontend_fields']['selected'] =
array_diff( $sd['frontend_fields']['selected'], array( 'excerpt' ) );
}
}
// ------------------------- 4.11 -------------------------------
// ------------------------- 4.11.6 -----------------------------
// User meta fields to array
if ( isset($sd['user_search_meta_fields']) && !is_array($sd['user_search_meta_fields']) ) {
$sd['user_search_meta_fields'] = explode(',', $sd['user_search_meta_fields']);
foreach ( $sd['user_search_meta_fields'] as $umk =>$umv ) {
$sd['user_search_meta_fields'][ $umk ] = trim($umv);
if ( $sd['user_search_meta_fields'][ $umk ] == '' ) {
unset($sd['user_search_meta_fields'][ $umk ]);
}
}
}
// ------------------------- 4.11.6 -----------------------------
// ------------------------- 4.11.10 ----------------------------
// Before, this was a string
if ( isset($sd['customtypes']) && !is_array($sd['customtypes']) ) {
$sd['customtypes'] = explode('|', $sd['customtypes']);
foreach ( $sd['customtypes'] as $ck => $ct ) {
if ( $ct == '' ) {
unset($sd['customtypes'][ $ck ]);
}
}
}
// No longer exists
if ( isset($sd['selected-customtypes']) ) {
unset($sd['selected-customtypes']);
}
// No longer exists
if ( isset($sd['searchinpages']) ) {
if ( $sd['searchinpages'] == 1 && !in_array('page', $sd['customtypes']) ) {
array_unshift($sd['customtypes'], 'page');
}
unset($sd['searchinpages']);
}
// No longer exists
if ( isset($sd['searchinposts']) ) {
if ( $sd['searchinposts'] == 1 && !in_array('post', $sd['customtypes']) ) {
array_unshift($sd['customtypes'], 'post');
}
unset($sd['searchinposts']);
}
// ------------------------- 4.11.10 ----------------------------
// ------------------------- 4.12 -------------------------------
if ( is_numeric($sd['i_item_width']) ) {
$sd['i_item_width'] = $sd['i_item_width'] . 'px';
}
// ------------------------- 4.12 -------------------------------
// ------------------------- 4.13.1 -----------------------------
$font_sources = array(
'inputfont',
'descfont',
'titlefont',
'authorfont',
'datefont',
'showmorefont',
'groupfont',
'exsearchincategoriestextfont',
'groupbytextfont',
'settingsdropfont',
'prestitlefont',
'presdescfont',
'pressubtitlefont',
'search_text_font',
);
if ( isset($sd['inputfont']) && strpos($sd['inputfont'], '--g--') !== false ) {
/**
* Remove the unneccessary --g-- tags and quotes
*/
foreach ( $font_sources as $fk ) {
if ( isset($sd[ $fk ]) ) {
$sd[ $fk ] = str_replace(array( '--g--', '"', "'" ), '', $sd[ $fk ]);
}
}
}
if ( isset($sd['results_order']) && strpos($sd['results_order'], 'peepso') === false ) {
$sd['results_order'] .= '|peepso_groups|peepso_activities';
}
if ( isset($sd['groupby_content_type']) && !isset($sd['groupby_content_type']['peepso_groups']) ) {
$sd['groupby_content_type']['peepso_groups'] = 'Peepso Groups';
$sd['groupby_content_type']['peepso_activities'] = 'Peepso Activities';
}
// ------------------------- 4.13.1 -----------------------------
// ------------------------- 4.14.4 -----------------------------
if ( isset($sd['frontend_fields']['labels']['comments']) ) {
unset($sd['frontend_fields']['labels']['comments']);
}
$sd['frontend_fields']['selected'] = array_diff( $sd['frontend_fields']['selected'], array( 'comments' ) );
$sd['frontend_fields']['unselected'] = array_diff( $sd['frontend_fields']['unselected'], array( 'comments' ) );
$sd['frontend_fields']['checked'] = array_diff( $sd['frontend_fields']['checked'], array( 'comments' ) );
// ------------------------- 4.14.4 -----------------------------
// ------------------------- 4.14.5 -----------------------------
// For non-existence checks use the raw_data array
if ( !isset($si['raw_data']['i_item_width_tablet']) ) {
$sd['i_item_width_tablet'] = $sd['i_item_width'];
$sd['i_item_width_phone'] = $sd['i_item_width'];
}
// For non-existence checks use the raw_data array
if ( !isset($si['raw_data']['i_item_height_tablet']) ) {
$sd['i_item_height_tablet'] = $sd['i_item_height'];
$sd['i_item_height_phone'] = $sd['i_item_height'];
}
// For non-existence checks use the raw_data array
if ( !isset($si['raw_data']['box_width_tablet']) ) {
$sd['box_width_tablet'] = $sd['box_width'];
$sd['box_width_phone'] = $sd['box_width'];
}
// ------------------------- 4.14.5 -----------------------------
// ------------------------- 4.15 -------------------------------
if ( is_numeric($sd['i_item_height']) ) {
$sd['i_item_height'] = $sd['i_item_height'] . 'px';
}
if ( is_numeric($sd['i_item_height_tablet']) ) {
$sd['i_item_height_tablet'] = $sd['i_item_height_tablet'] . 'px';
}
if ( is_numeric($sd['i_item_height_phone']) ) {
$sd['i_item_height_phone'] = $sd['i_item_height_phone'] . 'px';
}
// ------------------------- 4.15 -------------------------------
// ------------------------- 4.17 -------------------------------
if ( !empty($sd['image_default'])
&& !isset($si['raw_data']['tax_image_default'], $si['raw_data']['tax_image_default']) ) {
$sd['tax_image_default'] = $sd['image_default'];
$sd['user_image_default'] = $sd['image_default'];
}
// ------------------------- 4.17 -------------------------------
// ------------------------- 4.18.2 -----------------------------
if ( isset($sd['jquery_chosen_nores']) ) {
$sd['jquery_select2_nores'] = $sd['jquery_chosen_nores'];
}
// ------------------------- 4.18.2 -----------------------------
// ------------------------- 4.18.8 -----------------------------
if ( !isset($si['raw_data']['tax_res_showdescription']) ) {
$sd['tax_res_showdescription'] = $sd['showdescription'];
$sd['user_res_showdescription'] = $sd['showdescription'];
$sd['tax_res_descriptionlength'] = $sd['descriptionlength'];
$sd['user_res_descriptionlength'] = $sd['descriptionlength'];
}
// ------------------------- 4.18.8 -----------------------------
// ------------------------- 4.20.5 -----------------------------
// The mobile settings state can be forced without forcing the hover
if ( Plugin::previousVersion('4.20.4') ) {
if ( $sd['mob_force_sett_hover'] == 0 ) {
$sd['mob_force_sett_state'] = 'none';
}
}
// ------------------------- 4.20.5 -----------------------------
// ------------------------- 4.26.16 ----------------------------
if ( isset($sd['orderby']) ) {
$sd['orderby_secondary'] = $sd['orderby'];
unset($sd['orderby']);
}
if ( isset($sd['horizontal_res_height']) ) {
$sd['h_item_height'] = $sd['horizontal_res_height'];
$sd['h_item_height_tablet'] = $sd['horizontal_res_height'];
$sd['h_item_height_phone'] = $sd['horizontal_res_height'];
unset($sd['horizontal_res_height']);
}
if ( isset($sd['hreswidth']) ) {
$sd['h_item_width'] = $sd['hreswidth'];
$sd['h_item_width_tablet'] = $sd['hreswidth'];
$sd['h_item_width_phone'] = $sd['hreswidth'];
unset($sd['hreswidth']);
}
if ( isset($sd['hor_img_height']) ) {
$sd['h_image_height'] = $sd['hor_img_height'];
$sd['h_image_height_tablet'] = $sd['hor_img_height'];
$sd['h_image_height_phone'] = $sd['hor_img_height'];
unset($sd['hor_img_height']);
}
// ---------------------------- 4.27 ----------------------------
if ( Plugin::previousVersion('4.26.16') ) {
foreach ( array(
'advtitlefield',
'advdescriptionfield',
'user_search_advanced_title_field',
'user_search_advanced_description_field',
) as $fk
) {
$sd[ $fk ] = str_replace(
array( '{titlefield}', '{descriptionfield}' ),
array( "{result_field field_name='title' hash='x'}", "{result_field field_name='content' hash='y'}" ),
$sd[ $fk ]
);
}
}
// ----------------- Unset some unused search data --------------
// Leave this here, so it is executed as last
$values = array(
// from 4.10
'magnifierimage_selects',
'settingsimage_selects',
'loadingimage_selects',
'i_res_magnifierimage_selects',
'i_pagination_arrow_selects',
'keyword_logic_def',
'user_search_title_field_def',
'frontend_search_settings_position_def',
'term_logic_def',
'cf_logic_def',
'resultstype_def',
'resultsposition_def',
'box_compact_float_def',
'box_compact_position_def',
'keyword_suggestion_source_def',
'bpgroupstitle_def',
'bpgroupstitle',
'settingsimagepos_def',
'blogtitleorderby_def',
'i_ifnoimage_def',
'i_pagination_position_def',
'weight_def',
'user_search_description_field_def',
'triggeronclick',
'triggeronreturn',
'redirectonclick',
'redirect_click_to',
'redirect_on_enter',
'redirect_enter_to',
'mob_trigger_on_click',
// from 4.11
'showexactmatches',
'exactmatchestext',
'showsearchintitle',
'searchintitletext',
'showsearchincontent',
'searchincontenttext',
'showsearchincomments',
'searchincommentstext',
'showsearchinexcerpt',
'searchinexcerpttext',
// from 4.18.2
'jquery_chosen_nores',
);
foreach ( $values as $v ) {
if ( isset($sd[ $v ]) ) {
unset($sd[ $v ]);
}
}
// At the end, update
wd_asp()->instances->update($id, $sd);
}
}
public function pluginReset( $triggerActivate = true ) {
$options = array(
'asp_version',
'_asp_version',
'asp_glob_d',
'asp_performance_def',
'asp_performance',
'asp_it_def',
'asp_it',
'asp_it_options',
'asp_analytics_def',
'asp_analytics',
'asp_caching_def',
'asp_caching',
'asp_compatibility_def',
'asp_compatibility',
'asp_defaults',
'asp_st_override',
'asp_woo_override',
'asp_stat',
'asp_updates',
'asp_updates_lc',
'asp_media_query',
'asp_performance_stats',
'asp_recently_updated',
'asp_fonts',
'_asp_tables',
'_asp_priority_groups',
'_asp_it_pool_sizes',
'asp_license_data',
);
foreach ( $options as $o ) {
delete_option($o);
delete_site_option($o);
}
wp_clear_scheduled_hook('asp_cron_it_extend');
Script\Manager::getInstance()->cleanup();
if ( $triggerActivate ) {
$this->activate();
}
}
public function pluginWipe() {
// Options
$this->pluginReset( false );
// Meta
if ( is_multisite() ) {
global $switched;
$sites = get_sites(array( 'fields' => 'ids' ));
foreach ( $sites as $site ) {
switch_to_blog($site);
delete_metadata('post', 1, '_asp_additional_tags', '', true);
delete_metadata('post', 1, '_asp_metadata', '', true);
TextCache::clearDBCache(); // Delete options cache
restore_current_blog();
}
} else {
delete_metadata('post', 1, '_asp_additional_tags', '', true);
delete_metadata('post', 1, '_asp_metadata', '', true);
TextCache::clearDBCache(); // Delete options cache
}
// Database
wd_asp()->db->delete();
FileManager::instance()->removeRequiredDirectories();
// Deactivate
deactivate_plugins(ASP_FILE);
}
}

View File

@@ -0,0 +1,766 @@
<?php
namespace WPDRMS\ASP\Core;
use WP_Error;
use WPDRMS\ASP\Core\Models\SearchInstance;
use WPDRMS\ASP\Misc\Themes;
use WPDRMS\ASP\Options\Data\SearchOptions;
use WPDRMS\ASP\Patterns\SingletonTrait;
defined('ABSPATH') or die("You can't access this file directly.");
/**
* Class WD_ASP_Instances
*
* This class handles the data transfer between code and instance data
*
* @class WD_ASP_Instances
* @version 1.0
* @package AjaxSearchPro/Classes/Core
* @category Class
* @author Ernest Marcinko
*/
class Instances {
use SingletonTrait;
public const ALL_INSTANCES = -1;
/**
* This holds the search instances
*
* @var SearchInstance[]
*/
private array $search_instances;
/**
* This holds the search instances without data
*
* @var array{
* id: int,
* name: string
* }
*/
private array $instances_no_data;
/**
* When updating or first demand, this variable sets to true, telling that instances need re-parsing
*
* @var bool
*/
private bool $refresh = true;
/**
* The search instances init script JSON data
*
* @var string[]
*/
private array $script_data = array();
/**
* Gets the search instance if exists
*
* @param int $id
* @param bool $force_refresh
* @param bool|int $check_ownership
* @return ( $id is positive-int ? SearchInstance : SearchInstance[] )
*/
public function get(int $id = self::ALL_INSTANCES, bool $force_refresh = false, $check_ownership = false ) {
if ( $this->refresh || $force_refresh ) {
$this->init();
$this->refresh = false;
}
if ( $check_ownership !== false && !is_super_admin() ) {
if ( is_int($check_ownership) ) {
$user_id = $check_ownership;
} else {
$user_id = intval( get_current_user_id() );
}
foreach ( $this->search_instances as $key => $inst ) {
if ( $inst['data']['owner'] != 0 && $inst['data']['owner'] != $user_id ) {
unset($this->search_instances[ $key ]);
}
}
}
if ( $id > -1 ) {
return isset($this->search_instances[ $id ]) ? $this->search_instances[ $id ] : array();
}
return $this->search_instances;
}
/**
* Get an option value for a search instance ID
*
* @param $instance
* @param $option_name
* @return false|mixed
*/
public function getOption( $instance, $option_name ) {
if ( $this->exists($instance) ) {
$instance = $this->get($instance);
return $instance['data'][ $option_name ] ?? false;
}
return false;
}
/**
* Temporary changes the search instance data within the cache variable (not permanent)
*
* @param int $id
* @param array $data
* @return bool|array
*/
public function set( $id = 0, $data = array() ) {
if ( $this->refresh ) {
$this->init();
$this->refresh = false;
}
if ( isset($this->search_instances[ $id ]) ) {
$this->search_instances[ $id ]['data'] = array_merge($this->search_instances[ $id ]['data'], $data);
return true;
}
return false;
}
/**
* Gets the search instance if exists, without data
*
* @param int $id
* @param bool $force_refresh
* @return array
*/
public function getWithoutData( $id = self::ALL_INSTANCES, $force_refresh = false ) {
if ( $this->refresh || $force_refresh ) {
$this->init();
$this->refresh = false;
}
if ( $id > -1 ) {
return isset($this->instances_no_data[ $id ]) ? $this->instances_no_data[ $id ] : array();
}
return $this->instances_no_data;
}
/**
* Checks if the given search instance exists
*
* @param $id
* @return bool
*/
public function exists( $id = false ) {
if ( $this->refresh ) {
$this->init();
$this->refresh = false;
}
if ( $id === false ) {
return count($this->search_instances) > 0;
} else {
return isset($this->search_instances[ $id ]);
}
}
/**
* Create a new search instance with the default options set
*
* @param $name
* @param int $owner User ID of the owner
* @return bool|int
*/
public function add( $name, $owner = 0 ) {
global $wpdb;
$this->refresh = true;
$data = wd_asp()->options['asp_defaults'];
$data['owner'] = intval($owner);
if (
$wpdb->query(
'INSERT INTO ' . wd_asp()->db->table('main') . "
(name, data) VALUES
('" . esc_sql($name) . "', '" . wd_mysql_escape_mimic(json_encode($data)) . "')"
) !== false
) {
return $wpdb->insert_id;
}
return false;
}
/**
* Import the search from the Lite version, as a new search instance
*
* @param $name
* @param int $owner User ID of the owner
* @return bool|int
*/
public function importFromLite( $name, $owner = 0 ) {
global $wpdb;
$this->refresh = true;
$data = wd_asp()->options['asp_defaults'];
$data['owner'] = intval($owner);
$lite = get_option('asl_options', array());
if ( count($lite) > 0 && get_option('asl_version', 0) > 4732 ) {
// --- Resolve the options from the lite version ---
// 1. Resolve these as-is, no change required
$as_is = array(
'keyword_logic',
'triggerontype',
'customtypes',
'searchintitle',
'searchincontent',
'searchinexcerpt',
'search_in_permalinks',
'search_in_ids',
'search_all_cf',
'customfields',
'post_status',
'override_default_results',
'override_method',
'exactonly',
'exact_match_location',
'searchinterms',
'charcount',
'itemscount',
'orderby_primary',
'orderby_secondary',
'show_images',
'image_width',
'image_height',
'image_source1',
'image_source2',
'image_source3',
'image_source4',
'image_source5',
'image_source_featured',
'image_custom_field',
'show_frontend_search_settings',
'box_width',
'resultsposition',
'defaultsearchtext',
'showmoreresults',
'showmoreresultstext',
'v_res_max_height',
'results_click_blank',
'scroll_to_results',
'resultareaclickable',
'close_on_document_click',
'show_close_icon',
'showauthor',
'showdate',
'showdescription',
'descriptionlength',
'description_context',
'noresultstext',
'didyoumeantext',
'autocomplete',
'shortcode_op',
'striptagsexclude',
'excludeposts',
'wpml_compatibility',
'polylang_compatibility',
'click_action_location',
'return_action_location',
'showcustomtypes',
// 4.9
'primary_titlefield',
'primary_descriptionfield',
'primary_titlefield_cf',
'primary_descriptionfield_cf',
'advtitlefield',
'advdescriptionfield',
'kw_exceptions',
'kw_exceptions_e',
'single_highlight',
'single_highlightwholewords',
'single_highlightcolor',
'single_highlightbgcolor',
'single_highlight_scroll',
'single_highlight_offset',
'single_highlight_selector',
'image_display_mode',
);
foreach ( $as_is as $key ) {
if ( isset($lite[ $key ]) ) {
$data[ $key ] = $lite[ $key ];
}
}
// 2. Resolve by difference in keys only
$resolve_keys = array(
'trigger_on_facet_change' => 'trigger_on_facet',
'titlefield' => 'primary_titlefield',
'descriptionfield' => 'primary_descriptionfield',
'titlefield_cf' => 'primary_titlefield_cf',
'descriptionfield_cf' => 'primary_descriptionfield_cf',
'kw_suggestions' => 'keywordsuggestions',
'kw_length' => 'keyword_suggestion_length',
'kw_count' => 'keyword_suggestion_count',
'kw_google_lang' => 'keywordsuggestionslang',
'kw_exceptions' => 'autocompleteexceptions',
'kw_highlight' => 'highlight',
'kw_highlight_whole_words' => 'highlightwholewords',
'highlight_color' => 'highlightcolor',
'highlight_bg_color' => 'highlightbgcolor',
'redirect_click_to' => 'click_action',
'redirect_enter_to' => 'return_action',
'custom_redirect_url' => 'redirect_url',
'maxresults' => 'posts_limit',
);
foreach ( $resolve_keys as $lkey => $pkey ) {
if ( isset($lite[ $lkey ]) ) {
$data[ $pkey ] = $lite[ $lkey ];
}
}
// 3. Manually Resolve
// -- Default image
if ( !empty($lite['image_default']) && strpos($lite['image_default'], 'img/default.jpg') === false ) {
$data['image_default'] = $lite['image_default'];
}
// -- Generic filters
$data['frontend_fields']['selected'] = array();
$data['frontend_fields']['unselected'][] = 'exact';
if ( $lite['showexactmatches'] == 1 ) {
$data['frontend_fields']['selected'][] = 'exact';
$data['frontend_fields']['labels']['exact'] = $lite['exactmatchestext'];
}
if ( $lite['showsearchintitle'] == 1 ) {
$data['frontend_fields']['selected'][] = 'title';
$data['frontend_fields']['labels']['title'] = $lite['searchintitletext'];
}
if ( $lite['showsearchincontent'] == 1 ) {
$data['frontend_fields']['selected'][] = 'content';
$data['frontend_fields']['labels']['content'] = $lite['searchincontenttext'];
}
if ( $lite['showsearchinexcerpt'] == 1 ) {
$data['frontend_fields']['selected'][] = 'excerpt';
$data['frontend_fields']['labels']['excerpt'] = $lite['searchinexcerpttext'];
}
if ( count($data['frontend_fields']['selected']) > 0 ) {
$data['frontend_fields']['unselected'] = array_diff(
$data['frontend_fields']['unselected'],
$data['frontend_fields']['selected']
);
}
// -- Old version Post type filters
if ( isset($lite['showsearchinposts']) && $lite['showsearchinposts'] == 1 ) {
if ( $data['showcustomtypes'] == '' ) {
$data['showcustomtypes'] = 'post;' . $lite['searchinpoststext'];
} else {
$data['showcustomtypes'] = 'post;' . $lite['searchinpoststext'] . '|' . $data['showcustomtypes'];
}
}
if ( isset($lite['showsearchinpages']) && $lite['showsearchinpages'] == 1 ) {
if ( $data['showcustomtypes'] == '' ) {
$data['showcustomtypes'] = 'page;' . $lite['searchinpagestext'];
} else {
$data['showcustomtypes'] = 'page;' . $lite['searchinpagestext'] . '|' . $data['showcustomtypes'];
}
}
// -- Category filters
if ( $lite['showsearchincategories'] == 1 && $lite['exsearchincategories'] != '' ) {
$categories = explode('|', $lite['exsearchincategories']);
foreach ( $categories as $ck => $cc ) {
if ( $cc == '' ) {
unset($categories[ $ck ]);
}
}
if ( count($categories) > 0 ) {
// Set the display mode
$data['show_terms']['display_mode']['category'] = array(
'type' => 'checkboxes',
'select_all' => false,
'box_header_text' => $lite['exsearchincategoriestext'],
'select_all_text' => '',
'default' => 'checked',
);
$categories = get_terms(
array(
'taxonomy' => 'category',
'include' => $categories,
'orderby' => 'include',
)
);
if ( !is_wp_error($categories) && count($categories) > 0 ) {
$categories_sorted = array();
wd_sort_terms_hierarchicaly($categories, $categories_sorted);
wd_flatten_hierarchical_terms($categories_sorted, $categories);
foreach ( $categories as $category ) {
$data['show_terms']['terms'][] = array(
'taxonomy' => 'category',
'id' => $category->term_id,
'level' => $category->level,
'ex_ids' => array(),
);
}
}
}
}
// -- Themes & layout
$themes = array(
'simple-red' => 'Simple Red vertical (default)',
'simple-blue' => 'Simple Blue vertical',
'simple-grey' => 'Simple Grey vertical',
'classic-blue' => 'Classic Blue vertical',
'curvy-black' => 'Curvy Black vertical',
'curvy-red' => 'Curvy Red vertical',
'curvy-blue' => 'Curvy Blue vertical',
'underline' => 'Underline Grey vertical',
);
if ( isset($themes[ $lite['theme'] ]) ) {
$data['themes'] = $themes[ $lite['theme'] ];
if ( $lite['theme'] != 'simple-red' ) {
$theme = Themes::get('search', $themes[ $lite['theme'] ]);
foreach ( $theme as $tkey => $tval ) {
$data[ $tkey ] = $tval;
}
}
}
if ( $lite['override_bg'] == 1 ) {
$data['boxbackground'] = $lite['override_bg_color'];
// Simple themes, input background
if ( strpos($lite['theme'], 'simple-') === 0 ) {
$data['inputbackground'] = $lite['override_bg_color'];
}
}
if ( $lite['override_icon'] == 1 ) {
$data['settingsbackground'] = $lite['override_icon_bg_color'];
$data['magnifierbackground'] = $lite['override_icon_bg_color'];
$data['settingsimage_color'] = $lite['override_icon_color'];
$data['magnifierimage_color'] = $lite['override_icon_color'];
}
if ( $lite['override_border'] == 1 ) {
$data['boxborder'] = $lite['override_border_style'];
}
if ( $lite['results_bg_override'] == 1 ) {
$data['resultsbackground'] = $lite['results_bg_override_color'];
}
if ( $lite['results_item_bg_override'] == 1 ) {
$data['resultscontainerbackground'] = $lite['results_item_bg_override_color'];
}
if ( $lite['results_override_border'] == 1 ) {
$data['resultsborder'] = $lite['results_override_border_style'];
}
if ( $lite['settings_bg_override'] == 1 ) {
$data['settingsdropbackground'] = $lite['settings_bg_override_color'];
}
// -- Category based exclusions
if ( $lite['excludecategories'] != '' ) {
$terms = explode('|', $lite['excludecategories']);
foreach ( $terms as $tk => $tt ) {
if ( $tt == '' ) {
unset($terms[ $tk ]);
}
}
if ( count($terms) > 0 ) {
foreach ( $terms as $term ) {
$data['exclude_by_terms']['terms'][] = array(
'taxonomy' => 'category',
'id' => $term,
'level' => 0,
'ex_ids' => array(),
);
}
}
}
} else {
return false;
}
// Resume the import
if (
$wpdb->query(
'INSERT INTO ' . wd_asp()->db->table('main') . "
(name, data) VALUES
('" . esc_sql($name) . "', '" . wd_mysql_escape_mimic(json_encode($data)) . "')"
) !== false
) {
// Final import options, the form override
if ( $lite['override_search_form'] == 1 ) {
update_option('asp_st_override', $wpdb->insert_id);
}
if ( $lite['override_woo_search_form'] == 1 ) {
update_option('asp_woo_override', $wpdb->insert_id);
}
return $wpdb->insert_id;
}
return false;
}
/**
* Update the search data
*
* @param $id
* @param $data
* @param $update_owner bool|int
* @return false|int
*/
public function update( $id, $data = array(), $update_owner = false ) {
global $wpdb;
$this->refresh = true;
if ( isset($this->search_instances[ $id ], $this->search_instances[ $id ]['data']) ) {
$data = array_merge($this->search_instances[ $id ]['data'], $data);
}
$data = $this->clearData($data);
if ( $update_owner === true ) {
$data['owner'] = intval( get_current_user_id() );
} elseif ( $update_owner !== false ) {
$update_owner = intval($update_owner);
if ( $update_owner >= 0 ) {
$data['owner'] = $update_owner;
}
}
return $wpdb->query(
'
UPDATE ' . wd_asp()->db->table('main') . "
SET data = '" . wd_mysql_escape_mimic(json_encode($data)) . "'
WHERE id = " . intval($id) . '
'
);
}
/**
* Renames a search instance
*
* @param $new_name string
* @param $id int
* @return bool|int
*/
public function rename( $new_name, $id ) {
global $wpdb;
$this->refresh = true;
return $wpdb->query(
$wpdb->prepare('UPDATE ' . wd_asp()->db->table('main') . " SET name = '%s' WHERE id = %d", $new_name, $id)
);
}
/**
* Resets the search instance to the default options.
*
* @param int $id Search instance ID
*/
public function reset( $id ) {
global $wpdb;
$this->refresh = true;
$query = 'UPDATE ' . wd_asp()->db->table('main') . "
SET
data='" . wd_mysql_escape_mimic(json_encode(wd_asp()->options['asp_defaults'])) . "'
WHERE id=" . intval($id);
$wpdb->query($query);
}
/**
* Duplicates a search instance
*
* @param $id int
* @return bool|int
*/
public function duplicate( $id ) {
global $wpdb;
$this->refresh = true;
return $wpdb->query(
$wpdb->prepare(
'
INSERT INTO ' . wd_asp()->db->table('main') . "( name, data )
SELECT CONCAT(name, ' duplicate'), data FROM " . wd_asp()->db->table('main') . '
WHERE id=%d;',
$id
)
);
}
/**
* Deletes a search instance
*
* @param $id int
* @return bool|int
*/
public function delete( $id ) {
global $wpdb;
$this->refresh = true;
return $wpdb->query(
$wpdb->prepare('DELETE FROM ' . wd_asp()->db->table('main') . ' WHERE id=%d', $id)
);
}
/**
* @param int $id
* @return string
*/
public function export( $id = 0 ) {
if ( $this->exists($id) ) {
return base64_encode( json_encode( $this->get($id) ) );
}
return '';
}
/**
* @param array|string $data json encoded array of base 64 encoded instance objects (or only one base 64 encoded instance)
* @return int|string|WP_Error number of instances (int) or an error message from the Exception
*/
public function import( $data ) {
$imported = 0;
$instances = array();
if ( is_array($data) ) {
foreach ( $data as $d ) {
$instances[] = json_decode(base64_decode($d), true);
if ( json_last_error() != 0 ) {
break;
}
}
} elseif ( is_string($data) ) {
$instances[] = json_decode(base64_decode($data), true);
} else {
return new WP_Error('data', __('Invalid data', 'ajax-search-pro'));
}
if ( json_last_error() != 0 ) {
return new WP_Error( 'json', __('Invalid JSON data', 'ajax-search-pro'));
}
foreach ( $instances as $instance ) {
if ( isset($instance['name']) ) {
$id = $this->add($instance['name'] . ' imported');
$this->update($id, $instance['data']);
++$imported;
}
}
return $imported;
}
/**
* This method is intended to use on params AFTER parsed from the database
*
* @param $params
* @return mixed
*/
public function decode_params( $params ) {
/**
* New method for future use.
* Detects if there is a _decode_ prefixed input for the current field.
* If so, then decodes and overrides the posted value.
*/
foreach ( $params as $k =>$v ) {
if ( gettype($v) === 'string' && substr($v, 0, strlen('_decode_')) == '_decode_' ) {
$real_v = substr($v, strlen('_decode_'));
$params[ $k ] = json_decode(base64_decode($real_v), true);
}
}
return $params;
}
public function add_script_data( $id, $data ) {
$this->script_data[ $id ] = $data;
update_site_option('_asp_script_data', $this->script_data);
}
public function get_script_data(): array {
/**
* To avoid any data corruption, the datatype should be checked explicitly
* https://github.com/WPDreams/ajax-search-pro-development/issues/101
*/
$script_data = get_option('_asp_script_data', array());
return is_array($script_data) ? $script_data : array();
}
public function getInstancesPrinted(): array {
return array_keys($this->script_data);
}
public function areInstancesOnCurrentPage(): bool {
return count($this->script_data) > 0;
}
// ------------------------------------------------------------
// ---------------- PRIVATE --------------------
// ------------------------------------------------------------
/**
* Clears unwanted keys from the search instance data array
*
* @param $data array
* @return array
*/
private function clearData( $data ) {
$remove_keys = array( 'asp_options_serialized' );
if ( is_array($data) ) {
foreach ( $remove_keys as $key ) {
if ( isset($data[ $key ]) ) {
unset($data[ $key ]);
}
}
}
return $data;
}
/**
* Fetches the search instances from the DB and stores them internally for future use
*/
private function init() {
global $wpdb;
// Reset both variables, so in case of deleting no remains are left
$this->search_instances = array();
$this->instances_no_data = array();
if ( !wd_asp()->db->exists('main') ) {
return;
}
$instances = $wpdb->get_results('SELECT * FROM ' . wd_asp()->db->table('main') . ' ORDER BY id ASC', ARRAY_A);
foreach ( $instances as $k => $inst ) {
$instance = new SearchInstance(
array(
'name' => $inst['name'],
'id' => $inst['id'],
)
);
$this->instances_no_data[ $instance->id ] = array(
'name' => $instance->name,
'id' => $instance->id,
);
/**
* Explanation:
* 1. json_decode(..) -> converts the params from the database to PHP format
* 2. $this->decode_params(..) -> decodes params that are stored in base64 and prefixed to be decoded
*
* This is not equivalent with wd_parse_params(..) as that runs before inserting to the DB as well,
* and $this->decode_params(..) runs after getting the data from the database, so it stays redundant.
*
* NOTE:
* raw_data is used in backwards compatibility checks, to see if a certain option exists before merging
* with the defaults
*/
$instance->raw_data = $this->decode_params(json_decode($inst['data'], true));
$instance->data = array_merge(
wd_asp()->options['asp_defaults'],
$instance->raw_data
);
$instance->options = new SearchOptions(json_decode($inst['data'], true));
$instance->data = apply_filters('asp_instance_options', $instance->data , $instance->id);
$this->search_instances[ $instance->id ] = $instance;
}
}
}

View File

@@ -0,0 +1,404 @@
<?php
namespace WPDRMS\ASP\Core;
use WPDRMS\ASP\Api\Rest0\Rest;
use WPDRMS\ASP\Asset;
use WPDRMS\ASP\BlockEditor\BlockInterface;
use WPDRMS\ASP\Hooks\ActionsManager;
use WPDRMS\ASP\Hooks\AjaxManager;
use WPDRMS\ASP\Hooks\FiltersManager;
use WPDRMS\ASP\Modal\Factories\ModalFactory;
use WPDRMS\ASP\Patterns\SingletonTrait;
use WPDRMS\ASP\Rest\RestInterface;
use WPDRMS\ASP\Modal\Services\TimedModalService;
use WPDRMS\ASP\Updates\Remote as UpdatesRemote;
if ( !defined('ABSPATH') ) {
die('-1');
}
class Manager {
use SingletonTrait;
/**
* Context of the current WP environment
*
* Is used to include the correct and only necessary files for each context to save performance
*
* Possible values:
* ajax - an ajax call triggered by the search
* frontend - simple front-end call, or an ajax request not triggered by ASP
* backend - on any of the plugin back-end pages
* global_backend - on any other back-end page
* special - special cases
*
* @since 1.0
* @var string
*/
private $context = 'frontend';
/**
* Initialize and run the plugin-in
*/
private function __construct() {
do_action('wd_asp_before_load');
$this->preLoad();
$this->loadInstances();
$this->initUploadGlobals();
$this->initCacheGlobals();
/**
* Available after this point:
* (WD_ASP_Init) wd_asp()->instances, (global) $wd_asp->instances
*/
register_activation_hook(ASP_FILE, array( $this, 'activationHook' ));
/**
* Available after this point:
* (array) wd_asp()->options, (global) $wd_asp->options
* (WD_ASP_Init) wd_asp()->init, (global) $wd_asp->init
* (WD_ASP_DBMan) wd_asp()->db, (global) $wd_asp->db
*/
add_action( 'init', array( $this, 'init' ), 0 );
}
public function init() {
// Check if the plugin needs to be stopped on certain conditions
// ..this needs to be here, otherwise filter not accesible from functions.php
if ( $this->stopLoading() ) {
return;
}
do_action('wd_asp_loading_start');
// After 6.7 this must be executed in the "init" hook
load_plugin_textdomain( 'ajax-search-pro', false, ASP_DIR . '/languages' );
$this->getContext();
/**
* Available after this point:
* $this->context
*/
$this->loadIncludes();
$this->loadShortcodes();
$this->loadMenu();
$this->loadHooks();
\WPDRMS\ASP\NavMenu\Controller::getInstance();
wd_asp()->init->safety_check();
add_action('admin_notices', array( $this, 'loadNotices' ));
do_action('wd_asp_loaded');
}
private function stopLoading() {
$ret = false;
if ( isset($_GET, $_GET['action']) ) {
if ( $_GET['action'] == 'ere_property_search_ajax' ) {
$ret = true;
}
}
// Plugin uploading screen
if (
is_admin() &&
isset($_GET['action']) &&
$_GET['action'] === 'upload-plugin' &&
str_contains(wd_current_page_url(), 'update.php')
) {
$ret = true;
}
// Allow filtering this condition
return apply_filters('asp_stop_loading', $ret);
}
/**
* Preloading: for functions and other stuff needed
*/
private function preLoad() {
require_once ASP_PATH . '/backend/settings/default_options.php';
require_once ASP_FUNCTIONS_PATH . 'functions.php';
// We need to initialize the init here to get the init->table() function
wd_asp()->init = Init::getInstance();
// This needs to be registered here, the 'init' is too late to register
add_filter( 'cron_schedules', array( $this, 'cronExtraIntervals' ) );
}
/**
* Adds additional intervals to cron jobs
*
* @param $schedules
* @return mixed
*/
function cronExtraIntervals( $schedules ) {
$schedules['asp_cr_two_minutes'] = array(
'interval' => 120,
'display' => __( 'Every 2 Minutes', 'ajax-search-pro' ),
);
$schedules['asp_cr_three_minutes'] = array(
'interval' => 180,
'display' => __( 'Every 3 Minutes', 'ajax-search-pro' ),
);
$schedules['asp_cr_five_minutes'] = array(
'interval' => 300,
'display' => __( 'Every 5 Minutes', 'ajax-search-pro' ),
);
$schedules['asp_cr_fifteen_minutes'] = array(
'interval' => 900,
'display' => __( 'Every 15 Minutes', 'ajax-search-pro' ),
);
$schedules['asp_cr_thirty_minutes'] = array(
'interval' => 1800,
'display' => __( 'Every 30 Minutes', 'ajax-search-pro' ),
);
return $schedules;
}
/**
* Gets the upload path with back-slash
*/
public function initUploadGlobals() {
if ( is_multisite() ) {
/**
* On multisite, the wp_upload_dir() returns the current blog URLs,
* even if the switch_to_blog(1) is initiated (WordPress core bug?)
*
* Bypass solution: Save the upload dir option as a site option, when the main blog is visited,
* then get this value on each site, with a fallback.
* WARNING: DO NOT USE get_site_option() and update_site_option() - as those slow down the multisite loading by a LOT
* use get_blog_option() and update_blog_option() instead
*/
$upload_dir = wp_upload_dir();
if ( get_current_blog_id() == get_network()->site_id ) {
update_blog_option(get_network()->site_id, '_asp_upload_dir', $upload_dir);
} else {
$upload_dir = get_blog_option(get_network()->site_id, '_asp_upload_dir', $upload_dir);
}
} else {
$upload_dir = wp_upload_dir();
}
$upload_dir = apply_filters('asp_glob_upload_dir', $upload_dir);
wd_asp()->upload_path = $upload_dir['basedir'] . '/' . wd_asp()->upload_dir . '/';
wd_asp()->upload_url = $upload_dir['baseurl'] . '/' . wd_asp()->upload_dir . '/';
// Let us make sure, that the URL is using the correct protocol
if ( defined('ASP_URL') ) {
// Site is https, but URL is http
if ( strpos(ASP_URL, 'https://') === 0 && strpos(wd_asp()->upload_url, 'https://') === false ) {
wd_asp()->upload_url = str_replace('http://', 'https://', wd_asp()->upload_url);
// Site is http, but URL is https
} elseif ( strpos(ASP_URL, 'http://') === 0 && strpos(wd_asp()->upload_url, 'http://') === false ) {
wd_asp()->upload_url = str_replace('https://', 'http://', wd_asp()->upload_url);
}
}
if ( defined( 'BFITHUMB_UPLOAD_DIR' ) ) {
wd_asp()->bfi_path = $upload_dir['basedir'] . '/' . BFITHUMB_UPLOAD_DIR . '/';
} else {
wd_asp()->bfi_path = $upload_dir['basedir'] . '/' . wd_asp()->bfi_dir . '/';
}
// Allow globals modification for developers
wd_asp()->upload_path = apply_filters('asp_glob_upload_path', wd_asp()->upload_path);
wd_asp()->upload_url = apply_filters('asp_glob_upload_url', wd_asp()->upload_url);
wd_asp()->bfi_path = apply_filters('asp_glob_bfi_path', wd_asp()->bfi_path);
}
public function initCacheGlobals() {
$base_url = WP_CONTENT_URL;
if ( defined('ASP_URL') ) {
if ( strpos(ASP_URL, 'https://') === 0 && strpos($base_url, 'https://') === false ) {
$base_url = str_replace('http://', 'https://', $base_url);
}
}
wd_asp()->global_cache_path = apply_filters('asp_glob_global_cache_path', WP_CONTENT_DIR . '/cache/');
wd_asp()->cache_path = apply_filters('asp_glob_cache_path', WP_CONTENT_DIR . '/cache/asp/');
wd_asp()->cache_url = apply_filters('asp_glob_cache_url', $base_url . '/cache/asp/');
}
/**
* Gets the call context for further use
*/
public function getContext() {
$backend_pages = Menu::getMenuPages();
if ( !empty($_POST['action']) ) {
if ( in_array($_POST['action'], AjaxManager::getAll()) ) {
$this->context = 'ajax';
}
if ( isset($_POST['wd_required']) ) {
$this->context = 'special';
}
// If it is not part of the plugin ajax actions, the context stays "frontend"
} elseif ( !empty($_GET['page']) && in_array($_GET['page'], $backend_pages) ) {
$this->context = 'backend';
} elseif ( is_admin() ) {
$this->context = 'global_backend';
} else {
$this->context = 'frontend';
}
return $this->context;
}
/**
* Loads the instance data into the global scope
*/
private function loadInstances() {
wd_asp()->instances = Instances::getInstance();
}
/**
* Loads the required files based on the context
*/
private function loadIncludes() {
// This must be here!! If it's in a conditional statement, it will fail..
require_once ASP_PATH . '/backend/vc/vc.extend.php';
switch ( $this->context ) {
case 'special':
require_once ASP_PATH . '/backend/settings/types.inc.php';
break;
case 'ajax':
break;
case 'frontend':
break;
case 'backend':
require_once ASP_PATH . '/backend/settings/types.inc.php';
break;
case 'global_backend':
break;
default:
break;
}
// Special case
if ( wpdreams_on_backend_post_editor() ) {
require_once ASP_PATH . '/backend/tinymce/buttons.php';
require_once ASP_PATH . '/backend/metaboxes/default.php';
}
wd_asp()->css_manager = Asset\Css\Manager::getInstance();
// Lifting some weight off from ajax requests
if ( $this->context != 'ajax' ) {
if ( wd_asp()->o['asp_compatibility']['rest_api_enabled'] ) {
wd_asp()->rest_api = Rest::getInstance();
}
wd_asp()->updates = UpdatesRemote::getInstance();
}
}
/**
* Use the Shorcodes loader to assign the shortcodes to handler classes
*/
private function loadShortcodes() {
Shortcodes::registerAll();
}
/**
* This is hooked to the admin_notices action
*/
public function loadNotices() {
// -------------------- Handle requests here ----------------------
// Update related notes
if ( isset($_GET['asp_notice_clear_ru']) ) {
update_option('asp_recently_updated', 0);
}
if ( isset($_GET['asp_notice_clear_ri']) ) {
update_option('asp_recreate_index', 0);
}
// -------------------- Handle notices here ----------------------
// Index table re-creation note
if ( $this->context == 'backend' && get_option('asp_recreate_index', 0) == 1 ) {
?>
<div class="notice notice-error asp-notice-nohide asp-notice-ri">
<p>
<?php echo __('<b>Ajax Search Pro notice: </b> The Index Table options have been modified, please re-create the index table!', 'ajax-search-pro'); ?>
<a class="button button-primary" href="<?php echo get_admin_url() . 'admin.php?page=asp_index_table'; ?>"><?php echo __('Let\'s do it!', 'ajax-search-pro'); ?></a>
<a class="button button-secondary" href="<?php echo esc_url(add_query_arg(array( 'asp_notice_clear_ri' => '1' ))); ?>"><?php echo __('Hide this message', 'ajax-search-pro'); ?></a>
</p>
</div>
<?php
}
}
/**
* Generates the menu
*/
private function loadMenu() {
add_action('admin_menu', array( '\\WPDRMS\\ASP\\Core\\Menu', 'register' ));
}
/**
* Fires up the plugin hooks
*/
private function loadHooks(): void {
$factory = Factory::instance();
// Register handlers only if the context is ajax indeed
if ( $this->context === 'ajax' ) {
AjaxManager::registerAll();
}
if ( $this->context !== 'ajax' ) {
foreach ( $factory->get('Asset') as $asset ) {
$asset->register();
}
// Editor blocks
foreach ( $factory->get( 'Block' ) as $block ) {
$block->register();
}
if ( $this->context === 'backend' ) {
ActionsManager::register('admin_init', 'Compatibility');
TimedModalService::instance(new ModalFactory())->init();
}
ActionsManager::registerAll();
if ( wd_asp()->o['asp_compatibility']['rest_api_enabled'] ) {
wd_asp()->rest_api->init();
}
add_action(
'rest_api_init',
function () {
foreach ( Factory::instance()->get('Rest') as $rest ) {
$rest->registerRoutes();
}
}
);
}
foreach ( $factory->get('Integration') as $integration ) {
$integration->load();
}
FiltersManager::registerAll();
}
/**
* Run at the plugin activation
*/
public function activationHook(): void {
// Run the activation tasks
wd_asp()->init->activate();
}
}

View File

@@ -0,0 +1,166 @@
<?php
namespace WPDRMS\ASP\Core;
if ( !defined('ABSPATH') ) {
die('-1');
}
class Menu {
/**
* Holds the main menu item
*
* @var array the main menu
*/
private static $main_menu = array();
/**
* @var array
*/
private static $hooks = array();
/**
* Submenu titles and slugs
*
* @var array
*/
private static $submenu_items = array();
/**
* Bypass method to support translations, because static array varialbes cannot have a value defined as a result
* of a function, like 'key' => __('text', ..)
*/
private static function preInit() {
if ( count(self::$submenu_items) == 0 ) {
$main_menu = array(
'title' => __('Ajax Search Pro', 'ajax-search-pro'),
'slug' => 'asp_main_settings',
'file' => '/backend/settings.php',
'position' => '207.9',
'icon_url' => 'icon.png',
);
$submenu_items = array(
array(
'title' => __('Index Table', 'ajax-search-pro'),
'file' => '/backend/index_table.php',
'slug' => 'asp_index_table',
),
array(
'title' => __('Priorities', 'ajax-search-pro'),
'file' => '/backend/priorities.php',
'slug' => 'asp_priorities',
),
array(
'title' => __('Search Statistics', 'ajax-search-pro'),
'file' => '/backend/statistics.php',
'slug' => 'asp_statistics',
),
array(
'title' => __('Analytics Integration', 'ajax-search-pro'),
'file' => '/backend/analytics.php',
'slug' => 'asp_analytics',
),
array(
'title' => __('Cache Settings', 'ajax-search-pro'),
'file' => '/backend/cache_settings.php',
'slug' => 'asp_cache_settings',
),
array(
'title' => __('Performance tracking', 'ajax-search-pro'),
'file' => '/backend/performance.php',
'slug' => 'asp_performance',
),
array(
'title' => __('Compatibility & Other Settings', 'ajax-search-pro'),
'file' => '/backend/compatibility_settings.php',
'slug' => 'asp_compatibility_settings',
),
array(
'title' => __('Export/Import', 'ajax-search-pro'),
'file' => '/backend/export_import.php',
'slug' => 'asp_export_import',
),
array(
'title' => __('Maintenance', 'ajax-search-pro'),
'file' => '/backend/maintenance.php',
'slug' => 'asp_maintenance',
),
array(
'title' => __('Help & Updates', 'ajax-search-pro'),
'file' => '/backend/updates_help.php',
'slug' => 'asp_updates_help',
),
array(
'title' => 'Dev',
'file' => '/backend/dev.php',
'slug' => 'asp_dev',
),
);
self::$main_menu = $main_menu;
self::$submenu_items = $submenu_items;
}
}
/**
* Runs the menu registration process
*/
public static function register() {
$capability = ASP_DEMO == 1 ? 'read' : 'manage_options';
self::preInit();
$h = add_menu_page(
self::$main_menu['title'],
self::$main_menu['title'],
$capability,
self::$main_menu['slug'],
array( '\\WPDRMS\\ASP\\Core\\Menu', 'route' ),
ASP_URL . self::$main_menu['icon_url'],
self::$main_menu['position']
);
self::$hooks[ $h ] = self::$main_menu['slug'];
foreach ( self::$submenu_items as $submenu ) {
if ( $submenu['slug'] === 'asp_dev' && !defined('WP_ASP_TEST_ENV') ) {
continue;
}
$h = add_submenu_page(
self::$main_menu['slug'],
self::$main_menu['title'],
$submenu['title'],
$capability,
$submenu['slug'],
array( '\\WPDRMS\\ASP\\Core\\Menu', 'route' )
);
self::$hooks[ $h ] = $submenu['slug'];
}
}
/**
* Includes the correct back-end file based on the page string
*/
public static function route() {
$current_view = self::$hooks[ current_filter() ];
include ASP_PATH . 'backend/' . str_replace('asp_', '', $current_view) . '.php';
}
/**
* Method to obtain the menu pages for context checking
*
* @return array
*/
public static function getMenuPages(): array {
self::preInit();
$ret = array();
$ret[] = self::$main_menu['slug'];
foreach ( self::$submenu_items as $menu ) {
$ret[] = $menu['slug'];
}
return $ret;
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace WPDRMS\ASP\Core\Models;
use ArrayAccess;
use WPDRMS\ASP\Options\Data\SearchOptions;
use WPDRMS\ASP\Patterns\ObjectAsArrayTrait;
/**
* @implements ArrayAccess<string, mixed>
*/
class SearchInstance implements ArrayAccess {
use ObjectAsArrayTrait;
public string $name;
/**
* @var Array<string, mixed>
*/
public array $raw_data;
/**
* @var Array<string, mixed>
*/
public array $data;
public int $id;
public SearchOptions $options;
/**
* @param Array<string, mixed> $args
*/
public function __construct( array $args = array() ) {
$this->name = $args['name'] ?? '';
$this->id = $args['id'] ?? 0;
$this->data = $args['data'] ?? array();
if ( isset($args['options']) ) {
$this->options = new SearchOptions($args['options']);
}
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace WPDRMS\ASP\Core;
use WPDRMS\ASP\Patterns\SingletonTrait;
if ( !defined('ABSPATH') ) {
die('-1');
}
/**
* Allows Ajax Search Pro as a menu element
*/
class NavMenuMetaBox {
use SingletonTrait;
/**
* Default menu custom metadata
*
* @var array<string, mixed>
*/
public static array $defaults = array(
'prevent_events' => false,
);
/**
* Registers the meta boxes
*
* @hook admin_init
* @return void
*/
public function addMetaBoxes(): void {
add_meta_box(
'asp_nav_menu_link',
__('Ajax Search Pro', 'ajax-search-pro'),
array( $this, 'navMenuLink' ),
'nav-menus',
'side',
'low'
);
}
public function navMenuLink(): void {
?>
<div id="posttype-wl-login" class="posttypediv">
<div id="tabs-panel-wishlist-login" class="tabs-panel tabs-panel-active">
<ul id ="wishlist-login-checklist" class="categorychecklist form-no-clear">
<li>
<label class="menu-item-title">
<input type="checkbox" class="menu-item-checkbox" name="menu-item[-1][menu-item-object-id]" value="1"> Search 1
</label>
<input type="hidden" class="menu-item-type" name="menu-item[-1][menu-item-type]" value="custom">
<input type="hidden" class="menu-item-title" name="menu-item[-1][menu-item-title]" value="Search 1">
<input type="hidden" class="menu-item-url" name="menu-item[-1][menu-item-url]" value="<?php bloginfo('wpurl'); ?>/wp-login.php">
<input type="hidden" class="menu-item-classes" name="menu-item[-1][menu-item-classes]" value="wl-login-pop">
</li>
<li>
<label class="menu-item-title">
<input type="checkbox" class="menu-item-checkbox" name="menu-item[-1][menu-item-object-id]" value="2"> Search 2
</label>
<input type="hidden" class="menu-item-type" name="menu-item[-1][menu-item-type]" value="custom">
<input type="hidden" class="menu-item-title" name="menu-item[-1][menu-item-title]" value="Search 2">
<input type="hidden" class="menu-item-url" name="menu-item[-1][menu-item-url]" value="<?php bloginfo('wpurl'); ?>/wp-login.php">
<input type="hidden" class="menu-item-classes" name="menu-item[-1][menu-item-classes]" value="aspm_container">
</li>
</ul>
</div>
<p class="button-controls">
<span class="list-controls">
<a href="/wordpress/wp-admin/nav-menus.php?page-tab=all&amp;selectall=1#posttype-page" class="select-all">Select All</a>
</span>
<span class="add-to-menu">
<input type="submit" class="button-secondary submit-add-to-menu right" value="Add to Menu" name="add-post-type-menu-item" id="submit-posttype-wl-login">
<span class="spinner"></span>
</span>
</p>
</div>
<?php
}
public function printNavMenuCustomFields( $item_id ): void {
$data = get_post_meta($item_id, '_ajax_search_pro_menu_data', true);
$data = wp_parse_args($data, self::$defaults);
?>
<p class="aspm-show-as-button description description-wide">
<label for="aspm-menu-item-button-<?php echo esc_attr($item_id); ?>" >
<input type="checkbox"
id="aspm-prevent_events-<?php echo esc_attr($item_id); ?>"
name="aspm-prevent_events[<?php echo esc_attr($item_id); ?>]"
<?php checked($data['prevent_events']); ?>
/><?php esc_html_e('Prevent custom script events', 'ajax-search-pro'); ?>
</label>
</p>
<?php
}
public function updateNavMenuCustomFields( $menu_id, $menu_item_db_id ) {
$prevent_events = isset($_POST['aspm-prevent_events'][ $menu_item_db_id ]) && $_POST['aspm-prevent_events'][ $menu_item_db_id ] === 'on'; // phpcs:ignore
update_post_meta(
$menu_item_db_id,
'_ajax_search_pro_menu_data',
array(
'prevent_events' => $prevent_events,
)
);
}
}

View File

@@ -0,0 +1,116 @@
<?php
namespace WPDRMS\ASP\Core;
if ( !defined('ABSPATH') ) {
die('-1');
}
class Shortcodes {
const NAMESPACE = '\\WPDRMS\\ASP\\Shortcodes\\';
/**
* Array of internal known shortcodes
*
* @var array
*/
private static $shortcodes = array(
'wpdreams_ajaxsearchpro' => 'Search',
'wd_asp' => 'SearchBox',
'wpdreams_ajaxsearchpro_results' => 'Results',
'wd_asp_results' => 'Results',
'asp_results' => 'Results',
'wpdreams_asp_settings' => 'Settings',
'wd_asp_settings' => 'Settings',
'asp_settings' => 'Settings',
'wpdreams_ajaxsearchpro_two_column' => 'TwoColumn',
'wd_asp_two_column' => 'TwoColumn',
'asp_two_column' => 'TwoColumn',
'wpdreams_ajaxsearchlite' => 'AjaxSearchLite',
'wd_asl' => 'AjaxSearchLite',
);
/**
* Array of already registered shortcodes
*
* @var array
*/
private static $registered = array();
/**
* Registers all the handlers from the $actions variable
*/
public static function registerAll() {
foreach ( self::$shortcodes as $shortcode => $handler ) {
self::register($shortcode, $handler);
}
}
/**
* Get all the queued handlers
*
* @return array
*/
public static function getAll() {
return array_keys(self::$shortcodes);
}
/**
* Get all the already registered handlers
*
* @return array
*/
public static function getRegistered() {
return self::$registered;
}
/**
* Registers a filter with the handler class name.
*
* @param $shortcode
* @param $handler string|array
* @return bool
*/
public static function register( $shortcode, $handler ) {
if ( is_array($handler) ) {
$class = self::NAMESPACE . $handler[0];
$handle = $handler[1];
} else {
$class = self::NAMESPACE . $handler;
$handle = 'handle';
}
if ( !class_exists($class) ) {
return false;
}
if ( !shortcode_exists($shortcode) ) {
add_shortcode($shortcode, array( call_user_func(array( $class, 'getInstance' )), $handle ));
}
self::$registered[] = $shortcode;
return true;
}
/**
* Deregisters a shortcode
*
* @param $shortcode string
* @return bool
*/
public static function deregister( $shortcode ) {
// Check if it is already registered
if ( isset(self::$registered[ $shortcode ]) ) {
remove_shortcode( $shortcode );
} elseif ( isset(self::$shortcodes[ $shortcode ]) ) {
unset(self::$shortcodes[ $shortcode ]);
}
return true;
}
}