fix: resolve container width issues, spa redirects, and appearance settings overwrite. feat: enhance order/sub details and newsletter layout
This commit is contained in:
@@ -1,41 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace WooNooW\Admin;
|
||||
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
use WP_Error;
|
||||
|
||||
class AppearanceController {
|
||||
|
||||
class AppearanceController
|
||||
{
|
||||
|
||||
const OPTION_KEY = 'woonoow_appearance_settings';
|
||||
const API_NAMESPACE = 'woonoow/v1';
|
||||
|
||||
public static function init() {
|
||||
|
||||
public static function init()
|
||||
{
|
||||
add_action('rest_api_init', [__CLASS__, 'register_routes']);
|
||||
}
|
||||
|
||||
public static function register_routes() {
|
||||
|
||||
public static function register_routes()
|
||||
{
|
||||
// Get all settings (public access for frontend)
|
||||
register_rest_route(self::API_NAMESPACE, '/appearance/settings', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [__CLASS__, 'get_settings'],
|
||||
'permission_callback' => '__return_true',
|
||||
]);
|
||||
|
||||
|
||||
// Save general settings
|
||||
register_rest_route(self::API_NAMESPACE, '/appearance/general', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [__CLASS__, 'save_general'],
|
||||
'permission_callback' => [__CLASS__, 'check_permission'],
|
||||
]);
|
||||
|
||||
|
||||
// Save header settings
|
||||
register_rest_route(self::API_NAMESPACE, '/appearance/header', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [__CLASS__, 'save_header'],
|
||||
'permission_callback' => [__CLASS__, 'check_permission'],
|
||||
]);
|
||||
|
||||
|
||||
// Save footer settings
|
||||
register_rest_route(self::API_NAMESPACE, '/appearance/footer', [
|
||||
'methods' => 'POST',
|
||||
@@ -49,7 +53,7 @@ class AppearanceController {
|
||||
'callback' => [__CLASS__, 'save_menus'],
|
||||
'permission_callback' => [__CLASS__, 'check_permission'],
|
||||
]);
|
||||
|
||||
|
||||
// Save page-specific settings
|
||||
register_rest_route(self::API_NAMESPACE, '/appearance/pages/(?P<page>[a-zA-Z0-9_-]+)', [
|
||||
'methods' => 'POST',
|
||||
@@ -63,7 +67,7 @@ class AppearanceController {
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
|
||||
// Get all WordPress pages for page selector
|
||||
register_rest_route(self::API_NAMESPACE, '/pages/list', [
|
||||
'methods' => 'GET',
|
||||
@@ -71,40 +75,45 @@ class AppearanceController {
|
||||
'permission_callback' => [__CLASS__, 'check_permission'],
|
||||
]);
|
||||
}
|
||||
|
||||
public static function check_permission() {
|
||||
|
||||
public static function check_permission()
|
||||
{
|
||||
return current_user_can('manage_woocommerce');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all appearance settings
|
||||
*/
|
||||
public static function get_settings(WP_REST_Request $request) {
|
||||
public static function get_settings(WP_REST_Request $request)
|
||||
{
|
||||
$stored = get_option(self::OPTION_KEY, []);
|
||||
$defaults = self::get_default_settings();
|
||||
|
||||
|
||||
// Merge stored with defaults to ensure all fields exist (recursive)
|
||||
$settings = array_replace_recursive($defaults, $stored);
|
||||
|
||||
|
||||
return new WP_REST_Response([
|
||||
'success' => true,
|
||||
'data' => $settings,
|
||||
], 200);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save general settings
|
||||
*/
|
||||
public static function save_general(WP_REST_Request $request) {
|
||||
public static function save_general(WP_REST_Request $request)
|
||||
{
|
||||
$settings = get_option(self::OPTION_KEY, []);
|
||||
$defaults = self::get_default_settings();
|
||||
$settings = array_replace_recursive($defaults, $settings);
|
||||
|
||||
|
||||
$colors = $request->get_param('colors') ?? [];
|
||||
|
||||
$general_data = [
|
||||
'spa_mode' => sanitize_text_field($request->get_param('spaMode')),
|
||||
'spa_page' => absint($request->get_param('spaPage') ?? 0),
|
||||
|
||||
'container_width' => sanitize_text_field($request->get_param('containerWidth') ?? 'boxed'),
|
||||
'toast_position' => sanitize_text_field($request->get_param('toastPosition') ?? 'top-right'),
|
||||
'typography' => [
|
||||
'mode' => sanitize_text_field($request->get_param('typography')['mode'] ?? 'predefined'),
|
||||
@@ -125,23 +134,25 @@ class AppearanceController {
|
||||
'gradientEnd' => sanitize_hex_color($colors['gradientEnd'] ?? '#3b82f6'),
|
||||
],
|
||||
];
|
||||
|
||||
$settings['general'] = $general_data;
|
||||
|
||||
// Merge with existing general settings to preserve other keys (like spa_frontpage)
|
||||
$settings['general'] = array_merge($settings['general'] ?? [], $general_data);
|
||||
update_option(self::OPTION_KEY, $settings);
|
||||
|
||||
|
||||
return new WP_REST_Response([
|
||||
'success' => true,
|
||||
'message' => 'General settings saved successfully',
|
||||
'data' => $general_data,
|
||||
], 200);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save header settings
|
||||
*/
|
||||
public static function save_header(WP_REST_Request $request) {
|
||||
public static function save_header(WP_REST_Request $request)
|
||||
{
|
||||
$settings = get_option(self::OPTION_KEY, self::get_default_settings());
|
||||
|
||||
|
||||
$header_data = [
|
||||
'style' => sanitize_text_field($request->get_param('style')),
|
||||
'sticky' => (bool) $request->get_param('sticky'),
|
||||
@@ -159,23 +170,24 @@ class AppearanceController {
|
||||
'wishlist' => (bool) ($request->get_param('elements')['wishlist'] ?? false),
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
$settings['header'] = $header_data;
|
||||
update_option(self::OPTION_KEY, $settings);
|
||||
|
||||
|
||||
return new WP_REST_Response([
|
||||
'success' => true,
|
||||
'message' => 'Header settings saved successfully',
|
||||
'data' => $header_data,
|
||||
], 200);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save footer settings
|
||||
*/
|
||||
public static function save_footer(WP_REST_Request $request) {
|
||||
public static function save_footer(WP_REST_Request $request)
|
||||
{
|
||||
$settings = get_option(self::OPTION_KEY, self::get_default_settings());
|
||||
|
||||
|
||||
$social_links = $request->get_param('socialLinks') ?? [];
|
||||
$sanitized_links = [];
|
||||
foreach ($social_links as $link) {
|
||||
@@ -185,7 +197,7 @@ class AppearanceController {
|
||||
'url' => esc_url_raw($link['url'] ?? ''),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
// Sanitize contact data
|
||||
$contact_data = $request->get_param('contactData');
|
||||
$sanitized_contact = [
|
||||
@@ -196,7 +208,7 @@ class AppearanceController {
|
||||
'show_phone' => (bool) ($contact_data['show_phone'] ?? true),
|
||||
'show_address' => (bool) ($contact_data['show_address'] ?? true),
|
||||
];
|
||||
|
||||
|
||||
// Sanitize labels
|
||||
$labels = $request->get_param('labels');
|
||||
$sanitized_labels = [
|
||||
@@ -206,7 +218,7 @@ class AppearanceController {
|
||||
'newsletter_title' => sanitize_text_field($labels['newsletter_title'] ?? 'Newsletter'),
|
||||
'newsletter_description' => sanitize_text_field($labels['newsletter_description'] ?? 'Subscribe to get updates'),
|
||||
];
|
||||
|
||||
|
||||
// Sanitize custom sections
|
||||
$sections = $request->get_param('sections') ?? [];
|
||||
$sanitized_sections = [];
|
||||
@@ -219,28 +231,44 @@ class AppearanceController {
|
||||
'visible' => (bool) ($section['visible'] ?? true),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
$footer_data = [
|
||||
'payment' => [
|
||||
'enabled' => (bool) ($request->get_param('payment')['enabled'] ?? true),
|
||||
'title' => sanitize_text_field($request->get_param('payment')['title'] ?? 'We accept'),
|
||||
'methods' => array_map(function ($method) {
|
||||
return [
|
||||
'id' => sanitize_text_field($method['id'] ?? uniqid()),
|
||||
'url' => esc_url_raw($method['url'] ?? ''),
|
||||
'label' => sanitize_text_field($method['label'] ?? ''),
|
||||
'width' => sanitize_text_field($method['width'] ?? ''),
|
||||
];
|
||||
}, $request->get_param('payment')['methods'] ?? []),
|
||||
],
|
||||
'copyright' => [
|
||||
'enabled' => (bool) ($request->get_param('copyright')['enabled'] ?? true),
|
||||
'text' => wp_kses_post($request->get_param('copyright')['text'] ?? ''),
|
||||
],
|
||||
'columns' => sanitize_text_field($request->get_param('columns')),
|
||||
'style' => sanitize_text_field($request->get_param('style')),
|
||||
'copyright_text' => wp_kses_post($request->get_param('copyrightText')),
|
||||
// 'copyright_text' => Deprecated, moved to copyright.text
|
||||
// 'elements' => Deprecated, moved to individual sections (except menu/contact/social flags if needed)
|
||||
'elements' => [
|
||||
'newsletter' => (bool) ($request->get_param('elements')['newsletter'] ?? true),
|
||||
'social' => (bool) ($request->get_param('elements')['social'] ?? true),
|
||||
'payment' => (bool) ($request->get_param('elements')['payment'] ?? true),
|
||||
'copyright' => (bool) ($request->get_param('elements')['copyright'] ?? true),
|
||||
'menu' => (bool) ($request->get_param('elements')['menu'] ?? true),
|
||||
'contact' => (bool) ($request->get_param('elements')['contact'] ?? true),
|
||||
// Payment and Copyright moved
|
||||
],
|
||||
'social_links' => $sanitized_links,
|
||||
'contact_data' => $sanitized_contact,
|
||||
'labels' => $sanitized_labels,
|
||||
'sections' => $sanitized_sections,
|
||||
];
|
||||
|
||||
|
||||
$settings['footer'] = $footer_data;
|
||||
update_option(self::OPTION_KEY, $settings);
|
||||
|
||||
|
||||
return new WP_REST_Response([
|
||||
'success' => true,
|
||||
'message' => 'Footer settings saved successfully',
|
||||
@@ -251,11 +279,12 @@ class AppearanceController {
|
||||
/**
|
||||
* Save menu settings
|
||||
*/
|
||||
public static function save_menus(WP_REST_Request $request) {
|
||||
public static function save_menus(WP_REST_Request $request)
|
||||
{
|
||||
$settings = get_option(self::OPTION_KEY, self::get_default_settings());
|
||||
|
||||
|
||||
$menus = $request->get_param('menus') ?? [];
|
||||
|
||||
|
||||
// Sanitize menus
|
||||
$sanitized_menus = [
|
||||
'primary' => [],
|
||||
@@ -265,7 +294,7 @@ class AppearanceController {
|
||||
foreach (['primary', 'mobile'] as $location) {
|
||||
if (isset($menus[$location]) && is_array($menus[$location])) {
|
||||
foreach ($menus[$location] as $item) {
|
||||
$sanitized_menus[$location][] = [
|
||||
$sanitized_menus[$location][] = [
|
||||
'id' => sanitize_text_field($item['id'] ?? uniqid()),
|
||||
'label' => sanitize_text_field($item['label'] ?? ''),
|
||||
'type' => sanitize_text_field($item['type'] ?? 'page'), // page, custom
|
||||
@@ -275,46 +304,48 @@ class AppearanceController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$settings['menus'] = $sanitized_menus;
|
||||
update_option(self::OPTION_KEY, $settings);
|
||||
|
||||
|
||||
return new WP_REST_Response([
|
||||
'success' => true,
|
||||
'message' => 'Menu settings saved successfully',
|
||||
'data' => $sanitized_menus,
|
||||
], 200);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save page-specific settings
|
||||
*/
|
||||
public static function save_page_settings(WP_REST_Request $request) {
|
||||
public static function save_page_settings(WP_REST_Request $request)
|
||||
{
|
||||
$settings = get_option(self::OPTION_KEY, self::get_default_settings());
|
||||
$page = $request->get_param('page');
|
||||
|
||||
|
||||
// Get all parameters from request
|
||||
$page_data = $request->get_json_params();
|
||||
|
||||
|
||||
// Sanitize based on page type
|
||||
$sanitized_data = self::sanitize_page_data($page, $page_data);
|
||||
|
||||
|
||||
$settings['pages'][$page] = $sanitized_data;
|
||||
update_option(self::OPTION_KEY, $settings);
|
||||
|
||||
|
||||
return new WP_REST_Response([
|
||||
'success' => true,
|
||||
'message' => ucfirst($page) . ' page settings saved successfully',
|
||||
'data' => $sanitized_data,
|
||||
], 200);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitize page-specific data
|
||||
*/
|
||||
private static function sanitize_page_data($page, $data) {
|
||||
private static function sanitize_page_data($page, $data)
|
||||
{
|
||||
$sanitized = [];
|
||||
|
||||
|
||||
switch ($page) {
|
||||
case 'shop':
|
||||
$sanitized = [
|
||||
@@ -342,7 +373,7 @@ class AppearanceController {
|
||||
],
|
||||
];
|
||||
break;
|
||||
|
||||
|
||||
case 'product':
|
||||
$sanitized = [
|
||||
'layout' => [
|
||||
@@ -366,7 +397,7 @@ class AppearanceController {
|
||||
],
|
||||
];
|
||||
break;
|
||||
|
||||
|
||||
case 'cart':
|
||||
$sanitized = [
|
||||
'layout' => [
|
||||
@@ -381,7 +412,7 @@ class AppearanceController {
|
||||
],
|
||||
];
|
||||
break;
|
||||
|
||||
|
||||
case 'checkout':
|
||||
$sanitized = [
|
||||
'layout' => [
|
||||
@@ -399,7 +430,7 @@ class AppearanceController {
|
||||
],
|
||||
];
|
||||
break;
|
||||
|
||||
|
||||
case 'thankyou':
|
||||
$sanitized = [
|
||||
'template' => sanitize_text_field($data['template'] ?? 'basic'),
|
||||
@@ -414,7 +445,7 @@ class AppearanceController {
|
||||
],
|
||||
];
|
||||
break;
|
||||
|
||||
|
||||
case 'account':
|
||||
$sanitized = [
|
||||
'layout' => [
|
||||
@@ -430,31 +461,32 @@ class AppearanceController {
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return $sanitized;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get list of WordPress pages for page selector
|
||||
*/
|
||||
public static function get_pages_list(WP_REST_Request $request) {
|
||||
public static function get_pages_list(WP_REST_Request $request)
|
||||
{
|
||||
$pages = get_pages([
|
||||
'post_status' => 'publish',
|
||||
'sort_column' => 'post_title',
|
||||
'sort_order' => 'ASC',
|
||||
]);
|
||||
|
||||
|
||||
$store_pages = [
|
||||
(int) get_option('woocommerce_shop_page_id'),
|
||||
(int) get_option('woocommerce_cart_page_id'),
|
||||
(int) get_option('woocommerce_checkout_page_id'),
|
||||
(int) get_option('woocommerce_myaccount_page_id'),
|
||||
];
|
||||
|
||||
$pages_list = array_map(function($page) use ($store_pages) {
|
||||
|
||||
$pages_list = array_map(function ($page) use ($store_pages) {
|
||||
$is_woonoow = !empty(get_post_meta($page->ID, '_wn_page_structure', true));
|
||||
$is_store = in_array((int)$page->ID, $store_pages, true);
|
||||
|
||||
|
||||
return [
|
||||
'id' => $page->ID,
|
||||
'title' => $page->post_title,
|
||||
@@ -463,21 +495,24 @@ class AppearanceController {
|
||||
'is_store_page' => $is_store,
|
||||
];
|
||||
}, $pages);
|
||||
|
||||
|
||||
return new WP_REST_Response([
|
||||
'success' => true,
|
||||
'data' => $pages_list,
|
||||
], 200);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get default settings structure
|
||||
*/
|
||||
public static function get_default_settings() {
|
||||
public static function get_default_settings()
|
||||
{
|
||||
return [
|
||||
'general' => [
|
||||
'spa_mode' => 'full',
|
||||
'spa_page' => 0,
|
||||
|
||||
'container_width' => 'boxed',
|
||||
'toast_position' => 'top-right',
|
||||
'typography' => [
|
||||
'mode' => 'predefined',
|
||||
@@ -516,12 +551,22 @@ class AppearanceController {
|
||||
'footer' => [
|
||||
'columns' => '4',
|
||||
'style' => 'detailed',
|
||||
'copyright_text' => '© 2024 WooNooW. All rights reserved.',
|
||||
'payment' => [
|
||||
'enabled' => true,
|
||||
'title' => 'We accept',
|
||||
'methods' => [
|
||||
['id' => 'visa', 'url' => '', 'label' => 'Visa', 'default_icon' => 'visa'], // Placeholder logic for defaults
|
||||
['id' => 'mastercard', 'url' => '', 'label' => 'Mastercard', 'default_icon' => 'mastercard'],
|
||||
['id' => 'paypal', 'url' => '', 'label' => 'PayPal', 'default_icon' => 'paypal'],
|
||||
],
|
||||
],
|
||||
'copyright' => [
|
||||
'enabled' => true,
|
||||
'text' => '© 2024 WooNooW. All rights reserved.',
|
||||
],
|
||||
'elements' => [
|
||||
'newsletter' => true,
|
||||
'social' => true,
|
||||
'payment' => true,
|
||||
'copyright' => true,
|
||||
'menu' => true,
|
||||
'contact' => true,
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user