File: /home/www/web115/wordpress/wp-content/themes/neve/header-footer-grid/Core/Components/Logo.php
<?php
/**
* Custom Component 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\Components;
use HFG\Core\Script_Register;
use HFG\Core\Settings\Config;
use HFG\Core\Settings\Manager as SettingsManager;
use HFG\Main;
use Neve\Core\Dynamic_Css;
use Neve\Core\Settings\Mods;
use Neve\Core\Styles\Dynamic_Selector;
use WP_Post;
/**
* Class Logo.
*
* @package HFG\Core\Components
*/
class Logo extends Abstract_Component {
const COMPONENT_ID = 'logo';
const LOGO = 'logo';
const CUSTOM_LOGO = 'custom_logo';
const USE_SAME = 'same_logo';
const DISPLAY = 'display';
const MAX_WIDTH = 'max_width';
const SHOW_TITLE = 'show_title';
const SHOW_TAGLINE = 'show_tagline';
const DISABLE_LINK = 'disable_link';
const COLOR_ID = 'color';
const TITLE_FONT_SIZE = 'title_font_size';
const TAGLINE_FONT_SIZE = 'tagline_font_size';
/**
* Default spacing value
*
* @var array
*/
protected $default_padding_value = array(
'mobile' => array(
'top' => 10,
'right' => 0,
'bottom' => 10,
'left' => 0,
),
'tablet' => array(
'top' => 10,
'right' => 0,
'bottom' => 10,
'left' => 0,
),
'desktop' => array(
'top' => 10,
'right' => 0,
'bottom' => 10,
'left' => 0,
),
'mobile-unit' => 'px',
'tablet-unit' => 'px',
'desktop-unit' => 'px',
);
/**
* Logo constructor.
*
* @since 1.0.0
* @access public
*/
public function init() {
$this->set_property( 'label', __( 'Logo & Site Identity', 'neve' ) );
$this->set_property( 'description', __( 'Display your company logo here or simply use words to describe your business.', 'neve' ) );
$this->set_property( 'id', $this->get_class_const( 'COMPONENT_ID' ) );
$this->set_property( 'component_slug', 'hfg-logo' );
$this->set_property( 'width', 3 );
$this->set_property( 'icon', 'admin-appearance' );
$this->set_property( 'section', 'title_tagline' );
$this->set_property( 'preview_image', esc_url( get_template_directory_uri() . '/header-footer-grid/assets/images/customizer/component-site-logo.jpg' ) );
$this->set_property( 'default_selector', '.builder-item--' . $this->get_id() . ' .site-logo' );
$this->set_property( 'has_horizontal_alignment', true );
add_filter( 'hfg_component_scripts', [ $this, 'register_script' ] );
add_filter( 'hfg_logo_variants', [ $this, 'filter_logo_variants' ] );
// We use this filter to port changes to the logo from the templates on the new component.
add_filter( 'pre_set_theme_mod_custom_logo', [ $this, 'update_logo_theme_mod' ], 10, 2 );
// we remove the sizes for SVG
add_filter( 'wp_calculate_image_sizes', [ $this, 'filter_svg_logo_size' ], 10, 5 );
add_filter( 'wp_get_attachment_image_attributes', [ $this, 'clear_svg_size_attr' ], 10, 3 );
}
/**
* Clear width and height attributes for SVG.
*
* @param array $attr Attributes.
* @param WP_Post $attachment The attachment.
* @param string $size The size.
*
* @return array
*/
final public function clear_svg_size_attr( $attr, $attachment, $size = 'thumbnail' ) {
if ( ! $attachment instanceof WP_Post ) {
return $attr;
}
$mime = get_post_mime_type( $attachment->ID );
if ( 'image/svg+xml' === $mime ) {
unset( $attr['width'] );
unset( $attr['height'] );
}
return $attr;
}
/**
* Set the sizes for SVG.
*
* @param string $sizes The style sizes.
* @param string $size The specified size.
* @param string $image_src The source of the image.
* @param array $image_meta The meta for the image.
* @param int $attachment_id The attachment ID.
*
* @return string
*/
final public function filter_svg_logo_size( $sizes, $size, $image_src, $image_meta, $attachment_id ) {
$mime = get_post_mime_type( $attachment_id );
if ( 'image/svg+xml' === $mime ) {
return '';
}
return $sizes;
}
/**
* Updates the theme mode JSON based on the custom logo value.
* Used for backwards compatibility with previous component.
*
* @param string $value The new value for the theme mod.
* @param string $old_value The previous value.
*
* @return string
*/
public function update_logo_theme_mod( $value, $old_value ) {
$conditional_main = json_decode( Mods::get( self::COMPONENT_ID . '_' . self::LOGO, self::sanitize_logo_json( $old_value ) ), true );
$conditional_main['light'] = $value;
if ( $conditional_main['same'] ) {
$conditional_main['dark'] = $value;
}
$update_palette_logo = wp_json_encode( $conditional_main );
set_theme_mod( self::COMPONENT_ID . '_' . self::LOGO, $update_palette_logo );
return $value;
}
/**
* Register Inline Scripts for component.
*
* @return string
*/
public function register_script() {
$script_register = Script_Register::get_instance();
if ( ( $this->is_component_active() || is_customize_preview() ) && $script_register->is_queued( self::COMPONENT_ID ) === false ) {
$script_register->register_script( self::COMPONENT_ID, $this->toggle_script() );
}
return $script_register->inline_scripts();
}
/**
* Method to check that the component is active.
*
* @return bool
*/
protected function is_component_active() {
$builders = Main::get_instance()->get_builders();
foreach ( $builders as $builder ) {
if ( $builder->is_component_active( $this->get_id() ) ) {
return true;
}
}
return false;
}
/**
* Load Component Scripts
*
* @return void
*/
public function load_scripts() {
if ( $this->is_component_active() || is_customize_preview() ) {
wp_add_inline_script( 'neve-script', $this->toggle_script() );
}
}
/**
* Generate the variants for the Logo
*
* @param array $variants Contains other variants from similar components.
*
* @return array
*/
public function filter_logo_variants( $variants ) {
$main_logo = get_theme_mod( 'custom_logo' );
$conditional_main = json_decode( Mods::get( self::COMPONENT_ID . '_' . self::LOGO, self::sanitize_logo_json( $main_logo ) ), true );
$logo_main_light_id = $main_logo;
$logo_main_dark_id = $logo_main_light_id;
$logo_main_same = true;
if ( ! empty( $conditional_main ) ) {
$logo_main_light_id = isset( $conditional_main['light'] ) ? $conditional_main['light'] : $main_logo;
$logo_main_dark_id = isset( $conditional_main['dark'] ) ? $conditional_main['dark'] : $logo_main_light_id;
$logo_main_same = isset( $conditional_main['same'] ) ? $conditional_main['same'] : $logo_main_same;
}
$variants[ $this->get_id() ] = array(
'light' => array(
'src' => wp_get_attachment_image_url( $logo_main_light_id, apply_filters( 'hfg_logo_image_size', 'full' ), false ),
'srcset' => wp_get_attachment_image_srcset( $logo_main_light_id, apply_filters( 'hfg_logo_image_size', 'full' ) ),
'sizes' => wp_get_attachment_image_sizes( $logo_main_light_id, apply_filters( 'hfg_logo_image_size', 'full' ) ),
),
'dark' => array(
'src' => wp_get_attachment_image_url( $logo_main_dark_id, apply_filters( 'hfg_logo_image_size', 'full' ), false ),
'srcset' => wp_get_attachment_image_srcset( $logo_main_dark_id, apply_filters( 'hfg_logo_image_size', 'full' ) ),
'sizes' => wp_get_attachment_image_sizes( $logo_main_dark_id, apply_filters( 'hfg_logo_image_size', 'full' ) ),
),
'same' => $logo_main_same,
);
return $variants;
}
/**
* Get JS contents from file to use as inline script.
*
* @return string
*/
public function toggle_script() {
$variants = apply_filters( 'hfg_logo_variants', array() );
$variants_json = wp_json_encode( $variants );
$script = <<<JS
var html = document.documentElement;
var theme = html.getAttribute('data-neve-theme') || 'light';
var variants = {$variants_json};
function setCurrentTheme( theme ) {
var pictures = document.getElementsByClassName( 'neve-site-logo' );
for(var i = 0; i<pictures.length; i++) {
var picture = pictures.item(i);
if( ! picture ) {
continue;
};
var fileExt = picture.src.slice((Math.max(0, picture.src.lastIndexOf(".")) || Infinity) + 1);
if ( fileExt === 'svg' ) {
picture.removeAttribute('width');
picture.removeAttribute('height');
picture.style = 'width: var(--maxwidth)';
}
var compId = picture.getAttribute('data-variant');
if ( compId && variants[compId] ) {
var isConditional = variants[compId]['same'];
if ( theme === 'light' || isConditional || variants[compId]['dark']['src'] === false ) {
picture.src = variants[compId]['light']['src'];
picture.srcset = variants[compId]['light']['srcset'] || '';
picture.sizes = variants[compId]['light']['sizes'];
continue;
};
picture.src = variants[compId]['dark']['src'];
picture.srcset = variants[compId]['dark']['srcset'] || '';
picture.sizes = variants[compId]['dark']['sizes'];
};
};
};
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type == 'attributes') {
theme = html.getAttribute('data-neve-theme');
setCurrentTheme(theme);
};
});
});
observer.observe(html, {
attributes: true
});
JS;
return $script;
}
/**
* Sanitize the logo json
*
* @param string $input A json data for the logo component.
*
* @return string
*/
public static function sanitize_logo_json( $input ) {
$inputs = json_decode( $input, true );
if ( is_array( $inputs ) && ! empty( $inputs ) && ! empty( $input ) ) {
return $input;
}
return wp_json_encode(
array(
'light' => get_theme_mod( 'custom_logo' ),
'dark' => get_theme_mod( 'custom_logo' ),
'same' => true,
)
);
}
/**
* Called to register component controls.
*
* @since 1.0.0
* @access public
*/
public function add_settings() {
if ( $this->get_class_const( 'COMPONENT_ID' ) === 'logo' ) {
SettingsManager::get_instance()->add_controls_to_tabs(
$this->get_class_const( 'COMPONENT_ID' ),
array(
SettingsManager::TAB_GENERAL => array(
self::LOGO => array(),
'blogname' => array(),
'blogdescription' => array(),
'site_icon' => array(),
),
)
);
}
$custom_logo_args = get_theme_support( 'custom-logo' );
$default = array(
'light' => get_theme_mod( 'custom_logo' ),
'dark' => get_theme_mod( 'custom_logo' ),
'same' => true,
);
SettingsManager::get_instance()->add(
[
'id' => self::LOGO,
'group' => $this->get_class_const( 'COMPONENT_ID' ),
'tab' => SettingsManager::TAB_GENERAL,
'transport' => 'refresh',
'sanitize_callback' => array( $this, 'sanitize_logo_json' ),
'default' => wp_json_encode( $default ),
'type' => '\Neve\Customizer\Controls\React\Logo_Palette',
'options' => [
'priority' => 0,
'input_attrs' => [
'builderListen' => 'hfg_header_layout' . ( neve_is_new_builder() ? '_v2' : '' ),
'compChange' => PaletteSwitch::COMPONENT_ID,
'sameLabel' => __( 'Use one logo for both modes', 'neve' ),
'height' => isset( $custom_logo_args[0]['height'] ) ? $custom_logo_args[0]['height'] : null,
'width' => isset( $custom_logo_args[0]['width'] ) ? $custom_logo_args[0]['width'] : null,
'flexHeight' => isset( $custom_logo_args[0]['flex-height'] ) ? $custom_logo_args[0]['flex-height'] : true,
'flexWidth' => false, // this can not flex as to allow correct cropping
],
],
'section' => $this->section,
]
);
SettingsManager::get_instance()->add(
[
'id' => self::DISPLAY,
'group' => $this->get_class_const( 'COMPONENT_ID' ),
'tab' => SettingsManager::TAB_GENERAL,
'transport' => 'post' . $this->get_builder_id(),
'sanitize_callback' => 'wp_filter_nohtml_kses',
'default' => 'default',
'label' => __( 'Display', 'neve' ),
'type' => '\Neve\Customizer\Controls\React\Radio_Buttons',
'options' => [
'priority' => - 1,
'is_for' => 'logo',
'large_buttons' => true,
],
'section' => $this->section,
'conditional_header' => true,
]
);
SettingsManager::get_instance()->add(
[
'id' => self::SHOW_TAGLINE,
'group' => $this->get_class_const( 'COMPONENT_ID' ),
'tab' => SettingsManager::TAB_GENERAL,
'transport' => 'post' . $this->get_class_const( 'COMPONENT_ID' ),
'sanitize_callback' => 'absint',
'default' => 1,
'label' => __( 'Show Site Tagline', 'neve' ),
'type' => 'neve_toggle_control',
'section' => $this->section,
'conditional_header' => true,
]
);
SettingsManager::get_instance()->add(
[
'id' => self::SHOW_TITLE,
'group' => $this->get_class_const( 'COMPONENT_ID' ),
'tab' => SettingsManager::TAB_GENERAL,
'transport' => 'post' . $this->get_class_const( 'COMPONENT_ID' ),
'sanitize_callback' => 'absint',
'default' => 1,
'label' => __( 'Show Site Title', 'neve' ),
'type' => 'neve_toggle_control',
'section' => $this->section,
'conditional_header' => true,
]
);
SettingsManager::get_instance()->add(
[
'id' => self::MAX_WIDTH,
'group' => $this->get_class_const( 'COMPONENT_ID' ),
'tab' => SettingsManager::TAB_GENERAL,
'transport' => 'post' . $this->get_class_const( 'COMPONENT_ID' ),
'sanitize_callback' => 'neve_sanitize_range_value',
'default' => '{ "mobile": "120", "tablet": "120", "desktop": "120" }',
'label' => __( 'Logo max width', 'neve' ),
'type' => '\Neve\Customizer\Controls\React\Responsive_Range',
'options' => [
'priority' => 12,
'hide_responsive_switches' => true,
'media_query' => true,
'step' => 1,
'input_attrs' => [
'min' => 0,
'max' => 350,
'units' => [ 'px', 'em', 'rem' ],
'defaultVal' => [
'mobile' => 120,
'tablet' => 120,
'desktop' => 120,
'suffix' => [
'mobile' => 'px',
'tablet' => 'px',
'desktop' => 'px',
],
],
],
],
'section' => $this->section,
]
);
SettingsManager::get_instance()->add(
[
'id' => self::DISABLE_LINK,
'group' => $this->get_class_const( 'COMPONENT_ID' ),
'tab' => SettingsManager::TAB_GENERAL,
'transport' => 'post' . $this->get_class_const( 'COMPONENT_ID' ),
'sanitize_callback' => 'absint',
'default' => false,
'label' => __( 'Disable Homepage Link', 'neve' ),
'type' => 'neve_toggle_control',
'section' => $this->section,
'conditional_header' => true,
]
);
SettingsManager::get_instance()->add(
[
'id' => self::TITLE_FONT_SIZE,
'group' => $this->get_class_const( 'COMPONENT_ID' ),
'tab' => SettingsManager::TAB_STYLE,
'transport' => 'post' . $this->get_class_const( 'COMPONENT_ID' ),
'sanitize_callback' => 'neve_sanitize_range_value',
'default' => '{ "mobile": "24", "tablet": "24", "desktop": "24" }',
'label' => __( 'Site Title', 'neve' ) . ' ' . __( 'Font Size', 'neve' ),
'type' => '\Neve\Customizer\Controls\React\Responsive_Range',
'live_refresh_selector' => true,
'live_refresh_css_prop' => [
'cssVar' => [
'vars' => '--fs',
'selector' => $this->default_selector . ' .brand .nv-title-tagline-wrap',
'responsive' => true,
'suffix' => 'px',
],
],
'options' => [
'hide_responsive_switches' => true,
'media_query' => true,
'step' => 1,
'input_attrs' => [
'min' => 0,
'max' => 100,
'units' => [ 'px', 'em', 'rem' ],
'defaultVal' => [
'mobile' => 24,
'tablet' => 24,
'desktop' => 24,
'suffix' => [
'mobile' => 'px',
'tablet' => 'px',
'desktop' => 'px',
],
],
],
],
'section' => $this->section,
'conditional_header' => true,
]
);
SettingsManager::get_instance()->add(
[
'id' => self::COLOR_ID,
'group' => $this->get_class_const( 'COMPONENT_ID' ),
'tab' => SettingsManager::TAB_STYLE,
'transport' => 'postMessage',
'sanitize_callback' => 'neve_sanitize_colors',
'label' => __( 'Text Color', 'neve' ),
'type' => 'neve_color_control',
'section' => $this->section,
'live_refresh_selector' => true,
'live_refresh_css_prop' => [
'cssVar' => [
'vars' => '--color',
'selector' => '.builder-item--' . $this->get_id(),
],
[
'selector' => $this->default_selector . ' .brand .nv-title-tagline-wrap',
'prop' => 'color',
'fallback' => 'inherit',
],
],
'conditional_header' => true,
]
);
}
/**
* Render logo section.
*/
public function render_component() {
Main::get_instance()->load( 'components/component-logo' );
}
/**
* Method to add Component 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() ) {
$css_array[] = [
Dynamic_Selector::KEY_SELECTOR => '.builder-item--' . $this->get_id(),
Dynamic_Selector::KEY_RULES => [
'--maxwidth' => [
Dynamic_Selector::META_IS_RESPONSIVE => true,
Dynamic_Selector::META_KEY => $this->get_id() . '_' . self::MAX_WIDTH,
Dynamic_Selector::META_SUFFIX => 'responsive_suffix',
Dynamic_Selector::META_DEFAULT => '{ "mobile": "120", "tablet": "120", "desktop": "120" }',
],
'--color' => [
Dynamic_Selector::META_KEY => $this->get_id() . '_' . self::COLOR_ID,
],
'--fs' => [
Dynamic_Selector::META_IS_RESPONSIVE => true,
Dynamic_Selector::META_KEY => $this->get_id() . '_' . self::TITLE_FONT_SIZE,
Dynamic_Selector::META_SUFFIX => 'responsive_suffix',
Dynamic_Selector::META_DEFAULT => '{ "mobile": "24", "tablet": "24", "desktop": "24" }',
],
],
];
return parent::add_style( $css_array );
}
}