feat: Add dedicated SPA page selection (WooCommerce-style)
Problem: Shortcode 'island' architecture is fragile and theme-dependent - SPA div buried deep in theme structure (body > div.wp-site-blocks > main > div#app) - Theme and plugins can intervene at any level - Different themes have different structures - Breaks easily with theme changes Solution: Dedicated page-based SPA system (like WooCommerce) - Add page selection in Appearance > General settings - Store page IDs for Shop, Cart, Checkout, Account - Full-body SPA rendering on designated pages - No theme interference Changes: - AppearanceController.php: * Added spa_pages field to general settings * Stores page IDs for each SPA type (shop/cart/checkout/account) - TemplateOverride.php: * Added is_spa_page() method to check designated pages * Use blank template for designated pages (priority over legacy) * Remove theme elements for designated pages - Assets.php: * Added is_spa_page() check before mode/shortcode checks * Load assets on designated pages regardless of mode Architecture: - Designated pages render directly to <body> - No theme wrapper/structure interference - Clean full-page SPA experience - Works with ANY theme consistently Next: Add UI in admin-spa General tab for page selection
This commit is contained in:
@@ -82,6 +82,12 @@ class AppearanceController {
|
|||||||
|
|
||||||
$general_data = [
|
$general_data = [
|
||||||
'spa_mode' => sanitize_text_field($request->get_param('spaMode')),
|
'spa_mode' => sanitize_text_field($request->get_param('spaMode')),
|
||||||
|
'spa_pages' => [
|
||||||
|
'shop' => absint($request->get_param('spaPages')['shop'] ?? 0),
|
||||||
|
'cart' => absint($request->get_param('spaPages')['cart'] ?? 0),
|
||||||
|
'checkout' => absint($request->get_param('spaPages')['checkout'] ?? 0),
|
||||||
|
'account' => absint($request->get_param('spaPages')['account'] ?? 0),
|
||||||
|
],
|
||||||
'toast_position' => sanitize_text_field($request->get_param('toastPosition') ?? 'top-right'),
|
'toast_position' => sanitize_text_field($request->get_param('toastPosition') ?? 'top-right'),
|
||||||
'typography' => [
|
'typography' => [
|
||||||
'mode' => sanitize_text_field($request->get_param('typography')['mode'] ?? 'predefined'),
|
'mode' => sanitize_text_field($request->get_param('typography')['mode'] ?? 'predefined'),
|
||||||
@@ -378,6 +384,12 @@ class AppearanceController {
|
|||||||
return [
|
return [
|
||||||
'general' => [
|
'general' => [
|
||||||
'spa_mode' => 'full',
|
'spa_mode' => 'full',
|
||||||
|
'spa_pages' => [
|
||||||
|
'shop' => 0,
|
||||||
|
'cart' => 0,
|
||||||
|
'checkout' => 0,
|
||||||
|
'account' => 0,
|
||||||
|
],
|
||||||
'toast_position' => 'top-right',
|
'toast_position' => 'top-right',
|
||||||
'typography' => [
|
'typography' => [
|
||||||
'mode' => 'predefined',
|
'mode' => 'predefined',
|
||||||
|
|||||||
@@ -254,6 +254,12 @@ class Assets {
|
|||||||
|
|
||||||
error_log('[WooNooW Customer] should_load_assets check - Post ID: ' . ($post ? $post->ID : 'none'));
|
error_log('[WooNooW Customer] should_load_assets check - Post ID: ' . ($post ? $post->ID : 'none'));
|
||||||
|
|
||||||
|
// First check: Is this a designated SPA page?
|
||||||
|
if (self::is_spa_page()) {
|
||||||
|
error_log('[WooNooW Customer] Designated SPA page detected - loading assets');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Get Customer SPA settings
|
// Get Customer SPA settings
|
||||||
$spa_settings = get_option('woonoow_customer_spa_settings', []);
|
$spa_settings = get_option('woonoow_customer_spa_settings', []);
|
||||||
$mode = isset($spa_settings['mode']) ? $spa_settings['mode'] : 'disabled';
|
$mode = isset($spa_settings['mode']) ? $spa_settings['mode'] : 'disabled';
|
||||||
@@ -356,6 +362,31 @@ class Assets {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if current page is a designated SPA page
|
||||||
|
*/
|
||||||
|
private static function is_spa_page() {
|
||||||
|
global $post;
|
||||||
|
if (!$post) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get SPA page IDs from appearance settings
|
||||||
|
$appearance_settings = get_option('woonoow_appearance_settings', []);
|
||||||
|
$spa_pages = isset($appearance_settings['general']['spa_pages']) ? $appearance_settings['general']['spa_pages'] : [];
|
||||||
|
|
||||||
|
// Check if current page matches any SPA page
|
||||||
|
$current_page_id = $post->ID;
|
||||||
|
|
||||||
|
foreach ($spa_pages as $page_type => $page_id) {
|
||||||
|
if ($page_id && $current_page_id == $page_id) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dequeue conflicting scripts when SPA is active
|
* Dequeue conflicting scripts when SPA is active
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -68,10 +68,19 @@ class TemplateOverride {
|
|||||||
* Use SPA template (blank page)
|
* Use SPA template (blank page)
|
||||||
*/
|
*/
|
||||||
public static function use_spa_template($template) {
|
public static function use_spa_template($template) {
|
||||||
|
// Check if current page is a designated SPA page
|
||||||
|
if (self::is_spa_page()) {
|
||||||
|
$spa_template = plugin_dir_path(dirname(dirname(__FILE__))) . 'templates/spa-full-page.php';
|
||||||
|
if (file_exists($spa_template)) {
|
||||||
|
return $spa_template;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Legacy: Check SPA mode settings
|
||||||
$settings = get_option('woonoow_customer_spa_settings', []);
|
$settings = get_option('woonoow_customer_spa_settings', []);
|
||||||
$mode = isset($settings['mode']) ? $settings['mode'] : 'disabled';
|
$mode = isset($settings['mode']) ? $settings['mode'] : 'disabled';
|
||||||
|
|
||||||
// Mode 1: Disabled - but still check for shortcodes
|
// Mode 1: Disabled - but still check for shortcodes (legacy)
|
||||||
if ($mode === 'disabled') {
|
if ($mode === 'disabled') {
|
||||||
// Check if page has woonoow shortcodes
|
// Check if page has woonoow shortcodes
|
||||||
global $post;
|
global $post;
|
||||||
@@ -261,10 +270,40 @@ class TemplateOverride {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if current page is a designated SPA page
|
||||||
|
*/
|
||||||
|
private static function is_spa_page() {
|
||||||
|
global $post;
|
||||||
|
if (!$post) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get SPA page IDs from appearance settings
|
||||||
|
$appearance_settings = get_option('woonoow_appearance_settings', []);
|
||||||
|
$spa_pages = isset($appearance_settings['general']['spa_pages']) ? $appearance_settings['general']['spa_pages'] : [];
|
||||||
|
|
||||||
|
// Check if current page matches any SPA page
|
||||||
|
$current_page_id = $post->ID;
|
||||||
|
|
||||||
|
foreach ($spa_pages as $page_type => $page_id) {
|
||||||
|
if ($page_id && $current_page_id == $page_id) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if we should remove theme header/footer
|
* Check if we should remove theme header/footer
|
||||||
*/
|
*/
|
||||||
private static function should_remove_theme_elements() {
|
private static function should_remove_theme_elements() {
|
||||||
|
// Remove for designated SPA pages
|
||||||
|
if (self::is_spa_page()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
$settings = get_option('woonoow_customer_spa_settings', []);
|
$settings = get_option('woonoow_customer_spa_settings', []);
|
||||||
$mode = isset($settings['mode']) ? $settings['mode'] : 'disabled';
|
$mode = isset($settings['mode']) ? $settings['mode'] : 'disabled';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user