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,9 @@
<?php
namespace WPDRMS\ASP\Asset;
interface AssetInterface {
public function register(): void;
public function deregister(): void;
}

View File

@@ -0,0 +1,33 @@
<?php
namespace WPDRMS\ASP\Asset;
if ( !defined('ABSPATH') ) {
die('-1');
}
/**
* Common functions for CSS/Script/Font asset managers
*/
class AssetManager {
/**
* Checks if any compatibility issues should be considered in the current request
*
* @return bool
*/
protected function conflict(): bool {
// phpcs:disable
// Widgets screen
return (
wp_is_json_request() || // Widgets screen
wp_doing_ajax() || // Ajax Resuests in General
isset($_GET['et_fb']) || // Divi frontend editor
isset($_GET['vcv-ajax']) || // Visual Composer Frontend editor
isset($_GET['fl_builder']) || // Beaver Builder Frontend editor
isset($_GET['elementor-preview']) || // Elementor Frontend
isset($_GET['breakdance']) || isset($_GET['_breakdance_doing_ajax']) || // Breakdance editor
isset($_GET['wc-ajax']) || // WooCommerce Custom Ajax Request
( defined('BRICKS_VERSION') && isset($_GET['bricks']) ) || // Bricks Builder
( isset($_GET['action']) && $_GET['action'] == 'elementor' ) // Elementor Parts editor
);
}
}

View File

@@ -0,0 +1,136 @@
<?php
namespace WPDRMS\ASP\Asset\Css;
use WPDRMS\ASP\Asset\GeneratorInterface;
use WPDRMS\ASP\Asset\Script\Requirements;
use WPDRMS\ASP\Utils\FileManager;
use WPDRMS\ASP\Utils\Str;
use WPDRMS\ASP\Utils\Css;
defined('ABSPATH') or die("You can't access this file directly.");
if ( !class_exists(__NAMESPACE__ . '\Generator') ) {
class Generator implements GeneratorInterface {
private
$basic_flags_string = '',
$minify;
function __construct( $minify = false ) {
$this->minify = $minify;
}
function generate(): string {
if ( wd_asp()->instances->exists() ) {
$basic_css = $this->generateGlobal();
$instance_css_arr = $this->generateInstances();
return $this->saveFiles($basic_css, $instance_css_arr);
}
return '';
}
function verifyFiles(): bool {
if (
!file_exists(wd_asp()->cache_path . $this->filename('basic')) ||
!file_exists(wd_asp()->cache_path . $this->filename('instances')) ||
@filesize(wd_asp()->cache_path . $this->filename('instances')) < 1025
) {
return false;
} else {
return true;
}
}
function filename( $handle ) {
$media_flags = get_site_option('asp_css_flags', array(
'basic' => ''
));
$flag = Str::anyToString($media_flags['basic']);
$files = array(
'basic' => 'style.basic'.$flag.'.css',
'wpdreams-asp-basics' => 'style.basic'.$flag.'.css',
'instances' => 'style.instances'.$flag.'.css',
'wpdreams-ajaxsearchpro-instances' => 'style.instances'.$flag.'.css'
);
return $files[$handle] ?? 'search' . $handle . '.css';
}
private function generateGlobal() {
// Basic CSS
ob_start();
echo file_get_contents(ASP_CSS_PATH . "/global/woocommerce.css");
echo file_get_contents(ASP_CSS_PATH . "/global/advanced-result-fields.css");
include(ASP_PATH . "/css/style.basic.css.php");
$basic_css = ob_get_clean();
$unused_assets = Requirements::getUnusedAssets(false);
foreach ( $unused_assets['internal'] as $flag ) {
// Remove unneccessary CSS
$basic_css = asp_get_outer_substring($basic_css, '/*[' . $flag . ']*/');
$this->basic_flags_string .= '-' . substr($flag, 0, 2);
}
foreach ( $unused_assets['external'] as $flag ) {
// Remove unneccessary CSS
$basic_css = asp_get_outer_substring($basic_css, '/*[' . $flag . ']*/');
$this->basic_flags_string .= '-' . substr($flag, 0, 2);
}
return $basic_css;
}
private function generateInstances(): array {
// Instances CSS
$css_arr = array();
foreach (wd_asp()->instances->get() as $s) {
// $style and $id needed in the include
$style = &$s['data'];
$id = $s['id'];
ob_start();
include(ASP_PATH . "/css/style.css.php");
$out = ob_get_contents();
$css_arr[$id] = $out;
ob_end_clean();
}
return $css_arr;
}
private function saveFiles($basic_css, $instance_css_arr): string {
// Too big, disabled...
$css = implode(" ", $instance_css_arr);
// Individual CSS rules by search ID
foreach ($instance_css_arr as $sid => &$c) {
if ( $this->minify ) {
$c = Css::Minify($c);
}
FileManager::instance()->write(wd_asp()->cache_path . "search" . $sid . ".css", $c);
}
// Save the style instances file nevertheless, even if async enabled
if ( $this->minify ) {
$css = Css::Minify($css);
$basic_css = Css::Minify($basic_css);
}
FileManager::instance()->write(wd_asp()->cache_path . "style.instances.css", $basic_css . $css);
FileManager::instance()->write(wd_asp()->cache_path . "style.basic.css", $basic_css);
if ( $this->basic_flags_string != '' ) {
FileManager::instance()->write(wd_asp()->cache_path . "style.basic" . $this->basic_flags_string . ".css", $basic_css);
FileManager::instance()->write(wd_asp()->cache_path . "style.instances" . $this->basic_flags_string . ".css", $basic_css . $css);
}
update_site_option('asp_css_flags', array(
'basic' => $this->basic_flags_string
));
update_site_option("asp_media_query", asp_gen_rnd_str());
update_site_option('asp_css', array(
'basic' => $basic_css,
'instances' => $instance_css_arr
));
return $basic_css . $css;
}
}
}

View File

