File manager - Edit - /home/matthif/www/wp-content/languages/Builder.tar
Back
Abstract_Builder.php 0000666 00000176040 15226766106 0010515 0 ustar 00 <?php /** * Abstract Builder class for Header Footer Grid. * * Name: Header Footer Grid * Author: Bogdan Preda <bogdan.preda@themeisle.com> * * @version 1.0.0 * @package HFG */ namespace HFG\Core\Builder; use HFG\Core\Components\Abstract_Component; use HFG\Core\Components\Nav; use HFG\Core\Css_Generator; use HFG\Core\Interfaces\Builder; use HFG\Core\Interfaces\Component; use HFG\Core\Settings; use HFG\Core\Settings\Manager as SettingsManager; use HFG\Traits\Core; use Neve\Core\Settings\Config; use Neve\Core\Styles\Css_Prop; use Neve\Core\Styles\Dynamic_Selector; use Neve\Core\Theme_Info; use Neve\Customizer\Controls\React\Instructions_Section; use WP_Customize_Manager; /** * Class Abstract_Builder * * @package HFG\Core\Builder */ abstract class Abstract_Builder implements Builder { use Core; use Theme_Info; const LAYOUT_SETTING = 'layout'; const COLUMNS_NUMBER = 'columns_number'; const COLUMNS_LAYOUT = 'columns_layout'; const HEIGHT_SETTING = 'height'; const BOTTOM_BORDER = 'bottom_border'; const BORDER_COLOR = 'border_color'; const SKIN_SETTING = 'skin'; const TEXT_COLOR = 'new_text_color'; const BACKGROUND_SETTING = 'background'; const WIDTH = 'width'; const CONTENT_ALIGNMENT = 'content_alignment'; const VERTICAL_ALIGN = 'vertical_align'; /** * Layout config data. * * @var array Layout data. */ private $layout_data = []; /** * Active components ids. * * @var array Layout data. */ private $active_components = []; /** * Internal pointer for current device id. * * @var null|string Device id. */ public static $current_device = null; /** * Internal pointer for current row id. * * @var null|string Row id. */ public static $current_row = null; /** * Internal pointer for current slot id. * * @var null|string Slot id. */ public static $current_slot = null; /** * Internal pointer for current component id. * * @var null|string Component id. */ public static $current_component = null; /** * Internal pointer for current builder id. * * @var null|string Builder id. */ public static $current_builder = null; /** * Holds the control id. * * @since 1.0.0 * @access protected * @var string $control_id */ protected $control_id; /** * Holds the layout control id. * * @since 3.0.0 * @access protected * @var string $layout_control_id */ protected $layout_control_id; /** * Holds the panel id. * * @since 1.0.0 * @access protected * @var string $panel */ protected $panel; /** * Holds the section id. * * @since 1.0.0 * @access protected * @var string $section */ protected $section; /** * Holds the title. * * @since 1.0.0 * @access public * @var string|null $title */ public $title; /** * Holds the description. * * @since 1.0.1 * @access public * @var string|null $description */ public $description; /** * A list of panel keys to be removed. * * @since 1.0.0 * @access protected * @var array $remove_panels */ protected $remove_panels = []; /** * A list of sections keys to be removed. * * @since 1.0.0 * @access protected * @var array $remove_sections */ protected $remove_sections = []; /** * A list of supported devices and labels. * * @since 1.0.0 * @access protected * @var array $devices */ protected $devices = [ 'desktop' => 'Desktop', 'mobile' => 'Mobile', ]; /** * Default colors for rows. * * Holds the default values for row colors. * * @since 1.0.0 * @access protected * @var array */ protected $default_colors = array( 'header' => array( 'top' => '#f0f0f0', 'main' => '#ffffff', 'bottom' => '#ffffff', 'sidebar' => '#ffffff', ), 'footer' => array( 'top' => '#ffffff', 'bottom' => '#24292e', ), 'page_header' => array( 'top' => '#ffffff', 'bottom' => '#ffffff', ), ); /** * A list of builder components. * * @since 1.0.0 * @access protected * @var array $builder_components */ protected $builder_components = array(); /** * The quick links setup array. * * @var array */ protected $instructions_array = array(); /** * Does this layout have columns? * * @var boolean */ protected $columns_layout = false; /** * Abstract_Builder constructor. * * @since 1.0.0 * @access public */ public function __construct() { $this->set_property( 'control_id', 'hfg_' . $this->get_id() . '_layout' ); $this->set_property( 'layout_control_id', $this->control_id . ( neve_is_new_builder() ? '_v2' : '' ) ); $this->set_property( 'panel', 'hfg_' . $this->get_id() ); $this->set_property( 'section', $this->control_id . '_section' ); $this->init(); add_action( 'hfg_' . $this->get_id() . '_render', [ $this, 'load_template' ] ); $this->define_builder_settings(); foreach ( $this->get_rows() as $row_id => $row_name ) { $this->define_row_settings( $row_id ); } add_filter( 'hfg_header_row_classes', [ $this, 'add_header_row_utility_classes' ], 10, 2 ); add_filter( 'hfg_page_header_row_classes', [ $this, 'add_header_row_utility_classes' ], 10, 2 ); } /** * Method to set protected properties for class. * * @param string $key The property key name. * @param mixed $value The property value. * * @return bool * @since 1.0.0 * @access protected */ protected function set_property( $key = '', $value = '' ) { if ( ! property_exists( $this, $key ) ) { return false; } $this->$key = $value; return true; } /** * Define builder settings. */ public function define_builder_settings() { $is_new_builder = neve_is_new_builder(); SettingsManager::get_instance()->add( [ 'id' => $this->layout_control_id, 'group' => $this->control_id, 'tab' => false, 'noformat' => true, 'transport' => 'post' . $this->get_id(), 'sanitize_callback' => [ $this, 'sanitize_json' ], 'default' => '', 'label' => '', 'type' => $is_new_builder ? '\Neve\Customizer\Controls\React\Builder' : 'text', 'options' => [ 'builder_type' => $this->get_id(), 'columns_layout' => $this->columns_layout, ], 'conditional_header' => $this->get_id() === 'header', 'section' => $this->section, ] ); do_action( 'hfg_row_settings', $this->get_id(), $this->control_id ); } /** * Used to define the rows in the builder sections. * * @return array Rows array. */ abstract protected function get_rows(); /** * Define Row settings. * * @param string $row_id Row id. */ public function define_row_settings( $row_id ) { $row_setting_id = $this->control_id . '_' . $row_id; $row_class = '.' . join( '-', array( $this->get_id(), $row_id, 'inner', ) ); if ( $row_id === 'sidebar' ) { $row_class = '.header-menu-sidebar'; } SettingsManager::get_instance()->add( [ 'id' => $row_setting_id, 'transport' => 'postMessage', 'sanitize_callback' => array( $this, 'sanitize_json' ), 'default' => '', ] ); if ( $row_id === 'sidebar' ) { $this->add_sidebar_controls( $row_setting_id ); } if ( $row_id !== 'sidebar' ) { SettingsManager::get_instance()->add( [ 'id' => self::LAYOUT_SETTING, 'group' => $row_setting_id, 'tab' => SettingsManager::TAB_LAYOUT, 'label' => __( 'Layout', 'neve' ), 'type' => 'select', 'section' => $row_setting_id, 'options' => [ 'choices' => [ 'layout-full-contained' => __( 'Full Width', 'neve' ) . ' - ' . __( 'Contained', 'neve' ), 'layout-fullwidth' => __( 'Full Width', 'neve' ), 'layout-contained' => __( 'Contained', 'neve' ), ], ], 'conditional_header' => $this->get_id() === 'header', 'transport' => 'post' . $row_setting_id, 'sanitize_callback' => 'wp_filter_nohtml_kses', 'default' => 'layout-full-contained', ] ); SettingsManager::get_instance()->add( [ 'id' => self::HEIGHT_SETTING, 'group' => $row_setting_id, 'tab' => SettingsManager::TAB_STYLE, 'section' => $row_setting_id, 'label' => __( 'Row height', 'neve' ), 'type' => '\Neve\Customizer\Controls\React\Responsive_Range', 'live_refresh_selector' => $row_class, 'live_refresh_css_prop' => [ 'cssVar' => [ 'responsive' => true, 'vars' => '--height', 'suffix' => 'px', 'fallback' => 'auto', 'selector' => $row_class, 'dispatchWindowResize' => true, ], 'prop' => 'height', 'unit' => 'px', ], 'options' => [ 'input_attrs' => [ 'min' => 0, 'max' => 700, 'defaultVal' => [ 'mobile' => 0, 'tablet' => 0, 'desktop' => 0, 'suffix' => [ 'mobile' => 'px', 'tablet' => 'px', 'desktop' => 'px', ], ], 'units' => [ 'px', 'em', 'rem' ], ], ], 'transport' => 'postMessage', 'sanitize_callback' => array( $this, 'sanitize_responsive_int_json' ), 'default' => '{ "mobile": "0", "tablet": "0", "desktop": "0" }', 'conditional_header' => $this->get_id() === 'header', ] ); SettingsManager::get_instance()->add( [ 'id' => self::BOTTOM_BORDER, 'group' => $row_setting_id, 'tab' => SettingsManager::TAB_STYLE, 'section' => $row_setting_id, 'label' => __( 'Border Width', 'neve' ), 'type' => '\Neve\Customizer\Controls\React\Responsive_Range', 'live_refresh_selector' => true, 'live_refresh_css_prop' => [ 'cssVar' => [ 'responsive' => true, 'vars' => '--rowbwidth', 'suffix' => 'px', 'fallback' => '0', 'selector' => '.' . $this->get_id() . '-' . $row_id, 'dispatchWindowResize' => true, ], ], 'options' => [ 'input_attrs' => [ 'min' => 0, 'max' => 50, 'defaultVal' => [ 'mobile' => 0, 'tablet' => 0, 'desktop' => 0, 'suffix' => [ 'mobile' => 'px', 'tablet' => 'px', 'desktop' => 'px', ], ], 'units' => [ 'px' ], ], ], 'transport' => 'postMessage', 'sanitize_callback' => array( $this, 'sanitize_responsive_int_json' ), 'default' => '{ "mobile": "0", "tablet": "0", "desktop": "0" }', 'conditional_header' => $this->get_id() === 'header', ] ); SettingsManager::get_instance()->add( [ 'id' => self::BORDER_COLOR, 'group' => $row_setting_id, 'tab' => SettingsManager::TAB_STYLE, 'label' => __( 'Border Color', 'neve' ), 'section' => $row_setting_id, 'conditional_header' => $this->get_id() === 'header', 'type' => 'neve_color_control', 'transport' => 'postMessage', 'live_refresh_selector' => true, 'live_refresh_css_prop' => [ 'cssVar' => [ 'vars' => '--rowbcolor', 'selector' => '.' . $this->get_id() . '-' . $row_id, ], ], 'sanitize_callback' => 'neve_sanitize_colors', 'default' => 'var(--nv-light-bg)', ] ); } if ( $this->columns_layout && neve_is_new_builder() ) { $this->add_columns_layout_controls( $row_setting_id, $row_id ); } $default_colors = $this->get_default_row_colors( $row_id ); SettingsManager::get_instance()->add( [ 'id' => self::BACKGROUND_SETTING, 'group' => $row_setting_id, 'tab' => SettingsManager::TAB_STYLE, 'section' => $row_setting_id, 'label' => __( 'Row Background', 'neve' ), 'type' => '\Neve\Customizer\Controls\React\Background', 'live_refresh_selector' => $row_id === 'sidebar' ? $row_class . ' .header-menu-sidebar-bg' : $row_class, 'live_refresh_css_prop' => [ 'cssVar' => [ 'vars' => 'backgroundControl', 'selector' => $row_id === 'sidebar' ? '.header-menu-sidebar-bg' : '.' . $this->get_id() . '-' . $row_id, ], 'partial' => $row_id === 'sidebar' ? 'hfg_header_layout_partial' : $row_setting_id . '_partial', ], 'options' => [ 'priority' => 100, 'active_callback' => function () use ( $row_id ) { return $this->has_background_setting( $row_id ); }, ], 'default' => [ 'type' => 'color', 'colorValue' => $default_colors['background'], ], 'transport' => 'postMessage', 'sanitize_callback' => 'neve_sanitize_background', 'conditional_header' => $this->get_id() === 'header', ] ); do_action( 'hfg_add_settings_to_rows', SettingsManager::get_instance(), $row_setting_id, $row_id, $this->get_id() ); SettingsManager::get_instance()->add( [ 'id' => self::TEXT_COLOR, 'group' => $row_setting_id, 'tab' => SettingsManager::TAB_STYLE, 'label' => __( 'Text Color', 'neve' ), 'section' => $row_setting_id, 'conditional_header' => $this->get_id() === 'header', 'type' => 'neve_color_control', 'transport' => 'postMessage', 'live_refresh_selector' => $row_class, 'live_refresh_css_prop' => [ 'cssVar' => [ 'vars' => '--color', 'selector' => $row_id === 'sidebar' ? '.header-menu-sidebar-bg' : '.' . $this->get_id() . '-' . $row_id, ], 'partial' => $row_id === 'sidebar' ? 'hfg_header_layout_partial' : $row_setting_id . '_partial', ], 'sanitize_callback' => 'wp_filter_nohtml_kses', 'default' => $default_colors['text'], ] ); do_action( 'hfg_row_settings', $this->get_id(), $row_id, $row_setting_id ); } /** * Decides if the background setting should be visible for current row. * * @param string $row_id The row id. * @return bool True if setting should be displayed, false if not. */ public function has_background_setting( $row_id ) { if ( $this->get_id() !== 'header' ) { return true; } if ( $row_id === 'sidebar' ) { return true; } if ( get_theme_mod( 'neve_pro_global_header_settings_advanced_style', true ) === true ) { return true; } return false; } /** * Returns current builder id. * * @return string|null Builder id. */ public static function get_current_builder() { return self::$current_builder; } /** * Define templates used to loading the builder. */ abstract public function load_template(); /** * Method to get protected properties for class. * * @param string $key The property key name. * * @return mixed * @since 1.0.0 * @access protected */ public function get_property( $key = '' ) { if ( ! property_exists( $this, $key ) ) { return false; } return $this->$key; } /** * Register builder scripts * * @since 1.0.0 * @access public */ public function scripts() { wp_add_inline_style( 'hfg-customizer-control', $this->inline_builder_styles() ); } /** * Returns a string of css rules. * * @return string * @since 1.0.0 * @access protected */ protected function inline_builder_styles() { $style = ''; $style_array = []; $rows = $this->get_rows(); if ( ! empty( $rows ) ) { foreach ( $rows as $row_id => $row_label ) { $style_array[ '#accordion-section-' . $this->control_id . '_' . $row_id ] = array( 'display' => 'none !important', ); } } return $style . $this->css_array_to_css( $style_array ); } /** * Called to register component controls. * * @param WP_Customize_Manager $wp_customize The Customize Manager. * * @return WP_Customize_Manager * @since 1.0.0 * @access public */ public function customize_register( WP_Customize_Manager $wp_customize ) { /** * An instance of Component. * * @var Component $component */ foreach ( $this->builder_components as $component ) { $component->customize_register( $wp_customize ); } /** @var \WP_Customize_Panel|null $panel */ $panel = $wp_customize->get_panel( $this->panel ); if ( null !== $panel ) { return $wp_customize; } $title = ( isset( $this->title ) && ! empty( $this->title ) ) ? $this->title : __( 'Header', 'neve' ); $description = ( isset( $this->description ) && ! empty( $this->description ) ) ? $this->description : ''; $wp_customize->add_panel( $this->panel, /* @phpstan-ignore-next-line The wordpress-stub os incorect, proper type should be string|array for `theme_supports` */ array( 'priority' => 25, 'capability' => 'edit_theme_options', 'theme_supports' => Settings\Config::get_support(), 'title' => $title, 'description' => $description, ) ); $wp_customize->add_section( $this->section, array( 'title' => $title, 'priority' => 299, 'panel' => $this->panel, ) ); if ( ! empty( $this->instructions_array ) ) { $wp_customize->add_section( new Instructions_Section( $wp_customize, $this->section . '_quick_links', array( 'priority' => - 100, 'panel' => $this->panel, 'type' => 'hfg_instructions', 'options' => $this->instructions_array, ) ) ); } Settings\Manager::get_instance()->load( $this->control_id, $wp_customize ); $this->add_rows_controls( $wp_customize ); $wp_customize->selective_refresh->add_partial( $this->control_id . '_partial', array( 'selector' => '.' . $this->panel, 'settings' => Settings\Manager::get_instance()->get_transport_group( $this->get_id() ), 'render_callback' => array( $this, 'render' ), ) ); $wp_customize = apply_filters( 'hfg_after_builder_' . $this->get_id() . '_registered', $wp_customize, $this ); return $wp_customize; } /** * Adds row controls. * * @param WP_Customize_Manager $wp_customize The Customize Manager. * * @return WP_Customize_Manager|null * @since 1.0.0 * @access protected */ protected function add_rows_controls( $wp_customize ) { $rows = $this->get_rows(); if ( empty( $rows ) ) { return null; } foreach ( $rows as $row_id => $row ) { $row_setting_id = $this->control_id . '_' . $row_id; $title = $row; $description = ''; if ( is_array( $row ) ) { $title = ( isset( $row['title'] ) && ! empty( $row['title'] ) ) ? $row['title'] : __( 'Section Content', 'neve' ); $description = ( isset( $row['description'] ) && ! empty( $row['description'] ) ) ? $row['description'] : $description; } $wp_customize->add_section( $row_setting_id, array( 'title' => $title, 'description' => $description, 'description_hidden' => ( $description !== '' ), 'priority' => 100, 'panel' => $this->panel, ) ); Settings\Manager::get_instance()->load( $row_setting_id, $wp_customize ); $wp_customize->selective_refresh->add_partial( $row_setting_id . '_partial', array( 'selector' => '.' . $this->panel, 'settings' => Settings\Manager::get_instance()->get_transport_group( $row_setting_id ), 'render_callback' => array( $this, 'render' ), ) ); } return $wp_customize; } /** * Return current device in the loop. * * @return null|string Current device. */ public function get_current_device() { return self::$current_device; } /** * Return current row in the loop. * * @return null|string Current row. */ public function get_current_row_index() { return self::$current_row; } /** * Return current slot in the loop. * * @return null|string Current slot. */ public function get_current_slot_index() { return self::$current_slot; } /** * Render markup for builder. */ public function render() { $layout = $this->get_layout_data(); self::$current_builder = $this->get_id(); if ( is_customize_preview() ) { $style = $this->add_style( [] ); $generator = new Css_Generator(); $generator->set( $style ); $style = $generator->generate(); echo '<style type="text/css" id="' . esc_attr( $this->get_id() ) . '-style">' . $style . '</style>';// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } foreach ( $layout as $device_name => $device ) { if ( empty( $device ) ) { continue; } self::$current_device = $device_name; $this->render_device( $device_name, $device ); } } /** * Return builder data. * * @return array Builder data. */ public function get_layout_data() { if ( ! empty( $this->layout_data ) ) { return $this->layout_data; } $mod_value = json_decode( SettingsManager::get_instance()->get( $this->layout_control_id ), true ); $this->layout_data = wp_parse_args( $mod_value, array_fill_keys( array_keys( $this->devices ), array_fill_keys( array_keys( $this->get_rows() ), [] ) ) ); return $this->layout_data; } /** * See if row is populated. * * @param string $row_id Row id. * * @return bool Is row used? */ public function is_row_used( $row_id ) { foreach ( $this->get_layout_data() as $devices ) { if ( isset( $devices[ $row_id ] ) && ! empty( $devices[ $row_id ] ) ) { return true; } } return false; } /** * Check if component is used in builder. * * @param string $component_id Component id. * * @return bool Is used? */ public function is_component_active( $component_id ) { if ( empty( $this->active_components ) ) { $components = []; foreach ( $this->get_layout_data() as $devices ) { foreach ( $devices as $row_index => $row ) { if ( neve_is_new_builder() && $row_index !== 'sidebar' ) { foreach ( $row as $slot ) { if ( empty( $slot ) || ! is_array( $slot ) ) { continue; } $components = array_merge( $components, array_combine( wp_list_pluck( $slot, 'id' ), array_fill( 0, count( $slot ), true ) ) ); } continue; } // Legacy $row_components = []; foreach ( $row as $component ) { if ( isset( $component['id'] ) ) { $row_components[ $component['id'] ] = true; } } $components = array_merge( $components, $row_components ); } } $this->active_components = $components; } return isset( $this->active_components[ $component_id ] ); } /** * Method to add Builder css styles. * * @param array $css_array An array containing css rules. * * @return array * @since 1.0.0 * @access public */ public function add_style( array $css_array = array() ) { foreach ( $this->get_rows() as $row_index => $row_label ) { if ( ! $this->is_row_used( $row_index ) ) { continue; } $css_array = $this->add_row_style( $row_index, $css_array ); } /** * An instance of Component. * * @var Abstract_Component $component */ foreach ( $this->builder_components as $component ) { if ( ! $this->is_component_active( $component->get_id() ) ) { continue; } $css_array = $component->add_style( $css_array ); } return $css_array; } /** * Returns the featured image for the header row. * * @param string $image_url The image URL. * @param boolean $use_featured Flag if featured image should be used. * @param array $meta Additional meta for the image. * * @return string */ protected function get_row_featured_image( $image_url, $use_featured, $meta ) { $image = 'none'; if ( ! empty( $use_featured ) && $use_featured === true && is_singular() ) { $featured_image = get_the_post_thumbnail_url(); if ( ! empty( $featured_image ) ) { $image = sprintf( 'url("%s")', esc_url( $featured_image ) ); } else { $image = sprintf( 'url("%s")', esc_url( $image_url ) ); } } elseif ( ! empty( $image_url ) ) { $image = sprintf( 'url("%s")', esc_url( $image_url ) ); } /** * Filters the background featured image output url. * * @param string $image The background image value: `none` or `url(<url>)`. * @param boolean $use_featured Flag to specify if featured image should be used or fallback. * @param array $meta Additional meta for the image. * * @since 3.0.5 */ return apply_filters( 'nv_builder_row_image_url', $image, $use_featured, $meta ); } /** * Method to generate css array for each row. * * @param string $row_index The row index. * @param array $css_array The css array. * * @return array * @since 1.0.0 * @access private */ private function add_row_style( $row_index, $css_array = array() ) { $css_array = $this->add_new_builder_styles( $css_array, $row_index ); $rules = []; $selector = $row_index === 'sidebar' ? '.header-menu-sidebar-bg' : '.' . $this->get_id() . '-' . $row_index; $default_colors = $this->get_default_row_colors( $row_index ); if ( $row_index !== 'sidebar' ) { $rules['--height'] = [ Dynamic_Selector::META_KEY => $this->control_id . '_' . $row_index . '_height', Dynamic_Selector::META_IS_RESPONSIVE => true, Dynamic_Selector::META_FILTER => function ( $css_prop, $value, $meta, $device ) { $value = (int) $value; $unit_suffix = Css_Prop::get_suffix_responsive( $meta, $device ); if ( $value > 0 ) { return sprintf( '%s:%s;', $css_prop, $value . $unit_suffix ); } return ''; }, Dynamic_Selector::META_SUFFIX => 'responsive_suffix', Dynamic_Selector::META_DEFAULT => '{ desktop: 0, tablet: 0, mobile: 0 }', ]; $rules['--rowbwidth'] = [ Dynamic_Selector::META_KEY => $this->control_id . '_' . $row_index . '_' . self::BOTTOM_BORDER, Dynamic_Selector::META_IS_RESPONSIVE => true, Dynamic_Selector::META_FILTER => function ( $css_prop, $value, $meta, $device ) { $value = (int) $value; if ( $value >= 0 ) { return sprintf( '%s:%s;', $css_prop, $value . 'px' ); } return ''; }, ]; $rules['--rowbcolor'] = [ Dynamic_Selector::META_KEY => $this->control_id . '_' . $row_index . '_' . self::BORDER_COLOR, Dynamic_Selector::META_DEFAULT => 'var(--nv-light-bg)', ]; } $rules['--color'] = [ Dynamic_Selector::META_KEY => $this->control_id . '_' . $row_index . '_' . self::TEXT_COLOR, Dynamic_Selector::META_DEFAULT => $default_colors['text'], ]; // Exclude the following rules for the header when the global header background is active. if ( get_theme_mod( 'neve_pro_global_header_settings_advanced_style', true ) === true || $this->get_id() !== 'header' || $row_index === 'sidebar' ) { // If there is no default, use site background. $default_color = isset( $default_colors['background'] ) ? $default_colors['background'] : 'var(--nv-site-bg)'; $background = get_theme_mod( $this->control_id . '_' . $row_index . '_background', [ 'type' => 'color', 'colorValue' => $default_color, ] ); if ( $background['type'] === 'color' && ! empty( $background['colorValue'] ) ) { $rules = array_merge( $rules, [ '--bgcolor' => [ Dynamic_Selector::META_KEY => $this->control_id . '_' . $row_index . '_background.colorValue', Dynamic_Selector::META_DEFAULT => $default_color, ], ] ); } if ( $background['type'] === 'image' ) { $rules = array_merge( $rules, [ '--overlaycolor' => [ Dynamic_Selector::META_KEY => $this->control_id . '_' . $row_index . '_background.overlayColorValue', ], '--bgimage' => [ Dynamic_Selector::META_KEY => $this->control_id . '_' . $row_index . '_background', Dynamic_Selector::META_FILTER => function ( $css_prop, $value, $meta, $device ) { $image_url = array_key_exists( 'imageUrl', $value ) ? $value['imageUrl'] : ''; $use_featured = array_key_exists( 'useFeatured', $value ) ? $value['useFeatured'] : false; $image = $this->get_row_featured_image( $image_url, $use_featured, $meta ); return sprintf( '%s:%s;', $css_prop, $image ); }, ], '--bgposition' => [ Dynamic_Selector::META_KEY => $this->control_id . '_' . $row_index . '_background', Dynamic_Selector::META_FILTER => function ( $css_prop, $value, $meta, $device ) { $focus_point = array_key_exists( 'focusPoint', $value ) ? $value['focusPoint'] : false; if ( ! $this->is_valid_focus_point( $focus_point ) ) { return ''; } $parsed_position = round( $value['focusPoint']['x'] * 100 ) . '% ' . round( $value['focusPoint']['y'] * 100 ) . '%;'; return sprintf( '%s:%s;', $css_prop, $parsed_position ); }, ], '--bgattachment' => [ Dynamic_Selector::META_KEY => $this->control_id . '_' . $row_index . '_background', Dynamic_Selector::META_FILTER => function ( $css_prop, $value, $meta, $device ) { if ( ! isset( $value['fixed'] ) || $value['fixed'] !== true ) { return ''; } return sprintf( '%s:fixed;', $css_prop ); }, ], '--bgoverlayopacity' => [ Dynamic_Selector::META_KEY => $this->control_id . '_' . $row_index . '_background', Dynamic_Selector::META_FILTER => function ( $css_prop, $value, $meta, $device ) { if ( ! isset( $value['overlayOpacity'] ) ) { return ''; } return sprintf( '%s:%s;', $css_prop, $value['overlayOpacity'] / 100 ); }, ], ] ); } } $css_array[] = [ Dynamic_Selector::KEY_SELECTOR => $selector, Dynamic_Selector::KEY_RULES => $rules, ]; if ( $row_index === 'sidebar' ) { $css_array = $this->add_sidebar_styles( $css_array ); } return $css_array; } /** * Render device markup. * * @param string $device_name Device id. * @param array $device_details Device meta. */ public function render_device( $device_name, $device_details ) { // Make sure we hold the defined order. $default_order = array_keys( $this->get_rows() ); foreach ( $default_order as $row_index ) { if ( ! isset( $device_details[ $row_index ] ) ) { continue; } $row = $device_details[ $row_index ]; if ( neve_is_new_builder() ) { $used = []; foreach ( $row as $components ) { $used = array_merge( $used, $components ); } if ( empty( $used ) ) { if ( $this->get_id() !== 'footer' ) { continue; } if ( $row_index !== 'bottom' ) { continue; } if ( $this->has_valid_addons() ) { continue; } } } elseif ( empty( $row ) ) { continue; } self::$current_row = $row_index; $this->render_row( $device_name, $row_index, $row ); } } /** * Get the component alignment. * * @param string $id component id. * @param bool $vertical should get vertical alignment. * * @return array|string|false */ private function get_component_alignment( $id, $vertical = false ) { if ( $vertical ) { return SettingsManager::get_instance()->get( $id . '_' . Abstract_Component::VERTICAL_ALIGN_ID, null ); } $alignment = SettingsManager::get_instance()->get( $id . '_' . Abstract_Component::ALIGNMENT_ID, null ); // Make sure we migrate old alignment values. if ( is_array( $alignment ) ) { return $alignment; } $is_menu_component = strpos( $id, 'primary-menu' ) > - 1 || strpos( $id, 'secondary-menu' ); $tmp_align = ( is_string( $alignment ) && in_array( $alignment, [ 'left', 'right', 'center', 'justify', ] ) ) ? $alignment : 'left'; return [ 'desktop' => $tmp_align, 'tablet' => $is_menu_component ? 'left' : $tmp_align, 'mobile' => $is_menu_component ? 'left' : $tmp_align, ]; } /** * Checks if a row has items inside a slot. * * @param string $slot slot to check in row. * * @return bool */ private function row_has_slot( $slot ) { $current_row = $this->get_current_row_index(); $layout_data = $this->get_layout_data(); $device = $this->get_current_device(); if ( ! isset( $layout_data[ $device ] ) ) { return false; } if ( ! isset( $layout_data[ $device ][ $current_row ] ) ) { return false; } $row_data = $layout_data[ $device ][ $current_row ]; if ( ! isset( $row_data[ $slot ] ) || empty( $row_data[ $slot ] ) ) { return false; } return true; } /** * Add row utility classes. * * @param array $classes footer classes. * @param string $row_index row index. * * @return mixed */ public function add_header_row_utility_classes( $classes, $row_index ) { if ( $this->get_id() !== self::$current_builder ) { return $classes; } if ( $this->row_has_slot( 'center' ) ) { $classes[] = 'has-center'; } return $classes; } /** * Render the builder components. * * @param string|null $device the device [desktop|mobile]. */ public function new_render_components( $device ) { $row_index = 0; if ( $device === null ) { $device = self::$current_device; $row_index = self::$current_row; } $builder_id = $this->get_id(); $data = $this->get_layout_data()[ $device ][ $row_index ]; // Remap sidebar data so we can use it as a slot. if ( $row_index === 'sidebar' ) { $data = [ 'sidebar' => $data ]; } $render_buffer = [ 'left' => [], 'c-left' => [], 'center' => [], 'c-right' => [], 'right' => [], ]; $slot = null; $component_index = null; $slot_data = null; foreach ( $data as $slot => $slot_data ) { $is_side_slot = in_array( $slot, [ 'right', 'left' ], true ); if ( ! ( $this->row_has_slot( 'center' ) && $is_side_slot ) && empty( $slot_data ) && $builder_id !== 'footer' ) { continue; } $render_index = 0; $was_previous_mergeable = false; $has_divider = false; foreach ( $slot_data as $component_index => $component ) { if ( ! isset( $component['id'] ) ) { continue; } if ( ! isset( $this->builder_components[ $component['id'] ] ) ) { continue; } $has_divider = false; if ( preg_match( '/^divider/', $component['id'] ) ) { $has_divider = true; } /** * An instance of Abstract_Component * * @var Abstract_Component $component_instance */ $component_instance = $this->builder_components[ $component['id'] ]; $is_mergeable = $component_instance->get_property( 'is_auto_width' ); if ( ! $is_mergeable && ! $was_previous_mergeable ) { $render_index ++; } if ( $row_index === 'sidebar' ) { $render_index ++; } $align = $this->get_component_alignment( $component['id'] ); $vertical_align = $this->get_component_alignment( $component['id'], true ); $classes = [ 'builder-item' ]; if ( strpos( $component['id'], 'primary-menu' ) > - 1 ) { $classes[] = 'has-nav'; } // We don't add align classes to primary menus as there's no align control in new skin. if ( strpos( $component['id'], Nav::COMPONENT_ID ) === false ) { foreach ( $align as $device_slug => $align_slug ) { $alignment_is_mobile = in_array( $device_slug, [ 'tablet', 'mobile' ], true ); $is_header_sidebar = $builder_id === 'header' && $row_index === 'sidebar'; // Make sure we don't apply device-specific classes if the rows aren't visible on respective device. // Footer has same rows on all devices. if ( $builder_id === 'footer' || $is_header_sidebar || ( $device === $device_slug || ( $alignment_is_mobile && $device === 'mobile' ) ) ) { $classes[] = $device_slug . '-' . $align_slug; } } } // If we don't have anything at render index, make sure we do. if ( ! isset( $render_buffer[ $slot ][ $render_index ] ) ) { $render_buffer[ $slot ][ $render_index ] = [ 'classes' => $classes, 'components' => [], ]; } // If the component is a divider, add a supplementary class if ( $has_divider && ! in_array( 'has-divider', $render_buffer[ $slot ][ $render_index ]['classes'], true ) && $row_index !== 'sidebar' ) { $render_buffer[ $slot ][ $render_index ]['classes'][] = 'has-divider'; } $render_buffer[ $slot ][ $render_index ]['components'][] = $component['id']; if ( $is_mergeable ) { $was_previous_mergeable = true; continue; } $was_previous_mergeable = false; } if ( isset( $render_buffer[ $slot ] ) && is_array( $render_buffer[ $slot ] ) ) { $render_buffer[ $slot ] = array_values( $render_buffer[ $slot ] ); } } if ( ! $this->columns_layout ) { if ( $slot === 'c-left' && $component_index === 0 ) { $classes[] = 'hfg-end'; } if ( $slot === 'c-right' && $component_index === count( $slot_data ) - 1 ) { $classes[] = 'hfg-start'; } } if ( ! $this->columns_layout ) { // Move center-side-slot components inside the side slots. if ( isset( $render_buffer['c-right'] ) ) { $length = count( $render_buffer['c-right'] ) - 1; if ( $length >= 0 ) { $render_buffer['c-right'][ $length ]['classes'][] = 'hfg-start'; } $render_buffer['right'] = array_merge( $render_buffer['c-right'], $render_buffer['right'] ); } if ( isset( $render_buffer['c-left'] ) ) { $render_buffer['c-left'][0]['classes'][] = 'hfg-end'; $render_buffer['left'] = array_merge( $render_buffer['left'], $render_buffer['c-left'] ); } unset( $render_buffer['c-left'] ); unset( $render_buffer['c-right'] ); } else { // Drop the unused columns for columned layout. $columns = SettingsManager::get_instance()->get( 'hfg_footer_layout_' . $row_index . '_' . self::COLUMNS_NUMBER, 3 ); array_splice( $render_buffer, absint( $columns ) ); } foreach ( $render_buffer as $slot => $slot_data ) { if ( $slot === 'center' && empty( $slot_data ) && ! $this->columns_layout ) { continue; } $slot_classes = [ 'hfg-slot', $slot ]; foreach ( $slot_data as $item ) { if ( array_key_exists( 'components', $item ) && preg_grep( '/^divider/', $item['components'] ) ) { $slot_classes[] = 'has-divider'; } } if ( $row_index !== 'sidebar' ) { echo sprintf( '<div class="%s">', esc_attr( join( ' ', $slot_classes ) ) ); } self::$current_slot = $slot; foreach ( $slot_data as $group_index => $component_group ) { if ( empty( $component_group['components'] ) ) { continue; } if ( count( $component_group['components'] ) > 1 ) { $component_group['classes'][] = 'hfg-is-group'; // If there is a primary or secondary menu component inside the group, add a class to it. foreach ( $component_group['components'] as $component_slug ) { if ( strpos( $component_slug, 'primary-menu' ) === false && strpos( $component_slug, 'secondary-menu' ) === false ) { continue; } if ( strpos( $component_slug, 'primary-menu' ) !== false && ! in_array( 'has-nav', $component_group['classes'], true ) ) { $component_group['classes'][] = 'has-nav'; } $component_group['classes'][] = 'has-' . $component_slug; } } echo sprintf( '<div class="%s">', esc_attr( join( ' ', $component_group['classes'] ) ) ); foreach ( $component_group['components'] as $component ) { self::$current_component = $component; $instance = $this->builder_components[ $component ]; $instance->render( $device ); } echo '</div>'; } do_action( 'neve_after_slot_component', $this->get_id(), $row_index, $slot ); if ( $row_index !== 'sidebar' ) { echo '</div>'; } } } /** * Render components in the row. * * @param null|string $device Device id. */ public function render_components( $device = null ) { if ( neve_is_new_builder() ) { $this->new_render_components( $device ); return; } $row_index = 0; if ( $device === null ) { $device = self::$current_device; $row_index = self::$current_row; } $data = $this->get_layout_data()[ $device ][ $row_index ]; $max_columns = 12; $last_item = null; usort( $data, function ( $item1, $item2 ) { if ( $item1['x'] === $item2['x'] ) { return 0; } return $item1['x'] < $item2['x'] ? - 1 : 1; } ); $collection = new \CachingIterator( new \ArrayIterator( $data ), \CachingIterator::TOSTRING_USE_CURRENT ); $render_buffer = []; $render_index = 1; foreach ( $collection as $component_location ) { if ( ! isset( $this->builder_components[ $component_location['id'] ] ) ) { continue; } /** * An instance of Abstract_Component * * @var Abstract_Component $component */ $component = $this->builder_components[ $component_location['id'] ]; $x = intval( $component_location['x'] ); $width = intval( $component_location['width'] ); $align = $this->get_component_alignment( $component_location['id'] ); $vertical_align = $this->get_component_alignment( $component_location['id'], true ); if ( ! $collection->hasNext() && ( $x + $width < $max_columns ) ) { $width += $max_columns - ( $x + $width ); } $is_auto_width = $component->get_property( 'is_auto_width' ); if ( $row_index === 'sidebar' ) { $width = 12; $is_auto_width = false; } // Let's check if the component is nearby another. $is_near_next = $collection->hasNext(); $is_near_prev = $last_item !== null; // Check if component is nearby the next component. if ( $collection->hasNext() ) { $next_component_object = $collection->getInnerIterator()->current(); if ( $next_component_object['x'] - ( $x + $width ) !== 0 ) { $is_near_next = false; } } // Check if component is nearby the prev component. if ( $last_item !== null ) { if ( ( (int) $last_item['x'] + (int) $last_item['width'] ) - $x !== 0 ) { $is_near_prev = false; } } // If there is a gap between components, build new group. if ( $last_item !== null && ! $is_near_prev ) { $render_index ++; } // If there are two neighbours and none of them have auto_width, build new group. if ( $is_near_prev && ! $last_item['is_auto_width'] && ! $is_auto_width ) { $render_index ++; } // If there are neighbours prev and next, always group with the next on. if ( $is_near_prev && $is_near_next && ! $last_item['is_auto_width'] && $is_auto_width && ! isset( $render_buffer[ $render_index ] ) ) { $render_index ++; } // Use alignment only of non-auto width element. if ( ! $is_auto_width && isset( $render_buffer[ $render_index ] ) ) { $render_buffer[ $render_index ]['align'] = $align; $render_buffer[ $render_index ]['vertical-align'] = $vertical_align; } $is_first = false; $is_last = false; if ( $last_item === null ) { $is_first = true; $render_index = 0; } if ( ! $collection->hasNext() ) { $is_last = true; } if ( $row_index !== 'sidebar' ) { if ( $x > 0 && $last_item !== null ) { $origin = intval( $last_item['width'] ) + intval( $last_item['x'] ); if ( ( $x - $origin ) > 0 ) { $x = $x - $origin; } else { $x = 0; } } } if ( ! isset( $render_buffer[ $render_index ] ) ) { $render_buffer[ $render_index ] = [ 'components' => [], 'align' => $align, 'vertical-align' => $vertical_align, 'is_first' => $is_first, 'is_last' => false, ]; } if ( strpos( $component_location['id'], 'primary-menu' ) > - 1 ) { $render_buffer[ $render_index ]['has_primary_nav'] = true; } $render_buffer[ $render_index ]['is_last'] = $is_last; $render_buffer[ $render_index ]['components'][] = [ 'component' => $component, 'offset' => $x, 'width' => $width, ]; $component_location['is_auto_width'] = $is_auto_width; $component_location['align'] = $align; $component_location['vertical-align'] = $vertical_align; $last_item = $component_location; } foreach ( $render_buffer as $render_groups ) { $width = array_sum( array_column( $render_groups['components'], 'width' ) ); $x = max( array_column( $render_groups['components'], 'offset' ) ); $align = $render_groups['align']; $vertical_align = $render_groups['vertical-align']; $classes = [ 'builder-item' ]; if ( isset( $render_groups['has_primary_nav'] ) ) { $classes[] = 'has-nav'; } if ( $render_groups['is_last'] ) { $classes[] = 'hfg-item-last'; } if ( $render_groups['is_first'] ) { $classes[] = 'hfg-item-first'; } $classes[] = 'col-' . $width; foreach ( $align as $device_slug => $align_slug ) { $builder_id = $this->get_id(); $alignment_is_mobile = in_array( $device_slug, [ 'tablet', 'mobile' ], true ); $is_header_sidebar = $builder_id === 'header' && $row_index === 'sidebar'; // Make sure we don't apply device-specific classes if the rows aren't visible on respective device. // Footer has same rows on all devices. if ( $builder_id === 'footer' || $is_header_sidebar || ( $device === $device_slug || ( $alignment_is_mobile && $device === 'mobile' ) ) ) { $classes[] = $device_slug . '-' . $align_slug; } } if ( $vertical_align ) { $classes[] = 'hfg-item-v-' . $vertical_align; } if ( $row_index !== 'sidebar' && $x > 0 ) { $classes[] = 'offset-' . $x; } if ( count( $render_groups['components'] ) > 1 ) { $classes[] = 'hfg-is-group'; } echo sprintf( '<div class="%s">', esc_attr( join( ' ', $classes ) ) ); foreach ( $render_groups['components'] as $component_data ) { $component_data['component']->current_x = $x; $component_data['component']->current_width = $width; self::$current_component = $component_data['component']->get_id(); $component_data['component']->render(); } echo '</div>'; } } /** * Register a new component for builder. * * @param mixed $component_to_add A component. * * @return bool * @since 1.0.0 * @access public */ public function register_component( $component_to_add ) { if ( ! class_exists( $component_to_add ) || ! in_array( 'HFG\Core\Interfaces\Component', class_implements( $component_to_add ), true ) ) { return false; } /** * An instance of Component. * * @var Abstract_Component $component */ $component = new $component_to_add( $this->panel ); if ( $component->is_active() ) { $this->builder_components[ $component->get_id() ] = $component; $component->assign_builder( $this->get_id() ); } return true; } /** * Get a component from builder. * * @param string|null $id The id of the component. * * @return Abstract_Component|null * @since 1.0.0 * @access public */ public function get_component( $id = null ) { if ( $id === null ) { $id = ( self::$current_component === null ) ? Abstract_Component::$current_component : self::$current_component; } return $this->builder_components[ $id ]; } /** * Returns the builder components. * * @return array * @since 1.0.0 * @access public */ public function get_components() { return $this->builder_components; } /** * A representation of the builder as array. * * @return array * @since 1.0.0 * @access public */ final public function get_builder() { return array( 'id' => $this->control_id, 'control_id' => $this->control_id, 'panel' => $this->panel, 'section' => $this->section, 'title' => $this->title, 'devices' => $this->devices, 'items' => $this->get_components_settings(), 'rows' => $this->get_rows(), 'upsells' => $this->get_upsell_components(), ); } /** * Returns the components settings. * * @return array * @since 1.0.0 * @access public */ public function get_components_settings() { $components_settings = array(); /** * An instance of Component. * * @var Component $component */ foreach ( $this->builder_components as $component ) { $components_settings[ $component->get_id() ] = $component->get_settings(); } uasort( $components_settings, function ( $a, $b ) { if ( $a['name'] === $b['name'] ) { return 0; } return $a['name'] > $b['name'] ? 1 : - 1; } ); return $components_settings; } /** * Get the default row colors based on the old settings. * * @param string $row_id the row id. * * @return array */ protected function get_default_row_colors( $row_id ) { $bg_color_map = [ 'background' => [ 'dark-mode' => 'var(--nv-dark-bg)', 'light-mode' => 'var(--nv-site-bg)', ], 'text' => [ 'dark-mode' => 'var(--nv-text-dark-bg)', 'light-mode' => 'var(--nv-text-color)', ], ]; $is_footer_bottom = $this->get_id() === 'footer' && $row_id === 'bottom'; // On the new skin, the bottom footer row should be dark by default. if ( $is_footer_bottom ) { $bg_color_map = [ 'background' => [ 'dark-mode' => 'var(--nv-site-bg)', 'light-mode' => 'var(--nv-dark-bg)', ], 'text' => [ 'dark-mode' => 'var(--nv-text-color)', 'light-mode' => 'var(--nv-text-dark-bg)', ], ]; } $row_setting_id = $this->control_id . '_' . $row_id; $background = $bg_color_map['background']['light-mode']; $text = $bg_color_map['text']['light-mode']; $old_skin = get_theme_mod( $row_setting_id . '_' . self::SKIN_SETTING ); if ( ! empty( $old_skin ) ) { $background = $bg_color_map['background'][ $old_skin ]; $text = $bg_color_map['text'][ $old_skin ]; } return [ 'background' => $background, 'text' => $text, ]; } /** * Adds Sidebar Controls. * * @param string $row_setting_id row id. */ private function add_sidebar_controls( $row_setting_id ) { $align_choices = [ 'left' => [ 'tooltip' => __( 'Left', 'neve' ), 'icon' => 'editor-alignleft', ], 'center' => [ 'tooltip' => __( 'Center', 'neve' ), 'icon' => 'editor-aligncenter', ], 'right' => [ 'tooltip' => __( 'Right', 'neve' ), 'icon' => 'editor-alignright', ], ]; SettingsManager::get_instance()->add( [ 'id' => self::CONTENT_ALIGNMENT, 'group' => $row_setting_id, 'tab' => SettingsManager::TAB_LAYOUT, 'transport' => 'postMessage', 'label' => __( 'Alignment', 'neve' ), 'type' => '\Neve\Customizer\Controls\React\Responsive_Radio_Buttons', 'section' => $row_setting_id, 'options' => [ 'choices' => $align_choices, ], 'conditional_header' => true, 'sanitize_callback' => 'neve_sanitize_alignment', 'default' => [ 'desktop' => 'left', 'tablet' => 'left', 'mobile' => 'left', ], 'live_refresh_selector' => true, 'live_refresh_css_prop' => [ 'cssVar' => [ 'vars' => [ '--justify', '--textalign', '--flexg', '--wrapdropdownwidth', ], 'valueRemap' => [ '--justify' => [ 'left' => 'flex-start', 'center' => 'center', 'right' => 'flex-end', ], '--flexg' => [ 'left' => '1', 'center' => '0', 'right' => '0', ], '--wrapdropdownwidth' => [ 'left' => 'auto', 'center' => 'calc( 100% + 44px )', 'right' => 'auto', ], ], 'responsive' => true, 'selector' => '.header-menu-sidebar-bg', ], 'is_for' => 'horizontal', ], ] ); SettingsManager::get_instance()->add( [ 'id' => self::LAYOUT_SETTING, 'group' => $row_setting_id, 'tab' => SettingsManager::TAB_LAYOUT, 'label' => __( 'Open Behaviour', 'neve' ), 'type' => 'select', 'section' => $row_setting_id, 'options' => [ 'choices' => [ 'slide_left' => __( 'Slide from Left', 'neve' ), 'slide_right' => __( 'Slide from Right', 'neve' ), 'pull_left' => __( 'Pull from Left', 'neve' ), 'pull_right' => __( 'Pull from Right', 'neve' ), 'full_canvas' => __( 'Full Canvas', 'neve' ), 'dropdown' => __( 'Slide Down', 'neve' ), ], ], 'conditional_header' => true, 'transport' => 'refresh', 'sanitize_callback' => 'wp_filter_nohtml_kses', 'default' => 'slide_left', ] ); SettingsManager::get_instance()->add( [ 'id' => self::WIDTH, 'group' => $row_setting_id, 'tab' => SettingsManager::TAB_LAYOUT, 'label' => __( 'Sidebar Width', 'neve' ), 'transport' => 'postMessage', 'section' => $row_setting_id, 'conditional_header' => true, 'type' => '\Neve\Customizer\Controls\React\Responsive_Range', 'default' => '{ "mobile": "350", "tablet": "350", "desktop": "350" }', 'options' => [ 'active_callback' => function () { return in_array( get_theme_mod( $this->control_id . '_sidebar_' . self::LAYOUT_SETTING, 'slide_left' ), [ 'slide_left', 'slide_right', 'pull_left', 'pull_right', ], true ); }, 'input_attrs' => [ 'min' => 1, 'max' => 1000, 'units' => [ 'px', 'em', 'rem' ], 'defaultVal' => [ 'mobile' => 360, 'tablet' => 360, 'desktop' => 360, 'suffix' => [ 'mobile' => 'px', 'tablet' => 'px', 'desktop' => 'px', ], ], ], ], 'live_refresh_selector' => true, 'live_refresh_css_prop' => [ 'responsive' => true, 'template' => '.hfg_header .header-menu-sidebar { width: {{value}}px; }', ], 'sanitize_callback' => 'neve_sanitize_range_value', ] ); } /** * Adds Column Layout Controls. * * @param string $row_setting_id row setting id [e.g. hfg_footer_layout_bottom]. * @param string $row_id row id. */ private function add_columns_layout_controls( $row_setting_id, $row_id ) { $choices = []; for ( $i = 1; $i <= 5; $i ++ ) { $choices[ $i ] = [ 'tooltip' => $i, 'icon' => 'text', ]; } SettingsManager::get_instance()->add( [ 'id' => self::COLUMNS_NUMBER, 'group' => $row_setting_id, 'tab' => SettingsManager::TAB_LAYOUT, 'label' => __( 'Number of Columns', 'neve' ), 'type' => '\Neve\Customizer\Controls\React\Radio_Buttons', 'section' => $row_setting_id, 'options' => [ 'choices' => $choices, ], 'transport' => 'post' . $row_setting_id, 'sanitize_callback' => 'absint', 'default' => '3', ] ); SettingsManager::get_instance()->add( [ 'id' => self::COLUMNS_LAYOUT, 'group' => $row_setting_id, 'tab' => SettingsManager::TAB_LAYOUT, 'label' => __( 'Columns Layout', 'neve' ), 'type' => '\Neve\Customizer\Controls\React\Builder_Columns', 'section' => $row_setting_id, 'options' => [ 'columns_control' => $row_setting_id . '_' . self::COLUMNS_NUMBER, ], 'transport' => 'post' . $row_setting_id, 'sanitize_callback' => [ $this, 'sanitize_columns' ], 'default' => 'equal', ] ); $align_choices = [ 'flex-start' => [ 'tooltip' => __( 'Top', 'neve' ), 'icon' => 'arrow-up', ], 'center' => [ 'tooltip' => __( 'Middle', 'neve' ), 'icon' => 'sort', ], 'flex-end' => [ 'tooltip' => __( 'Bottom', 'neve' ), 'icon' => 'arrow-down', ], ]; SettingsManager::get_instance()->add( [ 'id' => self::VERTICAL_ALIGN, 'group' => $row_setting_id, 'tab' => SettingsManager::TAB_LAYOUT, 'transport' => 'postMessage', 'sanitize_callback' => 'wp_filter_nohtml_kses', 'default' => 'flex-start', 'section' => $row_setting_id, 'label' => __( 'Vertical Alignment', 'neve' ), 'type' => '\Neve\Customizer\Controls\React\Radio_Buttons', 'live_refresh_selector' => true, 'live_refresh_css_prop' => [ 'cssVar' => [ 'vars' => '--valign', 'selector' => '.' . $this->get_id() . '-' . $row_id . ' .row', ], 'is_for' => 'vertical', ], 'options' => [ 'choices' => $align_choices, ], ] ); } /** * Sanitize builder columns * * @param string $value control value. * * @return string */ public function sanitize_columns( $value ) { $allowed = [ 'equal', 'right-third', 'left-third', 'left-half', 'right-half', 'center-half', 'center-two-thirds', ]; if ( ! in_array( $value, $allowed ) ) { return 'equal'; } return $value; } /** * Adds sidebar styles. * * @param array $css_array array of styles. * * @return array */ private function add_sidebar_styles( $css_array ) { $type = get_theme_mod( $this->control_id . '_sidebar_' . self::LAYOUT_SETTING, 'slide_left' ); $default_sidebar_width = '{ "mobile": "360", "tablet": "360", "desktop": "360" }'; if ( ! in_array( $type, [ 'full_canvas', 'dropdown' ], true ) ) { $css_array[] = [ Dynamic_Selector::KEY_SELECTOR => '.header-menu-sidebar', Dynamic_Selector::KEY_RULES => [ Config::CSS_PROP_WIDTH => [ Dynamic_Selector::META_KEY => $this->control_id . '_sidebar_' . self::WIDTH, Dynamic_Selector::META_DEFAULT => $default_sidebar_width, Dynamic_Selector::META_SUFFIX => 'responsive_suffix', Dynamic_Selector::META_IS_RESPONSIVE => true, ], ], ]; } if ( $type === 'pull_left' ) { $css_array[] = [ Dynamic_Selector::KEY_SELECTOR => '.is-menu-sidebar > .wrapper', Dynamic_Selector::KEY_RULES => [ Config::CSS_PROP_LEFT => [ Dynamic_Selector::META_KEY => $this->control_id . '_sidebar_' . self::WIDTH, Dynamic_Selector::META_DEFAULT => $default_sidebar_width, Dynamic_Selector::META_SUFFIX => 'responsive_suffix', Dynamic_Selector::META_IS_RESPONSIVE => true, ], ], ]; } if ( $type === 'pull_right' ) { $css_array[] = [ Dynamic_Selector::KEY_SELECTOR => '.menu_sidebar_pull_right.is-menu-sidebar > .wrapper', Dynamic_Selector::KEY_RULES => [ Config::CSS_PROP_RIGHT => [ Dynamic_Selector::META_KEY => $this->control_id . '_sidebar_' . self::WIDTH, Dynamic_Selector::META_DEFAULT => $default_sidebar_width, Dynamic_Selector::META_SUFFIX => 'responsive_suffix', Dynamic_Selector::META_IS_RESPONSIVE => true, ], ], ]; } return $css_array; } /** * Adds the new builder row styles. * * @param array $css_array array of styles. * * @return array */ private function add_new_builder_styles( $css_array, $row ) { $justify_map = [ 'left' => 'flex-start', 'center' => 'center', 'right' => 'flex-end', ]; $align_default = [ 'desktop' => 'left', 'tablet' => 'left', 'mobile' => 'left', ]; $align_id = $this->control_id . '_' . $row . '_' . self::CONTENT_ALIGNMENT; if ( $row === 'sidebar' ) { $css_array[] = [ Dynamic_Selector::KEY_SELECTOR => '.header-menu-sidebar-bg', Dynamic_Selector::KEY_RULES => [ '--justify' => [ Dynamic_Selector::META_KEY => $align_id, Dynamic_Selector::META_IS_RESPONSIVE => true, Dynamic_Selector::META_FILTER => function ( $css_prop, $value, $meta, $device ) use ( $justify_map ) { return sprintf( '%s: %s;', $css_prop, $justify_map[ $value ] ); }, Dynamic_Selector::META_DEFAULT => $align_default, ], '--textalign' => [ Dynamic_Selector::META_KEY => $align_id, Dynamic_Selector::META_IS_RESPONSIVE => true, Dynamic_Selector::META_DEFAULT => $align_default, ], '--flexg' => [ Dynamic_Selector::META_KEY => $align_id, Dynamic_Selector::META_IS_RESPONSIVE => true, Dynamic_Selector::META_FILTER => function ( $css_prop, $value, $meta, $device ) { if ( $value === 'left' ) { return sprintf( '%s: 1;', $css_prop ); } return sprintf( '%s: 0;', $css_prop ); }, Dynamic_Selector::META_DEFAULT => $align_default, ], '--wrapdropdownwidth' => [ Dynamic_Selector::META_KEY => $align_id, Dynamic_Selector::META_IS_RESPONSIVE => true, Dynamic_Selector::META_FILTER => function ( $css_prop, $value, $meta, $device ) { if ( $value === 'center' ) { return sprintf( '%s: %s;', $css_prop, 'calc( 100% + 44px )' ); } return sprintf( '%s: auto;', $css_prop ); }, Dynamic_Selector::META_DEFAULT => $align_default, ], ], ]; } if ( ! $this->columns_layout ) { return $css_array; } $builder = $this->get_id(); $mods_prefix = 'hfg_' . $builder . '_layout_' . $row . '_'; $columns = SettingsManager::get_instance()->get( $mods_prefix . self::COLUMNS_NUMBER, 3 ); $layout = SettingsManager::get_instance()->get( $mods_prefix . self::COLUMNS_LAYOUT, 'equal' ); $styles_map = [ 1 => [ 'equal' => '1fr', ], 2 => [ 'equal' => '1fr 1fr', 'right-third' => '2fr 1fr', 'left-third' => '1fr 2fr', ], 3 => [ 'equal' => '1fr 1fr 1fr', 'left-half' => '2fr 1fr 1fr', 'right-half' => '1fr 1fr 2fr', 'center-half' => '1fr 2fr 1fr', 'center-two-thirds' => '1fr 3fr 1fr', ], 4 => [ 'equal' => 'repeat(4, 1fr)', 'left-half' => '3fr 1fr 1fr 1fr', 'right-half' => '1fr 1fr 1fr 3fr', ], 5 => [ 'equal' => 'repeat(5, 1fr)', ], ]; $proportions = 'equal'; if ( isset( $styles_map[ $columns ] ) && isset( $styles_map[ $columns ][ $layout ] ) ) { $proportions = $styles_map[ $columns ][ $layout ]; } $css_array[] = [ Dynamic_Selector::KEY_SELECTOR => '.' . $builder . '-' . $row . '-inner .row', Dynamic_Selector::KEY_RULES => [ Config::CSS_PROP_GRID_TEMPLATE_COLS => [ Dynamic_Selector::META_KEY => $mods_prefix . self::COLUMNS_LAYOUT, Dynamic_Selector::META_DEFAULT => 'auto', Dynamic_Selector::META_FILTER => function ( $css_prop, $value, $meta, $device ) use ( $proportions ) { return sprintf( '%s:%s;', $css_prop, $proportions ); }, ], '--valign' => [ Dynamic_Selector::META_KEY => $mods_prefix . self::VERTICAL_ALIGN, Dynamic_Selector::META_DEFAULT => 'flex-start', ], ], ]; return $css_array; } /** * Get upsell components. * * @return array */ protected function get_upsell_components() { return []; } } Header.php 0000666 00000051234 15226766106 0006471 0 ustar 00 <?php /** * Header class for Header Footer Grid. * * Name: Header Footer Grid * Author: Bogdan Preda <bogdan.preda@themeisle.com> * * @version 1.0.0 * @package HFG */ namespace HFG\Core\Builder; use HFG\Core\Customizer\Header_Presets; use HFG\Main; use Neve\Core\Styles\Dynamic_Selector; use Neve\Core\Theme_Info; use Neve\Customizer\Controls\React\Presets_Selector; use HFG\Core\Settings\Manager as SettingsManager; use WP_Customize_Control; use WP_Customize_Manager; /** * Class Header * * @package HFG\Core\Builder */ class Header extends Abstract_Builder { use Theme_Info; /** * Builder name. */ const BUILDER_NAME = 'header'; /** * Settings ids. */ const BACKGROUND_HEADING = 'background_heading'; const ADVANCED_STYLE = 'advanced_style'; const BACKGROUND_SETTING = 'background'; /** * Default color for global header background * * @var string Background default color. */ protected $default_background = 'var(--nv-site-bg)'; /** * Header init. * * @since 1.0.0 * @access public */ public function init() { $this->set_property( 'title', __( 'Header', 'neve' ) ); $this->set_property( 'description', apply_filters( 'hfg_header_panel_description', sprintf( /* translators: %s link to documentation */ esc_html__( 'Design your %1$s by dragging, dropping and resizing all the elements in real-time. %2$s.', 'neve' ), /* translators: %s builder type */ $this->get_property( 'title' ), /* translators: %s link text */ sprintf( '<br/><a target="_blank" rel="external noopener noreferrer" href="https://docs.themeisle.com/article/946-neve-doc#header"><span class="screen-reader-text">%s</span><svg xmlns="http://www.w3.org/2000/svg" focusable="false" role="img" viewBox="0 0 512 512" width="12" height="12" style="margin-right: 5px;"><path fill="currentColor" d="M432 320H400a16 16 0 0 0-16 16V448H64V128H208a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16H48A48 48 0 0 0 0 112V464a48 48 0 0 0 48 48H400a48 48 0 0 0 48-48V336A16 16 0 0 0 432 320ZM488 0h-128c-21.4 0-32 25.9-17 41l35.7 35.7L135 320.4a24 24 0 0 0 0 34L157.7 377a24 24 0 0 0 34 0L435.3 133.3 471 169c15 15 41 4.5 41-17V24A24 24 0 0 0 488 0Z"/></svg>%s</a>', esc_html__( '(opens in a new tab)', 'neve' ), esc_html__( 'Read full documentation', 'neve' ) ) ) ) ); $migrated_hfg = neve_is_new_builder(); $this->set_property( 'instructions_array', array( 'description' => __( 'Build your own header or choose from preset options.', 'neve' ), 'quickLinks' => array( 'custom_logo' => array( 'label' => esc_html__( 'Change Logo', 'neve' ), 'icon' => 'dashicons-editor-customchar', ), 'hfg_header_layout_main_background' => array( 'label' => esc_html__( 'Change Header Color', 'neve' ), 'icon' => 'dashicons-admin-appearance', ), 'primary-menu_shortcut' => array( 'label' => esc_html__( 'Change Menu', 'neve' ), 'icon' => 'dashicons-menu', ), ), 'builderMigrated' => $migrated_hfg, ) ); add_filter( 'hfg_header_wrapper_class', [ $this, 'add_class_to_header_wrapper' ] ); } /** * Called to register component controls. * * @param WP_Customize_Manager $wp_customize The Customize Manager. * * @return WP_Customize_Manager * @since 1.0.0 * @access public */ public function customize_register( WP_Customize_Manager $wp_customize ) { if ( ! neve_is_new_builder() ) { return parent::customize_register( $wp_customize ); } $section = $wp_customize->get_section( 'neve_pro_global_header_settings' ); if ( ! empty( $section ) ) { $section->priority = 201; } $wp_customize->add_section( 'neve_header_presets', [ 'title' => __( 'Header Presets', 'neve' ), 'priority' => 200, 'panel' => 'hfg_header', ] ); $wp_customize->add_setting( 'hfg_neve_header_presets', [ 'sanitize_callback' => 'sanitize_text_field', 'label' => __( 'Header Presets', 'neve' ), ] ); $wp_customize->add_control( new Presets_Selector( $wp_customize, 'hfg_neve_header_presets', [ 'section' => 'neve_header_presets', 'transport' => 'postMessage', 'priority' => 30, 'presets' => $this->get_header_presets(), 'builder' => $this->layout_control_id, ] ) ); $wp_customize->add_section( 'neve_pro_global_header_settings', [ 'title' => __( 'Global Header Settings', 'neve' ), 'priority' => 200, 'panel' => 'hfg_header', ] ); $this->customize_global_header(); SettingsManager::get_instance()->load( 'neve_pro_global_header_settings', $wp_customize ); $tabs = $wp_customize->get_control( 'neve_pro_global_header_settings_tabs' ); $this->move_pro_controls( $wp_customize, $tabs ); return parent::customize_register( $wp_customize ); } /** * Moves the controls from pro in the specific tabs so that they * merge well with the Neve global header setting * * @param WP_Customize_Manager $wp_customize The Customize Manager. * @param WP_Customize_Control $global_settings_tabs The Tabs Control. */ private function move_pro_controls( WP_Customize_Manager $wp_customize, WP_Customize_Control $global_settings_tabs ) { if ( ! property_exists( $global_settings_tabs, 'controls' ) || ! property_exists( $global_settings_tabs, 'tabs' ) ) { return; } if ( $wp_customize->get_control( 'neve_transparent_header' ) !== null ) { $global_settings_tabs->controls['style']['neve_transparent_header'] = []; } if ( $wp_customize->get_control( 'neve_transparent_only_on_home' ) !== null ) { $wp_customize->get_control( 'neve_transparent_only_on_home' )->priority = 10; $global_settings_tabs->controls['style']['neve_transparent_only_on_home'] = []; } if ( $wp_customize->get_control( 'neve_global_header' ) !== null ) { $global_settings_tabs->tabs['general'] = [ 'label' => esc_html__( 'General', 'neve' ), 'icon' => 'admin-generic', ]; $global_settings_tabs->controls['general']['neve_global_header'] = []; } if ( $wp_customize->get_control( 'neve_header_conditional_selector' ) !== null ) { $global_settings_tabs->controls['general']['neve_header_conditional_selector'] = []; } // sorts the tabs so the general tab is showed first ksort( $global_settings_tabs->tabs ); } /** * Registers controls for global header background */ private function customize_global_header() { $section_id = 'neve_pro_global_header_settings'; SettingsManager::get_instance()->add( [ 'id' => self::BACKGROUND_HEADING, 'group' => $section_id, 'label' => esc_html__( 'Background', 'neve' ), 'section' => $section_id, 'tab' => 'style', 'priority' => 15, 'transport' => 'postMessage', 'type' => 'Neve\Customizer\Controls\Heading', 'options' => [ 'accordion' => true, 'controls_to_wrap' => 20, 'expanded' => true, 'class' => 'background-accordion', ], ] ); SettingsManager::get_instance()->add( [ 'id' => self::ADVANCED_STYLE, 'group' => $section_id, 'label' => esc_html__( 'Enable Advanced Options', 'neve' ), 'section' => $section_id, 'tab' => 'style', 'type' => 'neve_toggle_control', 'priority' => 25, 'transport' => 'refresh', 'sanitize_callback' => 'neve_sanitize_checkbox', 'default' => true, 'conditional_header' => true, ] ); SettingsManager::get_instance()->add( [ 'id' => self::BACKGROUND_SETTING, 'group' => $section_id, 'section' => $section_id, 'tab' => 'style', 'label' => esc_html__( 'Global', 'neve' ), 'type' => '\Neve\Customizer\Controls\React\Background', 'live_refresh_selector' => true, 'live_refresh_css_prop' => [ 'cssVar' => [ 'vars' => 'backgroundControl', 'selector' => '.global-styled', ], ], 'options' => [ 'priority' => 30, 'active_callback' => [ $this, 'has_global_background' ], ], 'default' => [ 'type' => 'color', 'colorValue' => $this->default_background, ], 'transport' => 'postMessage', 'sanitize_callback' => 'neve_sanitize_background', 'conditional_header' => true, ] ); foreach ( $this->get_rows() as $row => $row_data ) { if ( $row === 'sidebar' ) { continue; } SettingsManager::get_instance()->add( [ 'id' => $row . '_shortcut', 'group' => $section_id, 'section' => $section_id, 'tab' => 'style', 'transport' => 'postMessage', 'sanitize_callback' => 'esc_attr', 'type' => '\Neve\Customizer\Controls\Button', 'priority' => 35, 'options' => [ 'button_text' => $row_data['title'], 'button_class' => 'button_background', 'icon_class' => 'edit', 'shortcut' => true, 'is_button' => false, 'control_to_focus' => 'hfg_header_layout_' . $row . '_background', 'active_callback' => [ $this, 'has_not_global_background' ], ], ] ); } } /** * Adds a class to the header wrapper. * * @param string $classes Existing classes. * @return string Updated classes. */ public function add_class_to_header_wrapper( $classes ) { return $classes . ( $this->has_global_background() ? ' global-styled' : '' ); } /** * Returns true if individual options from header background are disabled * * @return bool */ public function has_global_background() { return ! get_theme_mod( 'neve_pro_global_header_settings_advanced_style', true ); } /** * Returns true if individual options from header background are active * * @return bool */ public function has_not_global_background() { return ! $this->has_global_background(); } /** * Method called via hook. * * @since 1.0.0 * @access public */ public function load_template() { Main::get_instance()->load( 'header-wrapper' ); } /** * Get builder id. * * @return string Builder id. */ public function get_id() { return self::BUILDER_NAME; } /** * Render builder row. * * @param string $device_id The device id. * @param string $row_id The row id. * @param array $row_details Row data. */ public function render_row( $device_id, $row_id, $row_details ) { $name = $row_id; if ( $row_id === 'sidebar' && $device_id === 'mobile' ) { $name = 'mobile'; } Main::get_instance()->load( 'row-wrapper', $name ); } /** * Method to add global header css styles. * * @param array $css_array An array containing css rules. * @return array */ public function add_style( array $css_array = array() ) { $background = get_theme_mod( 'neve_pro_global_header_settings_background', [ 'type' => 'color', 'colorValue' => 'var(--nv-site-bg)', ] ); $rules = []; $control_id = 'neve_pro_global_header_settings_background'; $selector = '.global-styled'; $default_color = 'var(--nv-site-bg)'; if ( $background['type'] === 'color' && ! empty( $background['colorValue'] ) ) { $rules = array_merge( $rules, [ '--bgcolor' => [ Dynamic_Selector::META_KEY => $control_id . '.colorValue', Dynamic_Selector::META_DEFAULT => $default_color, ], ] ); } if ( $background['type'] === 'image' ) { $rules = array_merge( $rules, [ '--overlaycolor' => [ Dynamic_Selector::META_KEY => $control_id . '.overlayColorValue', ], '--bgimage' => [ Dynamic_Selector::META_KEY => $control_id, Dynamic_Selector::META_FILTER => function ( $css_prop, $value, $meta, $device ) { $image = $this->get_row_featured_image( $value['imageUrl'], $value['useFeatured'], $meta ); return sprintf( '%s:%s;', $css_prop, $image ); }, ], '--bgposition' => [ Dynamic_Selector::META_KEY => $control_id, Dynamic_Selector::META_FILTER => function ( $css_prop, $value, $meta, $device ) { if ( ! $this->is_valid_focus_point( $value['focusPoint'] ) ) { return ''; } $parsed_position = round( $value['focusPoint']['x'] * 100 ) . '% ' . round( $value['focusPoint']['y'] * 100 ) . '%;'; return sprintf( '%s:%s;', $css_prop, $parsed_position ); }, ], '--bgattachment' => [ Dynamic_Selector::META_KEY => $control_id, Dynamic_Selector::META_FILTER => function ( $css_prop, $value, $meta, $device ) { if ( ! isset( $value['fixed'] ) || $value['fixed'] !== true ) { return ''; } return sprintf( '%s:fixed;', $css_prop ); }, ], '--bgoverlayopacity' => [ Dynamic_Selector::META_KEY => $control_id, Dynamic_Selector::META_FILTER => function ( $css_prop, $value, $meta, $device ) { if ( ! isset( $value['overlayOpacity'] ) ) { return ''; } return sprintf( '%s:%s;', $css_prop, $value['overlayOpacity'] / 100 ); }, ], ] ); } $css_array[] = [ Dynamic_Selector::KEY_SELECTOR => $selector, Dynamic_Selector::KEY_RULES => $rules, ]; return parent::add_style( $css_array ); } /** * Return the builder rows. * * @return array * @since 1.0.0 * @updated 1.0.1 * @access protected */ protected function get_rows() { return [ 'top' => array( 'title' => esc_html__( 'Header Top', 'neve' ), 'description' => $this->get_property( 'description' ), ), 'main' => array( 'title' => esc_html__( 'Header Main', 'neve' ), 'description' => $this->get_property( 'description' ), ), 'bottom' => array( 'title' => esc_html__( 'Header Bottom', 'neve' ), 'description' => $this->get_property( 'description' ), ), 'sidebar' => array( 'title' => esc_html__( 'Mobile Sidebar', 'neve' ), 'description' => $this->get_property( 'description' ), ), ]; } /** * Get the header presets. * * @return array */ private function get_header_presets() { $presets = [ [ 'label' => 'Classic', 'image' => NEVE_ASSETS_URL . 'img/header-presets/Classic.jpg', 'setup' => '{"hfg_header_layout_v2":"{\"desktop\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[{\"id\":\"logo\"}],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[{\"id\":\"primary-menu\"},{\"id\":\"header_search_responsive\"}]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]}},\"mobile\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[{\"id\":\"logo\"}],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[{\"id\":\"nav-icon\"},{\"id\":\"header_search_responsive\"}]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"sidebar\":[{\"id\":\"primary-menu\"}]}}"}', ], [ 'label' => 'Inverted', 'image' => NEVE_ASSETS_URL . 'img/header-presets/Inverted.jpg', 'setup' => '{"hfg_header_layout_v2":"{\"desktop\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[{\"id\":\"primary-menu\"},{\"id\":\"header_search_responsive\"}],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[{\"id\":\"logo\"}]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]}},\"mobile\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[{\"id\":\"nav-icon\"},{\"id\":\"header_search_responsive\"}],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[{\"id\":\"logo\"}]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"sidebar\":[{\"id\":\"primary-menu\"}]}}","logo_component_align":{"mobile":"right","tablet":"right","desktop":"right"}}', ], [ 'label' => 'Centered', 'image' => NEVE_ASSETS_URL . 'img/header-presets/Centered.jpg', 'setup' => '{"hfg_header_layout_v2":"{\"desktop\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[],\"c-left\":[],\"center\":[{\"id\":\"logo\"}],\"c-right\":[],\"right\":[]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[{\"id\":\"primary-menu\"}],\"c-right\":[],\"right\":[]}},\"mobile\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[],\"c-left\":[],\"center\":[{\"id\":\"logo\"}],\"c-right\":[],\"right\":[]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[{\"id\":\"nav-icon\"}],\"c-right\":[],\"right\":[]},\"sidebar\":[{\"id\":\"primary-menu\"}]}}","logo_component_align":{"mobile":"center","tablet":"center","desktop":"center"}}', ], [ 'label' => 'Spaced', 'image' => NEVE_ASSETS_URL . 'img/header-presets/Spaced.jpg', 'setup' => '{"hfg_header_layout_v2":"{\"desktop\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[{\"id\":\"header_search_responsive\"}],\"c-left\":[],\"center\":[{\"id\":\"logo\"}],\"c-right\":[],\"right\":[{\"id\":\"nav-icon\"}]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]}},\"mobile\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[{\"id\":\"header_search_responsive\"}],\"c-left\":[],\"center\":[{\"id\":\"logo\"}],\"c-right\":[],\"right\":[{\"id\":\"nav-icon\"}]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"sidebar\":[{\"id\":\"primary-menu\"}]}}","logo_component_align":{"mobile":"center","tablet":"center","desktop":"center"}}', ], [ 'label' => 'Collapsed', 'image' => NEVE_ASSETS_URL . 'img/header-presets/ClassicCollapsed.jpg', 'setup' => '{"hfg_header_layout_v2":"{\"desktop\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[{\"id\":\"logo\"}],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[{\"id\":\"header_search_responsive\"},{\"id\":\"nav-icon\"}]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]}},\"mobile\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[{\"id\":\"logo\"}],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[{\"id\":\"header_search_responsive\"},{\"id\":\"nav-icon\"}]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"sidebar\":[{\"id\":\"primary-menu\"}]}}"}', ], [ 'label' => 'Search Field', 'image' => NEVE_ASSETS_URL . 'img/header-presets/SearchField.jpg', 'setup' => '{"hfg_header_layout_v2":"{\"desktop\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[{\"id\":\"logo\"},{\"id\":\"primary-menu\"}],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[{\"id\":\"header_search\"}]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]}},\"mobile\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[{\"id\":\"logo\"},{\"id\":\"nav-icon\"}],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[{\"id\":\"header_search_responsive\"}]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"sidebar\":[{\"id\":\"primary-menu\"}]}}"}', ], [ 'label' => 'Button Item', 'image' => NEVE_ASSETS_URL . 'img/header-presets/ButtonItem.jpg', 'setup' => '{"hfg_header_layout_v2":"{\"desktop\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[{\"id\":\"logo\"}],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[{\"id\":\"primary-menu\"},{\"id\":\"button_base\"}]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]}},\"mobile\":{\"top\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"main\":{\"left\":[{\"id\":\"logo\"}],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[{\"id\":\"nav-icon\"}]},\"bottom\":{\"left\":[],\"c-left\":[],\"center\":[],\"c-right\":[],\"right\":[]},\"sidebar\":[{\"id\":\"primary-menu\"},{\"id\":\"button_base\"}]}}"}', ], ]; return apply_filters( 'neve_header_presets_v2', $presets ); } /** * Get upsell components. * * @return array */ protected function get_upsell_components() { if ( $this->has_valid_addons() ) { return []; } return [ [ 'icon' => 'welcome-write-blog', 'name' => __( 'HTML', 'neve' ) . ' 2', ], [ 'icon' => 'embed-generic', 'name' => __( 'Custom Layouts', 'neve' ), ], [ 'icon' => 'share', 'name' => __( 'Social Icons', 'neve' ), ], ]; } } Footer.php 0000666 00000014006 15226766106 0006533 0 ustar 00 <?php /** * Footer class for Header Footer Grid. * * Name: Header Footer Grid * Author: Bogdan Preda <bogdan.preda@themeisle.com> * * @version 1.0.0 * @package HFG */ namespace HFG\Core\Builder; use HFG\Main; use Neve\Core\Theme_Info; /** * Class Footer * * @package HFG\Core\Builder */ class Footer extends Abstract_Builder { use Theme_Info; /** * Builder name. */ const BUILDER_NAME = 'footer'; /** * Footer constructor. * * @since 1.0.0 * @access public */ public function init() { $this->set_property( 'title', __( 'Footer', 'neve' ) ); $this->set_property( 'columns_layout', true ); $this->set_property( 'description', apply_filters( 'hfg_footer_panel_description', sprintf( /* translators: %s link to documentation */ esc_html__( 'Design your %1$s by dragging, dropping and resizing all the elements in real-time. %2$s.', 'neve' ), /* translators: %s builder type */ $this->get_property( 'title' ), /* translators: %s link text */ sprintf( '<br/><a target="_blank" rel="external noopener noreferrer" href="https://docs.themeisle.com/article/946-neve-doc#footer-builder"><span class="screen-reader-text">%s</span><svg xmlns="http://www.w3.org/2000/svg" focusable="false" role="img" viewBox="0 0 512 512" width="12" height="12" style="margin-right: 5px;"><path fill="currentColor" d="M432 320H400a16 16 0 0 0-16 16V448H64V128H208a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16H48A48 48 0 0 0 0 112V464a48 48 0 0 0 48 48H400a48 48 0 0 0 48-48V336A16 16 0 0 0 432 320ZM488 0h-128c-21.4 0-32 25.9-17 41l35.7 35.7L135 320.4a24 24 0 0 0 0 34L157.7 377a24 24 0 0 0 34 0L435.3 133.3 471 169c15 15 41 4.5 41-17V24A24 24 0 0 0 488 0Z"/></svg>%s</a>', esc_html__( '(opens in a new tab)', 'neve' ), esc_html__( 'Read full documentation', 'neve' ) ) ) ) ); $this->set_property( 'instructions_array', array( 'description' => sprintf( /* translators: 1: builder, 2: builder symbol */ esc_attr__( 'Welcome to the %1$s builder! Click the %2$s button to add a new component or follow the Quick Links.', 'neve' ), $this->get_property( 'title' ), '+' ), 'quickLinks' => array( 'footer_copyright_content' => array( 'label' => esc_html__( 'Change Copyright', 'neve' ), 'icon' => 'dashicons-nametag', 'url' => $this->has_valid_addons() ? null : tsdk_utmify( 'https://themeisle.com/themes/neve/upgrade/', 'copyright' ), ), 'hfg_footer_layout_bottom_background' => array( 'label' => esc_html__( 'Change Footer Color', 'neve' ), 'icon' => 'dashicons-admin-appearance', ), ), ) ); $this->devices = [ 'desktop' => __( 'Footer', 'neve' ), ]; /** * Fix legacy search widget display in footer * Only applies for versions < 5.8 */ add_filter( 'dynamic_sidebar_params', function ( $params ) { $processed_params = []; $has_legacy_search_style = apply_filters( 'neve_has_legacy_search_style_filter', false ); foreach ( $params as $param ) { if ( isset( $param['before_widget'] ) && strpos( $param['before_widget'], 'widget_search' ) !== false && $has_legacy_search_style === false ) { $param['before_widget'] = '<style type="text/css">.widget_search .search-form .search-submit, .widget_search .search-form .search-field { height: auto; }</style>' . $param['before_widget']; add_filter( 'neve_has_legacy_search_style_filter', '__return_true' ); } array_push( $processed_params, $param ); } return $processed_params; } ); add_action( 'neve_after_slot_component', [ $this, 'add_footer_component' ], 10, 3 ); } /** * Add footer component. * * @param string $builder Builder slug. * @param string $row Row slug. * @param string $slot Slot name. * * @return void */ public function add_footer_component( $builder, $row, $slot ) { if ( $this->has_valid_addons() ) { return; } if ( $builder !== self::BUILDER_NAME ) { return; } if ( $row !== 'bottom' ) { return; } if ( $slot !== 'left' ) { return; } $output = '<div class="builder-item"><div class="item--inner"><div class="component-wrap"><div>'; $output .= sprintf( /* translators: %1$s is Theme Name ( Neve ), %2$s is WordPress */ esc_html__( '%1$s | Powered by %2$s', 'neve' ), wp_kses_post( '<p><a href="https://themeisle.com/themes/neve/" rel="nofollow">Neve</a>' ), wp_kses_post( '<a href="http://wordpress.org" rel="nofollow">WordPress</a></p>' ) ); $output .= '</div></div></div></div>'; echo wp_kses_post( $output ); } /** * Method called via hook. * * @since 1.0.0 * @access public */ public function load_template() { Main::get_instance()->load( 'footer-wrapper' ); } /** * Render builder row. * * @param string $device_id The device id. * @param string $row_id The row id. * @param array $row_details Row data. */ public function render_row( $device_id, $row_id, $row_details ) { Main::get_instance()->load( 'footer-row-wrapper' ); } /** * Get builder id. * * @return string Builder id. */ public function get_id() { return self::BUILDER_NAME; } /** * Overrides parent method to limit rows. * * @return array * @since 1.0.0 * @access protected */ protected function get_rows() { if ( neve_is_new_builder() ) { return [ 'top' => array( 'title' => __( 'Footer Top', 'neve' ), 'description' => $this->get_property( 'description' ), ), 'main' => array( 'title' => __( 'Footer Main', 'neve' ), 'description' => $this->get_property( 'description' ), ), 'bottom' => array( 'title' => __( 'Footer Bottom', 'neve' ), 'description' => $this->get_property( 'description' ), ), ]; } return [ 'top' => array( 'title' => __( 'Footer Top', 'neve' ), 'description' => $this->get_property( 'description' ), ), 'bottom' => array( 'title' => __( 'Footer Bottom', 'neve' ), 'description' => $this->get_property( 'description' ), ), ]; } }
| ver. 1.4 |
Github
|
.
| PHP 5.4.45 | Generation time: 0 |
proxy
|
phpinfo
|
Settings