setup_error_handling(); $this->load_includes(); add_action('after_setup_theme', [$this, 'setup_theme']); add_action('wp_enqueue_scripts', [$this, 'enqueue_theme_styles']); add_action('enqueue_block_editor_assets', [$this, 'enqueue_editor_scripts']); // Add skip link for accessibility add_action('wp_body_open', [$this, 'add_skip_link']); // Temporarily disable complex features to test basic functionality // add_action('init', [$this, 'register_block_bindings']); // add_action('init', [$this, 'register_pattern_categories']); // add_action('after_setup_theme', [$this, 'enable_image_block_supports']); // Add debugging for admin pages add_action('admin_init', [$this, 'debug_admin_loading']); // Add simple test action to verify theme is loading add_action('init', function () { error_log("Axvart Theme: Theme is loading successfully"); }); // Register layout supports for blocks add_action('init', [$this, 'register_layout_supports']); // Register custom blocks add_action('init', [$this, 'register_blocks']); } /** * Set up error handling to prevent fatal errors. */ private function setup_error_handling() { // Only set up error handling in admin area if (!is_admin()) { return; } // Set up error handler to catch fatal errors set_error_handler(function ($errno, $errstr, $errfile, $errline) { // Log the error error_log("Axvart Error: $errstr in $errfile on line $errline"); // Only suppress specific REST API errors if ( strpos($errstr, 'get_data()') !== false && strpos($errfile, 'rest-api') !== false ) { return true; // Don't execute PHP internal error handler } return false; // Let PHP handle other errors normally }); // Set up exception handler set_exception_handler(function ($exception) { error_log("Axvart Exception: " . $exception->getMessage()); // Only suppress specific REST API exceptions if ( strpos($exception->getMessage(), 'get_data()') !== false && strpos($exception->getFile(), 'rest-api') !== false ) { return; // Don't show the error } // Re-throw other exceptions throw $exception; }); } /** * Debug admin page loading. */ public function debug_admin_loading() { error_log("Axvart Debug: Admin page loading - " . $_SERVER['REQUEST_URI']); // Check if we're on a post edit page if (isset($_GET['post']) && isset($_GET['action']) && $_GET['action'] === 'edit') { error_log("Axvart Debug: Post edit page detected - Post ID: " . $_GET['post']); } } /** * Load necessary files for the theme. * * Includes all required PHP files from the includes directory. */ private function load_includes() { $files = [ 'class-attributes.php', // Handles custom block attributes 'block-styles.php', // Registers custom block styles 'class-enqueue.php', // Handles asset loading 'features/scroll-top.php', // Scroll-to-top feature 'theme-settings.php', // Theme settings ]; foreach ($files as $file) { $path = get_template_directory() . '/includes/' . $file; if (file_exists($path)) { require_once $path; } } } /** * Set up theme features and support. * * Registers theme support for various WordPress features. */ public function setup_theme() { // Load theme text domain for translations load_theme_textdomain('axvart', get_template_directory() . '/languages'); // Add support for post formats add_theme_support( 'post-formats', ['aside', 'audio', 'chat', 'gallery', 'image', 'link', 'quote', 'status', 'video'] ); // Add support for block templates and layout controls add_theme_support('block-templates'); add_theme_support('align-wide'); add_theme_support('wp-block-styles'); add_theme_support('responsive-embeds'); // Add support for layout controls (required for justification) add_theme_support('layout'); add_theme_support('custom-spacing'); } /** * Register layout supports for blocks. * * Adds layout support for columns blocks to enable justification controls. */ public function register_layout_supports() { // Register layout supports for columns blocks add_filter('block_type_metadata', function ($metadata) { if (!is_array($metadata) || !isset($metadata['name'])) { return $metadata; } // Add layout support for columns and column blocks if (in_array($metadata['name'], ['core/columns', 'core/column'])) { if (!isset($metadata['supports'])) { $metadata['supports'] = []; } if (!isset($metadata['supports']['layout'])) { $metadata['supports']['layout'] = []; } $metadata['supports']['layout']['allowJustification'] = true; $metadata['supports']['layout']['allowVerticalAlignment'] = true; } return $metadata; }); } /** * Register custom blocks from build directory. * * Registers all theme blocks using block.json metadata. */ public function register_blocks() { // Register the Accordion block $accordion_block_path = get_template_directory() . '/build/features/accordion-block'; if (file_exists($accordion_block_path . '/block.json')) { register_block_type_from_metadata($accordion_block_path); // Manually enqueue frontend styles and scripts // Using wp_enqueue_scripts to ensure they load on frontend add_action('wp_enqueue_scripts', function () use ($accordion_block_path) { if (file_exists($accordion_block_path . '/style-index.css')) { wp_enqueue_style( 'axvart-accordion-block-style', get_template_directory_uri() . '/build/features/accordion-block/style-index.css', array(), filemtime($accordion_block_path . '/style-index.css') ); } if (file_exists($accordion_block_path . '/frontend.js')) { wp_enqueue_script( 'axvart-accordion-block-script', get_template_directory_uri() . '/build/features/accordion-block/frontend.js', array(), filemtime($accordion_block_path . '/frontend.js'), true ); } }); } // Register the Animated Counter block $animated_counter_block_path = get_template_directory() . '/build/features/animated-counter-block'; if (file_exists($animated_counter_block_path . '/block.json')) { register_block_type_from_metadata($animated_counter_block_path); // Manually enqueue frontend styles and scripts add_action('wp_enqueue_scripts', function () use ($animated_counter_block_path) { if (file_exists($animated_counter_block_path . '/style-index.css')) { wp_enqueue_style( 'axvart-animated-counter-block-style', get_template_directory_uri() . '/build/features/animated-counter-block/style-index.css', array(), filemtime($animated_counter_block_path . '/style-index.css') ); } if (file_exists($animated_counter_block_path . '/frontend.js')) { wp_enqueue_script( 'axvart-animated-counter-block-script', get_template_directory_uri() . '/build/features/animated-counter-block/frontend.js', array(), filemtime($animated_counter_block_path . '/frontend.js'), true ); } }); } // Register the Button Widget block $button_widget_block_path = get_template_directory() . '/build/features/button-widget'; if (file_exists($button_widget_block_path . '/block.json')) { register_block_type_from_metadata($button_widget_block_path); // Manually enqueue frontend styles add_action('wp_enqueue_scripts', function () use ($button_widget_block_path) { if (file_exists($button_widget_block_path . '/style-index.css')) { wp_enqueue_style( 'axvart-button-widget-block-style', get_template_directory_uri() . '/build/features/button-widget/style-index.css', array(), filemtime($button_widget_block_path . '/style-index.css') ); } }); } // Register the Card Widget block $card_widget_block_path = get_template_directory() . '/build/features/card-widget'; if (file_exists($card_widget_block_path . '/block.json')) { register_block_type_from_metadata($card_widget_block_path); // Manually enqueue frontend styles add_action('wp_enqueue_scripts', function () use ($card_widget_block_path) { if (file_exists($card_widget_block_path . '/style-index.css')) { wp_enqueue_style( 'axvart-card-widget-block-style', get_template_directory_uri() . '/build/features/card-widget/style-index.css', array(), filemtime($card_widget_block_path . '/style-index.css') ); } }); } // Register the SVG Icon block $svg_icon_block_path = get_template_directory() . '/build/features/svg-icon-block'; if (file_exists($svg_icon_block_path . '/block.json')) { register_block_type_from_metadata($svg_icon_block_path); // Add inline styles for proper color handling add_action('wp_enqueue_scripts', function () { $inline_css = ' .wp-block-axvart-svg-icon { display: inline-block; line-height: 0; } .wp-block-axvart-svg-icon .svg-icon-container { display: inline-flex; align-items: center; justify-content: center; color: var(--icon-color, currentColor); } .wp-block-axvart-svg-icon .svg-icon-container svg { width: 100%; height: 100%; fill: currentColor !important; color: currentColor !important; } .wp-block-axvart-svg-icon .svg-icon-container svg * { fill: inherit !important; stroke: inherit !important; } .wp-block-axvart-svg-icon .svg-icon-container img { width: 100%; height: 100%; object-fit: contain; } .wp-block-axvart-svg-icon .svg-icon-mask { display: block; width: 100%; height: 100%; background-color: currentColor; mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat; mask-position: center; -webkit-mask-position: center; mask-size: contain; -webkit-mask-size: contain; } .wp-block-axvart-svg-icon.has-text-align-center { margin-left: auto; margin-right: auto; } .wp-block-axvart-svg-icon.has-text-align-right { margin-left: auto; } '; wp_add_inline_style('wp-block-library', $inline_css); }); } // Register the Responsive Nav Menu block $responsive_nav_menu_block_path = get_template_directory() . '/build/features/responsive-nav-menu'; if (file_exists($responsive_nav_menu_block_path . '/block.json')) { register_block_type_from_metadata($responsive_nav_menu_block_path); } // Register the Advanced Icon Button block $advanced_icon_button_block_path = get_template_directory() . '/build/features/advanced-icon-button'; if (file_exists($advanced_icon_button_block_path . '/block.json')) { register_block_type_from_metadata($advanced_icon_button_block_path); // Ensure dashicons are loaded in editor add_action('enqueue_block_editor_assets', function () { wp_enqueue_style('dashicons'); }); // Manually enqueue frontend styles add_action('wp_enqueue_scripts', function () use ($advanced_icon_button_block_path) { // Enqueue dashicons on frontend wp_enqueue_style('dashicons'); if (file_exists($advanced_icon_button_block_path . '/style-index.css')) { wp_enqueue_style( 'axvart-advanced-icon-button-style', get_template_directory_uri() . '/build/features/advanced-icon-button/style-index.css', array(), filemtime($advanced_icon_button_block_path . '/style-index.css') ); } }); } // Register the Interactive Hotspot Image block $interactive_hotspot_image_block_path = get_template_directory() . '/build/features/interactive-hotspot-image'; if (file_exists($interactive_hotspot_image_block_path . '/block.json')) { register_block_type_from_metadata($interactive_hotspot_image_block_path); // Manually enqueue frontend styles and scripts add_action('wp_enqueue_scripts', function () use ($interactive_hotspot_image_block_path) { if (file_exists($interactive_hotspot_image_block_path . '/style-index.css')) { wp_enqueue_style( 'axvart-interactive-hotspot-image-style', get_template_directory_uri() . '/build/features/interactive-hotspot-image/style-index.css', array(), filemtime($interactive_hotspot_image_block_path . '/style-index.css') ); } if (file_exists($interactive_hotspot_image_block_path . '/view.js')) { wp_enqueue_script( 'axvart-interactive-hotspot-image-view-script', get_template_directory_uri() . '/build/features/interactive-hotspot-image/view.js', array(), filemtime($interactive_hotspot_image_block_path . '/view.js'), true ); } }); } // Register the Pricing Block $pricing_block_path = get_template_directory() . '/build/features/pricing-block'; if (file_exists($pricing_block_path . '/block.json')) { register_block_type_from_metadata($pricing_block_path); // Manually enqueue frontend styles if they exist add_action('wp_enqueue_scripts', function () use ($pricing_block_path) { if (file_exists($pricing_block_path . '/style-index.css')) { wp_enqueue_style( 'axvart-pricing-block-style', get_template_directory_uri() . '/build/features/pricing-block/style-index.css', array(), filemtime($pricing_block_path . '/style-index.css') ); } }); } // Register the Live Clock/Date block $live_clock_date_block_path = get_template_directory() . '/build/features/live-clock-date'; if (file_exists($live_clock_date_block_path . '/block.json')) { register_block_type_from_metadata($live_clock_date_block_path); // Manually enqueue frontend styles and scripts if they exist add_action('wp_enqueue_scripts', function () use ($live_clock_date_block_path) { if (file_exists($live_clock_date_block_path . '/style-index.css')) { wp_enqueue_style( 'axvart-live-clock-date-style', get_template_directory_uri() . '/build/features/live-clock-date/style-index.css', array(), filemtime($live_clock_date_block_path . '/style-index.css') ); } if (file_exists($live_clock_date_block_path . '/view.js')) { wp_enqueue_script( 'axvart-live-clock-date-view-script', get_template_directory_uri() . '/build/features/live-clock-date/view.js', array(), filemtime($live_clock_date_block_path . '/view.js'), true ); } }); } // Register the Marquee block $marquee_block_path = get_template_directory() . '/build/features/marquee'; if (file_exists($marquee_block_path . '/block.json')) { register_block_type_from_metadata($marquee_block_path); // Manually enqueue frontend styles add_action('wp_enqueue_scripts', function () use ($marquee_block_path) { if (file_exists($marquee_block_path . '/style-index.css')) { wp_enqueue_style( 'axvart-marquee-style', get_template_directory_uri() . '/build/features/marquee/style-index.css', array(), filemtime($marquee_block_path . '/style-index.css') ); } }); } // Register the 3D Tilt Card Block $tilt_card_block_path = get_template_directory() . '/build/features/3d-tilt-card-block'; if (file_exists($tilt_card_block_path . '/block.json')) { register_block_type_from_metadata($tilt_card_block_path); } // Register the Button Group Block $button_group_block_path = get_template_directory() . '/build/features/button-group-block'; if (file_exists($button_group_block_path . '/block.json')) { register_block_type_from_metadata($button_group_block_path); } // Register the Button Item Block $button_item_block_path = get_template_directory() . '/build/features/button-group-block/button-item'; if (file_exists($button_item_block_path . '/block.json')) { register_block_type_from_metadata($button_item_block_path); } // Register the Advanced Button block $advanced_button_block_path = get_template_directory() . '/build/features/advanced-button'; if (file_exists($advanced_button_block_path . '/block.json')) { register_block_type_from_metadata($advanced_button_block_path); // Manually enqueue frontend styles add_action('wp_enqueue_scripts', function () use ($advanced_button_block_path) { if (file_exists($advanced_button_block_path . '/style-index.css')) { wp_enqueue_style( 'axvart-advanced-button-style', get_template_directory_uri() . '/build/features/advanced-button/style-index.css', array(), filemtime($advanced_button_block_path . '/style-index.css') ); } }); } // Register the Modern Video Block $modern_video_block_path = get_template_directory() . '/build/features/modern-video-block'; if (file_exists($modern_video_block_path . '/block.json')) { register_block_type_from_metadata($modern_video_block_path); // Manually enqueue frontend styles and scripts add_action('wp_enqueue_scripts', function () use ($modern_video_block_path) { if (file_exists($modern_video_block_path . '/style-index.css')) { wp_enqueue_style( 'axvart-modern-video-block-style', get_template_directory_uri() . '/build/features/modern-video-block/style-index.css', array(), filemtime($modern_video_block_path . '/style-index.css') ); } if (file_exists($modern_video_block_path . '/view.js')) { wp_enqueue_script( 'axvart-modern-video-block-view-script', get_template_directory_uri() . '/build/features/modern-video-block/view.js', array(), filemtime($modern_video_block_path . '/view.js'), true ); } }); } // Register the Contact Form Widget $contact_form_widget_path = get_template_directory() . '/build/features/contact-form-widget'; if (file_exists($contact_form_widget_path . '/block.json')) { register_block_type_from_metadata($contact_form_widget_path); // Manually enqueue frontend styles and scripts add_action('wp_enqueue_scripts', function () use ($contact_form_widget_path) { if (file_exists($contact_form_widget_path . '/style-index.css')) { wp_enqueue_style( 'axvart-contact-form-widget-style', get_template_directory_uri() . '/build/features/contact-form-widget/style-index.css', array(), filemtime($contact_form_widget_path . '/style-index.css') ); } if (file_exists($contact_form_widget_path . '/view.js')) { wp_enqueue_script( 'axvart-contact-form-widget-view-script', get_template_directory_uri() . '/build/features/contact-form-widget/view.js', array(), filemtime($contact_form_widget_path . '/view.js'), true ); // Localize script for AJAX wp_localize_script( 'axvart-contact-form-widget-view-script', 'axvartContactForm', array( 'ajaxUrl' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('axvart_contact_form_nonce') ) ); } }); } // Register the Input Block $input_block_path = get_template_directory() . '/build/features/input-block'; if (file_exists($input_block_path . '/block.json')) { register_block_type_from_metadata($input_block_path); } } /** * Enqueue theme styles. * * Loads the main stylesheet for the theme. */ public function enqueue_theme_styles() { wp_enqueue_style( 'axvart-style', get_parent_theme_file_uri('style.css'), [], wp_get_theme()->get('Version') ); // Add inline CSS for skip link $skip_link_css = " .skip-link { position: absolute !important; top: -40px !important; left: 6px !important; background: #000 !important; color: #fff !important; padding: 8px 16px !important; text-decoration: none !important; border-radius: 4px !important; z-index: 10000 !important; transition: top 0.3s ease !important; font-weight: bold !important; display: block !important; width: auto !important; height: auto !important; overflow: clip !important; clip: rect(1px, 1px, 1px, 1px); } .skip-link:focus { top: 42px !important; outline: 2px solid #fff !important; outline-offset: 2px !important; clip: auto !important; height: auto !important; width: auto !important; overflow: clip !important; } #main-content:focus { outline: none; } "; wp_add_inline_style('axvart-style', $skip_link_css); } /** * Enqueue editor scripts. * * Loads scripts for the block editor including helper and main editor scripts. */ public function enqueue_editor_scripts() { // Load editor scripts only in admin if (!is_admin()) { return; } $theme_version = wp_get_theme()->get('Version'); $asset_path = get_template_directory() . '/build/index.asset.php'; if (file_exists($asset_path)) { $asset_data = require $asset_path; // Register helper script wp_register_script( 'axvart-helper-script', get_template_directory_uri() . '/assets/js/helper.js', [], $theme_version, true ); // Register main editor script wp_register_script( 'axvart-block-editor-script', get_template_directory_uri() . '/build/index.js', $asset_data['dependencies'], $asset_data['version'], true ); // Enqueue the script wp_enqueue_script('axvart-block-editor-script'); } } /** * Register block bindings for dynamic content. * * Sets up custom block bindings for the theme. */ public function register_block_bindings() { register_block_bindings_source( 'axvart/format', [ 'label' => _x('Post format name', 'Label for the block binding placeholder in the editor', 'axvart'), 'get_value_callback' => [$this, 'format_binding_callback'], ] ); } /** * Callback for the post format binding. * * Returns the formatted post format name. * * @return string|null The post format name or null if standard format. */ public function format_binding_callback() { $post_format_slug = get_post_format(); if ($post_format_slug && 'standard' !== $post_format_slug) { return get_post_format_string($post_format_slug); } } /** * Register block pattern categories. * * Creates custom pattern categories for the theme. */ public function register_pattern_categories() { register_block_pattern_category( 'axvart_page', [ 'label' => __('Pages', 'axvart'), 'description' => __('A collection of full page layouts.', 'axvart'), ] ); register_block_pattern_category( 'axvart_post-format', [ 'label' => __('Post formats', 'axvart'), 'description' => __('A collection of post format patterns.', 'axvart'), ] ); } /** * Enable additional block supports for image blocks. * * Adds padding and background color support to image blocks. */ public function enable_image_block_supports() { // Enable padding and background for image blocks add_theme_support('custom-spacing'); add_theme_support('padding'); add_theme_support('margin'); // Register support for background colors on image blocks add_filter('block_type_metadata', function ($metadata) { // Ensure metadata is valid if (!is_array($metadata) || !isset($metadata['name']) || $metadata['name'] !== 'core/image') { return $metadata; } // Ensure supports array exists if (!isset($metadata['supports']) || !is_array($metadata['supports'])) { $metadata['supports'] = []; } // Ensure spacing support exists if (!isset($metadata['supports']['spacing']) || !is_array($metadata['supports']['spacing'])) { $metadata['supports']['spacing'] = []; } // Ensure color support exists if (!isset($metadata['supports']['color']) || !is_array($metadata['supports']['color'])) { $metadata['supports']['color'] = []; } $metadata['supports']['spacing']['padding'] = true; $metadata['supports']['spacing']['margin'] = true; $metadata['supports']['color']['background'] = true; return $metadata; }); // Enable the render_block filter for proper image block handling add_filter('render_block', [$this, 'modify_image_block_output'], 10, 2); // Add filter to modify block attributes before rendering add_filter('block_type_metadata', [$this, 'modify_image_block_metadata'], 10, 1); // Add filter to modify block attributes in editor add_filter('block_editor_settings_all', [$this, 'modify_editor_settings'], 10, 2); // Add debugging to identify the source of warnings add_action('init', [$this, 'debug_block_registration'], 999); // Add filter to prevent REST API warnings add_filter('rest_pre_dispatch', [$this, 'prevent_rest_api_warnings'], 10, 3); // Add filter to handle REST API responses and prevent null errors add_filter('rest_post_dispatch', [$this, 'handle_rest_api_response'], 10, 3); // Add filter to handle block editor preload errors add_filter('block_editor_rest_api_preload', [$this, 'handle_block_editor_preload'], 10, 2); // Add filter to handle rest_preload_api_request errors add_filter('rest_preload_api_request', [$this, 'handle_preload_api_request'], 10, 2); // Add filter to handle REST API server errors // Temporarily disabled to prevent conflicts // add_filter('rest_pre_dispatch', [$this, 'handle_rest_server_errors'], 5, 3); // Add filter to handle response_to_data errors // Temporarily disabled to prevent conflicts // add_filter('rest_response_to_data', [$this, 'handle_response_to_data'], 10, 3); // Add filter to ensure all block metadata is properly structured add_filter('block_type_metadata', [$this, 'ensure_block_metadata_structure'], 5, 1); // Add filter to handle block editor settings add_filter('block_editor_settings_all', [$this, 'ensure_block_editor_settings'], 10, 2); // Add filter to ensure block editor loads properly add_filter('block_editor_rest_api_preload', [$this, 'ensure_block_editor_preload'], 5, 2); // Add custom CSS to apply styles to img tag instead of figure add_action('wp_enqueue_scripts', [$this, 'enqueue_image_block_styles']); add_action('enqueue_block_editor_assets', [$this, 'enqueue_image_block_styles']); // Add JavaScript to force border styles on figure elements add_action('wp_enqueue_scripts', [$this, 'enqueue_image_block_script']); add_action('enqueue_block_editor_assets', [$this, 'enqueue_image_block_script']); // Add editor-specific script add_action('enqueue_block_editor_assets', [$this, 'enqueue_editor_specific_script']); // Register custom block variation for image blocks // Temporarily disabled due to JSX syntax error in regular JS file // add_action('init', [$this, 'register_image_block_variation']); } /** * Enqueue custom styles for image blocks. * * Applies padding, background, border, and radius styles properly to image blocks. */ public function enqueue_image_block_styles() { $custom_css = ' /* Fix for image blocks with padding - ensure proper display */ .wp-block-image { display: block; overflow: clip; } /* Ensure img elements within padded blocks are visible */ .wp-block-image img { display: block; max-width: 100%; height: auto; border: none; border-radius: 0; } /* Handle padding on image blocks properly */ .wp-block-image[style*="padding"] { display: block; overflow: clip; } .wp-block-image[style*="padding"] figure { margin: 0; padding: 0; } .wp-block-image[style*="padding"] img { display: block; max-width: 100%; height: auto; } /* Handle background colors on image blocks */ .wp-block-image[style*="background"] { display: block; } .wp-block-image[style*="background"] figure { margin: 0; } /* Force border and radius to be on figure, not img */ .wp-block-image figure { border: inherit !important; border-radius: inherit !important; } .wp-block-image img { border: none !important; border-radius: 0 !important; } /* Target WordPress-generated border classes */ .wp-block-image.has-border-color figure { border-color: inherit !important; } .wp-block-image.has-border-color img { border-color: transparent !important; } .wp-block-image.has-border-width figure { border-width: inherit !important; } .wp-block-image.has-border-width img { border-width: 0 !important; } .wp-block-image.has-border-style figure { border-style: inherit !important; } .wp-block-image.has-border-style img { border-style: none !important; } /* Specific overrides for inline styles */ .wp-block-image figure[style*="border"] { border: inherit !important; } .wp-block-image figure[style*="border-radius"] { border-radius: inherit !important; overflow: hidden !important; } .wp-block-image img[style*="border"] { border: none !important; } .wp-block-image img[style*="border-radius"] { border-radius: 0 !important; } /* Additional specificity for WordPress border classes */ .wp-block-image[class*="has-border"] figure { border: inherit !important; border-radius: inherit !important; } .wp-block-image[class*="has-border"] img { border: none !important; border-radius: 0 !important; } /* Maximum specificity overrides for inline styles */ .wp-block-image img[style*="border"] { border: none !important; border-radius: 0 !important; border-width: 0 !important; border-color: transparent !important; border-style: none !important; } .wp-block-image img[style*="border-radius"] { border-radius: 0 !important; } .wp-block-image img[style*="border-width"] { border-width: 0 !important; } .wp-block-image img[style*="border-color"] { border-color: transparent !important; } .wp-block-image img[style*="border-style"] { border-style: none !important; } /* Force figure to inherit border styles */ .wp-block-image figure { border: inherit !important; border-radius: inherit !important; border-width: inherit !important; border-color: inherit !important; border-style: inherit !important; } /* Ensure proper spacing for image blocks with both padding and background */ .wp-block-image[style*="padding"][style*="background"] { display: block; overflow: clip; } /* Fix for editor preview mode */ .editor-styles-wrapper .wp-block-image[style*="padding"] { display: block !important; overflow: clip !important; } .editor-styles-wrapper .wp-block-image[style*="padding"] img { display: block !important; max-width: 100% !important; height: auto !important; } /* Editor-specific border fixes */ .editor-styles-wrapper .wp-block-image img[style*="border"] { border: none !important; border-radius: 0 !important; border-width: 0 !important; border-color: transparent !important; border-style: none !important; } .editor-styles-wrapper .wp-block-image img[style*="border-radius"] { border-radius: 0 !important; } .editor-styles-wrapper .wp-block-image figure { border: inherit !important; border-radius: inherit !important; border-width: inherit !important; border-color: inherit !important; border-style: inherit !important; } /* Force editor to apply borders to figure */ .editor-styles-wrapper .wp-block-image.has-border-color figure { border-color: inherit !important; } .editor-styles-wrapper .wp-block-image.has-border-width figure { border-width: inherit !important; } .editor-styles-wrapper .wp-block-image.has-border-style figure { border-style: inherit !important; } /* Maximum specificity for editor - override everything */ .editor-styles-wrapper .wp-block-image img, .editor-styles-wrapper .wp-block-image img[style*="border"], .editor-styles-wrapper .wp-block-image img[style*="border-radius"], .editor-styles-wrapper .wp-block-image img[style*="border-width"], .editor-styles-wrapper .wp-block-image img[style*="border-color"], .editor-styles-wrapper .wp-block-image img[style*="border-style"] { border: none !important; border-radius: 0 !important; border-width: 0 !important; border-color: transparent !important; border-style: none !important; } /* Force figure to inherit all border styles in editor */ .editor-styles-wrapper .wp-block-image figure, .editor-styles-wrapper .wp-block-image figure[style*="border"], .editor-styles-wrapper .wp-block-image figure[style*="border-radius"] { border: inherit !important; border-radius: inherit !important; border-width: inherit !important; border-color: inherit !important; border-style: inherit !important; } /* Target WordPress border classes in editor */ .editor-styles-wrapper .wp-block-image.has-border-color img, .editor-styles-wrapper .wp-block-image.has-border-width img, .editor-styles-wrapper .wp-block-image.has-border-style img, .editor-styles-wrapper .wp-block-image.has-border-radius img { border: none !important; border-radius: 0 !important; border-width: 0 !important; border-color: transparent !important; border-style: none !important; } .editor-styles-wrapper .wp-block-image.has-border-color figure, .editor-styles-wrapper .wp-block-image.has-border-width figure, .editor-styles-wrapper .wp-block-image.has-border-style figure, .editor-styles-wrapper .wp-block-image.has-border-radius figure { border: inherit !important; border-radius: inherit !important; border-width: inherit !important; border-color: inherit !important; border-style: inherit !important; overflow: hidden !important; } /* Additional fixes for preview mode */ .wp-block-image[style*="padding"] { position: relative; z-index: 1; } .wp-block-image[style*="padding"] figure { position: relative; z-index: 1; } /* Ensure images are always visible in preview */ .wp-block-image img { opacity: 1 !important; visibility: visible !important; } '; wp_add_inline_style('axvart-style', $custom_css); } /** * Modify image block output to move border/radius from img to figure. * * @param string $block_content The block content. * @param array $block The full block, including name and attributes. * @return string Modified block content. */ public function modify_image_block_output($block_content, $block) { // Only process image blocks if ($block['blockName'] !== 'core/image') { return $block_content; } // More aggressive approach - directly manipulate the HTML if (strpos($block_content, ']*style="([^"]*)"[^>]*>/', $block_content, $figure_matches); preg_match('/]*style="([^"]*)"[^>]*>/', $block_content, $img_matches); $figure_style = !empty($figure_matches[1]) ? $figure_matches[1] : ''; $img_style = !empty($img_matches[1]) ? $img_matches[1] : ''; // Extract border properties from img style $border_properties = []; $other_properties = []; if (!empty($img_style)) { $style_parts = explode(';', $img_style); foreach ($style_parts as $part) { $part = trim($part); if (empty($part)) continue; // Check if this is a border-related property if (preg_match('/border(-radius)?/', $part)) { $border_properties[] = $part; } else { $other_properties[] = $part; } } } // If we found border properties, move them to figure if (!empty($border_properties)) { // Add border properties to figure style $new_figure_style = $figure_style; foreach ($border_properties as $prop) { $new_figure_style .= '; ' . $prop; } // Add overflow hidden if we have border-radius if (array_filter($border_properties, function ($p) { return strpos($p, 'border-radius') !== false; })) { $new_figure_style .= '; overflow: hidden'; } // Update figure style if (!empty($figure_matches[0])) { $block_content = str_replace( $figure_matches[0], str_replace('style="' . $figure_style . '"', 'style="' . $new_figure_style . '"', $figure_matches[0]), $block_content ); } else { // No existing style, add one $block_content = preg_replace( '/(]*)(>)/', '$1 style="' . $new_figure_style . '"$2', $block_content ); } // Remove border properties from img and add border: none $new_img_style = implode('; ', $other_properties); if (!empty($new_img_style)) { $new_img_style .= '; border: none; border-radius: 0;'; } else { $new_img_style = 'border: none; border-radius: 0;'; } // Update img style if (!empty($img_matches[0])) { $block_content = str_replace( $img_matches[0], str_replace('style="' . $img_style . '"', 'style="' . $new_img_style . '"', $img_matches[0]), $block_content ); } } } return $block_content; } /** * Modify image block metadata to ensure proper border handling. * * @param array $metadata The block metadata. * @return array Modified metadata. */ public function modify_image_block_metadata($metadata) { // Add error handling to prevent warnings try { // Ensure metadata is an array if (!is_array($metadata)) { return $metadata; } // Check if name exists and is core/image if (!isset($metadata['name']) || $metadata['name'] !== 'core/image') { return $metadata; } // Ensure supports array exists if (!isset($metadata['supports']) || !is_array($metadata['supports'])) { $metadata['supports'] = []; } // Ensure border support exists if (!isset($metadata['supports']['border']) || !is_array($metadata['supports']['border'])) { $metadata['supports']['border'] = []; } // Force border to be applied to the block wrapper, not the img $metadata['supports']['border']['__experimentalDefaultControls'] = [ 'color' => true, 'radius' => true, 'style' => true, 'width' => true, ]; // Ensure attributes array exists if (!isset($metadata['attributes']) || !is_array($metadata['attributes'])) { $metadata['attributes'] = []; } // Ensure className attribute exists if (!isset($metadata['attributes']['className']) || !is_array($metadata['attributes']['className'])) { $metadata['attributes']['className'] = []; } // Add custom CSS class to help with styling $metadata['attributes']['className']['default'] = 'axvart-image-block'; // Ensure all required properties have proper structure to prevent REST API warnings if (!isset($metadata['attributes']['className']['type'])) { $metadata['attributes']['className']['type'] = 'string'; } // Ensure other common attributes have proper structure $common_attributes = ['align', 'sizeSlug', 'linkTarget', 'rel', 'title']; foreach ($common_attributes as $attr) { if (!isset($metadata['attributes'][$attr])) { $metadata['attributes'][$attr] = [ 'type' => 'string', 'default' => '' ]; } elseif (!isset($metadata['attributes'][$attr]['type'])) { $metadata['attributes'][$attr]['type'] = 'string'; } } return $metadata; } catch (Exception $e) { // Log error but don't break the site error_log('Axvart: Error in modify_image_block_metadata: ' . $e->getMessage()); return $metadata; } } /** * Modify editor settings to ensure proper border handling. * * @param array $settings The editor settings. * @param array $context The editor context. * @return array Modified settings. */ public function modify_editor_settings($settings, $context) { // Add error handling to prevent warnings try { // Ensure settings is an array if (!is_array($settings)) { $settings = []; } // Add custom CSS to editor if (!isset($settings['styles']) || !is_array($settings['styles'])) { $settings['styles'] = []; } $settings['styles'][] = [ 'css' => ' /* Force borders to be on figure, not img in editor */ .wp-block-image { --axvart-border: inherit; --axvart-border-radius: inherit; --axvart-border-width: inherit; --axvart-border-color: inherit; --axvart-border-style: inherit; } .wp-block-image img { border: none !important; border-radius: 0 !important; border-width: 0 !important; border-color: transparent !important; border-style: none !important; } .wp-block-image figure { border: var(--axvart-border) !important; border-radius: var(--axvart-border-radius) !important; border-width: var(--axvart-border-width) !important; border-color: var(--axvart-border-color) !important; border-style: var(--axvart-border-style) !important; overflow: hidden; } /* Override any inline styles */ .wp-block-image img[style*="border"] { border: none !important; border-radius: 0 !important; border-width: 0 !important; border-color: transparent !important; border-style: none !important; } .wp-block-image figure[style*="border"] { border: inherit !important; border-radius: inherit !important; border-width: inherit !important; border-color: inherit !important; border-style: inherit !important; } /* Target WordPress border classes */ .wp-block-image.has-border-color figure { border-color: inherit !important; } .wp-block-image.has-border-width figure { border-width: inherit !important; } .wp-block-image.has-border-style figure { border-style: inherit !important; } .wp-block-image.has-border-radius figure { border-radius: inherit !important; overflow: hidden !important; } ' ]; return $settings; } catch (Exception $e) { // Log error but don't break the site error_log('Axvart: Error in modify_editor_settings: ' . $e->getMessage()); return $settings; } } /** * Enqueue JavaScript to force border styles on figure elements. */ public function enqueue_image_block_script() { $script = " function fixImageBlockBorders() { // Target both main document and editor iframe const contexts = [document]; // Add editor iframe if available const editorFrame = document.querySelector('iframe[name=\"editor-canvas\"]'); if (editorFrame && editorFrame.contentDocument) { contexts.push(editorFrame.contentDocument); } // Also check for any other iframes that might contain editor content const allIframes = document.querySelectorAll('iframe'); allIframes.forEach(function(iframe) { if (iframe.contentDocument && iframe.contentDocument.body) { contexts.push(iframe.contentDocument); } }); contexts.forEach(function(doc) { const imageBlocks = doc.querySelectorAll('.wp-block-image'); imageBlocks.forEach(function(block) { const img = block.querySelector('img'); const figure = block.querySelector('figure'); if (img && figure) { // Get computed styles const computedStyle = doc.defaultView ? doc.defaultView.getComputedStyle(img) : window.getComputedStyle(img); // Check for any border properties const hasBorder = computedStyle.border !== 'none' || computedStyle.borderWidth !== '0px' || computedStyle.borderRadius !== '0px' || computedStyle.borderColor !== 'rgba(0, 0, 0, 0)'; if (hasBorder) { console.log('Found border on img, moving to figure'); // Move all border properties to figure figure.style.border = computedStyle.border; figure.style.borderWidth = computedStyle.borderWidth; figure.style.borderColor = computedStyle.borderColor; figure.style.borderStyle = computedStyle.borderStyle; figure.style.borderRadius = computedStyle.borderRadius; // Add overflow hidden for border-radius if (computedStyle.borderRadius !== '0px') { figure.style.overflow = 'hidden'; } // Remove all border properties from img img.style.setProperty('border', 'none', 'important'); img.style.setProperty('border-radius', '0', 'important'); img.style.setProperty('border-width', '0', 'important'); img.style.setProperty('border-color', 'transparent', 'important'); img.style.setProperty('border-style', 'none', 'important'); } } }); }); } // Run immediately fixImageBlockBorders(); // Run on DOM ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', fixImageBlockBorders); } else { setTimeout(fixImageBlockBorders, 100); } // Run on window load window.addEventListener('load', fixImageBlockBorders); // Editor-specific handling if (typeof wp !== 'undefined' && wp.data) { console.log('WordPress editor detected, setting up listeners'); // Run on any editor change wp.data.subscribe(function() { setTimeout(fixImageBlockBorders, 50); }); // Run when image blocks are selected wp.data.subscribe(function() { const selectedBlock = wp.data.select('core/block-editor').getSelectedBlock(); if (selectedBlock && selectedBlock.name === 'core/image') { setTimeout(fixImageBlockBorders, 25); } }); } // Run very frequently in editor if (document.body.classList.contains('wp-admin') || document.body.classList.contains('editor-styles-wrapper') || document.body.classList.contains('block-editor-page')) { console.log('Editor detected, setting up frequent monitoring'); setInterval(fixImageBlockBorders, 100); // Also run on any DOM changes const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'childList' || mutation.type === 'attributes') { setTimeout(fixImageBlockBorders, 50); } }); }); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); } // Additional iframe monitoring function setupIframeMonitoring() { const iframes = document.querySelectorAll('iframe'); iframes.forEach(function(iframe) { if (iframe.contentDocument) { iframe.addEventListener('load', function() { setTimeout(fixImageBlockBorders, 100); // Inject CSS directly into iframe const style = iframe.contentDocument.createElement('style'); style.textContent = ` .wp-block-image figure { border: inherit !important; border-radius: inherit !important; border-width: inherit !important; border-color: inherit !important; border-style: inherit !important; } .wp-block-image img { border: none !important; border-radius: 0 !important; border-width: 0 !important; border-color: transparent !important; border-style: none !important; } .wp-block-image.has-border-color figure, .wp-block-image.has-border-width figure, .wp-block-image.has-border-style figure, .wp-block-image.has-border-radius figure { border: inherit !important; border-radius: inherit !important; border-width: inherit !important; border-color: inherit !important; border-style: inherit !important; overflow: hidden !important; } .wp-block-image.has-border-color img, .wp-block-image.has-border-width img, .wp-block-image.has-border-style img, .wp-block-image.has-border-radius img { border: none !important; border-radius: 0 !important; border-width: 0 !important; border-color: transparent !important; border-style: none !important; } `; iframe.contentDocument.head.appendChild(style); }); } }); } setupIframeMonitoring(); setInterval(setupIframeMonitoring, 1000); "; wp_add_inline_script('axvart-style', $script); } /** * Enqueue editor-specific script for image block borders. */ public function enqueue_editor_specific_script() { $script = " // Editor-specific border fix function editorFixImageBorders() { console.log('Editor border fix running...'); // Wait for editor to be ready if (typeof wp === 'undefined' || !wp.data) { setTimeout(editorFixImageBorders, 500); return; } // Get all image blocks in editor const blocks = wp.data.select('core/block-editor').getBlocks(); const imageBlocks = blocks.filter(block => block.name === 'core/image'); imageBlocks.forEach(function(block) { if (block.attributes.style && block.attributes.style.border) { console.log('Found image block with border:', block); // Force the block to re-render wp.data.dispatch('core/block-editor').updateBlockAttributes(block.clientId, { style: block.attributes.style }); } }); // Also check DOM elements const domImageBlocks = document.querySelectorAll('.wp-block-image'); domImageBlocks.forEach(function(block) { const img = block.querySelector('img'); const figure = block.querySelector('figure'); if (img && figure) { const computedStyle = window.getComputedStyle(img); if (computedStyle.border !== 'none' || computedStyle.borderRadius !== '0px') { console.log('Moving border from img to figure in editor'); // Move border to figure figure.style.border = computedStyle.border; figure.style.borderRadius = computedStyle.borderRadius; figure.style.overflow = 'hidden'; // Remove from img img.style.setProperty('border', 'none', 'important'); img.style.setProperty('border-radius', '0', 'important'); } } }); } // Run when editor is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', editorFixImageBorders); } else { editorFixImageBorders(); } // Run on editor changes if (typeof wp !== 'undefined' && wp.data) { wp.data.subscribe(function() { setTimeout(editorFixImageBorders, 100); }); } // Run frequently in editor setInterval(editorFixImageBorders, 300); "; wp_add_inline_script('axvart-style', $script); } /** * Register custom block variation for image blocks. */ public function register_image_block_variation() { // Check if the script file exists before enqueuing $script_path = get_template_directory() . '/assets/js/image-block-variation.js'; if (file_exists($script_path)) { wp_enqueue_script( 'axvart-image-block-variation', get_template_directory_uri() . '/assets/js/image-block-variation.js', ['wp-blocks', 'wp-dom-ready', 'wp-edit-post'], wp_get_theme()->get('Version'), true ); } } /** * Debug function to identify block registration issues. */ public function debug_block_registration() { // Only run in admin and when debugging is enabled if (!is_admin() || !defined('WP_DEBUG') || !WP_DEBUG) { return; } // Check if there are any block registration issues try { $blocks = WP_Block_Type_Registry::get_instance()->get_all_registered(); foreach ($blocks as $block_name => $block) { if ($block_name === 'core/image') { // Log the block structure for debugging error_log('Axvart Debug: Image block structure - ' . print_r($block, true)); // Check for missing properties if (!isset($block->attributes)) { error_log('Axvart Debug: Image block missing attributes'); } if (!isset($block->supports)) { error_log('Axvart Debug: Image block missing supports'); } } } } catch (Exception $e) { error_log('Axvart Debug: Error in debug_block_registration: ' . $e->getMessage()); } } /** * Prevent REST API warnings by ensuring array keys exist. */ public function prevent_rest_api_warnings($result, $server, $request) { // Only run if we're in debug mode if (!defined('WP_DEBUG') || !WP_DEBUG) { return $result; } // Suppress warnings for specific REST API endpoints that might cause issues if ( strpos($request->get_route(), '/wp/v2/blocks') !== false || strpos($request->get_route(), '/wp/v2/block-types') !== false ) { // Temporarily suppress warnings for this request $old_error_reporting = error_reporting(); error_reporting(E_ALL & ~E_WARNING); // Restore error reporting after a short delay add_action('rest_post_dispatch', function () use ($old_error_reporting) { error_reporting($old_error_reporting); }, 999); } return $result; } /** * Handle REST API response to prevent null get_data() errors. */ public function handle_rest_api_response($response, $handler, $request) { // Check if response is null and handle gracefully if ($response === null) { // Return an empty response object instead of null return new WP_REST_Response([], 200); } // If response is a WP_REST_Response but has null data, fix it if ($response instanceof WP_REST_Response && $response->get_data() === null) { $response->set_data([]); } return $response; } /** * Handle block editor preload to prevent REST API errors. */ public function handle_block_editor_preload($preload_data, $context) { // Filter out any null responses from preload data if (is_array($preload_data)) { foreach ($preload_data as $key => $value) { if ($value === null) { $preload_data[$key] = []; } } } return $preload_data; } /** * Handle rest_preload_api_request to prevent null get_data() errors. */ public function handle_preload_api_request($response, $path) { // If response is null, return empty array to prevent errors if ($response === null) { return []; } // If response is a WP_REST_Response but has null data, fix it if ($response instanceof WP_REST_Response) { try { $data = $response->get_data(); if ($data === null) { $response->set_data([]); } } catch (Exception $e) { // If get_data() throws an error, return empty array error_log("Axvart: Error in get_data(): " . $e->getMessage()); return []; } } return $response; } /** * Handle REST API server errors to prevent fatal errors. */ public function handle_rest_server_errors($result, $server, $request) { // Check if we're dealing with blocks endpoint if (strpos($request->get_route(), '/wp/v2/blocks') !== false) { // Set error handling to prevent fatal errors set_error_handler(function ($errno, $errstr, $errfile, $errline) { // Log the error but don't throw fatal error error_log("Axvart REST API Error: $errstr in $errfile on line $errline"); return true; // Don't execute PHP internal error handler }); // Restore error handler after request add_action('rest_post_dispatch', function () { restore_error_handler(); }, 999); } return $result; } /** * Handle response_to_data to prevent null get_data() errors. */ public function handle_response_to_data($data, $response, $request) { // If response is null, return empty array if ($response === null) { return []; } // If data is null, return empty array if ($data === null) { return []; } return $data; } /** * Ensure all block metadata has proper structure to prevent REST API warnings. */ public function ensure_block_metadata_structure($metadata) { try { // Validate input if (!is_array($metadata)) { return $metadata; } // Ensure basic structure exists if (!isset($metadata['attributes']) || !is_array($metadata['attributes'])) { $metadata['attributes'] = []; } // Ensure all attributes have proper type definitions foreach ($metadata['attributes'] as $attr_name => $attr_config) { if (is_array($attr_config) && !isset($attr_config['type'])) { // Set default type based on attribute name or default value if (isset($attr_config['default'])) { if (is_bool($attr_config['default'])) { $metadata['attributes'][$attr_name]['type'] = 'boolean'; } elseif (is_int($attr_config['default'])) { $metadata['attributes'][$attr_name]['type'] = 'number'; } else { $metadata['attributes'][$attr_name]['type'] = 'string'; } } else { $metadata['attributes'][$attr_name]['type'] = 'string'; } } } // Ensure supports structure exists if (!isset($metadata['supports']) || !is_array($metadata['supports'])) { $metadata['supports'] = []; } return $metadata; } catch (Exception $e) { error_log('Axvart: Error in ensure_block_metadata_structure: ' . $e->getMessage()); return $metadata; } } /** * Ensure block editor settings are properly configured. */ public function ensure_block_editor_settings($settings, $context) { try { // Ensure settings is an array if (!is_array($settings)) { $settings = []; } // Ensure required settings exist if (!isset($settings['hasFixedToolbar'])) { $settings['hasFixedToolbar'] = false; } if (!isset($settings['hasReducedUI'])) { $settings['hasReducedUI'] = false; } if (!isset($settings['canUserUseUnfilteredHTML'])) { $settings['canUserUseUnfilteredHTML'] = false; } // Ensure blockTypes exists if (!isset($settings['blockTypes']) || !is_array($settings['blockTypes'])) { $settings['blockTypes'] = []; } // Ensure allowedBlockTypes exists if (!isset($settings['allowedBlockTypes'])) { $settings['allowedBlockTypes'] = true; } return $settings; } catch (Exception $e) { error_log('Axvart: Error in ensure_block_editor_settings: ' . $e->getMessage()); return $settings; } } /** * Ensure block editor preload works properly. */ public function ensure_block_editor_preload($preload_data, $context) { try { // Log preload attempt error_log("Axvart Debug: Block editor preload called"); // Ensure preload_data is an array if (!is_array($preload_data)) { $preload_data = []; } // Filter out any problematic data foreach ($preload_data as $key => $value) { if ($value === null) { unset($preload_data[$key]); } } return $preload_data; } catch (Exception $e) { error_log('Axvart: Error in ensure_block_editor_preload: ' . $e->getMessage()); return []; } } /** * Add skip link for accessibility. * * Outputs skip link at the beginning of the body. */ public function add_skip_link() { echo ''; } }