@@ -0,0 +1,141 @@
<?php
namespace WPDRMS\ASP\Asset\Css;
use WPDRMS\ASP\Asset\AssetManager;
use WPDRMS\ASP\Asset\ManagerInterface;
use WPDRMS\ASP\Patterns\SingletonTrait;
use WPDRMS\ASP\Utils\Html;
if ( !defined('ABSPATH') ) {
die('-1');
}
class Manager extends AssetManager implements ManagerInterface {
use SingletonTrait;
private
$method, // file, optimized, inline
$force_inline = false, // When "file" is the $method, but the files can't be created
$media_query,
$minify;
public
$generator;
function __construct() {
$comp_settings = wd_asp()->o['asp_compatibility'];
$this->method = $comp_settings['css_loading_method']; // optimized, inline, file
$this->minify = $comp_settings['css_minify'];
$this->media_query = get_site_option("asp_media_query", "defncss");
$this->generator = new Generator( $this->minify );
$this->adjustOptionsForCompatibility();
if ( $this->method == 'optimized' || $this->method == 'file' ) {
if ( !$this->generator->verifyFiles() ) {
$this->generator->generate();
if ( !$this->generator->verifyFiles() ) {
// Swap to inline if the files were not generated
$this->force_inline = true;
}
}
}
/**
* Call order:
* wp_enqueue_scripts -> enqueue()
* wp_head -> headerStartBuffer() -> start buffer
* shutdown -> print() -> end buffer trigger
*/
}
/**
* Called at wp_enqueue_scripts
*/
function enqueue( $force = false ): void {
if ( $force || $this->method == 'file' ) {
if ( !$this->generator->verifyFiles() ) {
$this->generator->generate();
if ( !$this->generator->verifyFiles() ) {
$this->force_inline = true;
}
}
// Still enqueue to the head, but the file was not possible to create.
if ( $this->force_inline ) {
add_action('wp_head', function(){
echo $this->getBasic();
echo $this->getInstances();
}, 999);
} else {
wp_enqueue_style('asp-instances', $this->url('instances'), array(), $this->media_query);
}
}
}
// asp_ob_end
function injectToBuffer($buffer, $instances): string {
if ( $this->method != 'file' ) {
$output = $this->getBasic();
$output .= $this->getInstances( $instances );
Html::inject($output, $buffer);
}
return $buffer;
}
/**
* Called at shutdown, after asp_ob_end, checks if the items were printed
*/
function printInline( $instances = array() ): void {
if ( $this->method != 'file' ) {
echo $this->getBasic();
echo $this->getInstances($instances);
}
}
private function getBasic(): string {
$output = '';
if ( $this->method == 'inline' || $this->force_inline ) {
$css = get_site_option('asp_css', array('basic' => '', 'instances' => array()));
if ( $css['basic'] != '' ) {
$output .= "<style id='asp-basic'>" . $css['basic'] . "</style>";
}
} else if ( $this->method == 'optimized' ) {
$output = '<link rel="stylesheet" id="asp-basic" href="' . $this->url('basic') . '?mq='.$this->media_query.'" media="all" />';
}
return $output;
}
private function adjustOptionsForCompatibility() {
if ( defined('SiteGround_Optimizer\VERSION') ) {
// SiteGround Optimized CSS combine does not pick up the CSS files when injected
if ( $this->method == 'optimized' ) {
$this->method = 'inline';
}
}
if ( $this->conflict() ) {
$this->method = 'file';
}
}
private function getInstances( $instances = false ): string {
$css = get_site_option('asp_css', array('basic' => '', 'instances' => array()));
$output = '';
$instances = $instances === false ? array_keys($css['instances']) : $instances;
foreach ($instances as $search_id) {
if ( isset($css['instances'][$search_id]) && $css['instances'][$search_id] != '' ) {
$output .= "<style id='asp-instance-$search_id'>" . $css['instances'][$search_id] . "</style>";
}
}
return $output;
}
private function url( $handle ): string {
if ( '' != $file = $this->generator->filename($handle) ) {
return wd_asp()->cache_url . $file;
} else {
return '';
}
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace WPDRMS\ASP\Asset\Font;
use WPDRMS\ASP\Asset\GeneratorInterface;
defined('ABSPATH') or die("You can't access this file directly.");
if ( !class_exists(__NAMESPACE__ . '\Generator') ) {
class Generator implements GeneratorInterface {
function generate(): array {
$imports = array();
$font_sources = array("inputfont", "descfont", "titlefont", 'fe_sb_font',
"authorfont", "datefont", "showmorefont", "groupfont",
"exsearchincategoriestextfont", "groupbytextfont", "settingsdropfont",
"prestitlefont", "presdescfont", "pressubtitlefont", "search_text_font");
foreach (wd_asp()->instances->get() as $instance) {
foreach($font_sources as $fs) {
if (
isset($instance['data']["import-".$fs]) &&
!in_array(trim($instance['data']["import-".$fs]), $imports)
) {
$imports[] = trim($instance['data']["import-" . $fs]);
}
}
}
foreach ( $imports as $ik => $im ) {
if ( $im == '' ) {
unset($imports[$ik]);
}
}
$imports = apply_filters('asp_custom_fonts', $imports);
$fonts = array();
foreach ($imports as $import) {
$import = trim(str_replace(array("@import url(", ");", "https:", "http:"), "", $import));
$import = trim(str_replace("//fonts.googleapis.com/css?family=", "", $import));
if ( $import != '' ) {
$fonts[] = $import;
}
}
return $fonts;
}
}
}

View File

@@ -0,0 +1,80 @@
<?php
namespace WPDRMS\ASP\Asset\Font;
/* Prevent direct access */
use WPDRMS\ASP\Asset\AssetManager;
use WPDRMS\ASP\Asset\ManagerInterface;
use WPDRMS\ASP\Patterns\SingletonTrait;
use WPDRMS\ASP\Utils\Html;
if ( !defined('ABSPATH') ) {
die('-1');
}
/**
* Manager for the Font assets
*/
class Manager extends AssetManager implements ManagerInterface {
use SingletonTrait;
public function enqueue( $force = false ): void {}
public function injectToBuffer( string $buffer, $instances = false ): string {
if ( !$this->conflict() ) {
$output = $this->get();
if ( $output !== '' ) {
Html::inject($output, $buffer);
}
}
return $buffer;
}
public function printInline( $instances = array() ): void {
if ( !$this->conflict() ) {
echo $this->get();
}
}
private function get(): string {
$comp_options = wd_asp()->o['asp_compatibility'];
$out = '';
if ( $comp_options['load_google_fonts'] == 1 ) {
$generator = new Generator();
$fonts = $generator->generate();
if ( count($fonts) > 0 ) {
$stored_fonts = get_site_option('asp_fonts', array());
$key = md5(implode('|', $fonts));
$fonts_css = '';
if ( isset($stored_fonts[ $key ]) ) {
$fonts_css = $stored_fonts[ $key ];
} else {
$fonts_request = wp_safe_remote_get('https://fonts.googleapis.com/css?family=' . implode('|', $fonts) . '&display=swap');
if ( !is_wp_error($fonts_request) ) {
$fonts_css = wp_remote_retrieve_body($fonts_request);
if ( $fonts_css != '' ) {
$stored_fonts[ $key ] = $fonts_css;
update_site_option('asp_fonts', $stored_fonts);
}
}
}
if ( !is_wp_error($fonts_css) && $fonts_css != '' ) {
// Do NOT preload the fonts - it will give worst PagesPeed score. Preconnect is sufficient.
$out = '
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<style>
' . $fonts_css . '
</style>';
} else {
$out = '
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="preload" as="style" href="//fonts.googleapis.com/css?family=' . implode('|', $fonts) . '&display=swap" />
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=' . implode('|', $fonts) . '&display=swap" media="all" />
';
}
}
}
return $out;
}
}

View File

@@ -0,0 +1,9 @@
<?php
namespace WPDRMS\ASP\Asset;
/* Prevent direct access */
defined('ABSPATH') or die("You can't access this file directly.");
interface GeneratorInterface {
function generate();
}

View File

@@ -0,0 +1,135 @@
<?php
namespace WPDRMS\ASP\Asset;
use WPDRMS\ASP\Misc\OutputBuffer;
use WPDRMS\ASP\Patterns\SingletonTrait;
/* Prevent direct access */
defined('ABSPATH') or die("You can't access this file directly.");
class Manager {
use SingletonTrait;
private
$instances = array();
/**
* hook: wp_enqueue_scripts
*/
function enqueue() {
if ( $this->shouldLoadCss() ) {
Css\Manager::instance()->enqueue();
}
if ( $this->shouldLoadJs() ) {
Script\Manager::instance()->enqueue();
}
}
/**
* hook: wp_print_footer_scripts, priority 6
* hook: admin_print_footer_scripts, priority 6
*/
function onPluginFooter() {
// Needed to enqueue the internal (jquery, UI) requirements
$this->getVisibleSearchIds();
if ( count($this->instances) ) {
if ( $this->shouldLoadJs() ) {
Script\Manager::instance()->earlyFooterEnqueue($this->instances);
}
}
}
/**
* Classic script enqueue for the plugin backend
*
* hook: admin_print_footer_scripts, priority 7
*/
function onPluginBackendFooter() {
Script\Manager::instance()->enqueue( true );
}
// asp_ob_end
function injectToBuffer($buffer) {
$this->getVisibleSearchIds($buffer);
if ( count($this->instances) ) {
if ( $this->shouldLoadCss() ) {
$buffer = Css\Manager::instance()->injectToBuffer($buffer, $this->instances);
$buffer = Font\Manager::instance()->injectToBuffer($buffer);
}
if ( $this->shouldLoadJs() ) {
$buffer = Script\Manager::instance()->injectToBuffer($buffer, $this->instances);
}
}
return $buffer;
}
/**
* Called at shutdown, after asp_ob_end, checks if the items were printed
*/
function printBackup() {
$this->getVisibleSearchIds();
if ( count($this->instances) && !OutputBuffer::getInstance()->obFound() ) {
if ( $this->shouldLoadCss() ) {
Css\Manager::instance()->printInline($this->instances);
Font\Manager::instance()->printInline();
}
if ( $this->shouldLoadJs() ) {
Script\Manager::instance()->printInline($this->instances);
}
}
}
public function shouldLoadCss(): bool {
return
wd_asp()->instances->exists() &&
!apply_filters('asp_load_css_js', false) &&
!apply_filters('asp_load_css', false);
}
public function shouldLoadJs(): bool {
return
wd_asp()->instances->exists() &&
!apply_filters('asp_load_css_js', false) &&
!apply_filters('asp_load_js', false);
}
function getVisibleSearchIds( $html = '' ): array {
$this->instances = $this->getInstancesFromHtml($html);
$this->instances = array_merge(
$this->instances,
wd_asp()->instances->getInstancesPrinted()
);
// Search results page && keyword highlighter
if (
isset($_GET['p_asid']) && intval($_GET['p_asid']) > 0 &&
wd_asp()->instances->exists($_GET['p_asid'])
) {
$instance = wd_asp()->instances->get(intval($_GET['p_asid']));
if (
( $instance['data']['single_highlight'] && isset($_GET['asp_highlight']) ) ||
( $instance['data']['result_page_highlight'] && isset($_GET['s']) )
) {
$this->instances[] = $instance['id'];
}
}
$this->instances = array_unique($this->instances);
sort($this->instances);
return $this->instances;
}
private function getInstancesFromHtml($out): array {
if ( $out !== false && $out !== '' ) {
if ( preg_match_all('/data-asp-id=["\'](\d+)[\'"]\s/', $out, $matches) > 0 ) {
foreach ( $matches[1] as $search_id ) {
$search_id = (int) $search_id;
if ( $search_id !== 0 ) {
$this->instances[] = $search_id;
}
}
}
}
return $this->instances;
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace WPDRMS\ASP\Asset;
if ( !defined('ABSPATH') ) {
die('-1');
}
interface ManagerInterface {
/**
* To be called before (or within) wp_print_footer_scripts|admin_print_footer_scripts
*
* @param bool $force
* @return void
*/
public function enqueue( bool $force = false ): void;
/**
* To be called on shutdown - backup print scripts for panic mode
*
* @param array<string, mixed> $instances
* @return void
*/
public function printInline( array $instances = array() ): void;
/**
* Injection handler for the output buffer
*
* @param string $buffer
* @param bool|array<string, mixed> $instances
* @return string
*/
public function injectToBuffer( string $buffer, $instances ): string;
}

View File

@@ -0,0 +1,82 @@
<?php
namespace WPDRMS\ASP\Asset\Script;
use WPDRMS\ASP\Asset\GeneratorInterface;
use WPDRMS\ASP\Utils\FileManager;
defined('ABSPATH') or die("You can't access this file directly.");
if ( !class_exists(__NAMESPACE__ . '\Generator') ) {
class Generator implements GeneratorInterface {
private
$scripts;
function __construct($scripts) {
$this->scripts = $scripts;
}
function get() {
if ( $this->verifyFiles() ) {
return $this->filename();
} else {
$this->generate();
if ( $this->verifyFiles() ) {
return $this->filename();
}
}
return '';
}
function generate(): bool {
if ( !$this->verifyFiles() ) {
$final_content = '';
foreach ($this->scripts as $script) {
if ( !isset($script['path']) ) {
return false;
} else {
$content = file_get_contents($script['path']);
if ( $content == '' ) {
return false;
} else {
$final_content .= $content;
}
}
}
FileManager::instance()->write(wd_asp()->cache_path . $this->fileName(), $final_content);
return $this->verifyFiles();
}
return true;
}
function verifyFiles(): bool {
if (
!file_exists(wd_asp()->cache_path . $this->filename()) ||
@filesize(wd_asp()->cache_path . $this->filename()) < 1025
) {
return false;
} else {
return true;
}
}
public static function deleteFiles(): int {
if ( !empty(wd_asp()->cache_path) && wd_asp()->cache_path !== '' ) {
return FileManager::instance()->deleteByPattern(wd_asp()->cache_path, '*.js');
}
return 0;
}
function fileName(): string {
return $this->fileHandle() . '.min.js';
}
function fileHandle(): string {
$concat = ASP_CURR_VER_STRING . ASP_CURR_VER;
foreach ( $this->scripts as $script ) {
$concat .= $script['handle'];
}
return 'asp-' . substr(md5($concat), 0, 8);
}
}
}

View File

@@ -0,0 +1,585 @@
<?php
namespace WPDRMS\ASP\Asset\Script;
use stdClass;
use WPDRMS\ASP\Asset\AssetManager;
use WPDRMS\ASP\Asset\ManagerInterface;
use WPDRMS\ASP\Patterns\SingletonTrait;
use WPDRMS\ASP\Utils\Html;
use WPDRMS\ASP\Utils\Script;
if ( !defined('ABSPATH') ) {
die('-1');
}
class Manager extends AssetManager implements ManagerInterface {
use SingletonTrait;
private $prepared = array();
private $media_query = '';
private $inline = '';
private $inline_instance = '';
private $instances = false;
private $args = array();
private $scripts = array(
'wd-asp-photostack' => array(
'src' => 'js/{js_source}/external/photostack.js',
'prereq' => false,
),
'wd-asp-select2' => array(
'src' => 'js/{js_source}/external/jquery.select2.js',
'prereq' => array( 'jquery' ),
),
'wd-asp-nouislider' => array(
'src' => 'js/{js_source}/external/nouislider.all.js',
'prereq' => false,
),
'wd-asp-rpp-isotope' => array(
'src' => 'js/{js_source}/external/isotope.js',
'prereq' => false,
),
'wd-asp-ajaxsearchpro' => array(
'src' => 'js/{js_source}/plugin/merged/asp{js_min}.js',
'prereq' => false,
),
'wd-asp-prereq-and-wrapper' => array(
'src' => 'js/{js_source}/plugin/merged/asp-prereq-and-wrapper{js_min}.js',
'prereq' => false,
),
);
private $optimized_scripts = array(
'wd-asp-ajaxsearchpro' => array(
'wd-asp-ajaxsearchpro-prereq' => array(
'handle' => 'wd-asp-ajaxsearchpro', // Handle alias, for the enqueue
'src' => 'js/{js_source}/plugin/optimized/asp-prereq.js',
),
'wd-asp-ajaxsearchpro-core' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-core.js',
),
'wd-asp-ajaxsearchpro-settings' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-settings.js',
'prereq' => array( 'wd-asp-ajaxsearchpro' ),
),
'wd-asp-ajaxsearchpro-compact' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-compact.js',
'prereq' => array( 'wd-asp-ajaxsearchpro' ),
),
'wd-asp-ajaxsearchpro-vertical' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-results-vertical.js',
'prereq' => array( 'wd-asp-ajaxsearchpro' ),
),
'wd-asp-ajaxsearchpro-horizontal' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-results-horizontal.js',
'prereq' => array( 'wd-asp-ajaxsearchpro' ),
),
'wd-asp-ajaxsearchpro-polaroid' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-results-polaroid.js',
'prereq' => array( 'wd-asp-ajaxsearchpro' ),
),
'wd-asp-ajaxsearchpro-isotopic' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-results-isotopic.js',
'prereq' => array( 'wd-asp-ajaxsearchpro' ),
),
'wd-asp-ajaxsearchpro-ga' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-ga.js',
'prereq' => array( 'wd-asp-ajaxsearchpro' ),
),
'wd-asp-ajaxsearchpro-live' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-live.js',
'prereq' => array( 'wd-asp-ajaxsearchpro' ),
),
'wd-asp-ajaxsearchpro-autocomplete' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-autocomplete.js',
'prereq' => array( 'wd-asp-ajaxsearchpro' ),
),
'wd-asp-ajaxsearchpro-wrapper' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-wrapper.js',
'prereq' => true, // TRUE => previously loaded script
),
'wd-asp-ajaxsearchpro-addon-elementor' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-addons-elementor.js',
'prereq' => true, // TRUE => previously loaded script
),
'wd-asp-ajaxsearchpro-addon-bricks' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-addons-bricks.js',
'prereq' => true, // TRUE => previously loaded script
),
'wd-asp-ajaxsearchpro-addon-divi' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-addons-divi.js',
'prereq' => true, // TRUE => previously loaded script
),
'wd-asp-ajaxsearchpro-addon-blocksy' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-addons-blocksy.js',
'prereq' => true, // TRUE => previously loaded script
),
'wd-asp-ajaxsearchpro-addon-woocommerce' => array(
'src' => 'js/{js_source}/plugin/optimized/asp-addons-woocommerce.js',
'prereq' => true, // TRUE => previously loaded script
),
),
);
public function enqueue( $force = false ): void {
if ( $force || $this->args['method'] === 'classic' ) {
// Do not allow async method in footer enqueue
$this->args['method'] = $this->args['method'] === 'optimized_async' ? 'optimized' :$this->args['method'];
$this->earlyFooterEnqueue();
$this->initialize();
echo $this->inline; // @phpcs:ignore
foreach ( $this->prepared as $script ) {
wp_enqueue_script($script['handle']);
}
}
}
public function printInline( $instances = array() ): void {
if ( $this->args['method'] !== 'classic' ) {
$this->initialize();
$output = $this->inline_instance . $this->inline . $this->preparedToInline();
if ( $output !== '' ) {
echo $output; // @phpcs:ignore
}
}
}
public function injectToBuffer( $buffer, $instances ): string {
if ( $this->args['method'] !== 'classic' ) {
$this->initialize($instances);
$output = $this->inline_instance . $this->inline . $this->preparedToInline();
if ( $output !== '' ) {
Html::inject($output, $buffer, array( '</body>', '</html>', '<script' ), false);
}
}
return $buffer;
}
public function cleanup() {
Generator::deleteFiles();
}
private function preparedToInline() {
$out = '';
foreach ( $this->prepared as $script ) {
$async = isset($script['async']) ? 'async ' : '';
$out .= '<script ' . $async . "type='text/javascript' src='" . $script['src'] . "' id='" . $script['handle'] . "-js'></script>";
}
return $out;
}
private function __construct() {
$this->args = array(
'method' => wd_asp()->o['asp_compatibility']['script_loading_method'],
'source' => wd_asp()->o['asp_compatibility']['js_source'],
'detect_ajax' => wd_asp()->o['asp_compatibility']['detect_ajax'],
'init_only_in_viewport' => wd_asp()->o['asp_compatibility']['init_instances_inviewport_only'],
'custom_ajax_handler' => wd_asp()->o['asp_compatibility']['usecustomajaxhandler'],
);
$this->adjustOptionsForCompatibility();
}
private function adjustOptionsForCompatibility() {
if ( $this->conflict() ) {
$this->args['method'] = 'classic';
}
}
private function get( $handles = array(), $minified = true, $optimized = false, $except = array() ): array {
$handles = is_string($handles) ? array( $handles ) : $handles;
$handles = count($handles) === 0 ? array_keys($this->scripts) : $handles;
$js_source = $minified ? 'min' : 'nomin';
$js_min = $minified ? '.min' : '';
$return = array();
foreach ( $handles as $handle ) {
if ( in_array($handle, $except, true) || !Requirements::isRequired($handle, $this->instances) ) {
continue;
}
if ( isset($this->scripts[ $handle ]) ) {
if ( $optimized && isset($this->optimized_scripts[ $handle ]) ) {
$prev_handle = '';
foreach ( $this->optimized_scripts[ $handle ] as $optimized_script_handle => $optimized_script ) {
if ( in_array($optimized_script_handle, $except, true) || !Requirements::isRequired($optimized_script_handle, $this->instances) ) {
continue;
}
$prereq = !isset($optimized_script['prereq']) || $optimized_script['prereq'] === false ? array() : $optimized_script['prereq'];
if ( $prereq === true ) {
$prereq = array( $prev_handle );
}
$return[] = array(
'handle' => $optimized_script['handle'] ?? $optimized_script_handle,
'path' => ASP_PATH . str_replace(
array( '{js_source}' ),
array( $js_source ),
$js_source === 'min' ? str_replace('.js', '.min.js', $optimized_script['src']) : $optimized_script['src']
),
'src' => ASP_URL . str_replace(
array( '{js_source}' ),
array( $js_source ),
$js_source === 'min' ? str_replace('.js', '.min.js', $optimized_script['src']) : $optimized_script['src']
),
'prereq' => $prereq,
);
$prev_handle = $optimized_script_handle;
}
continue;
}
$return[] = array(
'handle' => $handle,
'path' => ASP_PATH . str_replace(
array( '{js_source}' ),
array( $js_source ),
str_replace('{js_min}', $js_min, $this->scripts[ $handle ]['src'])
),
'src' => ASP_URL . str_replace(
array( '{js_source}' ),
array( $js_source ),
str_replace('{js_min}', $js_min, $this->scripts[ $handle ]['src'])
),
'prereq' => $this->scripts[ $handle ]['prereq'],
);
} elseif ( $optimized && wd_in_array_r($handle, $this->optimized_scripts) ) {
foreach ( $this->optimized_scripts as $scripts ) {
if ( isset($scripts[ $handle ]) ) {
$return[] = array(
'handle' => $handle,
'path' => ASP_PATH . str_replace(
array( '{js_source}' ),
array( $js_source ),
$scripts[ $handle ]['src']
),
'src' => ASP_URL . str_replace(
array( '{js_source}' ),
array( $js_source ),
$scripts[ $handle ]['src']
),
'prereq' => $scripts[ $handle ]['prereq'],
);
}
}
}
}
return $return;
}
public function earlyFooterEnqueue( $instances = false ) {
/**
* Internal WP Scripts have to be enqueued at this point
*/
if ( Requirements::isRequired('jquery', $instances) ) {
wp_enqueue_script('jquery');
}
if ( Requirements::isRequired('jquery-ui-datepicker', $instances) ) {
wp_enqueue_script('jquery-ui-datepicker');
}
}
public function initialize( $instances = false ): bool {
$this->instances = $instances;
$analytics = wd_asp()->o['asp_analytics'];
$load_in_footer = true;
$media_query = ASP_DEBUG ? asp_gen_rnd_str() : get_site_option('asp_media_query', 'defn');
if ( wd_asp()->manager->getContext() === 'backend' ) {
$js_minified = false;
$js_optimized = true;
$js_async_load = false;
$js_aggregate = false;
} else {
$js_minified = $this->args['source'] === 'jqueryless-min';
$js_optimized = $this->args['method'] !== 'classic';
$js_async_load = $this->args['method'] === 'optimized_async';
$js_aggregate = !$js_async_load && !ASP_DEBUG && !( defined('WP_ASP_TEST_ENV') && is_user_logged_in() );
}
$single_highlight = false;
$single_highlight_arr = array();
// Search results page && keyword highlighter
if (
isset($_GET['p_asid']) && intval($_GET['p_asid']) > 0 &&
wd_asp()->instances->exists($_GET['p_asid']) // @phpcs:ignore
) {
$phrase = $_GET['s'] ?? $_GET['asp_highlight'] ?? ''; // @phpcs:ignore
if ( $phrase !== '' ) {
$search = wd_asp()->instances->get(intval($_GET['p_asid']));
if ( $search['data']['single_highlight'] || $search['data']['result_page_highlight'] ) {
$single_highlight = true;
$single_highlight_arr = array(
'id' => $search['id'],
'selector' => $search['data']['single_highlight_selector'],
'scroll' => boolval($search['data']['single_highlight_scroll']),
'scroll_offset' => intval($search['data']['single_highlight_offset']),
'whole' => boolval($search['data']['single_highlightwholewords']),
'minWordLength' => intval($search['data']['min_word_length']),
);
}
}
}
$ajax_url = admin_url('admin-ajax.php');
if ( !is_admin() ) {
if ( $this->args['custom_ajax_handler'] ) {
$ajax_url = ASP_URL . 'ajax_search.php';
}
if ( wd_asp()->o['asp_caching']['caching'] && wd_asp()->o['asp_caching']['caching_method'] === 'sc_file' ) {
$ajax_url = ASP_URL . 'sc-ajax.php';
}
}
$handle = 'wd-asp-ajaxsearchpro';
if ( !$js_async_load ) {
$handle = $this->prepare(
$this->get(
array(),
$js_minified,
$js_optimized,
array(
'wd-asp-prereq-and-wrapper',
)
),
array(
'media_query' => $media_query,
'in_footer' => $load_in_footer,
'aggregate' => $js_aggregate,
'handle' => $handle,
)
);
$additional_scripts = $this->get(
array(),
$js_minified,
$js_optimized,
array( 'wd-asp-prereq-and-wrapper', 'wd-asp-ajaxsearchpro-wrapper' )
);
} else {
$handle = 'wd-asp-prereq-and-wrapper';
$this->prepare(
$this->get($handle, $js_minified, $js_optimized),
array(
'media_query' => $media_query,
'in_footer' => $load_in_footer,
)
);
$additional_scripts = $this->get(
array(),
$js_minified,
$js_optimized,
array(
'wd-asp-prereq-and-wrapper',
'wd-asp-ajaxsearchpro-wrapper',
'wd-asp-ajaxsearchpro-prereq',
)
);
}
// Safety against Path Traversal attacks
$additional_scripts = array_map(
function ( $script ) {
unset($script['path']);
return $script;
},
$additional_scripts
);
// The new variable is ASP
$this->inline = Script::objectToInlineScript(
$handle,
'ASP',
array(
'wp_rocket_exception' => 'DOMContentLoaded', // WP Rocket hack to prevent the wrapping of the inline script: https://docs.wp-rocket.me/article/1265-load-javascript-deferred
'ajaxurl' => $ajax_url,
'backend_ajaxurl' => admin_url('admin-ajax.php'),
'asp_url' => ASP_URL,
'upload_url' => wd_asp()->upload_url,
'detect_ajax' => $this->args['detect_ajax'],
'media_query' => get_site_option('asp_media_query', 'defn'),
'version' => ASP_CURR_VER_STRING,
'build' => ASP_CURR_VER,
'pageHTML' => '',
'additional_scripts' => $additional_scripts,
'script_async_load' => $js_async_load,
'font_url' => str_replace('http:', '', plugins_url()) . '/ajax-search-pro/css/fonts/icons/icons2.woff2',
'init_only_in_viewport' => boolval( $this->args['init_only_in_viewport']),
'highlight' => array(
'enabled' => $single_highlight,
'data' => $single_highlight_arr,
),
'debug' => ASP_DEBUG || defined('WP_ASP_TEST_ENV'),
'instances' => new stdClass(),
'analytics' => array(
'method' => $analytics['analytics'],
'tracking_id' => $analytics['analytics_tracking_id'],
'event' => array(
'focus' => array(
'active' => boolval($analytics['gtag_focus']),
'action' => $analytics['gtag_focus_action'],
'category' => $analytics['gtag_focus_ec'],
'label' => $analytics['gtag_focus_el'],
'value' => $analytics['gtag_focus_value'],
),
'search_start' => array(
'active' => boolval($analytics['gtag_search_start']),
'action' => $analytics['gtag_search_start_action'],
'category' => $analytics['gtag_search_start_ec'],
'label' => $analytics['gtag_search_start_el'],
'value' => $analytics['gtag_search_start_value'],
),
'search_end' => array(
'active' => boolval($analytics['gtag_search_end']),
'action' => $analytics['gtag_search_end_action'],
'category' => $analytics['gtag_search_end_ec'],
'label' => $analytics['gtag_search_end_el'],
'value' => $analytics['gtag_search_end_value'],
),
'magnifier' => array(
'active' => boolval($analytics['gtag_magnifier']),
'action' => $analytics['gtag_magnifier_action'],
'category' => $analytics['gtag_magnifier_ec'],
'label' => $analytics['gtag_magnifier_el'],
'value' => $analytics['gtag_magnifier_value'],
),
'return' => array(
'active' => boolval($analytics['gtag_return']),
'action' => $analytics['gtag_return_action'],
'category' => $analytics['gtag_return_ec'],
'label' => $analytics['gtag_return_el'],
'value' => $analytics['gtag_return_value'],
),
'try_this' => array(
'active' => boolval($analytics['gtag_try_this']),
'action' => $analytics['gtag_try_this_action'],
'category' => $analytics['gtag_try_this_ec'],
'label' => $analytics['gtag_try_this_el'],
'value' => $analytics['gtag_try_this_value'],
),
'facet_change' => array(
'active' => boolval($analytics['gtag_facet_change']),
'action' => $analytics['gtag_facet_change_action'],
'category' => $analytics['gtag_facet_change_ec'],
'label' => $analytics['gtag_facet_change_el'],
'value' => $analytics['gtag_facet_change_value'],
),
'result_click' => array(
'active' => boolval($analytics['gtag_result_click']),
'action' => $analytics['gtag_result_click_action'],
'category' => $analytics['gtag_result_click_ec'],
'label' => $analytics['gtag_result_click_el'],
'value' => $analytics['gtag_result_click_value'],
),
),
),
),
'before',
true,
false
);
// Instance data
$script_data = wd_asp()->instances->get_script_data();
if ( count($script_data) > 0 ) {
if ( $instances === false ) {
$script = 'window.ASP_INSTANCES = [];';
foreach ( $script_data as $id => $data ) {
$script .= "window.ASP_INSTANCES[$id] = $data;";
}
$script_id = 'wd-asp-instances-' . substr(md5($script), 0, 8);
$this->inline_instance .= "<script id='$script_id'>$script</script>";
} else {
$script = '';
foreach ( $instances as $id ) {
if ( isset($script_data[ $id ]) ) {
$script .= "window.ASP_INSTANCES[$id] = $script_data[$id];";
}
}
if ( $script !== '' ) {
$script = 'window.ASP_INSTANCES = [];' . $script;
}
}
/**
* Why not wp_add_inline_script(), why this way?
*
* Because the script ID needs to be different for each different output, to signify difference
* for cache plugin. Otherwise caches like wp-optimize will cache the same output for the same
* script ID - and then the search instances will be missing.
*
* WordPress prints scripts at priority: 10 in this hook
*/
if ( $script !== '' ) {
$script_id = 'wd-asp-instances-' . substr(md5($script), 0, 8);
$this->inline_instance .= "<script id='$script_id'>$script</script>";
}
}
return true;
}
private function prepare( $scripts = array(), $args = array() ) {
$defaults = array(
'media_query' => '',
'in_footer' => true,
'prereq' => array(),
'aggregate' => false,
'handle' => '',
);
$args = wp_parse_args($args, $defaults);
$register_scripts = $scripts;
if ( $args['aggregate'] ) {
$generator = new Generator($scripts);
$filename = $generator->get();
if ( $filename !== '' ) {
$handle = $generator->fileHandle();
$prereq = $args['prereq'];
foreach ( $scripts as $script ) {
if ( is_array($script['prereq']) ) {
$prereq = array_merge($prereq, $script['prereq']);
}
}
$prereq = array_unique($prereq);
$prereq = array_filter(
$prereq,
function ( $p ) {
return strpos($p, 'asp-') === false;
}
);
$register_scripts = array(
array(
'handle' => $handle,
'src' => wd_asp()->cache_url . $filename,
'prereq' => $prereq,
'async' => true,
),
);
}
}
foreach ( $register_scripts as $script ) {
if ( isset($script['prereq']) ) {
if ( $script['prereq'] === false ) {
$script['prereq'] = array();
}
} else {
$script['prereq'] = $args['prereq'];
}
wp_register_script(
$script['handle'],
$script['src'],
$script['prereq'],
$args['media_query'],
$args['in_footer']
);
$this->prepared[] = $script;
}
return $handle ?? $args['handle'];
}
}

