GIF94;
| Path : /var/www/wordpress/wp-content/plugins/oxymade/includes/ |
| Current File : /var/www/wordpress/wp-content/plugins/oxymade/includes/class-builder-autocomplete.php |
<?php
/**
* OxyMade Builder Class Autocomplete
*
* Injects the OxyMade class registry and autocomplete script into the Oxygen
* builder. Classes are created on-demand in the Vuex store when selected,
* pasted, or detected as invalid tokens.
*
* Also provides server-side transient caching for the selectors option.
*
* @package OxyMade
* @since 1.3.1
*/
namespace OxyMade\Autocomplete;
class BuilderAutocomplete {
const TRANSIENT_KEY = 'oxymade_selectors_option_cache';
const TRANSIENT_EXPIRY = DAY_IN_SECONDS;
/**
* Register all hooks
*/
public static function init() {
self::init_option_preload();
self::init_builder_scripts();
}
// =========================================================================
// Server-side: Option Pre-loading
// =========================================================================
private static function init_option_preload() {
$option_key = self::get_selectors_option_key();
if ($option_key) {
add_filter("pre_option_{$option_key}", [self::class, 'preload_selectors_option'], 10, 3);
}
add_action('breakdance_option_updated_oxy_selectors_json_string', [self::class, 'invalidate_cache']);
add_action('oxygen_option_updated_oxy_selectors_json_string', [self::class, 'invalidate_cache']);
add_action('breakdance_option_updated_oxy_selectors_collections_json_string', [self::class, 'invalidate_cache']);
add_action('oxygen_option_updated_oxy_selectors_collections_json_string', [self::class, 'invalidate_cache']);
}
private static function get_selectors_option_key() {
if (function_exists('\\Breakdance\\BreakdanceOxygen\\Strings\\__bdox')) {
$prefix = \Breakdance\BreakdanceOxygen\Strings\__bdox('meta_prefix');
return $prefix . 'oxy_selectors_json_string';
}
if (defined('BREAKDANCE_MODE') && BREAKDANCE_MODE === 'oxygen') {
return 'oxygen_oxy_selectors_json_string';
}
return null;
}
public static function preload_selectors_option($pre_option, $option, $default) {
if ($pre_option !== false) {
return $pre_option;
}
$cached = get_transient(self::TRANSIENT_KEY);
if ($cached !== false) {
return $cached;
}
static $warming = false;
if ($warming) {
return $pre_option;
}
$warming = true;
$value = get_option($option, $default);
$warming = false;
if ($value !== false) {
set_transient(self::TRANSIENT_KEY, $value, self::TRANSIENT_EXPIRY);
}
return $value;
}
public static function invalidate_cache() {
delete_transient(self::TRANSIENT_KEY);
}
// =========================================================================
// Client-side: Builder Script Injection
// =========================================================================
private static function init_builder_scripts() {
add_action('unofficial_i_am_kevin_geary_master_of_all_things_css_and_html', [self::class, 'inject_builder_autocomplete_script']);
}
/**
* Inject class registry and autocomplete script into the builder.
*/
public static function inject_builder_autocomplete_script() {
$autocomplete_enabled = !in_array(get_option('oxymade_autocomplete_enabled', '1'), ['0', '', false], true);
// Pass autocomplete setting to JS
echo '<script>window.OXYMADE_AUTOCOMPLETE_ENABLED=' . ($autocomplete_enabled ? 'true' : 'false') . ';</script>' . "\n";
// Inject lightweight class registry for autocomplete
// Only {id, name, collection} per selector — ~50-60 KB inline
$class_registry = [];
// 1. Utility classes from selectors-only.json (~1,178 entries)
$selectors_file = OXYMADE_PLUGIN_DIR . 'data/selectors-only.json';
if (file_exists($selectors_file)) {
$json = file_get_contents($selectors_file);
$selectors = json_decode($json, true);
if (is_array($selectors)) {
foreach ($selectors as $sel) {
if (isset($sel['id'], $sel['name'], $sel['collection'])) {
$class_registry[] = [
'i' => $sel['id'],
'n' => $sel['name'],
'c' => $sel['collection'],
];
}
}
}
}
// 2. Component classes from components.json (~25 assignable entries)
// Skip compound selectors (names starting with "." or containing ",")
$components_file = OXYMADE_PLUGIN_DIR . 'data/components.json';
if (file_exists($components_file)) {
$comp_json = file_get_contents($components_file);
$components = json_decode($comp_json, true);
if (is_array($components)) {
foreach ($components as $comp) {
if (!isset($comp['id'], $comp['name'])) continue;
$name = $comp['name'];
if (strpos($name, '.') === 0 || strpos($name, ',') !== false) continue;
$class_registry[] = [
'i' => $comp['id'],
'n' => $name,
'c' => $comp['collection'] ?? 'OxyMade Components',
];
}
}
}
if (!empty($class_registry)) {
echo '<script>window.OXYMADE_CLASS_REGISTRY=' . wp_json_encode($class_registry) . ';</script>' . "\n";
}
$script_url = OXYMADE_PLUGIN_URL . 'assets/js/builder-autocomplete.js?ver=' . OXYMADE_VERSION;
echo '<script src="' . esc_url($script_url) . '"></script>' . "\n";
}
}