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,16 @@
<?php
namespace WPDRMS\ASP\Hooks\Actions;
use WPDRMS\ASP\Patterns\SingletonTrait;
if (!defined('ABSPATH')) die('-1');
abstract class AbstractAction {
use SingletonTrait;
/**
* The handler
*
* This function is called by the appropriate handler
*/
abstract public function handle();
}

View File

@@ -0,0 +1,50 @@
<?php
namespace WPDRMS\ASP\Hooks\Actions;
if (!defined('ABSPATH')) die('-1');
class Cookies extends AbstractAction {
public function handle() {
// Forcefully unset the cookies, if requested
if ( isset($_GET['asp_unset_cookies']) ) {
self::forceUnsetCookies();
}
/**
* NOTES
* ---------------------------------------
* DO NOT DELETE THE COOKIES HERE, UNLESS A CERTAIN CRITERIA MET!!
* This filter is executed on ajax requests and redirects and during all
* kinds of background tasks. Unset only if the criteria is deterministic,
* and applies on a very specific case. (like the example above)
*/
// Set cookie if this is search, and asp is active
if ( isset($_POST['asp_active']) && isset($_GET['s']) ) {
if (isset($_POST['p_asp_data']) || isset($_POST['np_asp_data'])) {
$parse = parse_url(get_bloginfo('url'));
$host = $parse['host'];
$_p_data = $_POST['p_asp_data'] ?? $_POST['np_asp_data'];
$_p_id = $_POST['p_asid'] ?? $_POST['np_asid'];
setcookie('asp_data', $_p_data, time() + (30 * DAY_IN_SECONDS), '/', $host, is_ssl() );
setcookie('asp_id', $_p_id, time() + (30 * DAY_IN_SECONDS), '/', $host, is_ssl() );
setcookie('asp_phrase', $_GET['s'], time() + (30 * DAY_IN_SECONDS), '/', $host, is_ssl() );
$_COOKIE['asp_data'] = $_p_data;
$_COOKIE['asp_id'] = $_p_id;
$_COOKIE['asp_phrase'] = $_GET['s'];
}
}
}
public static function forceUnsetCookies() {
$parse = parse_url(get_bloginfo('url'));
$host = $parse['host'];
setcookie('asp_data', '', time() - 7200, '/', $host, is_ssl() );
setcookie('asp_id', '', time() - 7200, '/', $host, is_ssl() );
setcookie('asp_phrase', '', time() - 7200, '/', $host, is_ssl() );
unset($_COOKIE['asp_data']);
unset($_COOKIE['asp_id']);
unset($_COOKIE['asp_phrase']);
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace WPDRMS\ASP\Hooks\Actions;
if (!defined('ABSPATH')) die('-1');
class Footer extends AbstractAction {
public function handle() {
$exit1 = apply_filters('asp_load_css_js', false);
$exit2 = apply_filters('asp_load_css', false);
if ($exit1 || $exit2)
return;
// Blur for isotopic
?>
<div class='asp_hidden_data' id="asp_hidden_data" style="display: none !important;">
<svg style="position:absolute" height="0" width="0">
<filter id="aspblur">
<feGaussianBlur in="SourceGraphic" stdDeviation="4"/>
</filter>
</svg>
<svg style="position:absolute" height="0" width="0">
<filter id="no_aspblur"></filter>
</svg>
</div>
<?php
}
}

View File

@@ -0,0 +1,236 @@
<?php
namespace WPDRMS\ASP\Hooks\Actions;
use Closure;
use WPDRMS\ASP\Index\Manager;
use WPDRMS\ASP\Options\Data\IndexTableOptions;
if ( !defined('ABSPATH') ) {
die('-1');
}
class IndexTable extends AbstractAction {
/**
* @var Array<string, Closure>
*/
private static array $queue = array();
public function handle(): void {}
/**
* Executes the queued tasks
*
* @return void
*/
public function executeQueue(): void {
foreach ( self::$queue as $callable ) {
$callable();
}
}
/**
* Triggers on post metadata update
*
* @param int $mid The meta ID after successful update.
* @param int $object_id ID of the object metadata is for.
* @return void
*/
public function update_post_meta( int $mid, int $object_id ) {
$it_options = wd_asp()->o['asp_it_options'];
if ( $it_options['it_index_on_update_post_meta'] ) {
self::update($object_id, null, true);
}
}
/**
* Queues an index table update action
*
* @param int|null $post_id
* @param mixed $_post
* @param bool $update
* @return bool
*/
public function update( ?int $post_id = null, $_post = null, bool $update = false ): bool {
/**
* Argument default values are set to NULL, as some developers like to call
* this action without arguments, which causes an error.
*/
if ( !isset($post_id) || wp_is_post_revision( $post_id ) ) {
return false;
}
$stop = apply_filters('asp_index_on_save_stop', false, $post_id, $_post, $update);
if ( $stop ) {
return false;
}
// It's already queued :)
if ( isset(self::$queue[ 'post_' . $post_id ]) ) {
return false;
}
self::$queue[ 'post_' . $post_id ] = function () use ( $post_id, $update ): void {
$it_options = wd_asp()->o['asp_it_options'];
if ( $it_options === false ) {
return;
}
/**
* In some cases custom fields are not created in time of saving the post.
* To solve that, the user has an option to turn off automatic indexing
* when the post is created - but not when updated, or when a CRON job is executed.
*/
if ( !$it_options['it_index_on_save'] && !$update ) {
return;
}
$args = array();
foreach ( $it_options as $k => $o ) {
$args[ str_replace('it_', '', $k) ] = $o;
}
/**
* @var IndexTableOptions $new_options
*/
$new_options = $it_options['options'];
$args['attachment_exclude_directories'] = $new_options->get('attachment_exclude_directories')->directories;
$args['attachment_include_directories'] = $new_options->get('attachment_include_directories')->directories;
$it_o = new Manager( $args );
$post_status = get_post_status( $post_id );
$allowed_statuses = array_filter(explode(',', $args['post_statuses']), fn( $v )=>trim($v) !=='');
if ( count($allowed_statuses) === 0 ) {
return;
}
foreach ( $allowed_statuses as &$v ) {
$v = trim($v);
}
$allowed_statuses = apply_filters('asp/index/hooks/post_update/allowed_statuses', $allowed_statuses, $post_id);
if ( $post_status === 'trash' || !in_array($post_status, $allowed_statuses, true) ) {
$this->delete( $post_id );
return;
}
$post_type = get_post_type( $post_id );
$allowed_types = $args['post_types'];
// If this is a product, and product variations should be indexed, index them as well
if ( class_exists('WooCommerce') &&
in_array($post_type, array( 'product', 'product_variation' ), true)
) { // Woo products and variations
if ( $post_type === 'product' ) { // Product saving
// Save the variations, if selected
if ( in_array('product_variation', $allowed_types, true) ) {
$args = array(
'post_type' => 'product_variation',
'post_status' => $allowed_statuses,
'numberposts' => -1,
'fields' => 'ids',
'post_parent' => $post_id, // $post->ID
);
$variations = get_posts($args);
foreach ( $variations as $variation ) {
if ( is_numeric($variation) ) {
$it_o->indexDocument($variation, true, true);
}
}
}
// Save the product, if selected
if ( in_array('product', $allowed_types, true) ) {
$it_o->indexDocument( $post_id, true, true );
}
} elseif ( in_array('product_variation', $allowed_types, true) ) { // variation saving
// Check if post parent status before indexing
$parent = wp_get_post_parent_id( $post_id );
if ( $parent !== false ) {
$parent_post_status = get_post_status( $parent );
if ( in_array($parent_post_status, $allowed_statuses, true) ) {
$it_o->indexDocument( $post_id, true, true );
}
}
}
} else { // Any other post type
$it_o->indexDocument( $post_id, true, true );
}
};
return true;
}
public function delete( int $post_id ): void {
$it_o = new Manager();
$post_type = get_post_type( $post_id );
if ( class_exists('WooCommerce') &&
$post_type === 'product'
) {
$args = array(
'post_type' => 'product_variation',
'post_status' => 'any',
'numberposts' => -1,
'fields' => 'ids',
'post_parent' => $post_id, // $post->ID
);
$variations = get_posts( $args );
$variations[] = $post_id;
$it_o->removeDocument( $variations );
} else {
$it_o->removeDocument( $post_id );
}
}
public function extend(): void {
$asp_it_options = wd_asp()->o['asp_it_options'];
if ( $asp_it_options !== false ) {
$args = array();
foreach ( $asp_it_options as $k => $o ) {
$args[ str_replace('it_', '', $k) ] = $o;
}
/**
* @var IndexTableOptions $new_options
*/
$new_options = $asp_it_options['options'];
$args['attachment_exclude_directories'] = $new_options->get('attachment_exclude_directories')->directories;
$args['attachment_include_directories'] = $new_options->get('attachment_include_directories')->directories;
$it_obj = new Manager( $args );
$res = $it_obj->extendIndex( );
update_option(
'asp_it_cron',
array(
'last_run' => time(),
'result' => $res,
)
);
}
}
public function cron_extend(): void {
if ( wp_next_scheduled( 'asp_cron_it_extend' ) !== false ) {
return;
}
$asp_it_options = wd_asp()->o['asp_it_options'];
if ( $asp_it_options === false ) {
return;
}
$enabled = $asp_it_options['it_cron_enable'];
$period = $asp_it_options['it_cron_period'];
$do_media = is_array($asp_it_options['it_post_types']) && in_array( 'attachment', $asp_it_options['it_post_types'], true );
// If enabled, or attachments are queued for index
if ( $enabled || $do_media ) {
if ( $do_media ) {
// Index media at least every 5 minutes
if ( $enabled && in_array($period, array( 'asp_cr_two_minutes', 'asp_cr_three_minutes' ), true) ) {
wp_schedule_event(time(), $period, 'asp_cron_it_extend');
} else {
wp_schedule_event(time(), 'asp_cr_five_minutes', 'asp_cron_it_extend');
}
} else {
wp_schedule_event(time(), $period, 'asp_cron_it_extend');
}
}
}
}

View File

@@ -0,0 +1,52 @@
<?php /** @noinspection PhpUnused */
namespace WPDRMS\ASP\Hooks\Actions;
use WPDRMS\ASP\Hooks\Ajax\DeleteCache;
use WPDRMS\ASP\Index\Database;
use WPDRMS\ASP\Utils\Polylang\StringTranslations as PolylangStringTranslations;
if (!defined('ABSPATH')) die('-1');
class Other extends AbstractAction {
public function handle() {}
public function on_save_post() {
// Clear all the cache just in case
DeleteCache::getInstance()->handle(false);
}
/**
* Fix for 'WP External Links' plugin
* https://wordpress.org/plugins/wp-external-links/
*
* @param $link
*/
public function plug_WPExternalLinks_fix( $link ) {
// ignore links with class "asp_showmore"
if ( $link->has_attr_value( 'class', 'asp_showmore' ) ) {
$link->set_ignore();
}
}
public function pll_init_string_translations() {
PolylangStringTranslations::init();
}
public function pll_save_string_translations() {
// Save any possible PLL translation strings stack
PolylangStringTranslations::save();
}
public function pll_register_string_translations() {
PolylangStringTranslations::register();
}
/**
* Triggers when asp_scheduled_activation_events is triggered (during activation only)
*/
public function scheduledActivationEvents() {
$index = new Database();
$index->scheduled();
}
}

View File

@@ -0,0 +1,18 @@
<?php /** @noinspection PhpUnused */
namespace WPDRMS\ASP\Hooks\Actions;
if (!defined('ABSPATH')) die('-1');
class OutputBuffer extends AbstractAction {
// template_redirect
function obStart() {
\WPDRMS\ASP\Misc\OutputBuffer::getInstance()->obStart();
}
// shutdown
function obClose() {
\WPDRMS\ASP\Misc\OutputBuffer::getInstance()->obClose();
}
function handle(){}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace WPDRMS\ASP\Hooks\Actions;
use WPDRMS\ASP\Updates\Manager;
if (!defined('ABSPATH')) die('-1');
class Updates extends AbstractAction {
function handle() {
new Manager(ASP_PLUGIN_NAME, ASP_PLUGIN_BASE, wd_asp()->updates);
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace WPDRMS\ASP\Hooks\Actions;
if (!defined('ABSPATH')) die('-1');
class Widgets extends AbstractAction {
public function handle() {
register_widget("\\WPDRMS\\ASP\\Widgets\\Search");
register_widget("\\WPDRMS\\ASP\\Widgets\\LastSearches");
register_widget("\\WPDRMS\\ASP\\Widgets\\TopSearches");
}
}

View File

@@ -0,0 +1,277 @@
<?php
namespace WPDRMS\ASP\Hooks;
if ( !defined('ABSPATH') ) {
die('-1');
}
class ActionsManager {
const NAMESPACE = 'WPDRMS\\ASP\\Hooks\\Actions\\';
/**
* Array of internal known actions
*
* @var array
*/
private static $actions = array(
array(
'action' => 'init',
'handler' => 'Cookies',
'priority' => 10,
'args' => 0,
),
array(
'action' => 'template_redirect',
'handler' => array( 'OutputBuffer', 'obStart' ),
'priority' => 9999,
'args' => 0,
),
array(
'action' => 'shutdown',
'handler' => array( 'OutputBuffer', 'obClose' ),
'priority' => -101,
'args' => 0,
),
array(
'action' => 'wp_footer',
'handler' => 'Footer',
'priority' => 10,
'args' => 0,
),
array(
'action' => 'init',
'handler' => 'Updates',
'priority' => 10,
'args' => 0,
),
array(
'action' => 'widgets_init',
'handler' => 'Widgets',
'priority' => 10,
'args' => 0,
),
array(
'action' => 'edit_attachment',
'handler' => array( 'IndexTable', 'update' ),
'priority' => 999999998,
'args' => 3,
),
array(
'action' => 'add_attachment',
'handler' => array( 'IndexTable', 'update' ),
'priority' => 999999998,
'args' => 3,
),
array(
'action' => 'save_post',
'handler' => array( 'IndexTable', 'update' ),
'priority' => 999999998,
'args' => 3,
),
array(
'action' => 'added_post_meta',
'handler' => array( 'IndexTable', 'update_post_meta' ),
'priority' => 999999999,
'args' => 2,
),
array(
'action' => 'updated_post_meta',
'handler' => array( 'IndexTable', 'update_post_meta' ),
'priority' => 999999999,
'args' => 2,
),
array(
'action' => 'wp_insert_post',
'handler' => array( 'IndexTable', 'update' ),
'priority' => 999999999,
'args' => 3,
),
array(
'action' => 'new_to_publish',
'handler' => array( 'Other', 'on_save_post' ),
'priority' => 999999999,
'args' => 0,
),
array(
'action' => 'draft_to_publish',
'handler' => array( 'Other', 'on_save_post' ),
'priority' => 999999999,
'args' => 0,
),
array(
'action' => 'pending_to_publish',
'handler' => array( 'Other', 'on_save_post' ),
'priority' => 999999999,
'args' => 0,
),
array(
'action' => 'delete_post',
'handler' => array( 'IndexTable', 'delete' ),
'priority' => 10,
'args' => 1,
),
array(
'action' => 'asp_cron_it_extend',
'handler' => array( 'IndexTable', 'extend' ),
'priority' => 10,
'args' => 0,
'cron' => true,
),
array(
'action' => 'wp_footer',
'handler' => array( 'IndexTable', 'executeQueue' ),
'priority' => 10,
'args' => 0,
),
array(
'action' => 'admin_bar_menu',
'handler' => array( 'IndexTable', 'executeQueue' ),
'priority' => 10,
'args' => 0,
),
array(
'action' => 'shutdown',
'handler' => array( 'IndexTable', 'executeQueue' ),
'priority' => 10,
'args' => 0,
),
array(
'action' => 'wpel_before_apply_link',
'handler' => array( 'Other', 'plug_WPExternalLinks_fix' ),
'priority' => 9999,
'args' => 1,
),
array(
'action' => 'wp_footer',
'handler' => array( 'Other', 'pll_save_string_translations' ),
'priority' => 9999,
'args' => 0,
),
array(
'action' => 'init',
'handler' => array( 'Other', 'pll_init_string_translations' ),
'priority' => 9998,
'args' => 0,
),
array(
'action' => 'init',
'handler' => array( 'Other', 'pll_register_string_translations' ),
'priority' => 9999,
'args' => 0,
),
array(
'action' => 'asp_scheduled_activation_events',
'handler' => array( 'Other', 'scheduledActivationEvents' ),
'priority' => 9999,
'args' => 0,
),
);
/**
* Array of already registered handlers
*
* @var array
*/
private static $registered = array();
/**
* Registers all the handlers from the $actions variable
*/
public static function registerAll() {
foreach ( self::$actions as $data ) {
self::register($data['action'], $data['handler'], $data['priority'], $data['args']);
if ( !empty($data['cron']) ) {
self::registerCron( $data['handler'] );
}
}
}
/**
* Get all the queued handlers
*
* @return array
*/
public static function getAll(): array {
return array_keys(self::$actions);
}
/**
* Get all the already registered handlers
*
* @return array
*/
public static function getRegistered(): array {
return self::$registered;
}
/**
* Registers an action with the handler class name.
*
* @param $action
* @param $handler
* @param int $priority
* @param int $accepted_args
* @return bool
*/
public static function register( $action, $handler, int $priority = 10, int $accepted_args = 0 ): bool {
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;
}
add_action($action, array( call_user_func(array( $class, 'getInstance' )), $handle ), $priority, $accepted_args);
self::$registered[] = $action;
return true;
}
public static function registerCron( $handler ) {
if ( is_array($handler) ) {
$class = self::NAMESPACE . $handler[0];
$handle = 'cron_' . $handler[1];
} else {
$class = self::NAMESPACE . $handler;
$handle = 'cron_handle';
}
$o = call_user_func(array( $class, 'getInstance' ));
// Run the handler, that will register the event
$o->$handle();
}
/**
* Deregisters an action handler.
*
* @param $action
* @param $handler
* @noinspection PhpMissingParamTypeInspection
*/
public static function deregister( $action, $handler = false ) {
if ( $handler === false ) {
foreach ( self::$actions as $a ) {
if ( $a['action'] == $action ) {
if ( is_array($a['handler']) ) {
remove_action($action, array( call_user_func(array( self::NAMESPACE . $a['handler'][0], 'getInstance' )), $a['handler'][1] ));
} else {
remove_action($action, array( call_user_func(array( self::NAMESPACE . $a['handler'], 'getInstance' )), 'handle' ));
}
}
}
} elseif ( is_array($handler) ) {
remove_action($action, array( call_user_func(array( self::NAMESPACE . $handler[0], 'getInstance' )), $handler[1] ));
} elseif ( is_string($handler) ) {
remove_action($action, array( call_user_func(array( self::NAMESPACE . $handler, 'getInstance' )), 'handle' ));
}
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace WPDRMS\ASP\Hooks\Ajax;
use WPDRMS\ASP\Patterns\SingletonTrait;
if (!defined('ABSPATH')) die('-1');
abstract class AbstractAjax {
use SingletonTrait;
/**
* The handler
*
* This function is called by the appropriate handler
*/
abstract public function handle();
}

View File

@@ -0,0 +1,20 @@
<?php
namespace WPDRMS\ASP\Hooks\Ajax;
use WPDRMS\ASP\Misc\Statistics;
use WPDRMS\ASP\Utils\Ajax;
if (!defined('ABSPATH')) die('-1');
class AddKeyword extends AbstractAjax {
function handle() {
if ( isset($_POST['id'], $_POST['keyword']) ) {
echo (Statistics::addKeyword($_POST['id'] + 0, $_POST['keyword']) === true) ? 1 : 0;
exit;
}
Ajax::prepareHeaders();
echo 0;
die();
}
}

View File

@@ -0,0 +1,86 @@
<?php
namespace WPDRMS\ASP\Hooks\Ajax;
use WPDRMS\ASP\Suggest\KeywordSuggest;
use WPDRMS\ASP\Utils\Ajax;
if (!defined('ABSPATH')) die('-1');
class Autocomplete extends AbstractAjax {
public function handle() {
// DO NOT TRIM! It will give incorrect results :)
$s = preg_replace('/\s+/', ' ', $_POST['sauto']);
do_action('asp_before_autocomplete', $s);
if ( empty($_POST['asid']) ) return "";
$search = wd_asp()->instances->get( $_POST['asid'] + 0 );
if ( empty($search['data']) )
return false;
$sd = &$search['data'];
$options = array();
if ( isset($_POST['options']) ) {
if (is_array($_POST['options']))
$options = $_POST['options'];
else
parse_str($_POST['options'], $options);
}
$keyword = '';
$types = array();
if (isset($sd['customtypes']) && count($sd['customtypes']) > 0)
$types = array_merge($types, $sd['customtypes']);
foreach (w_isset_def($sd['selected-autocomplete_source'], array('google')) as $source) {
if ( empty($source) )
continue;
$taxonomy = "";
// Check if this is a taxonomy
if (strpos($source, 'xtax_') !== false) {
$taxonomy = str_replace('xtax_', '', $source);
$source = "terms";
}
if ( function_exists( 'qtranxf_use' ) && !empty($options['qtranslate_lang']) ) {
$lang = $options['qtranslate_lang'];
} else if ( !empty($options['wpml_lang']) ) {
$lang = $options['wpml_lang'];
} else if ( !empty($options['polylang_lang']) ) {
$lang = $options['polylang_lang'];
} else {
$lang = $sd['keywordsuggestionslang'];
}
$t = new KeywordSuggest($source, array(
'maxCount' => 1,
'maxCharsPerWord' => $sd['autocomplete_length'],
'postTypes' => $types,
'lang' => $lang,
'overrideUrl' => '',
'taxonomy' => $taxonomy,
'match_start' => true,
'api_key' => $sd['autoc_google_places_api'],
'search_id' => $_POST['asid'] + 0,
'options' => $options
));
$res = $t->getKeywords($s);
if (isset($res[0]) && $keyword = $res[0])
break;
}
do_action('asp_after_autocomplete', $s, $keyword);
Ajax::prepareHeaders();
print $keyword;
die();
}
}

View File

@@ -0,0 +1,47 @@
<?php
/** @noinspection PhpMissingParamTypeInspection */
/** @noinspection PhpMissingReturnTypeInspection */
namespace WPDRMS\ASP\Hooks\Ajax;
use WPDRMS\ASP\Cache\TextCache;
use WPDRMS\ASP\Utils\Ajax;
use WPDRMS\ASP\Utils\FileManager;
if (!defined('ABSPATH')) die('-1');
class DeleteCache extends AbstractAjax {
/**
* Deletes the Ajax Search Pro directory
*/
public function handle( $exit = true ) {
// $exit can be an empty string "", so force boolean
$exit = $exit !== false ? true : false;
if (
current_user_can( 'manage_options' ) &&
( !$exit || (
isset($_POST['asp_delete_cache_request_nonce']) &&
wp_verify_nonce( $_POST['asp_delete_cache_request_nonce'], 'asp_delete_cache_request_nonce' )
) )
) {
if ( !empty(wd_asp()->cache_path) && wd_asp()->cache_path !== '' )
$count = FileManager::instance()->deleteByPattern(wd_asp()->cache_path, '*.wpd');
if ( !empty(wd_asp()->bfi_path) && wd_asp()->bfi_path !== '' ) {
$count = $count + FileManager::instance()->deleteByPattern(wd_asp()->bfi_path, '*.jpg');
$count = $count + FileManager::instance()->deleteByPattern(wd_asp()->bfi_path, '*.jpeg');
$count = $count + FileManager::instance()->deleteByPattern(wd_asp()->bfi_path, '*.png');
}
// Clear database cache
$count = $count + TextCache::clearDBCache();
}
if ( $exit !== false ) {
Ajax::prepareHeaders();
print $count;
die();
}
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace WPDRMS\ASP\Hooks\Ajax;
use WPDRMS\ASP\Misc\Statistics;
use WPDRMS\ASP\Utils\Ajax;
if (!defined('ABSPATH')) die('-1');
class DeleteKeyword extends AbstractAjax {
function handle() {
if (
isset($_POST['asp_statistics_request_nonce']) &&
wp_verify_nonce( $_POST['asp_statistics_request_nonce'], 'asp_statistics_request_nonce' ) &&
current_user_can( 'manage_options' )
) {
if (isset($_POST['keywordid'])) {
echo Statistics::deleteKw($_POST['keywordid'] + 0);
exit;
}
Ajax::prepareHeaders();
echo 0;
}
die();
}
}

View File

@@ -0,0 +1,147 @@
<?php
namespace WPDRMS\ASP\Hooks\Ajax;
use WPDRMS\ASP\Index\Database;
use WPDRMS\ASP\Index\Manager;
use WPDRMS\ASP\Utils\Ajax;
if ( !defined('ABSPATH') ) {
die('-1');
}
class IndexTable extends AbstractAjax {
public function handle() {
if ( isset($_POST['asp_it_request_nonce']) &&
wp_verify_nonce( $_POST['asp_it_request_nonce'], 'asp_it_request_nonce' ) &&
current_user_can( 'manage_options' )
) {
if ( $_POST['action'] == 'asp_indextable_optimize' ) {
$it = new Database();
print 'OPTIMIZE: ' . $it->optimize();
die();
}
Ajax::prepareHeaders();
if ( isset($_POST['data']) ) {
if ( is_array($_POST['data']) ) {
$options = $_POST['data'];
} else {
parse_str($_POST['data'], $options);
}
$options = wd_asp()->instances->decode_params($options);
} else {
print 'No post data detected, function terminated.';
die();
}
update_option('asp_recreate_index', 0);
$limit = $options['it_limit'];
// Adjust the limit based on the previous and longest request duration
if ( isset($_POST['last_request_duration'], $_POST['longest_request_duration']) ) {
$dur = ( intval( $_POST['last_request_duration'] ) + intval( $_POST['longest_request_duration'] ) ) / 2;
if ( $dur > 25 ) {
$limit = intval($limit / 5);
} elseif ( $dur > 20 ) {
$limit = intval($limit / 4);
} elseif ( $dur > 15 ) {
$limit = intval($limit / 3);
} elseif ( $dur > 10 ) {
$limit = intval($limit / 2);
}
$limit = $limit < 1 ? 1 : $limit;
}
$it_obj = new Manager(
array(
'index_title' => $options['it_index_title'],
'index_content' => $options['it_index_content'],
'index_excerpt' => $options['it_index_excerpt'],
'index_tags' => $options['it_index_tags'],
'index_categories' => $options['it_index_categories'],
'post_types' => $options['it_post_types'],
'attachment_mime_types' => $options['it_attachment_mime_types'],
'index_pdf_content' => $options['it_index_pdf_content'],
'index_pdf_method' => $options['it_index_pdf_method'],
'index_text_content' => $options['it_index_text_content'],
'index_richtext_content' => $options['it_index_richtext_content'],
'index_msword_content' => $options['it_index_msword_content'],
'index_msexcel_content' => $options['it_index_msexcel_content'],
'index_msppt_content' => $options['it_index_msppt_content'],
'media_service_send_file' => $options['it_media_service_send_file'],
'attachment_exclude_directories' =>
$options['attachment_exclude_directories']['directories'] ??
wd_asp()->options['asp_it_options']['options']->get('attachment_exclude_directories')->directories,
'attachment_include_directories' =>
$options['attachment_include_directories']['directories'] ??
wd_asp()->options['asp_it_options']['options']->get('attachment_include_directories')->directories,
'post_statuses' => $options['it_post_statuses'],
'post_password_protected' => $options['it_post_password_protected'],
'index_taxonomies' =>$options['it_index_taxonomies'],
'index_permalinks' =>$options['it_index_permalinks'],
'index_customfields' => $options['it_index_customfields'],
'index_author_name' => $options['it_index_author_name'],
'index_author_bio' => $options['it_index_author_bio'],
'blog_id' => !empty($_POST['blog_id']) ? $_POST['blog_id'] : get_current_blog_id(),
'inflections' => $options['it_inflections'],
'language' => $options['it_language'],
'extend' => ( w_isset_def($_POST['asp_index_action'], 'new') == 'extend' ? 1 : 0 ),
'limit' => $limit,
'use_stopwords' => $options['it_use_stopwords'],
'stopwords' => $options['it_stopwords'],
'min_word_length' => $options['it_min_word_length'],
'extract_gutenberg_blocks' => $options['it_extract_gutenberg_blocks'],
'extract_shortcodes' => $options['it_extract_shortcodes'],
'exclude_shortcodes' => $options['it_exclude_shortcodes'],
'synonyms_as_keywords' => $options['it_synonyms_as_keywords'],
)
);
if ( $_POST['action'] == 'asp_indextable_get_stats' ) {
$stats = array(
'postsIndexed' => $it_obj->getPostsIndexed(),
'postsToIndex' => $it_obj->getPostIdsToIndexCount(),
'totalKeywords' => $it_obj->getTotalKeywords(),
);
print '!!!ASP_INDEX_STAT_START!!!';
print_r(json_encode($stats));
print '!!!ASP_INDEX_STAT_STOP!!!';
die();
}
if ( isset($_POST['asp_index_action']) ) {
switch ( $_POST['asp_index_action'] ) {
case 'new':
$ret = $it_obj->newIndex();
print 'New index !!!ASP_INDEX_START!!!';
print_r(json_encode($ret));
print '!!!ASP_INDEX_STOP!!!';
die();
case 'extend':
$ret = $it_obj->extendIndex();
print 'Extend index !!!ASP_INDEX_START!!!';
print_r(json_encode($ret));
print '!!!ASP_INDEX_STOP!!!';
die();
case 'switching_blog':
$ret = $it_obj->extendIndex(true);
print 'Extend index (blog_switch) !!!ASP_INDEX_START!!!';
print_r(json_encode($ret));
print '!!!ASP_INDEX_STOP!!!';
die();
case 'delete':
$ret = $it_obj->emptyIndex();
print 'Delete index !!!ASP_INDEX_START!!!';
print_r(json_encode($ret));
print '!!!ASP_INDEX_STOP!!!';
die();
}
}
// no action set, or other failure
print 'No action !!!ASP_INDEX_START!!!0!!!ASP_INDEX_STOP!!!';
}
die();
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace WPDRMS\ASP\Hooks\Ajax;
use WPDRMS\ASP\Misc\PluginLicense;
if (!defined('ABSPATH')) die('-1');
class License extends AbstractAjax {
function handle() {
if (
isset($_POST['asp_license_request_nonce']) &&
wp_verify_nonce( $_POST['asp_license_request_nonce'], 'asp_license_request_nonce' ) &&
current_user_can( 'manage_options' )
) {
if ( !isset($_POST['op']) ) die(-2);
if ( ASP_DEMO ) {
print_r(json_encode(array("status"=>0, "message"=>"This functions is disabled on this demo.")));
die();
}
if ( $this->excessiveUsage() ) {
print_r(json_encode(array("status"=>0, "message"=>"WP Excessive usage Warning: Please wait a few seconds before the next request.")));
die();
}
if ( $_POST['op'] == "activate" && !empty($_POST['asp_key']) ) {
$key = $this->preValidateKey( $_POST['asp_key'] );
if ( $key === false ) {
print_r(json_encode(array("status"=>0, "message"=>"WP: Invalid key specified.")));
die();
}
$res = PluginLicense::activate( $key );
if ($res === false)
print_r(json_encode(array("status"=>0, "message"=>"WP: Connection error, please try again later.")));
else
print_r(json_encode($res));
die();
} else if ($_POST['op'] == "deactivate") {
$res = PluginLicense::deactivate();
if ($res === false)
print_r(json_encode(array("status"=>0, "message"=>"WP: Connection error, please try again later.")));
else
print_r(json_encode($res));
die();
}
// We reached here, something is missing..
print_r(json_encode(array("status"=>0, "message"=>"WP: Missing information, please check the input fields.")));
}
die();
}
function preValidateKey( $key ) {
$key = trim($key);
if ( strlen($key)!=36 )
return false;
return $key;
}
function excessiveUsage(): bool {
$usage = get_option("_asp_update_usage", array());
$n_usage = array();
// Leave only recent usages
foreach ($usage as $u) {
if ($u > (time() - 60))
$n_usage[] = $u;
}
if ( count($n_usage) <= 10 ) {
$n_usage[] = time();
update_option("_asp_update_usage", $n_usage);
return false;
} else {
return true;
}
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace WPDRMS\ASP\Hooks\Ajax;
use WPDRMS\ASP\Index\Database;
use WPDRMS\ASP\Utils\Ajax;
if (!defined('ABSPATH')) die('-1');
class Maintenance extends AbstractAjax {
public function handle() {
if (
current_user_can( 'manage_options' )
) {
if (ASP_DEMO) {
print "Maintenance !!!ASP_MAINT_START!!!";
print_r(json_encode(array(
'status' => 0,
'action' => '',
'msg' => 'Not allowed in demo mode!'
)));
Ajax::prepareHeaders();
print "!!!ASP_MAINT_STOP!!!";
die();
}
$status = 0;
$msg = 'Missing POST information, please try again!';
$action = 'none';
$nonce = false;
if ( isset($_POST, $_POST['data']) ) {
if (is_array($_POST['data']))
$data = $_POST['data'];
else
parse_str($_POST['data'], $data);
if ( isset($data['asp_reset_nonce']) ) {
$nonce = 'asp_reset_nonce';
} else if ( isset($data['asp_wipe_nonce']) ) {
$nonce = 'asp_wipe_nonce';
} else if ( isset($data['asp_index_defrag_nonce']) ) {
$nonce = 'asp_index_defrag_nonce';
}
if (
$nonce !== false &&
isset($data[$nonce]) &&
wp_verify_nonce( $data[$nonce], $nonce )
) {
if ( $nonce == 'asp_reset_nonce' ) { // Reset
wd_asp()->init->pluginReset();
$status = 1;
$action = 'refresh';
$msg = 'The plugin data was successfully reset!';
} else if ( $nonce == 'asp_wipe_nonce' ) { // Wipe
wd_asp()->init->pluginWipe();
$status = 1;
$action = 'redirect';
$msg = 'All plugin data was successfully wiped, you will be redirected in 5 seconds!';
} else {
$it = new Database();
$it->optimize();
$status = 1;
$action = 'nothing';
$msg = 'Index Table Optimized and Defragmented!';
}
} else {
$msg = 'Missing or invalid NONCE, please <strong>reload this page</strong> and try again!';
}
}
$ret = array(
'status' => $status,
'action' => $action,
'msg' => $msg
);
Ajax::prepareHeaders();
print "Maintenance !!!ASP_MAINT_START!!!";
print_r(json_encode($ret));
print "!!!ASP_MAINT_STOP!!!";
}
die();
}
}

View File

@@ -0,0 +1,42 @@
<?php
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/** @noinspection PhpIncludeInspection */
namespace WPDRMS\ASP\Hooks\Ajax;
use WPDRMS\ASP\Utils\Ajax;
use WPDRMS\ASP\Media\RemoteService;
if (!defined('ABSPATH')) die('-1');
class MediaService extends AbstractAjax {
function handle() {
if (
isset($_POST['asp_mediaservice_request_nonce']) &&
wp_verify_nonce( $_POST['asp_mediaservice_request_nonce'], 'asp_mediaservice_request_nonce' ) &&
current_user_can( 'manage_options' )
) {
if ( isset($_POST['ms_deactivate']) ) {
RemoteService\License::getInstance()->delete();
Ajax::prepareHeaders();
print 0;
} else {
$success = 0;
if ( isset($_POST['ms_license_key']) ) {
$r = RemoteService\License::getInstance()->activate($_POST['ms_license_key']);
$success = $r['success'];
$text = $r['text'];
} else {
$text = "License key is missing or invalid.";
}
Ajax::prepareHeaders();
print_r(json_encode(array(
'success' => $success,
'text' => $text
)));
}
}
exit;
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace WPDRMS\ASP\Hooks\Ajax;
use WPDRMS\ASP\Utils\Ajax;
if (!defined('ABSPATH')) die('-1');
class Preview extends AbstractAjax {
function handle() {
if (
isset($_POST['asp_backend_preview_nonce']) &&
wp_verify_nonce( $_POST['asp_backend_preview_nonce'], 'asp_backend_preview_nonce' ) &&
( current_user_can( 'manage_options' ) || apply_filters('wpdrms/backend/options/ajax/user_role_override', false) )
) {
$o = \WPDRMS\ASP\Shortcodes\Search::getInstance();
// Needs to be here, as the $o->handle(..) also prints out things :)
Ajax::prepareHeaders();
parse_str($_POST['formdata'], $style);
$out = $o->handle(array(
"id" => $_POST['asid'],
"style" => $style,
"preview" => true,
));
print $out;
}
die();
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace WPDRMS\ASP\Hooks\Ajax;
use WPDRMS\ASP\Utils\Ajax;
if (!defined('ABSPATH')) die('-1');
class Priorities extends AbstractAjax {
function handle() {
if (
isset($_POST['asp_priorities_request_nonce']) &&
wp_verify_nonce( $_POST['asp_priorities_request_nonce'], 'asp_priorities_request_nonce' ) &&
current_user_can( 'manage_options' )
) {
if ( !empty($_POST['ptask']) ) {
Ajax::prepareHeaders();
if ( ASP_DEMO && $_POST['ptask'] == "set" ) {
echo "!!PSASPSTART!!0!!PSASPEND!!";
die();
}
if ( $_POST['ptask'] == "get" )
\WPDRMS\ASP\Misc\Priorities::ajax_get_posts();
else if ( $_POST['ptask'] == "set" )
\WPDRMS\ASP\Misc\Priorities::ajax_set_priorities();
}
}
die();
}
}

View File

@@ -0,0 +1,164 @@
<?php /** @noinspection PhpMissingParamTypeInspection */
/** @noinspection PhpComposerExtensionStubsInspection */
namespace WPDRMS\ASP\Hooks\Ajax;
use WPDRMS\ASP\Cache\TextCache;
use WPDRMS\ASP\Misc\Performance;
use WPDRMS\ASP\Query\SearchQuery;
use WPDRMS\ASP\Utils\Ajax;
use WPDRMS\ASP\Utils\Search as SearchUtils;
if (!defined('ABSPATH')) die('-1');
class Search extends AbstractAjax {
private $cache;
/**
* Oversees and handles the search request
*
* @param bool $dontGroup
* @return array|mixed|void
* @noinspection PhpIncludeInspection
*/
public function handle($dontGroup = false) {
$perf_options = wd_asp()->o['asp_performance'];
if (w_isset_def($perf_options['enabled'], 1)) {
$performance = new Performance('asp_performance_stats');
$performance->start_measuring();
}
$s = $_POST['aspp'];
if (is_array($_POST['options']))
$options = $_POST['options'];
else
parse_str($_POST['options'], $options);
$id = (int)$_POST['asid'];
$instance = wd_asp()->instances->get($id);
$sd = &$instance['data'];
if (
wd_asp()->o['asp_caching']['caching'] == 1
) {
$this->printCache($options, $s, $id);
}
// If previewed, we need the details
if ( isset($_POST['asp_preview_options']) && (current_user_can("activate_plugins") || ASP_DEMO) ) {
require_once(ASP_PATH . "backend" . DIRECTORY_SEPARATOR . "settings" . DIRECTORY_SEPARATOR . "types.inc.php");
parse_str( $_POST['asp_preview_options'], $preview_options );
$_POST['asp_preview_options'] = wpdreams_parse_params($preview_options);
$_POST['asp_preview_options'] = wd_asp()->instances->decode_params($_POST['asp_preview_options']);
$sd = $_POST['asp_preview_options'];
}
$asp_query = new SearchQuery(array(
"s" => $s,
"_id" => $id,
"_ajax_search" => true,
"_call_num" => $_POST['asp_call_num'] ?? 0
), $id, $options);
$results = $asp_query->posts;
if ( count($results) > 0 ) {
$results = apply_filters('asp_only_non_keyword_results', $results, $id, $s, $asp_query->getArgs());
} else {
if ( $sd['result_suggestions'] ) {
$results = $asp_query->resultsSuggestions( $sd['keywordsuggestions'] );
} else if ( $sd['keywordsuggestions'] ) {
$results = $asp_query->kwSuggestions();
}
}
if (
count($results) <= 0 &&
$sd['keywordsuggestions'] &&
(!isset($_GET['asp_call_num']) || $_GET['asp_call_num'] < 2)
) {
$results = $asp_query->resultsSuggestions();
} else if (count($results) > 0) {
$results = apply_filters('asp_only_non_keyword_results', $results, $id, $s, $asp_query->getArgs());
}
$results = apply_filters('asp_ajax_results', $results, $id, $s, $sd);
do_action('asp_after_search', $s, $results, $id);
if ( isset($performance) ) {
$performance->stop_measuring();
}
$html_results = SearchUtils::generateHTMLResults($results, $sd, $id, $s);
// Override from hooks
if (isset($_POST['asp_get_as_array'])) {
return $results;
}
$html_results = apply_filters('asp_before_ajax_output', $html_results, $id, $results, $asp_query->getArgs());
$final_output = "";
/* Clear output buffer, possible warnings */
$final_output .= "___ASPSTART_HTML___" . $html_results . "___ASPEND_HTML___";
$final_output .= "___ASPSTART_DATA___";
if ( defined('JSON_INVALID_UTF8_IGNORE') ) {
$final_output .= json_encode(array(
'results_count' => isset($results["keywords"]) ? 0 : $asp_query->returned_posts,
'full_results_count' => $asp_query->found_posts,
'results' => $results
), JSON_INVALID_UTF8_IGNORE);
} else {
$final_output .= json_encode(array(
'results_count' => isset($results["keywords"]) ? 0 : $asp_query->returned_posts,
'full_results_count' => $asp_query->found_posts,
'results' => $results
));
}
$final_output .= "___ASPEND_DATA___";
$this->setCache($final_output);
Ajax::prepareHeaders();
print_r($final_output);
die();
}
private function printCache($options, $s, $id) {
$o = $options;
$this->cache = new TextCache(wd_asp()->cache_path, "z_asp", wd_asp()->o['asp_caching']['cachinginterval'] * 60);
$call_num = $_POST['asp_call_num'] ?? 0;
unset($o['filters_initial'], $o['filters_changed']);
$file_name = md5(json_encode($o) . $call_num . $s . $id);
if ( wd_asp()->o['asp_caching']['caching_method'] == 'file' || wd_asp()->o['asp_caching']['caching_method'] == 'sc_file' ) {
$cache_content = $this->cache->getCache($file_name);
} else {
$cache_content = $this->cache->getDBCache($file_name);
}
if ( $cache_content !== false ) {
$cache_content = apply_filters('asp_cached_content', $cache_content, $s, $id);
do_action('asp_after_search', $cache_content, $s, $id);
print "cached(" . date("F d Y H:i:s.", $this->cache->getLastFileMtime()) . ")";
print_r($cache_content);
die;
}
}
private function setCache($content) {
if ( isset($this->cache) ) {
if (
wd_asp()->o['asp_caching']['caching_method'] == 'file' ||
wd_asp()->o['asp_caching']['caching_method'] == 'sc_file'
) {
$this->cache->setCache('!!ASPSTART!!' . $content . "!!ASPEND!!");
} else {
$this->cache->setDBCache('!!ASPSTART!!' . $content . "!!ASPEND!!");
}
}
}
}

View File

@@ -0,0 +1,108 @@
<?php /** @noinspection PhpComposerExtensionStubsInspection */
namespace WPDRMS\ASP\Hooks\Ajax;
use WPDRMS\ASP\Synonyms\Manager as SynonymsManager;
use WPDRMS\ASP\Utils\Ajax;
if (!defined('ABSPATH')) die('-1');
class Synonyms extends AbstractAjax {
function handle() {
if (
isset($_POST['asp_synonyms_request_nonce']) &&
wp_verify_nonce( $_POST['asp_synonyms_request_nonce'], 'asp_synonyms_request_nonce' ) &&
current_user_can( 'manage_options' )
) {
if ( !isset($_POST['op']) ) {
print -1;
die();
} else if ($_POST['op'] == 'find' || $_POST['op'] == 'findexact') {
$this->find();
} else if ($_POST['op'] == 'update') {
$this->update();
} else if ($_POST['op'] == 'delete') {
$this->delete();
} else if ($_POST['op'] == 'wipe') {
$this->wipe();
} else if ($_POST['op'] == 'export') {
$this->export();
} else if ($_POST['op'] == 'import') {
$this->import();
}
}
}
private function find() {
$syn = SynonymsManager::getInstance();
$exact = $_POST['op'] == 'findexact';
$limit = $exact == true ? 1 : 30;
if ( isset($_POST['keyword'], $_POST['lang']) )
$ret = $syn->find($_POST['keyword'], $_POST['lang'], $limit, $exact);
else
$ret = -1;
print '!!!ASP_SYN_START!!!';
Ajax::prepareHeaders();
print_r(json_encode($ret));
print '!!!ASP_SYN_END!!!';
die();
}
private function update() {
$syn = SynonymsManager::getInstance();
if ( isset($_POST['keyword'], $_POST['synonyms'], $_POST['lang'], $_POST['overwrite_existing']) )
$ret = $syn->update($_POST['keyword'], $_POST['synonyms'], $_POST['lang'], $_POST['overwrite_existing']);
else
$ret = -1;
Ajax::prepareHeaders();
print
'!!!ASP_SYN_START!!!'.
$ret.
'!!!ASP_SYN_END!!!';
die();
}
private function delete() {
$syn = SynonymsManager::getInstance();
if ( isset($_POST['id']) )
$ret = $syn->deleteByID($_POST['id']);
else
$ret = -1;
Ajax::prepareHeaders();
print
'!!!ASP_SYN_START!!!'.
$ret.
'!!!ASP_SYN_END!!!';
die();
}
private function wipe() {
$syn = SynonymsManager::getInstance();
$syn->wipe();
Ajax::prepareHeaders();
print
'!!!ASP_SYN_START!!!0!!!ASP_SYN_END!!!';
die();
}
private function export() {
$syn = SynonymsManager::getInstance();
Ajax::prepareHeaders();
print
'!!!ASP_SYN_START!!!'.$syn->export().'!!!ASP_SYN_END!!!';
die();
}
private function import() {
$syn = SynonymsManager::getInstance();
if ( !isset($_POST['path']) )
$ret = -1;
else
$ret = $syn->import($_POST['path']);
Ajax::prepareHeaders();
print
'!!!ASP_SYN_START!!!'.$ret.'!!!ASP_SYN_END!!!';
die();
}
}

View File

@@ -0,0 +1,222 @@
<?php /** @noinspection PhpUnused */
namespace WPDRMS\ASP\Hooks;
if (!defined('ABSPATH')) die('-1');
class AjaxManager {
const NAMESPACE = "WPDRMS\\ASP\\Hooks\\Ajax\\";
/**
* Array of internal ajax actions
*
* @var array
*/
private static $actions = array(
"ajaxsearchpro_search" => array(
"handler" => "Search",
"priv" => true,
"nopriv" => true
),
"ajaxsearchpro_autocomplete" => array(
"handler" => "Autocomplete",
"priv" => true,
"nopriv" => true
),
"ajaxsearchpro_addkeyword" => array(
"handler" => "AddKeyword",
"priv" => true,
"nopriv" => true
),
"ajaxsearchpro_preview" => array(
"handler" => "Preview",
"priv" => true,
"nopriv" => false
),
"ajaxsearchpro_precache" => array(
"handler" => "Precache",
"priv" => true,
"nopriv" => false
),
"ajaxsearchpro_priorities" => array(
"handler" => "Priorities",
"priv" => true,
"nopriv" => false
),
"ajaxsearchpro_deletecache" => array(
"handler" => "DeleteCache",
"priv" => true,
"nopriv" => false
),
"ajaxsearchpro_deletekeyword" => array(
"handler" => "DeleteKeyword",
"priv" => true,
"nopriv" => false
),
"asp_indextable_admin_ajax" => array(
"handler" => "IndexTable",
"priv" => true,
"nopriv" => false
),
"asp_indextable_optimize" => array(
"handler" => "IndexTable",
"priv" => true,
"nopriv" => false
),
"asp_indextable_get_stats" => array(
"handler" => "IndexTable",
"priv" => true,
"nopriv" => false
),
"asp_media_service" => array(
"handler" => "MediaService",
"priv" => true,
"nopriv" => false
),
'asp_maintenance_admin_ajax' => array(
"handler" => 'Maintenance',
"priv" => true,
"nopriv" => false
),
"asp_license_ajax" => array(
"handler" => "License",
"priv" => true,
"nopriv" => false
),
"asp_syn_admin_ajax" => array(
"handler" => "Synonyms",
"priv" => true,
"nopriv" => false
)
);
/**
* Array of already registered handlers
*
* @var array
*/
private static $registered = array();
/**
* Registers all the handlers from the $actions variable
*/
public static function registerAll( $custom_ajax = false) {
foreach (self::$actions as $action => $data)
self::register($action, $data['handler'], $data['priv'], $data['nopriv'], $custom_ajax);
}
/**
* Get all the queued handlers
*
* @return array
*/
public static function getAll( ): array {
return array_keys(self::$actions);
}
/**
* Get all the already registered handlers
*
* @return array
*/
public static function getRegistered(): array {
return self::$registered;
}
/**
* Checks if currently a Search Plugin ajax is in progress
*
* @param string $handle
* @return bool
*/
public static function doingAjax(string $handle = "" ): bool {
if (!empty($_POST['action'])) {
if ($handle != "")
return $_POST['action'] == $handle;
return in_array($_POST['action'], self::getAll());
}
return false;
}
/**
* Registers an action with the handler class name.
*
* @param $action
* @param $handler
* @param bool $priv
* @param bool $nopriv
* @param bool $custom_ajax
* @return bool
*/
public static function register($action, $handler, bool $priv = true, bool $nopriv = true, bool $custom_ajax = false): bool {
if ( !$priv && !$nopriv) return false;
$class = self::NAMESPACE . $handler;
$prefix = $custom_ajax == true ? "ASP_" : "wp_ajax_";
if ( !class_exists($class) ) return false;
if ( $priv )
add_action($prefix . $action, array(call_user_func(array($class, 'getInstance')), 'handle'));
if ( $nopriv )
add_action($prefix . 'nopriv_' . $action, array(call_user_func(array($class, 'getInstance')), 'handle'));
self::$registered[] = $action;
return true;
}
/**
* Deregisters an action handler.
*
* @param $action
* @param bool $handler
*/
public static function deregister($action, bool $handler = false ) {
if ( $handler === false ) {
foreach ( self::$actions as $k => $a ) {
if ( $k == $action ) {
remove_action($action, array(call_user_func(array(self::NAMESPACE . $a['handler'], 'getInstance')), 'handle'));
}
}
} else if ( is_string($handler) ) {
remove_action($action, array(call_user_func(array(self::NAMESPACE . $handler, 'getInstance')), 'handle'));
}
}
/**
* Adds an action to the register queue
*
* @param $action
* @param $handler
* @param bool $priv
* @param bool $nopriv
*/
public static function queue($action, $handler, bool $priv = true, bool $nopriv = true) {
self::$actions[$action] = array(
"handler" => $handler,
"priv" => $priv,
"nopriv" => $nopriv
);
}
/**
* Dequeues an action from the register queue.
*
* @param $action
*/
public static function dequeue($action) {
if ( isset(self::$actions[$action]) )
unset(self::$actions[$action]);
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace WPDRMS\ASP\Hooks\Filters;
use WP_Post;
if ( !defined('ABSPATH') ) {
die('-1');
}
/**
* Advanced Custom Fields related Hooks
*/
class ACF extends AbstractFilter {
/**
* @return void
*/
public function handle() {}
/**
* @param array<string, mixed> $values
* @param WP_Post $the_post
* @param string $field
* @return array<string|int, mixed>
*/
public function indexRepeaterAndFlexFields( array $values, WP_Post $the_post, string $field ): array {
if ( function_exists('have_rows') && function_exists( 'the_row') ) {
if ( have_rows($field, $the_post->ID) ) {
while ( have_rows($field, $the_post->ID ) ) {
$row = the_row();
if ( !is_array($row) ) {
continue;
}
foreach ( $row as $sub_field ) {
$values[] = $sub_field;
}
}
}
}
return $values;
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace WPDRMS\ASP\Hooks\Filters;
use WPDRMS\ASP\Patterns\SingletonTrait;
if ( !defined('ABSPATH') ) {
die('-1');
}
abstract class AbstractFilter {
use SingletonTrait;
/**
* The handler
*
* This function is called by the appropriate handler
*/
public function handle() {}
}

View File

@@ -0,0 +1,100 @@
<?php /** @noinspection PhpUnused */
namespace WPDRMS\ASP\Hooks\Filters;
use WPDRMS\ASP\Asset\Manager;
if ( !defined('ABSPATH') ) {
die('-1');
}
class Asset extends AbstractFilter {
/**
* hook: wp_enqueue_scripts
*/
function onPluginFrontendHead() {
Manager::instance()->enqueue();
}
/**
* hook: wp_print_footer_scripts, priority 6
* hook: admin_print_footer_scripts, priority 6
*/
function onPluginFooter() {
Manager::instance()->onPluginFooter();
}
/**
* Classic script enqueue for the plugin backend
*
* hook: admin_print_footer_scripts, priority 7
*/
function onPluginBackendFooter() {
if ( wd_asp()->manager->getContext() == 'backend' ) {
Manager::instance()->onPluginBackendFooter();
}
}
/**
* hook: asp_ob_end
*
* @param $buffer
* @return mixed
*/
function injectToOutputBuffer( $buffer ) {
return Manager::instance()->injectToBuffer($buffer);
}
/**
* Safety check, if the injections were not successful
*
* hook: shutdown (executed after asp_ob_end)
*/
function onShutdown() {
if (
wd_asp()->manager->getContext() == 'frontend' && !wp_is_json_request()
&& !isset($_POST['ags_wc_filters_ajax_shop']) // divi shop live pagination
&& !(
isset($_SERVER['REQUEST_URI']) &&
substr_compare($_SERVER['REQUEST_URI'], '.xml', -strlen('.xml')) === 0
) // Skip for XML document requests
) {
Manager::instance()->printBackup();
}
}
public function applySelectiveAssetLoader( $exit ) {
$comp_settings = wd_asp()->o['asp_compatibility'];
if ( $comp_settings['selective_enabled'] ) {
if ( is_front_page() ) {
if ( $comp_settings['selective_front'] == 0 ) {
$exit = true;
}
} elseif ( is_archive() ) {
if ( $comp_settings['selective_archive'] == 0 ) {
$exit = true;
}
} elseif ( is_singular() ) {
if ( $comp_settings['selective_exin'] != '' ) {
global $post;
if ( isset($post, $post->ID) ) {
$_ids = wpd_comma_separated_to_array($comp_settings['selective_exin']);
if ( !empty($_ids) ) {
if ( $comp_settings['selective_exin_logic'] == 'exclude' && in_array($post->ID, $_ids) ) {
$exit = true;
} elseif ( $comp_settings['selective_exin_logic'] == 'include' && !in_array($post->ID, $_ids) ) {
$exit = true;
}
}
}
}
}
}
return $exit;
}
function handle() {}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace WPDRMS\ASP\Hooks\Filters;
use WPDRMS\ASP\Query\SearchQuery;
use WPDRMS\ASP\Utils\Search;
/**
* GenerateBlocks plugin Query Loop live search and filter compatibility
*/
class BlocksyAdvancedPostsBlock extends AbstractFilter {
/**
* Hooks into: blocksy:general:blocks:query:args
*
* @param array $query
* @param array $attributes
* @return array
*/
public function queryVars( array $query, array $attributes ) {
if ( !isset($_GET['p_asid'], $_GET['unique_id']) ) {
return $query;
}
$query_id = strval($attributes['uniqueId']) ?? '';
if ( $query_id !== '' && strval($_GET['unique_id']) !== $query_id ) {
return $query;
}
$query['asp_override'] = true;
/**
* The $query_args['page'] should not be set as we want the full set
* and the loop will take care of the page.
*/
if ( isset($_GET['asp_force_reset_pagination']) ) {
// For the correct pagination highlight
$query['offset'] = 0;
}
return $query;
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace WPDRMS\ASP\Hooks\Filters;
use WP_Query;
use WPDRMS\ASP\Models\SearchQueryArgs;
use WPDRMS\ASP\Utils\Search;
use WPDRMS\ASP\Utils\WPQueryUtils;
if ( !defined('ABSPATH') ) {
die('-1');
}
/**
* Bricks Query Loop Integration
*/
class BricksQueryLoop extends AbstractFilter {
/**
* Hooks into bricks/posts/query_vars
*/
public function bricksPostsQueryVars( $query_vars, $settings, $element_id, $element_name ) {
$id = Search::overrideSearchId();
if (
$id > 0 &&
isset($settings['_cssClasses']) &&
strpos($settings['_cssClasses'], 'asp_es_' . $id) !== false
) {
if ( isset($_GET['asp_force_reset_pagination']) ) {
// For the correct pagination highlight
$query_vars['paged'] = 1;
}
$query_vars['asp_override'] = true;
}
return $query_vars;
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace WPDRMS\ASP\Hooks\Filters;
use WP_Query;
use WPDRMS\ASP\Models\SearchQueryArgs;
use WPDRMS\ASP\Utils\Search;
if ( !defined('ABSPATH') ) {
die('-1');
}
class Divi extends AbstractFilter {
public function handle() {}
/**
* Handles override for Divi built-in blogs module
*
* @param WP_Query $wp_query
* @param array<string, mixed> $atts
* @return WP_Query
*/
public function blog( WP_Query $wp_query, array $atts = array() ): WP_Query {
$id = Search::overrideSearchId();
if ( !isset($atts['module_class']) || !str_contains('asp_es_' . $id, $atts['module_class']) ) {
return $wp_query;
}
add_filter(
'asp_query_args',
function ( SearchQueryArgs $args ) use ( $wp_query ) {
$args->search_type = array( 'cpt' );
$args->_sd['shortcode_op'] = 'remove';
$args->posts_per_page = $wp_query->query_vars['posts_per_page'] ?? $args->posts_per_page;
return $args;
},
100,
1
);
$wp_query->query_vars['asp_override'] = true;
$wp_query->query_vars['asp_not_archive'] = true;
$wp_query->is_home = false; // This will prevent archive detection
$new_query = SearchOverride::instance()->override(array(), $wp_query, 'wp_query');
return $new_query;
}
/**
* Divi extras blog module
*
* @param array<string, mixed> $args
* @param array<string, mixed> $atts
* @return array<string, mixed>
*/
public function blogExtras( array $args, array $atts = array() ): array {
$id = Search::overrideSearchId();
if ( !isset($atts['module_class']) || !str_contains('asp_es_' . $id, $atts['module_class']) ) {
return $args;
}
$args['asp_override'] = true;
return $args;
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace WPDRMS\ASP\Hooks\Filters;
use WP_Query;
use WPDRMS\ASP\Models\SearchQueryArgs;
use WPDRMS\ASP\Utils\WPQueryUtils;
if ( !defined('ABSPATH') ) {
die('-1');
}
/**
* Advanced Custom Fields related Hooks
*/
class DiviFilterGrid {
private ?WP_Query $wp_query;
public function __construct( ?WP_Query $wp_query ) {
$this->wp_query = $wp_query;
}
/**
* Fixes ordering and other query arguments on Divi Filter Grid
*
* Hook: asp_query_args
*
* @param SearchQueryArgs $args
* @return SearchQueryArgs
*/
public function filterGridQueryArgs( SearchQueryArgs $args ): SearchQueryArgs {
$wp_query = $this->wp_query;
if ( !isset($wp_query, $wp_query->query_vars['dfg_context'], $wp_query->query_vars['asp_override']) ) {
return $args;
}
if ( isset($_POST['module_data']['query_var']['s']) ) {
$args->s = $_POST['module_data']['query_var']['s']; // @phpcs:ignore
}
$args = WPQueryUtils::toASPQueryOrdering($wp_query, $args);
return WPQueryUtils::toASPQueryTaxFilters($wp_query, $args);
}
}

View File

@@ -0,0 +1,145 @@
<?php
namespace WPDRMS\ASP\Hooks\Filters;
use WPDRMS\ASP\Query\SearchQuery;
use WPDRMS\ASP\Utils\Search;
if ( !defined('ABSPATH') ) {
die('-1');
}
class Elementor extends AbstractFilter {
function handle() {}
public function jetListingGridQuery( $args, $obj, $settings ) {
$id = Search::overrideSearchId();
if (
$id > 0 &&
isset($settings['_css_classes']) &&
strpos($settings['_css_classes'], 'asp_es_' . $id) !== false
) {
if ( isset($_GET['asp_force_reset_pagination']) ) {
// For the correct pagination highlight
$args['paged'] = 1;
}
$args['post_type'] = 'asp_override';
}
return $args;
}
/**
* Converts the "query" query type (query builder) to post so the override can apply
*
* @param $source
* @param $settings
* @param $widget
* @return string
*/
public function jetListingGridQueryBuilderToPost( $source, $settings, $widget ) {
$id = Search::overrideSearchId();
if (
$id > 0 &&
isset($settings['_css_classes']) &&
strpos($settings['_css_classes'], 'asp_es_' . $id) !== false
) {
return 'posts';
}
return $source;
}
/**
* Posts and Loop Grid widget Support
*
* @param $args
* @param $widget
* @return array|mixed
*/
public function posts( $args = array(), $widget = array() ) {
$id = Search::overrideSearchId();
$data = $widget->get_data();
if (
$id > 0 &&
isset($data['settings']['_css_classes']) &&
strpos($data['settings']['_css_classes'], 'asp_es_' . $id) !== false
) {
if ( isset($_GET['asp_force_reset_pagination']) ) {
// For the correct pagination highlight
$args['paged'] = 1;
}
$args['post_type'] = 'asp_override';
$args['is_elementor'] = true;
}
return $args;
}
public function posts_archive( $args = array() ) {
$id = Search::overrideSearchId();
if ( $id > 0 ) {
if ( isset($_GET['asp_force_reset_pagination']) ) {
// For the correct pagination highlight
$args['paged'] = 1;
}
$args['post_type'] = is_array($args['post_type']) ? $args['post_type'] : array($args['post_type']);
$args['post_type'][] = 'asp_override';
}
return $args;
}
/** @noinspection PhpUnusedParameterInspection */
public function products( $args = array(), $atts = array(), $type = '' ) {
$id = Search::overrideSearchId();
if ( $id > 0 ) {
$instance = wd_asp()->instances->get($id);
$sd = $instance['data'];
if ( isset($sd['customtypes']) ) {
$post_type = in_array('product_variation', $sd['customtypes']) ? array( 'product', 'product_variation' ) : array( 'product' );
} else {
$post_type = array( 'product' );
}
$ids = array();
$phrase = $_GET['asp_ls'] ?? $_GET['s'];
$search_args = array(
's' => $phrase,
'_ajax_search' => false,
'post_type' => $post_type,
'search_type' => array( 'cpt' ),
// Do not recommend going over that, as the post__in argument will generate a
// too long query to complete, as well as Elementor processes all of these
// results, yielding a terrible loading time.
'posts_per_page' =>500,
);
add_filter('asp_query_args', array( SearchOverride::getInstance(), 'getAdditionalArgs' ));
if ( isset($_GET['asp_force_reset_pagination']) ) {
// For the correct pagination highlight
$search_args['page'] = 1;
}
$options = Search::getOptions();
if ( $options === false || count($options) == 0 ) {
$asp_query = new SearchQuery($search_args, $id);
} else {
$asp_query = new SearchQuery($search_args, $id, $options);
}
foreach ( $asp_query->posts as $r ) {
$ids[] = $r->ID;
}
if ( count($ids) > 0 ) {
$args['post__in'] = $ids;
} else {
$args['post__in'] = array( -1 );
echo Search::generateHTMLResults(array(), false, $id, $phrase, 'elementor');
}
$args['orderby'] = 'post__in';
}
return $args;
}
}

View File

@@ -0,0 +1,219 @@
<?php
/** @noinspection PhpUnusedParameterInspection */
/** @noinspection PhpMissingReturnTypeInspection */
/** @noinspection PhpUnused */
namespace WPDRMS\ASP\Hooks\Filters;
use WPDRMS\ASP\NavMenu\Controller;
use WPDRMS\ASP\Utils\Html;
if ( !defined('ABSPATH') ) {
die('-1');
}
/**
* @phpstan-import-type WP_Menu_Item from Controller
*/
class EtcFixes extends AbstractFilter {
protected static $diviElementsLoaded = false;
function handle() {}
/**
* Fix for the Download Monitor plugin download urls
*
* @param $results
* @return mixed
*/
function plug_DownloadMonitorLink( $results ) {
if ( class_exists('\\DLM_Download') ) {
foreach ( $results as $r ) {
if ( $r->post_type == 'dlm_download' ) {
$dl = new \DLM_Download($r->id);
if ( $dl->exists() ) {
$r->link = $dl->get_the_download_link();
}
}
}
}
return $results;
}
/**
* Executes search shortcodes when placed as menu titles
*
* @deprecated 4.27 This handler will be moved to \WPDRMS\ASP\NavMenu\Controller::handleMenuOutput()
* @see \WPDRMS\ASP\NavMenu\Controller::handleMenuOutput()
* @param WP_Menu_Item[] $menu_items
* @return WP_Menu_Item[]
*/
public function allowShortcodeInMenus( array $menu_items ): array {
foreach ( $menu_items as $menu_item ) {
if (
strpos($menu_item->title, '[wd_asp') !== false ||
strpos($menu_item->title, '[wd_asl') !== false ||
strpos($menu_item->title, '[wpdreams_') !== false
) {
$menu_item->title = do_shortcode($menu_item->title);
$menu_item->url = '';
}
}
return $menu_items;
}
/**
* Adds the 'Standard' post format virtual term to the filter list
*/
function fixPostFormatStandard( $terms, $taxonomy, $args, $needed_all ) {
if (
$taxonomy == 'post_format' && !is_wp_error($terms) &&
( $needed_all || in_array(-200, $args['include_ids']) )
) {
$std_term = new \stdClass();
$std_term->term_id = -200;
$std_term->taxonomy = 'post_format';
$std_term->children = array();
$std_term->name = asp_icl_t('Post format: Standard', 'Standard');
$std_term->label = asp_icl_t('Post format: Standard', 'Standard');
$std_term->parent = 0;
$std_term = apply_filters('asp_post_format_standard', $std_term);
array_unshift($terms, $std_term);
}
return $terms;
}
/**
* Fixes the 'Standard' post format filter back-end
*/
function fixPostFormatStandardArgs( $args ) {
if ( isset($args['post_tax_filter']) && is_array($args['post_tax_filter']) ) {
foreach ( $args['post_tax_filter'] as $v ) {
if ( $v['taxonomy'] == 'post_format' ) {
if ( isset($v['_termset']) && in_array(-200, $v['_termset']) && !in_array(-200, $v['exclude']) ) {
// Case 1: Checkbox, not unselected, but displayed
$v['allow_empty'] = 1;
} elseif ( in_array(-200, $v['exclude']) ) {
// Case 2: 'Standard' unchecked
$v['allow_empty'] = 0;
} elseif ( in_array(-200, $v['include']) && count($v['include']) == 1 ) {
// Case 3: Non-checkbox, and 'Standard' selected.
$v['allow_empty'] = 1;
} elseif ( isset($v['_is_checkbox']) && !$v['_is_checkbox'] && !in_array(-200, $v['include']) ) {
$v['allow_empty'] = 0;
}
}
}
}
return $args;
}
/**
* Fix for the Oxygen builder plugin editor error console
*/
function fixOxygenEditorJS( $exit ) {
if ( isset($_GET['ct_builder']) ) {
return true;
}
return false;
}
/**
* Remove extra line breaks from within HTML tags
*/
function optimizeHTML( $output ) {
return Html::optimize($output);
}
/**
* Fix images on multisite installation results pages with search override
*
* @param $image
* @param $attachment_id
* @param $size
* @param $icon
* @return array
*/
function multisiteImageFix( $image, $attachment_id, $size, $icon ) {
if (
defined('ASP_MULTISITE_IMAGE_FIX') &&
is_multisite() &&
!empty( get_asp_result_field('image') )
) {
return array( get_asp_result_field('image'), 300, 300, true );
} else {
return $image;
}
}
function allow_json_mime_type( $mimes ) {
$mimes['json'] = 'application/json';
return $mimes;
}
function http_request_host_is_external_filter( $allow, $host, $url ) {
return ( false !== strpos( $host, 'wp-dreams' ) ) ? true : $allow;
}
function http_request_args( $args, $url ) {
// If it is a https request, and we are performing a package download, disable ssl verification.
if ( strpos( $url, 'update.wp-dreams.com' ) ) {
$args['sslverify'] = false;
$args['reject_unsafe_urls'] = false;
}
return $args;
}
public function breakdanceFixShortcodeInEditor( $include_styles ) {
return isset($_GET['_breakdance_doing_ajax']) ? 1 : $include_styles;
}
public function diviBuilderReady() {
self::$diviElementsLoaded = true;
}
/**
* Init DIVI builder modules for index table save process on the front-end divi editor screen
*/
function diviInitModules( $content ) {
if ( !self::$diviElementsLoaded && function_exists('et_builder_add_main_elements') ) {
if (
( isset($_POST['action']) && $_POST['action'] == 'et_fb_ajax_save' )
) {
self::$diviElementsLoaded = true;
et_builder_add_main_elements();
}
}
return $content;
}
/**
* Init DIVI builder modules for index table ajax process
*/
function diviInitModulesOnAjax( $actions ) {
$actions[] = 'asp_indextable_admin_ajax';
return $actions;
}
/**
* gTranslate plugin auto-translation trigger by changing the ajax headers conten-type
*
* @param string $content_type
* @return string
*/
public function gTranslateAjaxHeaders( string $content_type ): string {
// GTranslate +
if (
isset($_SERVER['HTTP_X_GT_LANG']) &&
!empty(isset($_SERVER['HTTP_X_GT_LANG'])) &&
wd_asp()->manager->getContext() === 'ajax'
) {
return 'text/html';
}
return $content_type;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace WPDRMS\ASP\Hooks\Filters;
if (!defined('ABSPATH')) die('-1');
class FormOverride extends AbstractFilter {
public function handle( $form = "" ) {
$asp_st_override = get_option("asp_st_override", -1);
if ( $asp_st_override > -1 && wd_asp()->instances->exists( $asp_st_override ) ) {
$new_form = do_shortcode("[wpdreams_ajaxsearchpro id=".$asp_st_override."]");
if (strlen($new_form) > 100)
return $new_form;
else
return $form;
}
return $form;
}
}

View File

@@ -0,0 +1,128 @@
<?php
namespace WPDRMS\ASP\Hooks\Filters;
use WPDRMS\ASP\Query\SearchQuery;
use WPDRMS\ASP\Utils\Search;
/**
* GenerateBlocks plugin Query Loop live search and filter compatibility
*/
class GenerateBlocksQueryBlock extends AbstractFilter {
/**
* Cache for POST ids for each query block
*
* This is needed because in case of pagination the search query should not execute twice
*
* @var array<int, int[]>
*/
private array $cached_results = array();
/**
* Adds a custom 'isDecorative' attribute to all Image blocks.
*
* @param array $args The block arguments for the registered block type.
* @param string $block_type The block type name, including namespace.
* @return array The modified block arguments.
*/
public function addAttributes( $args, $block_type ) {
if ( $block_type === 'generateblocks/query' ) {
if ( !isset( $args['attributes'] ) ) {
$args['attributes'] = array();
}
if ( !isset( $args['provides_context'] ) ) {
$args['provides_context'] = array();
}
$args['attributes']['asp_override_id'] = array(
'type' => 'integer',
'default' => 0,
);
// To pass the attribute down as context variable
$args['provides_context']['asp_override_id'] = 'asp_override_id';
}
/**
* This will make sure that the $block->context['asp_override_id']
* exists on child blocks within the Query Loop and all pagination blocks.
*/
if ( $block_type === 'generateblocks/looper'
|| str_starts_with($block_type, 'generateblocks/query-page-numbers')
|| str_starts_with($block_type, 'generateblocks/query-no-results')
) {
if ( !isset( $args['uses_context'] ) ) {
$args['uses_context'] = array();
}
$args['uses_context'][] = 'asp_override_id';
}
return $args;
}
/**
* Hooks into: generateblocks_query_wp_query_args
*
* @param array $query
* @param array $attributes
* @return array
*/
public function queryVars( array $query, array $attributes ) {
if ( !isset($_GET['p_asid'], $attributes['asp_override_id']) ) {
return $query;
}
if ( intval($_GET['p_asid']) === intval($attributes['asp_override_id']) ) {
$query_id = intval($attributes['uniqueId']) ?? 0;
if ( $query_id > 0 && isset($this->cached_results[ $query_id ]) ) {
$query['orderby'] = 'post__in';
$query['post__in'] = $this->cached_results[ $query_id ];
return $query;
}
$id = intval($_GET['p_asid']);
$query['asp_override'] = false;
$page = isset($_GET[ "query-$query_id-page" ]) ? intval($_GET[ "query-$query_id-page" ]) : 1;
$phrase = $_GET['asp_ls'] ?? $_GET['s'] ?? $wp_query->query_vars['s'] ?? '';
$ids = array();
$search_args = array(
's' => $phrase,
'_ajax_search' => false,
'search_type' => array( 'cpt' ),
// Do not recommend going over that, as the post__in argument will generate a
// too long query to complete, as well as Elementor processes all of these
// results, yielding a terrible loading time.
'posts_per_page' => 500,
);
add_filter('asp_query_args', array( SearchOverride::getInstance(), 'getAdditionalArgs' ));
/**
* The $query_args['page'] should not be set as we want the full set
* and the loop will take care of the page.
*/
if ( isset($_GET['asp_force_reset_pagination']) ) {
// For the correct pagination highlight
$query['offset'] = 0;
}
$options = Search::getOptions();
if ( $options === false || count($options) === 0 ) {
$asp_query = new SearchQuery($search_args, $id);
} else {
$asp_query = new SearchQuery($search_args, $id, $options);
}
foreach ( $asp_query->posts as $r ) {
$ids[] = $r->ID;
}
if ( count($ids) > 0 ) {
$query['post__in'] = $ids;
$query['orderby'] = 'post__in';
$this->cached_results[ $query_id ] = $query['post__in'];
} else {
$query['post_type'] = '____non_existent';
}
}
return $query;
}
}

View File

@@ -0,0 +1,27 @@
<?php /** @noinspection PhpMissingReturnTypeInspection */
namespace WPDRMS\ASP\Hooks\Filters;
use WPDRMS\ASP\Utils\Polylang\StringTranslations as PolylangStringTranslations;
if (!defined('ABSPATH')) die('-1');
class IclTranslations extends AbstractFilter {
function handle() {}
/**
* Registered to: apply_filters("asp_query_args", $args, $search_id, $options);
* @noinspection PhpUnused
*/
public function aspQueryArgsTranslations($args, $search_id) {
PolylangStringTranslations::init();
if ( $args['_ajax_search'] && isset($args["_sd"]['advtitlefield'] ) ) {
$args["_sd"]['advtitlefield'] = asp_icl_t("Advanced Title Field for Post Type ($search_id)", $args["_sd"]['advtitlefield']);
$args["_sd"]['user_search_advanced_title_field'] = asp_icl_t("Advanced Title Field for Users ($search_id)", $args["_sd"]['user_search_advanced_title_field']);
$args["_sd"]['advdescriptionfield'] = asp_icl_t("Advanced Content Field for Post Type ($search_id)", $args["_sd"]['advdescriptionfield']);
$args["_sd"]['user_search_advanced_description_field'] = asp_icl_t("Advanced Content Field for Users ($search_id)", $args["_sd"]['user_search_advanced_description_field']);
}
PolylangStringTranslations::save();
return $args;
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace WPDRMS\ASP\Hooks\Filters;
class JsCompatibility extends AbstractFilter {
public function handle() {
// TODO: Implement handle() method.
}
/**
* Rocket WP js exclude
*
* @param mixed $handles
* @return mixed
*/
public function rocket_exclude_js( $handles ) {
$rules = array(
'/asp/asp-(.*).js',
'/ajax-search-pro/(.*)/asp-(.*).js',
);
if ( is_null($handles) ) {
return $rules;
}
if ( is_array($handles) ) {
return array_merge($handles, $rules);
}
return $handles;
}
/**
* Rocket WP inline js exclude by content match
*
* @param mixed $handles
* @return mixed
*/
public function rocket_excluded_inline_js_content( $handles ) {
$rules = array(
'ajax-search-pro',
);
if ( is_null($handles) ) {
return $rules;
}
if ( is_array($handles) ) {
return array_merge($handles, $rules);
}
return $handles;
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace WPDRMS\ASP\Hooks\Filters;
if (!defined('ABSPATH')) die('-1');
class MediaScreen extends AbstractFilter {
public function handle( $form_fields = array(), $post = null ) {
$field_value = get_post_meta( $post->ID, '_asp_attachment_text', true );
if ( $field_value !== '' ) {
$form_fields['asp_attachment_text'] = array(
'value' => $field_value,
'label' => __( 'Content (not editable)' ),
'helps' => __( 'Parsed content by Ajax Search Pro Media Parser service' ),
'input' => 'textarea'
);
}
return $form_fields;
}
}

View File

@@ -0,0 +1,117 @@
<?php
namespace WPDRMS\ASP\Hooks\Filters;
use WP_Block;
use WPDRMS\ASP\Query\SearchQuery;
use WPDRMS\ASP\Utils\Search;
class QueryLoopBlock extends AbstractFilter {
/**
* Cache for POST ids for each query block
*
* This is needed because in case of pagination the search query should not execute twice
*
* @var array<int, int[]>
*/
private array $cached_results = array();
/**
* Adds a custom 'isDecorative' attribute to all Image blocks.
*
* @param array $args The block arguments for the registered block type.
* @param string $block_type The block type name, including namespace.
* @return array The modified block arguments.
*/
public function addAttributes( $args, $block_type ) {
if ( $block_type === 'core/query' ) {
if ( !isset( $args['attributes'] ) ) {
$args['attributes'] = array();
}
if ( !isset( $args['provides_context'] ) ) {
$args['provides_context'] = array();
}
$args['attributes']['asp_override_id'] = array(
'type' => 'integer',
'default' => 0,
);
// To pass the attribute down as context variable
$args['provides_context']['asp_override_id'] = 'asp_override_id';
}
/**
* This will make sure that the $block->context['asp_override_id']
* exists on child blocks within the Query Loop and all pagination blocks.
*/
if ( $block_type === 'core/post-template'
|| str_starts_with($block_type, 'core/query-pagination')
|| str_starts_with($block_type, 'core/query-no-results')
) {
if ( !isset( $args['uses_context'] ) ) {
$args['uses_context'] = array();
}
$args['uses_context'][] = 'asp_override_id';
}
return $args;
}
public function queryVars( array $query, WP_Block $block, int $page ) {
if ( !isset($_GET['p_asid'], $block->context['asp_override_id']) ) {
return $query;
}
if ( intval($_GET['p_asid']) === intval($block->context['asp_override_id']) ) {
$query_id = intval($block->context['queryId']) ?? 0;
if ( $query_id > 0 && isset($this->cached_results[ $query_id ]) ) {
$query['orderby'] = 'post__in';
$query['post__in'] = $this->cached_results[ $query_id ];
return $query;
}
$id = intval($_GET['p_asid']);
$query['asp_override'] = false;
$page = isset($_GET[ "query-$query_id-page" ]) ? intval($_GET[ "query-$query_id-page" ]) : 1;
$phrase = $_GET['asp_ls'] ?? $_GET['s'] ?? $wp_query->query_vars['s'] ?? '';
$ids = array();
$search_args = array(
's' => $phrase,
'_ajax_search' => false,
'search_type' => array( 'cpt' ),
// Do not recommend going over that, as the post__in argument will generate a
// too long query to complete, as well as Elementor processes all of these
// results, yielding a terrible loading time.
'posts_per_page' => 1000,
);
add_filter('asp_query_args', array( SearchOverride::getInstance(), 'getAdditionalArgs' ));
/**
* The $query_args['page'] should not be set as we want the full set
* and the loop will take care of the page.
*/
if ( isset($_GET['asp_force_reset_pagination']) ) {
// For the correct pagination highlight
$query['offset'] = 0;
}
$options = Search::getOptions();
if ( $options === false || count($options) == 0 ) {
$asp_query = new SearchQuery($search_args, $id);
} else {
$asp_query = new SearchQuery($search_args, $id, $options);
}
foreach ( $asp_query->posts as $r ) {
$ids[] = $r->ID;
}
if ( count($ids) > 0 ) {
$query['post__in'] = $ids;
$query['orderby'] = 'post__in';
$this->cached_results[ $query_id ] = $query['post__in'];
} else {
$query['post_type'] = '____non_existent';
}
}
return $query;
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace WPDRMS\ASP\Hooks\Filters;
use WPDRMS\ASP\Models\SearchQueryArgs;
if ( !defined('ABSPATH') ) {
die('-1');
}
/**
* Makes Search Exclude plugin exclusions compatible with Ajax Search Lite
*
* @see https://wordpress.org/plugins/search-exclude/
*/
class SearchExclude extends AbstractFilter {
/**
* @param SearchQueryArgs $args
* @return SearchQueryArgs
*/
public function handleExclusions( SearchQueryArgs $args ): SearchQueryArgs {
if ( class_exists('\QuadLayers\QLSE\Models\Settings') ) {
/** @noinspection All */
$excluded = \QuadLayers\QLSE\Models\Settings::instance()->get();
if ( ! isset( $excluded ) ) {
return $args;
}
/**
* Exclude posts by post type
*/
if ( isset( $excluded->entries ) ) {
$post__not_in = array();
foreach ( $excluded->entries as $post_type => $excluded_post_type ) {
$post_type_ids = ! empty( $excluded_post_type['all'] ) ? $this->getAllPostTypeIds( $post_type ) : $excluded_post_type['ids'];
$post__not_in = array_merge( $post__not_in, $post_type_ids );
}
$args->post_not_in = array_unique( array_merge( $args->post_not_in, $post__not_in ) );
}
}
return $args;
}
/**
* @param string $post_type
* @return int[]
*/
private function getAllPostTypeIds( string $post_type ): array {
// @phpstan-ignore-next-line
return get_posts(
array(
'post_type' => $post_type,
'posts_per_page' => -1,
'fields' => 'ids',
)
);
}
}

View File

@@ -0,0 +1,576 @@
<?php
/** @noinspection PhpMissingReturnTypeInspection */
/** @noinspection RegExpSingleCharAlternation */
namespace WPDRMS\ASP\Hooks\Filters;
use WP_Post;
use WP_Query;
use WPDRMS\ASP\Query\SearchQuery;
use WPDRMS\ASP\Utils\Archive;
use WPDRMS\ASP\Utils\Search;
use WPDRMS\ASP\Utils\WooCommerce;
if ( !defined('ABSPATH') ) {
die('-1');
}
class SearchOverride extends AbstractFilter {
public static $overrideCount = 0;
public function handle() {}
/**
* Checks and cancels the original search query made by WordPress, if required
*
* @param string $request - The SQL query
* @param WP_Query $wp_query - The instance of WP_Query() for this query
* @return string
* @noinspection PhpUnused
*/
public function maybeCancelWPQuery( string $request, WP_Query $wp_query ) {
// is_home check is needed for the blog/home page filtering, query reset will break it
if ( $this->checkSearchOverride(true, $wp_query) === true && !$wp_query->is_home ) {
$request = '';
}
return $request;
}
/**
* Overrides the $posts object array with the results from Ajax Search Pro
*
* @param mixed $posts array of posts
* @param null|WP_Query $wp_query The instance of WP_Query() for this query
* @param 'posts'|'wp_query' $return_as to return the $posts or the modified $wp_query
* @return ($return_as is 'posts' ? WP_Post[] : WP_Query)
*/
public function override( $posts, ?WP_Query $wp_query, string $return_as = 'posts' ) {
$check_override = $this->checkSearchOverride(false, $wp_query);
if ( $check_override === false ) {
return $posts;
} else {
$_p_id = $check_override[0];
$s_data = $check_override[1];
}
// The get_query_var() is malfunctioning in some cases!!! use $_GET['paged']
// $paged = (get_query_var('paged') != 0) ? get_query_var('paged') : 1;
if ( isset($_GET['asp_force_reset_pagination']) ) {
// For the correct pagination highlight
$_GET['paged'] = 1;
$paged = 1;
set_query_var('paged', 1);
set_query_var('page', 1);
} else {
$paged = $_GET['paged'] ?? $wp_query->query_vars['paged'] ?? 1;
}
if ( !wd_asp()->instances->exists($_p_id) ) {
return $posts;
}
$instance = wd_asp()->instances->get($_p_id);
$sd = $instance['data'];
// First check the asp_ls, as s might be set already
$phrase = $_GET['asp_ls'] ?? $_GET['s'] ?? $wp_query->query_vars['s'] ?? '';
$paged = $paged <= 0 ? 1 : $paged;
// Elementor related
if (
isset($wp_query->query_vars, $wp_query->query_vars['posts_per_page']) &&
$this->queryVarsHasAspOverridePostType($wp_query)
) {
$posts_per_page = $wp_query->query_vars['posts_per_page'];
} else {
$posts_per_page = $sd['results_per_page'];
}
if ( $posts_per_page === 'auto' ) {
if ( isset($wp_query->query_vars, $wp_query->query_vars['posts_per_page']) ) {
$posts_per_page = $wp_query->query_vars['posts_per_page'];
} else {
$posts_per_page = get_option( 'posts_per_page' );
}
}
$posts_per_page = intval($posts_per_page);
$posts_per_page = $posts_per_page === 0 ? 1 : $posts_per_page;
$s_data = apply_filters('asp_search_override_data', $s_data, $posts, $wp_query, $_p_id, $phrase);
// A possible exit point for the user, if he sets the _abort argument
if ( isset($s_data['_abort']) ) {
return $posts;
}
$args = array(
's' => $phrase,
'_ajax_search' => false,
'posts_per_page' => $posts_per_page,
'page' => $paged,
);
// $args = self::getAdditionalArgs($args);
add_filter('asp_query_args', array( $this, 'getAdditionalArgs' ));
add_filter('asp_query_args', array( new DiviFilterGrid($wp_query), 'filterGridQueryArgs' ), 99, 1);
if ( count($s_data) === 0 ) {
$asp_query = new SearchQuery($args, $_p_id);
} else {
$asp_query = new SearchQuery($args, $_p_id, $s_data);
}
$res = $asp_query->posts;
if ( $sd['result_suggestions_results_page'] && count($res) === 0 ) {
$asp_query->resultsSuggestions();
$res = $asp_query->posts;
}
do_action('asp_after_search', $phrase, $res, $_p_id);
// Elementor Posts widget no results text
if (
count($res) === 0 &&
isset($wp_query->query_vars, $wp_query->query_vars['is_elementor'])
) {
echo Search::generateHTMLResults(array(), false, $_p_id, $phrase, 'elementor');
}
$wp_query->query_vars['post__in'] = $wp_query->query_vars['post__in'] ?? array();
if ( is_array($wp_query->query_vars['post__in']) ) {
$wp_query->query_vars['post__in'] = array_unique(
array_merge(
$wp_query->query_vars['post__in'],
array_map(
function ( $aspr ) {
return $aspr->id;
},
$asp_query->all_results
)
)
);
$wp_query->query_vars['orderby'] = 'post__in';
}
if ( isset($wp_query->posts) ) {
$wp_query->posts = $res;
}
$wp_query->post_count = count($res);
/**
* Reset post type
* Very important. Some archive posts modules fail because asp_override is non-existent.
*/
if ( empty($wp_query->query_vars['post_type']) || $this->queryVarsHasAspOverridePostType( $wp_query ) ) {
$wp_query->query_vars['post_type'] = $asp_query->args->post_type;
}
$wp_query->found_posts = $asp_query->found_posts;
if ( ( $wp_query->found_posts / $posts_per_page ) > 1 ) {
$wp_query->max_num_pages = intval(ceil($wp_query->found_posts / $posts_per_page));
} else {
$wp_query->max_num_pages = 1;
}
$res = apply_filters('asp/search/override/results', $res, $posts, $wp_query, $asp_query);
$wp_query = apply_filters('asp/search/override/wp_query', $wp_query, $res, $posts, $asp_query);
++self::$overrideCount;
if ( $return_as === 'posts' ) {
return $res;
} else {
return $wp_query;
}
}
/**
* Checks and gets additional arguments for the override query
*
* @param $args - query arguments for the SearchQuery()
*/
public static function getAdditionalArgs( $args ) {
global $wpdb, $wp_query;
// WooCommerce price filter
if ( isset($_GET['min_price'], $_GET['max_price']) ) {
$args['post_meta_filter'][] = array(
'key' => '_price', // meta key
'value' => array( floatval($_GET['min_price']), floatval($_GET['max_price']) ),
'operator' => 'BETWEEN',
);
}
// WooCommerce or other custom Ordering
if ( isset($_GET['orderby']) || isset($_GET['product_orderby']) ) {
$o_by = $_GET['orderby'] ?? $_GET['product_orderby'];
$o_by = str_replace(' ', '', ( strtolower($o_by) ));
if ( isset($_GET['order']) || isset($_GET['product_order']) ) {
$o_way = $_GET['order'] ?? $_GET['product_order'];
} elseif ( $o_by == 'price' || $o_by == 'product_price' ) {
$o_way = 'ASC';
} elseif ( $o_by == 'alphabetical' ) {
$o_way = 'ASC';
} else {
$o_way = 'DESC';
}
$o_way = strtoupper($o_way);
if ( $o_way != 'DESC' && $o_way != 'ASC' ) {
$o_way = 'DESC';
}
switch ( $o_by ) {
case 'id':
case 'post_id':
case 'product_id':
$args['post_primary_order'] = "id $o_way";
break;
case 'popularity':
case 'post_popularity':
case 'product_popularity':
$args['post_primary_order'] = "customfp $o_way";
$args['post_primary_order_metatype'] = 'numeric';
$args['_post_primary_order_metakey'] = 'total_sales';
break;
case 'rating':
case 'post_rating':
case 'product_rating':
// Custom query args here
$args['cpt_query']['fields'] = "(
SELECT
IF(AVG( $wpdb->commentmeta.meta_value ) IS NULL, 0, AVG( $wpdb->commentmeta.meta_value ))
FROM
$wpdb->comments
LEFT JOIN $wpdb->commentmeta ON($wpdb->comments.comment_ID = $wpdb->commentmeta.comment_id)
WHERE
$wpdb->posts.ID = $wpdb->comments.comment_post_ID
AND ( $wpdb->commentmeta.meta_key = 'rating' OR $wpdb->commentmeta.meta_key IS null )
) as average_rating, ";
$args['cpt_query']['orderby'] = "average_rating $o_way, ";
// Force different field order for index table
$args['post_primary_order'] = "average_rating $o_way";
break;
case 'date':
case 'post_date':
case 'product_date':
$args['post_primary_order'] = "post_date $o_way";
break;
case 'name':
case 'post_name':
case 'product_name':
case 'alphabetical':
case 'reverse_alpha':
case 'reverse_alphabetical':
$args['post_primary_order'] = "post_title $o_way";
break;
case 'price':
case 'product_price':
case 'price-desc':
$args['post_primary_order'] = "customfp $o_way";
$args['post_primary_order_metatype'] = 'numeric';
$args['_post_primary_order_metakey'] = '_price';
break;
case 'relevance':
$args['post_primary_order'] = "relevance $o_way";
break;
}
}
if ( isset($_GET['post_type']) && $_GET['post_type'] == 'product' ) {
$args['search_type'] = array( 'cpt' );
$old_ptype = $args['post_type'];
$args['post_type'] = array();
if ( in_array('product', $old_ptype) ) {
$args['post_type'][] = 'product';
}
if ( in_array('product_variation', $old_ptype) ) {
$args['post_type'][] = 'product_variation';
}
// Exclude from search products
$visibility_term = get_term_by('slug', 'exclude-from-search', 'product_visibility');
if ( $visibility_term !== false ) {
$found = false;
if ( isset($args['post_tax_filter']) ) {
foreach ( $args['post_tax_filter'] as &$filter ) {
if ( $filter['taxonomy'] == 'product_visibility' ) {
$filter['exclude'] = $filter['exclude'] ?? array();
$filter['exclude'] = array_merge($filter['exclude'], array( $visibility_term->term_id ));
$found = true;
break;
}
}
}
if ( !$found ) {
$args['post_tax_filter'][] = array(
'taxonomy' => 'product_visibility',
'include' => array(),
'exclude' => array( $visibility_term->term_id ),
'allow_empty' => true,
);
}
}
}
// Archive pages
if ( isset($_GET['asp_ls']) && !isset($wp_query->query_vars['asp_not_archive']) ) {
if ( WooCommerce::isShop() ) {
$args['search_type'] = array( 'cpt' );
// Only allow product or product variations if selected
$args['post_type'] = in_array('product_variation', $args['post_type']) ? array( 'product', 'product_variation' ) : array( 'product' );
// Exclude from catalog products
$visibility_term = get_term_by('slug', 'exclude-from-search', 'product_visibility');
$catalog_term = get_term_by('slug', 'exclude-from-catalog', 'product_visibility');
if ( $visibility_term !== false && $catalog_term !== false ) {
$found = false;
if ( isset($args['post_tax_filter']) ) {
foreach ( $args['post_tax_filter'] as &$filter ) {
if ( $filter['taxonomy'] == 'product_visibility' ) {
$filter['exclude'] = $filter['exclude'] ?? array();
$filter['exclude'] = array_merge(
$filter['exclude'],
array(
$visibility_term->term_id,
$catalog_term->term_id,
)
);
$found = true;
break;
}
}
}
if ( !$found ) {
$args['post_tax_filter'][] = array(
'taxonomy' => 'product_visibility',
'include' => array(),
'exclude' => array(
$visibility_term->term_id,
$catalog_term->term_id,
),
'allow_empty' => true,
);
}
}
} elseif ( Archive::isTaxonomyArchive() ) {
$args['search_type'] = array( 'cpt' );
$found = false;
$children = get_term_children(get_queried_object()->term_id, get_queried_object()->taxonomy);
$include = !is_wp_error($children) ? array_merge(array( get_queried_object()->term_id ), $children) : array( get_queried_object()->term_id );
if ( isset($args['post_tax_filter']) ) {
foreach ( $args['post_tax_filter'] as &$filter ) {
if ( $filter['taxonomy'] == get_queried_object()->taxonomy ) {
$filter['include'] = array_diff($include, $filter['exclude']);
$found = true;
break;
}
}
}
if ( !$found ) {
$args['post_tax_filter'][] = array(
'taxonomy' => get_queried_object()->taxonomy,
'include' => $include,
'exclude' => array(),
'allow_empty' => true,
);
}
} elseif ( Archive::isPostTypeArchive() ) {
$args['search_type'] = array( 'cpt' );
$post_type = $wp_query->get( 'post_type' );
$args['post_type'] = $post_type == '' ? array( 'post' ) : array( $post_type );
}
}
return $args;
}
/**
* Checks if the default WordPress search query is executed right now, and if it needs an override.
* Also sets some cookie and request variables, if needed.
*
* @param bool $check_only - when true, only checks if the override should be initiated, no variable changes
* @param null|WP_Query $wp_query - The instance of WP_Query() for this query
* @return array|bool
*/
public function checkSearchOverride( bool $check_only, ?WP_Query $wp_query ) {
// Check the search query
if ( !$this->isSearch($wp_query) ) {
return false;
}
// If you get method is used, then the cookies are not present or not used
if ( isset($_GET['p_asp_data']) ) {
if ( $check_only ) {
return true;
}
$_p_id = $_GET['p_asid'] ?? $_GET['np_asid'];
if ( $_GET['p_asp_data'] == 1 ) {
$s_data = $_GET;
} else {
// Legacy support
parse_str(base64_decode($_GET['p_asp_data']), $s_data);
}
} elseif (
isset($_GET['s'], $_COOKIE['asp_data']) && (
( $_GET['s'] != '' && isset($_COOKIE['asp_phrase']) && $_COOKIE['asp_phrase'] == $_GET['s'] ) ||
( $_GET['s'] == '' )
)
) {
if ( $check_only ) {
return true;
}
parse_str($_COOKIE['asp_data'], $s_data);
$_POST['np_asp_data'] = $_COOKIE['asp_data'];
$_POST['np_asid'] = $_COOKIE['asp_id'];
$_p_id = $_COOKIE['asp_id'];
} elseif (
isset($wp_query, $wp_query->query_vars['asp_id'])
) {
if ( $check_only ) {
return true;
}
$_p_id = $wp_query->query_vars['asp_id'];
$s_data = array();
} else {
// Probably the search results page visited via URL, not triggered via search bar
if ( isset($_GET['post_type']) && $_GET['post_type'] == 'product' ) {
$override_id = get_option('asp_woo_override', -1);
} else {
$override_id = get_option('asp_st_override', -1);
}
if ( $override_id > -1 && wd_asp()->instances->exists( $override_id ) ) {
$inst = wd_asp()->instances->get( $override_id );
if ( $inst['data']['override_default_results'] == 1 ) {
return array( $override_id, array() );
}
}
// Something is not right
return false;
}
return array( $_p_id, $s_data );
}
public function isSearch( ?WP_Query $wp_query ): bool {
$is_search = true;
$soft_check =
defined('ELEMENTOR_VERSION') || // Elementor
defined( 'ET_CORE' ) || // Divi
wd_asp()->o['asp_compatibility']['query_soft_check'];
// This can't be a search query if none of this is set
if ( !isset($wp_query, $wp_query->query_vars, $_GET['s']) ) {
$is_search = false;
} else {
// Possible candidates for search below
if ( $soft_check ) {
// In soft check mode, it does not have to be the main query
if ( !$wp_query->is_search() ) {
$is_search = false;
}
} elseif ( !$wp_query->is_search() || !$wp_query->is_main_query() ) {
$is_search = false;
}
if ( !$is_search && isset($wp_query->query_vars['aps_title']) ) {
$is_search = true;
}
}
// GEO directory search, do not override
if ( $is_search && isset($_GET['geodir_search']) ) {
$is_search = false;
}
// Elementor or other forced override
// Only allow override once in this case, otherwise duplicates will appear
// @ticket: https://wp-dreams.com/forums/topic/filtered-results-show-duplicate-posts/
if ( $this->queryVarsHasAspOverridePostType($wp_query) && self::$overrideCount === 0 ) {
$is_search = true;
}
// Archive pages
if ( isset($_GET['asp_ls'], $_GET['p_asid']) && $wp_query->is_main_query() ) {
if (
( wd_asp()->instances->getOption($_GET['p_asid'], 'woo_shop_live_search') && WooCommerce::isShop() ) ||
( wd_asp()->instances->getOption($_GET['p_asid'], 'cpt_archive_live_search') && Archive::isPostTypeArchive() ) ||
( wd_asp()->instances->getOption($_GET['p_asid'], 'taxonomy_archive_live_search') && Archive::isTaxonomyArchive() ) ) {
$is_search = true;
}
}
// Is this the admin area?
if ( $is_search && is_admin() ) {
$is_search = false;
}
// Forced non-override
if ( isset($wp_query->query_vars['asp_override']) ) {
$is_search = (bool) $wp_query->query_vars['asp_override'];
}
// Possibility to add exceptions
return (bool) apply_filters('asp_query_is_search', $is_search, $wp_query);
}
/**
* Fixes the non-live result URLs for generic themes
*
* @param $url
* @param $post
* @return mixed
* @noinspection PhpUnused
*/
public function fixUrls( $url, $post ) {
if ( isset($post->asp_data, $post->asp_data->link) ) {
return $post->asp_data->link;
} elseif ( isset($post->asp_guid) ) {
return $post->asp_guid;
}
return $url;
}
/**
* Fixes the URLs of the non-live search results, when using the Genesis Framework
*
* @param $output
* @param $wrap
* @param $title
* @return mixed
* @noinspection PhpUnused
*/
public function fixUrlsGenesis( $output, $wrap, $title ) {
global $post;
if ( isset($post, $post->asp_guid) && is_object($post) && function_exists('genesis_markup') ) {
$pattern = "/(?<=href=(\"|'))[^\"']+(?=(\"|'))/";
$title = preg_replace($pattern, $post->asp_guid, $title);
$output = genesis_markup(
array(
'open' => "<{$wrap} %s>",
'close' => "</{$wrap}>",
'content' => $title,
'context' => 'entry-title',
'params' => array(
'wrap' => $wrap,
),
'echo' => false,
)
);
}
return $output;
}
private function queryVarsHasAspOverridePostType( ?WP_Query $wp_query ): bool {
if ( $wp_query === null || !isset($wp_query->query_vars['post_type']) ) {
return false;
}
if ( is_array($wp_query->query_vars['post_type']) ) {
return in_array('asp_override', $wp_query->query_vars['post_type']);
} else {
return $wp_query->query_vars['post_type'] === 'asp_override';
}
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace WPDRMS\ASP\Hooks\Filters;
if (!defined('ABSPATH')) die('-1');
class WooFormOverride extends AbstractFilter {
public function handle( $form = "" ) {
$asp_woo_override = get_option("asp_woo_override", -1);
if ( $asp_woo_override > -1 && wd_asp()->instances->exists( $asp_woo_override ) ) {
$new_form = do_shortcode("[wpdreams_ajaxsearchpro id=".$asp_woo_override."]");
if (strlen($new_form) > 100)
return $new_form;
else
return $form;
}
return $form;
}
}

View File

@@ -0,0 +1,434 @@
<?php
namespace WPDRMS\ASP\Hooks;
if ( !defined('ABSPATH') ) {
die('-1');
}
class FiltersManager {
const NAMESPACE = 'WPDRMS\\ASP\\Hooks\\Filters\\';
/**
* Array of internal known filters
*
* @var array
*/
private static $filters = array(
array(
'filter' => 'posts_request',
'handler' => array( 'SearchOverride', 'maybeCancelWPQuery' ),
'priority' => 999999999,
'args' => 2,
),
array(
'filter' => 'posts_results',
'handler' => array( 'SearchOverride', 'override' ),
'priority' => 999999999,
'args' => 2,
),
array(
'filter' => 'page_link',
'handler' => array( 'SearchOverride', 'fixUrls' ),
'priority' => 999999999,
'args' => 2,
),
array(
'filter' => 'post_link',
'handler' => array( 'SearchOverride', 'fixUrls' ),
'priority' => 999999999,
'args' => 2,
),
array(
'filter' => 'post_type_link',
'handler' => array( 'SearchOverride', 'fixUrls' ),
'priority' => 999999999,
'args' => 2,
),
array(
'filter' => 'elementor/query/query_args',
'handler' => array( 'Elementor', 'posts' ),
'priority' => 999,
'args' => 2,
),
array(
'filter' => 'elementor/theme/posts_archive/query_posts/query_vars',
'handler' => array( 'Elementor', 'posts_archive' ),
'priority' => 999,
'args' => 1,
),
array(
'filter' => 'woocommerce_shortcode_products_query',
'handler' => array( 'Elementor', 'products' ),
'priority' => 999,
'args' => 3,
),
array(
'filter' => 'jet-engine/listing/grid/posts-query-args',
'handler' => array( 'Elementor', 'jetListingGridQuery' ),
'priority' => 0,
'args' => 3,
),
array(
'filter' => 'jet-engine/listing/grid/source',
'handler' => array( 'Elementor', 'jetListingGridQueryBuilderToPost' ),
'priority' => 99999,
'args' => 3,
),
array(
'filter' => 'register_block_type_args',
'handler' => array( 'QueryLoopBlock', 'addAttributes' ),
'priority' => 10,
'args' => 2,
),
array(
'filter' => 'query_loop_block_query_vars',
'handler' => array( 'QueryLoopBlock', 'queryVars' ),
'priority' => 99,
'args' => 3,
),
array(
'filter' => 'register_block_type_args',
'handler' => array( 'GenerateBlocksQueryBlock', 'addAttributes' ),
'priority' => 10,
'args' => 2,
),
array(
'filter' => 'generateblocks_query_wp_query_args',
'handler' => array( 'GenerateBlocksQueryBlock', 'queryVars' ),
'priority' => 10,
'args' => 2,
),
array(
'filter' => 'blocksy:general:blocks:query:args',
'handler' => array( 'BlocksyAdvancedPostsBlock', 'queryVars' ),
'priority' => 10,
'args' => 2,
),
array(
'filter' => 'bricks/posts/query_vars',
'handler' => array( 'BricksQueryLoop', 'bricksPostsQueryVars' ),
'priority' => 10,
'args' => 4,
),
array(
'filter' => 'wp_enqueue_scripts',
'handler' => array( 'Asset', 'onPluginFrontendHead' ),
'priority' => 10,
'args' => 0,
),
array(
'filter' => 'wp_print_footer_scripts',
'handler' => array( 'Asset', 'onPluginFooter' ),
'priority' => 6,
'args' => 0,
),
array(
'filter' => 'admin_print_footer_scripts',
'handler' => array( 'Asset', 'onPluginFooter' ),
'priority' => 6,
'args' => 0,
),
array(
'filter' => 'admin_print_footer_scripts',
'handler' => array( 'Asset', 'onPluginBackendFooter' ),
'priority' => 7,
'args' => 0,
),
array(
'filter' => 'asp_ob_end',
'handler' => array( 'Asset', 'injectToOutputBuffer' ),
'priority' => -101,
'args' => 1,
),
array(
'filter' => 'shutdown',
'handler' => array( 'Asset', 'onShutdown' ),
'priority' => -100,
'args' => 0,
),
array(
'filter' => 'asp_load_css_js',
'handler' => array( 'Asset', 'applySelectiveAssetLoader' ),
'priority' => 10,
'args' => 1,
),
/* GENESIS REPLACEMENT FOR MULTISITE */
array(
'filter' => 'genesis_post_title_output',
'handler' => array( 'SearchOverride', 'fixUrlsGenesis' ),
'priority' => 999999999,
'args' => 3,
),
/* ALLOW SHORTCODE AS MENU TITLE */
array(
'filter' => 'wp_nav_menu_objects',
'handler' => array( 'EtcFixes', 'allowShortcodeInMenus' ),
'priority' => 10,
'args' => 1,
),
array(
'filter' => 'asp_theme_search_form',
'handler' => 'FormOverride',
'priority' => 999999999,
'args' => 1,
),
array(
'filter' => 'get_search_form',
'handler' => 'FormOverride',
'priority' => 999999999,
'args' => 1,
),
array(
'filter' => 'get_product_search_form',
'handler' => 'WooFormOverride',
'priority' => 999999999,
'args' => 1,
),
array(
'filter' => 'asp_query_args',
'handler' => array( 'SearchExclude', 'handleExclusions' ),
'priority' => 20,
'args' => 1,
),
array(
'filter' => 'asp_results',
'handler' => array( 'EtcFixes', 'plug_DownloadMonitorLink' ),
'priority' => 999999999,
'args' => 1,
),
array(
'filter' => 'asp_fontend_get_taxonomy_terms',
'handler' => array( 'EtcFixes', 'fixPostFormatStandard' ),
'priority' => 999,
'args' => 4,
),
array(
'filter' => 'asp_query_args',
'handler' => array( 'EtcFixes', 'fixPostFormatStandardArgs' ),
'priority' => 999,
'args' => 1,
),
array(
'filter' => 'asp_query_args',
'handler' => array( 'IclTranslations', 'aspQueryArgsTranslations' ),
'priority' => 999,
'args' => 2,
),
array(
'filter' => 'asp_load_js',
'handler' => array( 'EtcFixes', 'fixOxygenEditorJS' ),
'priority' => 999,
'args' => 1,
),
array(
'filter' => 'wp_get_attachment_image_src',
'handler' => array( 'EtcFixes', 'multisiteImageFix' ),
'priority' => 999,
'args' => 4,
),
array(
'filter' => 'upload_mimes',
'handler' => array( 'EtcFixes', 'allow_json_mime_type' ),
'priority' => 999,
'args' => 1,
),
array(
'filter' => 'http_request_host_is_external',
'handler' => array( 'EtcFixes', 'http_request_host_is_external_filter' ),
'priority' => 9999,
'args' => 3,
),
array(
'filter' => 'http_request_args',
'handler' => array( 'EtcFixes', 'http_request_args' ),
'priority' => 9999,
'args' => 2,
),
array(
'filter' => 'asp/shortcode/include_styles',
'handler' => array( 'EtcFixes', 'breakdanceFixShortcodeInEditor' ),
'priority' => 10,
'args' => 1,
),
array(
'filter' => 'asp_post_content_before_tokenize_clear',
'handler' => array( 'EtcFixes', 'diviInitModules' ),
'priority' => 9999,
'args' => 1,
),
array(
'filter' => 'asp/ajax/headers/content_type',
'handler' => array( 'EtcFixes', 'gTranslateAjaxHeaders' ),
'priority' => 10,
'args' => 1,
),
array(
'filter' => 'attachment_fields_to_edit',
'handler' => 'MediaScreen',
'priority' => 9999,
'args' => 2,
),
array(
'filter' => 'et_builder_blog_query',
'handler' => array( 'Divi', 'blog' ),
'priority' => 9999,
'args' => 2,
),
array(
'filter' => 'et_builder_load_actions',
'handler' => array( 'EtcFixes', 'diviInitModulesOnAjax' ),
'priority' => 9999,
'args' => 1,
),
array(
'filter' => 'divi_blog_extras_query_args',
'handler' => array( 'Divi', 'blogExtras' ),
'priority' => 9999,
'args' => 2,
),
array(
'filter' => 'asp_post_custom_field_before_tokenize',
'handler' => array( 'ACF', 'indexRepeaterAndFlexFields' ),
'priority' => 10,
'args' => 3,
),
array(
'filter' => 'et_builder_ready',
'handler' => array( 'EtcFixes', 'diviBuilderReady' ),
'priority' => 9999,
'args' => 0,
),
/**
* Optimizes the HTML output by removing line breaks.
* This prevents some wpautop applied paragraphs and line breaks from appearing
* when the shortcode is used in a shortcode block.
*/
array(
'filter' => 'asp_shortcode_output',
'handler' => array( 'EtcFixes', 'optimizeHTML' ),
'priority' => 9999,
'args' => 1,
),
array(
'filter' => 'rocket_exclude_js',
'handler' => array( 'JsCompatibility', 'rocket_exclude_js' ),
'priority' => 9999,
'args' => 1,
),
array(
'filter' => 'rocket_excluded_inline_js_content',
'handler' => array( 'JsCompatibility', 'rocket_excluded_inline_js_content' ),
'priority' => 9999,
'args' => 1,
),
);
/**
* Array of already registered objects
*
* @var array
*/
private static $registered = array();
/**
* Registers all the handlers from the $actions variable
*/
public static function registerAll() {
foreach ( self::$filters as $data ) {
self::register($data['filter'], $data['handler'], $data['priority'], $data['args']);
}
}
/**
* Get all the queued handlers
*
* @return array
*/
public static function getAll(): array {
return array_keys(self::$filters);
}
/**
* Get all the already registered handlers (singleton instance storage)
*
* @return array
*/
public static function getRegistered(): array {
return self::$registered;
}
/**
* Registers a filter with the handler class name.
*
* @param $filter
* @param $handler string|array
* @param int $priority
* @param int $accepted_args
* @return bool
*/
public static function register( $filter, $handler, int $priority = 10, int $accepted_args = 0 ): bool {
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 ( !isset(self::$registered[ $class ]) ) {
self::$registered[ $class ] = call_user_func(array( $class, 'getInstance' ));
}
if ( !has_filter($filter, array( self::$registered[ $class ], $handle )) ) {
add_filter($filter, array( self::$registered[ $class ], $handle ), $priority, $accepted_args);
}
return true;
}
/**
* Deregisters an action handler.
*
* @param $filter
* @param $handler
*/
public static function deregister( $filter, $handler ) {
if ( is_array($handler) ) {
$class = self::NAMESPACE . $handler[0];
$handle = $handler[1];
} else {
$class = self::NAMESPACE . $handler;
$handle = 'handle';
}
if ( isset(self::$registered[ $class ]) ) {
// Deregister via custom method, as WordPress sometimes does not recognize object->method filters
self::remove_object_filter($filter, $class, $handle);
}
}
private static function remove_object_filter( $filter_name, $class_name, $function_name ) {
global $wp_filter;
foreach ( $wp_filter[ $filter_name ]->callbacks as $priority => $pri_data ) {
foreach ( $pri_data as $cb => $cb_data ) {
if (
is_array($cb_data['function']) &&
isset($cb_data['function'][0], $cb_data['function'][1])
&& get_class($cb_data['function'][0]) == $class_name &&
$cb_data['function'][1] == $function_name
) {
unset($wp_filter[ $filter_name ]->callbacks[ $priority ][ $cb ]);
}
}
}
}
}