View File

@@ -0,0 +1,236 @@
<?php
namespace WPDRMS\ASP\Asset\Script;
defined('ABSPATH') or die("You can't access this file directly.");
class Requirements {
public static function isRequired( $handle, $instances = false ): bool {
if ( wd_asp()->manager->getContext() == "backend" ) {
return true;
}
$unused = self::getUnusedAssets(false, $instances);
$wp_scripts = wp_scripts();
$required = false;
switch ( strtolower($handle) ) {
case 'jquery':
if ( !wd_in_array_r('select2', $unused) && !isset($wp_scripts->done['jquery']) ) {
$required = true;
}
break;
case 'jquery-ui-datepicker':
case 'datepicker':
if ( !wd_in_array_r('datepicker', $unused) && !isset($wp_scripts->done['jquery-ui-datepicker']) ) {
$required = true;
}
break;
case 'wd-asp-photostack':
case 'wd-asp-ajaxsearchpro-polaroid':
if ( !wd_in_array_r('polaroid', $unused) ) {
$required = true;
}
break;
case 'wd-asp-select2':
if ( !wd_in_array_r('select2', $unused) ) {
$required = true;
}
break;
case 'wd-asp-nouislider':
if ( !wd_in_array_r('noui', $unused) ) {
$required = true;
}
break;
case 'wd-asp-rpp-isotope':
if ( !wd_in_array_r('isotope', $unused) ) {
$required = true;
}
break;
case 'wd-asp-ajaxsearchpro-settings':
if ( !wd_in_array_r('settings', $unused) ) {
$required = true;
}
break;
case 'wd-asp-ajaxsearchpro-compact':
if ( !wd_in_array_r('compact', $unused) ) {
$required = true;
}
break;
case 'wd-asp-ajaxsearchpro-vertical':
if ( !wd_in_array_r('vertical', $unused) ) {
$required = true;
}
break;
case 'wd-asp-ajaxsearchpro-horizontal':
if ( !wd_in_array_r('horizontal', $unused) ) {
$required = true;
}
break;
case 'wd-asp-ajaxsearchpro-isotopic':
if ( !wd_in_array_r('isotopic', $unused) ) {
$required = true;
}
break;
case 'wd-asp-ajaxsearchpro-autopopulate':
if ( !wd_in_array_r('autopopulate', $unused) ) {
$required = true;
}
break;
case 'wd-asp-ajaxsearchpro-ga':
if ( !wd_in_array_r('ga', $unused) ) {
$required = true;
}
break;
case 'wd-asp-ajaxsearchpro-autocomplete':
if ( !wd_in_array_r('autocomplete', $unused) ) {
$required = true;
}
break;
case 'wd-asp-ajaxsearchpro-addon-bricks':
if ( defined('BRICKS_VERSION') ) {
$required = true;
}
break;
case 'wd-asp-ajaxsearchpro-addon-elementor':
if ( defined('ELEMENTOR_PRO_VERSION') ) {
$required = true;
}
break;
case 'wd-asp-ajaxsearchpro-addon-divi':
if ( function_exists('et_setup_theme') ) {
$required = true;
}
break;
case 'wd-asp-ajaxsearchpro-addon-blocksy':
if ( defined('BLOCKSY_PATH') ) {
$required = true;
}
break;
case 'wd-asp-ajaxsearchpro-live':
default:
$required = true;
break;
}
return $required;
}
public static function getUnusedAssets( $return_stored = false, $instances = false ) {
$dependencies = array(
'vertical', 'horizontal', 'isotopic', 'polaroid', 'noui', 'datepicker', 'autocomplete',
'settings', 'compact', 'autopopulate', 'ga'
);
$external_dependencies = array(
'select2', 'isotope'
);
if ( $return_stored !== false && $instances === false ) {
return get_site_option('asp_unused_assets', array(
'internal' => $dependencies,
'external' => $external_dependencies
));
}
// --- Analytics
// php 7.4 "string" != 0 -> false, 7.4+ "string" != 0 -> true
if ( wd_asp()->o['asp_analytics']['analytics'] !== "0" ) {
$dependencies = array_diff($dependencies, array('ga'));
}
if ( $instances === false ) {
$search = wd_asp()->instances->get();
} else {
$search = array();
foreach ( $instances as $instance ) {
$search[] = wd_asp()->instances->get($instance);
}
}
if (is_array($search) && count($search)>0) {
foreach ($search as $s) {
// $style and $id needed in the include
$style = $s['data'];
$id = $s['id'];
// Calculate flags for the generated basic CSS
// --- Results type
$dependencies = array_diff($dependencies, array($s['data']['resultstype']));
// --- Compact box
if ( $s['data']['box_compact_layout'] ) {
$dependencies = array_diff($dependencies, array('compact'));
}
// --- Auto populate
if ( $s['data']['auto_populate'] != 'disabled' ) {
$dependencies = array_diff($dependencies, array('autopopulate'));
}
// --- Autocomplete
if ( $s['data']['autocomplete'] ) {
$dependencies = array_diff($dependencies, array('autocomplete'));
}
// --- NOUI
asp_parse_filters($id, $style, true, true);
// --- Settings visibility
/**
* DO NOT check the switch or if the settings are visible, because the user
* can still use the settings shortcode, and that is not possible to check
*/
if ( count(wd_asp()->front_filters->get()) > 0 ) {
$dependencies = array_diff($dependencies, array('settings'));
}
foreach (wd_asp()->front_filters->get() as $filter) {
if ($filter->display_mode == 'slider' || $filter->display_mode == 'range') {
$dependencies = array_diff($dependencies, array('noui'));
break;
}
}
// --- Datepicker
foreach (wd_asp()->front_filters->get() as $filter) {
if ($filter->display_mode == 'date' || $filter->display_mode == 'datepicker') {
$dependencies = array_diff($dependencies, array('datepicker'));
break;
}
}
// --- Scrollable filters
foreach (wd_asp()->front_filters->get() as $filter) {
if ( isset($filter->data['visible']) && $filter->data['visible'] == 0 ) {
continue;
}
if ($filter->display_mode == 'checkboxes' || $filter->display_mode == 'radio') {
break;
}
}
// --- Autocomplete (not used yet)
// --- Select2
foreach (wd_asp()->front_filters->get() as $filter) {
if ($filter->display_mode == 'dropdownsearch' || $filter->display_mode == 'multisearch') {
$external_dependencies = array_diff($external_dependencies, array('select2'));
break;
}
}
// --- Isotope
if ( $s['data']['resultstype'] == 'isotopic' || $s['data']['fss_column_layout'] == 'masonry' ) {
$external_dependencies = array_diff($external_dependencies, array('isotope'));
}
}
}
// Store for the init script
if ( $instances === false ) {
update_site_option('asp_unused_assets', array(
'internal' => $dependencies,
'external' => $external_dependencies
));
}
return array(
'internal' => $dependencies,
'external' => $external_dependencies
);
}
}