kollapsminoriteten/wp-content/themes/astra/inc/metabox/class-astra-elementor-edito...

978 lines
30 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Elementor Editor Settings Integration.
*
* Adds custom React-based settings to the Elementor editor page settings panel.
*
* @package Astra
* @link https://wpastra.com/
* @since 4.11.3
*/
defined( 'ABSPATH' ) || exit; // Exit if accessed directly.
/**
* Elementor Editor Settings integration class.
*
* @since 4.11.3
*/
if ( ! class_exists( 'Astra_Elementor_Editor_Settings' ) ) {
/**
* Elementor Editor Settings integration class.
*
* @since 4.11.3
*/
class Astra_Elementor_Editor_Settings {
/**
* Class instance.
*
* @var self|null
* @since 4.11.3
*/
private static $instance = null;
/**
* Get instance.
*
* @since 4.11.3
* @return self
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor.
*
* @since 4.11.3
*/
private function __construct() {
// Bail if Elementor is not active.
if ( ! did_action( 'elementor/loaded' ) ) {
return;
}
// Get post ID.
$post_id = 0;
if ( isset( $_REQUEST['post'] ) ) {
$post_id = absint( $_REQUEST['post'] );
}
if ( isset( $_REQUEST['editor_post_id'] ) ) {
$post_id = absint( $_REQUEST['editor_post_id'] );
}
$post_type = get_post_type( $post_id );
// Bail if post type is excluded.
if ( ! $post_id || in_array( $post_type, self::get_excluded_post_types(), true ) ) {
return;
}
$this->init_hooks();
}
/**
* Initialize WordPress hooks.
*
* @since 4.11.3
*/
private function init_hooks() {
// Registering actions for Elementor editor assets, document controls, and custom control styles.
add_action( 'elementor/editor/after_enqueue_scripts', array( $this, 'enqueue_editor_assets' ) );
add_action( 'elementor/documents/register_controls', array( $this, 'register_document_controls' ), 20 );
add_action( 'elementor/editor/after_enqueue_styles', array( $this, 'add_custom_control_style' ) );
// Hook into Elementor's document saving process to persist Astra-specific settings.
add_action( 'elementor/document/after_save', array( $this, 'sync_save_settings' ) );
// Hook into the template redirect action to handle Elementor preview.
add_action( 'template_redirect', array( $this, 'handle_preview' ) );
// Hook into wp_after_insert_post to sync site-post-title with Elementor hide_title.
add_action( 'wp_after_insert_post', array( $this, 'sync_site_post_title_to_elementor' ) );
}
/**
* Check if in Elementor editor mode.
*
* @since 4.11.9
* @return bool
*/
public static function is_elementor_editor() {
// Check if in Elementor editor mode.
/** @psalm-suppress UndefinedClass */
if ( ! class_exists( '\Elementor\Plugin' ) || ! \Elementor\Plugin::$instance->editor || ! \Elementor\Plugin::$instance->editor->is_edit_mode() ) {
return false;
}
return true;
}
/**
* Get array of setting keys for Astra Elementor settings.
*
* @since 4.11.3
*
* @return array Array of setting keys.
*/
public static function get_astra_elementor_setting_keys() {
$settings = array(
'site-post-title', // Astra Disable Title.
'ast-site-content-layout', // Container Layout.
'site-content-style', // Container Style.
'site-sidebar-layout', // Sidebar Layout.
'site-sidebar-style', // Sidebar Style.
'ast-global-header-display', // Disable Header.
'footer-sml-layout', // Disable Footer.
'ast-banner-title-visibility', // Disable Banner Area.
'ast-breadcrumbs-content', // Disable breadcrumb.
'ast-hfb-above-header-display', // Disable Above Header.
'ast-main-header-display', // Disable Primary Header.
'ast-hfb-below-header-display', // Disable Below Header.
'ast-hfb-mobile-header-display', // Disable Mobile Header.
'theme-transparent-header-meta', // Transparent Header.
'stick-header-meta', // Sticky Header (Pro Option).
'header-above-stick-meta', // Stick Above Header (Pro Option).
'header-main-stick-meta', // Stick Primary Header (Pro Option).
'header-below-stick-meta', // Stick Below Header (Pro Option).
);
/**
* Filter to modify the Astra Elementor setting keys.
*
* @since 4.11.3
*
* @param array $keys Array of Astra Elementor setting keys.
*/
return apply_filters( 'astra_elementor_page_setting_keys', $settings );
}
/**
* Enqueue scripts for Elementor editor settings React app.
*
* @since 4.11.3
*/
public function enqueue_editor_assets() {
// Check if in Elementor editor mode.
if ( ! self::is_elementor_editor() ) {
return;
}
$handle = 'astra-elementor-meta-settings';
$path = ASTRA_THEME_URI . '/inc/metabox/extend-metabox/build/elementor.js';
// Get the script dependencies from the asset file.
$dependencies = array();
if ( file_exists( ASTRA_THEME_DIR . 'inc/metabox/extend-metabox/build/elementor.asset.php' ) ) {
$assets = require ASTRA_THEME_DIR . 'inc/metabox/extend-metabox/build/elementor.asset.php';
if ( isset( $assets['dependencies'] ) ) {
$dependencies = $assets['dependencies'];
}
}
wp_enqueue_script(
$handle,
$path,
$dependencies,
ASTRA_THEME_VERSION,
true
);
/**
* Filter to modify the localized data for Astra astraElementor editor settings.
*
* @since 4.11.3
* @param array $localize_data Localized data for astraElementor editor settings.
*/
$localize_data = apply_filters(
'astra_elementor_editor_localize_data',
array(
'themeName' => astra_get_theme_name(),
'themeIconUrl' => esc_url( apply_filters( 'astra_admin_menu_icon', ASTRA_THEME_URI . 'inc/assets/images/astra-logo.svg' ) ),
'postTitle' => get_post_meta( intval( get_the_ID() ), 'site-post-title', true ),
)
);
wp_localize_script( $handle, 'astraElementorEditor', $localize_data );
}
/**
* Get formatted container layout options with 'title' and 'icon'.
*
* @return array Formatted content layout options.
*/
public static function get_formatted_container_layout_options() {
$options = Astra_Meta_Boxes::get_instance()->get_content_layout_options();
foreach ( $options as $key => $label ) {
$options[ $key ] = array(
'title' => $label,
'icon' => 'default' === $key ? 'layout-default' : $key, // alternatively we can use 'image' key to provide custom image URLs.
);
}
return $options;
}
/**
* Get formatted container style options with only 'title'.
*
* @return array Formatted content style options.
*/
public static function get_formatted_container_style_options() {
$options = Astra_Meta_Boxes::get_instance()->get_content_style_options();
return array_map(
static function( $title ) {
return array( 'title' => $title );
},
$options
);
}
/**
* Get formatted sidebar layout options with 'title' and 'icon'.
*
* @return array Formatted sidebar layout options.
*/
public static function get_formatted_sidebar_layout_options() {
$options = Astra_Meta_Boxes::get_instance()->get_sidebar_options();
foreach ( $options as $key => $label ) {
$options[ $key ] = array(
'title' => $label,
'icon' => 'default' === $key ? 'layout-default' : $key,
);
}
return $options;
}
/**
* Get formatted sidebar style options with only 'title'.
*
* @return array Formatted sidebar style options.
*/
public static function get_formatted_sidebar_style_options() {
$options = Astra_Meta_Boxes::get_instance()->get_sidebar_style_options();
return array_map(
static function( $title ) {
return array( 'title' => $title );
},
$options
);
}
/**
* Get formatted header enabled options with only 'title'.
* Usage: For Transparent and Sticky Header options.
*
* @return array Formatted header enabled options.
*/
public static function get_formatted_header_enabled_options() {
$options = Astra_Meta_Boxes::get_instance()->get_header_enabled_options();
return array_map(
static function( $title ) {
return array( 'title' => $title );
},
$options
);
}
/**
* Register additional document controls.
*
* Adds a new section and control to the Elementor Page Settings panel,
* providing a placeholder div for the React-powered Astra Settings UI.
*
* @param \Elementor\Core\DocumentTypes\PageBase $document The PageBase document instance.
*
* @since 4.11.3
*
* @psalm-suppress DocblockTypeContradiction
* @psalm-suppress UndefinedDocblockClass
* @psalm-suppress UndefinedClass
*/
public function register_document_controls( $document ) {
if ( ! class_exists( '\Elementor\Controls_Manager' ) || ! class_exists( '\Elementor\Core\DocumentTypes\PageBase' ) ) {
return;
}
// Only proceed if the document is a valid Elementor PageBase type and has elements.
if ( ! $document instanceof \Elementor\Core\DocumentTypes\PageBase || ! $document::get_property( 'has_elements' ) ) {
return;
}
$id = intval( get_the_ID() );
// Start a new section in the Elementor Page Settings -> Setting tab.
$document->start_controls_section(
'astra_section',
array(
'label' => esc_html__( 'Astra Settings', 'astra' ),
'tab' => \Elementor\Controls_Manager::TAB_SETTINGS,
)
);
// Container Section Title.
$document->add_control(
'ast-container-heading',
array(
'label' => __( 'Container', 'astra' ),
'type' => \Elementor\Controls_Manager::HEADING,
)
);
// Container Layout using Choose control with images.
$document->add_control(
'ast-site-content-layout',
array(
'classes' => 'ast-layout-control',
'label' => __( 'Container Layout', 'astra' ),
'type' => \Elementor\Controls_Manager::CHOOSE,
'options' => self::get_formatted_container_layout_options(),
'default' => get_post_meta( $id, 'ast-site-content-layout', true ),
'toggle' => false,
)
);
// Container Style using Choose control (button group style).
$document->add_control(
'site-content-style',
array(
'classes' => 'ast-selector-control',
'label' => __( 'Container Style', 'astra' ),
'type' => \Elementor\Controls_Manager::CHOOSE,
'options' => self::get_formatted_container_style_options(),
'default' => get_post_meta( $id, 'site-content-style', true ),
'description' => __( 'Container style will apply only when layout is set to either Normal or Narrow.', 'astra' ),
'toggle' => false,
)
);
// Sidebar Section Title.
$document->add_control(
'ast-sidebar-heading',
array(
'label' => __( 'Sidebar', 'astra' ),
'type' => \Elementor\Controls_Manager::HEADING,
'separator' => 'before',
)
);
$document->add_control(
'site-sidebar-layout',
array(
'classes' => 'ast-layout-control',
'label' => __( 'Sidebar Layout', 'astra' ),
'type' => \Elementor\Controls_Manager::CHOOSE,
'options' => self::get_formatted_sidebar_layout_options(),
'default' => get_post_meta( $id, 'site-sidebar-layout', true ),
'description' => __( 'Sidebar will only apply when container layout is set to normal.', 'astra' ),
'toggle' => false,
)
);
$document->add_control(
'site-sidebar-style',
array(
'classes' => 'ast-selector-control',
'label' => __( 'Sidebar Style', 'astra' ),
'type' => \Elementor\Controls_Manager::CHOOSE,
'options' => self::get_formatted_sidebar_style_options(),
'default' => get_post_meta( $id, 'site-sidebar-style', true ),
'toggle' => false,
)
);
// Disable Elements Section Title.
$document->add_control(
'ast-disable-elements-heading',
array(
'label' => __( 'Disable Elements', 'astra' ),
'type' => \Elementor\Controls_Manager::HEADING,
'separator' => 'before',
)
);
$controls = Astra_Meta_Boxes::get_instance()->get_disable_section_fields();
foreach ( $controls as $details ) {
$meta_key = $details['key'];
$document->add_control(
$meta_key,
array(
'label' => $details['label'],
'type' => \Elementor\Controls_Manager::SWITCHER,
'default' => get_post_meta( $id, $meta_key, true ) === 'disabled' ? 'yes' : '',
)
);
}
$document->add_control(
'ast-advanced-settings-heading',
array(
'label' => __( 'Advanced Settings', 'astra' ),
'type' => \Elementor\Controls_Manager::HEADING,
'separator' => 'before',
)
);
$document->add_control(
'ast-header-rows-popover',
array(
'classes' => 'ast-popover-control',
'type' => \Elementor\Controls_Manager::POPOVER_TOGGLE,
'label' => __( 'Header Rows', 'astra' ),
)
);
$document->start_popover();
$controls = Astra_Meta_Boxes::get_instance()->get_header_disable_meta_fields();
foreach ( $controls as $details ) {
$meta_key = $details['key'];
$document->add_control(
$meta_key,
array(
'label' => $details['label'],
'type' => \Elementor\Controls_Manager::SWITCHER,
'default' => get_post_meta( $id, $meta_key, true ) === 'disabled' ? 'yes' : '',
)
);
}
$document->end_popover();
$document->add_control(
'theme-transparent-header-meta',
array(
'classes' => 'ast-selector-control',
'label' => __( 'Transparent Header', 'astra' ),
'type' => \Elementor\Controls_Manager::CHOOSE,
'options' => self::get_formatted_header_enabled_options(),
'default' => get_post_meta( $id, 'theme-transparent-header-meta', true ),
'toggle' => false,
)
);
if ( defined( 'ASTRA_EXT_VER' ) && class_exists( 'Astra_Ext_Extension' ) && Astra_Ext_Extension::is_active( 'sticky-header' ) ) {
$document->add_control(
'stick-header-meta',
array(
'classes' => 'ast-selector-control',
'label' => __( 'Sticky Header', 'astra' ),
'type' => \Elementor\Controls_Manager::CHOOSE,
'options' => self::get_formatted_header_enabled_options(),
'default' => get_post_meta( $id, 'stick-header-meta', true ),
'toggle' => false,
)
);
$document->add_control(
'ast-sticky-header-rows-popover',
array(
'classes' => 'ast-popover-control',
'type' => \Elementor\Controls_Manager::POPOVER_TOGGLE,
'label' => __( 'Sticky Header Rows', 'astra' ),
'condition' => array(
'stick-header-meta' => 'enabled', // show only when Sticky Header is enabled.
),
)
);
$document->start_popover();
$controls = Astra_Meta_Boxes::get_instance()->get_sticky_header_options();
foreach ( $controls as $details ) {
$meta_key = $details['key'];
$document->add_control(
$meta_key,
array(
'label' => $details['label'],
'type' => \Elementor\Controls_Manager::SWITCHER,
'default' => get_post_meta( $id, $meta_key, true ) === 'disabled' ? 'yes' : '',
)
);
}
$document->end_popover();
}
$document->add_control(
'ast-save-changes-notice',
array(
'type' => \Elementor\Controls_Manager::NOTICE,
'notice_type' => 'warning',
'content' => __( 'Make sure to update your post for changes to take effect.', 'astra' ),
)
);
// Preview changes button.
$document->add_control(
'ast-preview-changes-button',
array(
'type' => \Elementor\Controls_Manager::BUTTON,
'button_type' => 'success',
'text' => esc_html__( 'Preview Changes', 'astra' ),
'event' => 'namespace:editor:astraRefresh',
'disabled' => true,
)
);
if ( ! defined( 'ASTRA_EXT_VER' ) ) {
$document->add_control(
'ast-pro-notice',
array(
'type' => \Elementor\Controls_Manager::RAW_HTML,
'raw' => sprintf(
'<div class="ast-pro-upgrade-cta-wrapper">
<img src="%1$s" alt="Astra Logo">
<p class="elementor-control-field-description">%2$s</p>
<a href="%3$s" class="ast-pro-upgrade-link" target="_blank">%4$s</a>
</div>',
esc_url( ASTRA_THEME_URI . 'inc/assets/images/astra-logo.svg' ),
__( 'Unlock your full design potential and build a website to be proud of with Astra Pro.', 'astra' ),
astra_get_pro_url( '/pricing/', 'free-theme', 'elementor-editor', 'upgrade' ),
__( 'Upgrade Now', 'astra' )
),
)
);
}
$document->end_controls_section();
// Add a info notice below the Hide Title control.
$document->start_injection(
array(
'of' => 'post_status',
'fallback' => array(
'of' => 'post_title',
),
)
);
$document->add_control(
'ast-hide-title-notice',
array(
'type' => \Elementor\Controls_Manager::NOTICE,
'notice_type' => 'info',
'content' => __( "Changes to 'Hide Title' will automatically sync with Astras 'Disable Title' option.", 'astra' ),
)
);
$document->end_injection();
}
/**
* Adds inline styles to enhance Astra controls in Elementor Page Settings.
*
* Optimizes layout and display of CHOOSE controls (like container and sidebar settings).
* by using grid layouts and ensuring button labels are visible.
*
* @since 4.11.3
*
* @return void
*/
public function add_custom_control_style() {
$css_rules = '
<style>
.ast-layout-control .elementor-control-field,
.ast-selector-control .elementor-control-field {
flex-direction: column;
align-items: flex-start;
gap: 10px;
}
.ast-layout-control .elementor-control-input-wrapper,
.ast-selector-control .elementor-control-input-wrapper {
width: 100%;
}
.ast-layout-control .elementor-choices {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
height: auto;
}
.ast-layout-control .elementor-choices-label,
.ast-selector-control .elementor-choices-label {
position: relative;
width: 100%;
}
.ast-layout-control .elementor-choices-label {
min-height: 92.5px;
border-radius: 3px;
border: none !important;
}
.ast-selector-control .elementor-choices-label::before {
content: attr(data-tooltip);
}
.ast-popover-control .elementor-control-popover-toggle-reset-label {
display: none;
}
.elementor-control-ast-preview-changes-button.elementor-control {
position: sticky;
bottom: 0;
padding-top: 15px;
backdrop-filter: blur(2px);
}
.elementor-control-ast-preview-changes-button.elementor-control .elementor-control-input-wrapper,
.elementor-control-ast-preview-changes-button.elementor-control .elementor-button {
width: 100%;
}
.ast-pro-upgrade-cta-wrapper {
padding: 20px 0;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 15px;
}
.ast-pro-upgrade-cta-wrapper .elementor-control-field-description {
margin-top: 0;
}
.ast-pro-upgrade-cta-wrapper a.ast-pro-upgrade-link {
color: #0284C7;
width: 100%;
padding: 8px;
border: 1px solid #0284C7;
border-radius: 2px;
}
';
// Icons CSS.
$icon_svgs = array(
'.layout-default' => self::get_svg( 'layout-default' ),
'.normal-width-container' => self::get_svg( 'normal-width-container' ),
'.narrow-width-container' => self::get_svg( 'narrow-width-container' ),
'.full-width-container' => self::get_svg( 'full-width-container' ),
'.no-sidebar' => self::get_svg( 'no-sidebar' ),
'.left-sidebar' => self::get_svg( 'left-sidebar' ),
'.right-sidebar' => self::get_svg( 'right-sidebar' ),
);
foreach ( $icon_svgs as $selector => $svg ) {
$encoded_svg = self::transform_svg( $svg );
$css_rules .= "{$selector}::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: url(\"data:image/svg+xml;utf8,{$encoded_svg}\") no-repeat center / contain;
}";
}
$css_rules .= '</style>';
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- This is inline CSS and does not require escaping.
echo class_exists( 'Astra_Minify' ) ? Astra_Minify::trim_css( $css_rules ) : $css_rules;
}
/**
* Handle Elementor template redirect for previewing Astra settings changes.
*
* @since 4.11.3
*/
public function handle_preview() {
$post_id = intval( get_the_ID() );
$preview_id = intval( isset( $_GET['preview_id'] ) ? $_GET['preview_id'] : 0 );
$preview_nonce = isset( $_GET['preview_nonce'] ) && is_scalar( $_GET['preview_nonce'] ) ? sanitize_text_field( $_GET['preview_nonce'] ) : '';
/** @psalm-suppress UndefinedClass */
$is_elementor_editor_preview = class_exists( '\Elementor\Plugin' ) && \Elementor\Plugin::$instance->preview->is_preview_mode();
$is_elementor_frontend_preview = is_preview() && $post_id === $preview_id && wp_verify_nonce( $preview_nonce, 'post_preview_' . $preview_id );
// Bail early if not in Elementor preview.
if ( ! $is_elementor_editor_preview && ! $is_elementor_frontend_preview ) {
return;
}
$revision_id = $post_id;
$revisions = wp_get_post_revisions(
$post_id,
array(
'order' => 'DESC',
'orderby' => 'ID',
)
);
foreach ( $revisions as $revision ) {
// Elementor stores this meta in preview revisions.
if ( get_post_meta( $revision->ID, '_elementor_edit_mode', true ) ) {
$revision_id = $revision->ID;
break;
}
}
$settings = get_post_meta( $revision_id, '_elementor_page_settings', true );
$keys = self::get_astra_elementor_setting_keys();
foreach ( $keys as $meta_key ) {
$meta_val = isset( $settings[ $meta_key ] ) ? $settings[ $meta_key ] : get_post_meta( $post_id, $meta_key, true );
add_filter(
'get_post_metadata',
static function( $value, $object_id, $key ) use ( $post_id, $meta_key, $meta_val ) {
if ( $object_id === $post_id && $key === $meta_key ) {
return array( $meta_val === 'yes' ? 'disabled' : $meta_val );
}
return $value;
},
10,
3
);
}
// Ensure the title is enabled for Elementor preview so that Hide Title toggle works correctly.
add_action( 'astra_the_title_enabled', '__return_true', 999 );
}
/**
* Sync specific Astra settings from Elementor's Page Settings to post meta.
*
* This function checks if certain custom Elementor controls are enabled (like disabling the header, footer,
* or banner area) and updates the corresponding post meta values accordingly. If the setting is not enabled,
* the meta key is removed.
*
* @psalm-suppress UndefinedDocblockClass
* @param \Elementor\Core\Base\Document $document The Elementor document object being saved.
*
* @since 4.11.3
*
* @return void
*/
public function sync_save_settings( $document ) {
$post_id = $document->get_id();
if ( ! $post_id || wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
return;
}
// Get fresh saved settings directly from the meta.
$page_settings = $document->get_meta( '_elementor_page_settings' );
// If the settings are not an array, initialize it as an empty array.
if ( ! is_array( $page_settings ) ) {
$page_settings = array();
}
// Sync astra site-post-title with elementor hide_title.
$page_settings['site-post-title'] = isset( $page_settings['hide_title'] ) ? $page_settings['hide_title'] : '';
$keys = array(
'ast-site-content-layout', // Container Layout.
'site-content-style', // Container Style.
'site-sidebar-layout', // Sidebar Layout.
'site-sidebar-style', // Sidebar Style.
'theme-transparent-header-meta', // Transparent Header.
'stick-header-meta', // Sticky Header (Pro Option).
);
foreach ( $keys as $meta_key ) {
if ( isset( $page_settings[ $meta_key ] ) ) {
$value = $page_settings[ $meta_key ];
if ( $value ) {
update_post_meta( $post_id, $meta_key, $value );
} else {
delete_post_meta( $post_id, $meta_key );
}
// Remove setting from Elementor's saved settings.
unset( $page_settings[ $meta_key ] );
}
}
$keys = array(
'site-post-title', // Astra Disable Title.
'ast-global-header-display', // Disable Header.
'footer-sml-layout', // Disable Footer.
'ast-banner-title-visibility', // Disable Banner Area.
'ast-breadcrumbs-content', // Disable breadcrumb.
'ast-hfb-above-header-display', // Disable Above Header.
'ast-main-header-display', // Disable Primary Header.
'ast-hfb-below-header-display', // Disable Below Header.
'ast-hfb-mobile-header-display', // Disable Mobile Header.
'header-above-stick-meta', // Stick Above Header (Pro Option).
'header-main-stick-meta', // Stick Primary Header (Pro Option).
'header-below-stick-meta', // Stick Below Header (Pro Option).
);
foreach ( $keys as $meta_key ) {
if ( isset( $page_settings[ $meta_key ] ) ) {
$value = $page_settings[ $meta_key ];
if ( $value === 'yes' ) {
update_post_meta( $post_id, $meta_key, 'disabled' );
} else {
delete_post_meta( $post_id, $meta_key );
}
// Remove setting from Elementor's saved settings.
unset( $page_settings[ $meta_key ] );
}
}
// $document->update_meta( '_elementor_page_settings', $page_settings );
update_post_meta( $post_id, '_elementor_page_settings', $page_settings );
}
/**
* Retrieves an SVG icon based on the given icon name.
*
* @param string $icon The name of the icon to retrieve.
*
* @since 4.11.3
*
* @return string The SVG code for the icon or an empty string if the icon does not exist.
*/
public static function get_svg( $icon = '' ) {
if ( ! class_exists( 'Astra_Builder_UI_Controller' ) ) {
return '';
}
// Ensure the SVG icons are loaded.
$svg_icons = Astra_Builder_UI_Controller::$ast_svgs;
if ( ! Astra_Builder_UI_Controller::$ast_svgs ) {
Astra_Builder_UI_Controller::fetch_svg_icon();
$svg_icons = Astra_Builder_UI_Controller::$ast_svgs;
}
return isset( $svg_icons[ $icon ] ) ? $svg_icons[ $icon ] : '';
}
/**
* Transforms SVG markup for use in inline CSS by modifying colors and encoding.
*
* @param string $svg The raw SVG markup.
*
* @since 4.11.3
*
* @return string The transformed and encoded SVG string.
*/
private static function transform_svg( $svg ) {
// Basic validation: check if input is a non-empty string.
if ( trim( $svg ) === '' ) {
return rawurlencode( "<svg xmlns='http://www.w3.org/2000/svg' width='1' height='1'></svg>" );
}
// Replace only the first occurrence of stroke='#D1D5DB' with a semi-transparent color.
// phpcs:ignore Generic.PHP.ForbiddenFunctions.FoundWithAlternative -- Safe usage: no /e modifier, transforms SVG colors for dark mode
$svg = preg_replace( "/stroke='#D1D5DB'/", "stroke='#9DA5AE55'", $svg, 1 );
// Perform bulk replacements for remaining known values.
$svg = str_replace(
array( "fill='white'", "stroke='#D8DBDF'", "fill='#E5E7EB'", "fill='#D1D5DB'", "stroke='#D1D5DB'" ),
array( "fill='#9DA5AE55'", "stroke='#9DA5AE55'", "fill='currentColor'", "fill='currentColor'", "stroke='currentColor'" ),
$svg
);
// URL-encode the SVG for embedding as a background-image.
return rawurlencode( $svg );
}
/**
* Sync site-post-title meta to Elementor hide_title when post is saved via WP editor.
*
* @param int $post_id Post id.
*
* @since 4.11.9
*/
public function sync_site_post_title_to_elementor( $post_id ) {
// Skip if this is a revision or autosave.
if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
return;
}
// Bail early if this is an Elementor AJAX request.
if ( ( isset( $_REQUEST['action'] ) && 'elementor_ajax' === $_REQUEST['action'] ) ) {
return true;
}
// Skip if saving from Elementor to avoid conflicts.
if ( did_action( 'elementor/document/after_save' ) ) {
return;
}
// Skip if post builder is not Elementor.
if ( 'builder' !== get_post_meta( $post_id, '_elementor_edit_mode', true ) ) {
return;
}
// Get the site-post-title meta value.
$site_post_title = get_post_meta( $post_id, 'site-post-title', true );
// Get current Elementor page settings.
$elementor_settings = get_post_meta( $post_id, '_elementor_page_settings', true );
if ( ! is_array( $elementor_settings ) ) {
$elementor_settings = array();
}
// Check if we need to update the hide_title setting.
$current_hide_title = isset( $elementor_settings['hide_title'] ) ? $elementor_settings['hide_title'] : '';
$new_hide_title = 'disabled' === $site_post_title ? 'yes' : '';
// Only update if the value has changed.
if ( $current_hide_title !== $new_hide_title ) {
if ( 'yes' === $new_hide_title ) {
$elementor_settings['hide_title'] = 'yes';
} else {
unset( $elementor_settings['hide_title'] );
}
// Update the Elementor page settings meta.
empty( $elementor_settings )
? delete_post_meta( $post_id, '_elementor_page_settings' )
: update_post_meta( $post_id, '_elementor_page_settings', $elementor_settings );
// Regenerate Elementor CSS cache to update --page-title-display variable.
if ( class_exists( '\Elementor\Plugin' ) ) {
/** @psalm-suppress UndefinedClass */
\Elementor\Plugin::$instance->files_manager->clear_cache();
}
}
}
/**
* Get excluded post types for Astra Meta setting in Elementor editor.
*
* @since 4.11.11
* @return array
*/
public static function get_excluded_post_types() {
/**
* Filter to exclude post types from rendering Astra Meta setting in Elementor editor.
*
* @param array $excluded_post_types Array of post types to exclude.
*/
return apply_filters(
'astra_elementor_editor_excluded_post_types',
array(
'astra-advanced-hook', // Astra Theme Builder Advanced Layout.
'elementskit_template', // ElementsKit Template.
)
);
}
}
}
/**
* Initialize the class singleton.
*/
Astra_Elementor_Editor_Settings::get_instance();