<?php /** * 2 classes to manage social media icons and share entry links * ============================================================ * */ if( ! defined( 'ABSPATH' ) ) { exit; } // Exit if accessed directly if( ! class_exists( 'avia_social_media_icons' ) ) { /** * Social Media Icon builder * * @since ??? */ class avia_social_media_icons { /** * @since < 4.0 * @var array */ protected $args; /** * @since < 4.0 * @var array */ protected $post_data; /** * @since < 4.0 * @var array */ protected $icons; /** * @since < 4.0 * @var string */ protected $html; /** * @since < 4.0 * @var int */ protected $counter; /** * Initialize the variables necessary for all social media links * * @since < 4.0 * @param array $args * @param array $post_data */ public function __construct( $args = array(), $post_data = array() ) { $default_arguments = array( 'outside' => 'ul', 'inside' => 'li', 'class' => 'social_bookmarks', 'append' => '' ); $this->args = array_merge( $default_arguments, $args ); $this->post_data = $post_data; $this->icons = apply_filters( 'avia_filter_social_icons', avia_get_option( 'social_icons' ) ); $this->html = ''; $this->counter = 1; $this->validate_urls(); } /** * @since 4.5.6 */ public function __destruct() { unset( $this->args ); unset( $this->post_data ); unset( $this->icons ); } /** * Returns the array of social icons defined in theme options (or filtered on creating class) * * @since 4.8.3 * @return array */ public function get_icons() { return $this->icons; } /** * Returns the social profile info from theme options settings * * @since 4.8.3 * @param string $key * @return array|false */ public function get_icon( $key ) { foreach( $this->icons as $icon ) { if( isset( $icon['social_icon'] ) && $key == $icon['social_icon'] ) { return $icon; } } return false; } /** * Handle special URL cases * * @since 4.8.3 */ protected function validate_urls() { foreach ( $this->icons as &$icon ) { switch( $icon['social_icon'] ) { case 'rss': if( empty( $icon['social_icon_link'] ) ) { $icon['social_icon_link'] = get_bloginfo( 'rss2_url' ); } break; case 'twitter': case 'dribbble': case 'vimeo': case 'behance': if( strpos( $icon['social_icon_link'], 'http' ) === false && ! empty( $icon['social_icon_link'] ) ) { /** * Protocoll changed with 4.5.6 to https. Allow to filter in case http is needed * * @since 4.5.6 * @return string */ $protocol = apply_filters( 'avf_social_media_icon_protocol', 'https', $icon ); $icon['social_icon_link'] = "{$protocol}://{$icon['social_icon']}.com/{$icon['social_icon_link']}/"; } break; } } unset( $icon ); } /** * Builds the html string for a single item, with a few options for special items like rss feeds * * @since < 4.0 * @param array $icon * @return string */ protected function build_icon( $icon ) { global $avia_config; $display_name = ucfirst( $icon['social_icon'] ); if( ! empty( $avia_config['font_icons'][ $icon['social_icon'] ]['display_name'] ) ) { $display_name = $avia_config['font_icons'][ $icon['social_icon'] ]['display_name']; } $aria_label = sprintf( __( 'Link to %s', 'avia_framework' ), $display_name ); if( 'rss' == $icon['social_icon'] ) { $aria_label .= ' ' . __( ' this site', 'avia_framework' ); } if( empty( $icon['social_icon_link'] ) ) { $icon['social_icon_link'] = '#'; } //dont add target blank to relative urls or urls to the same domain $blank = ( strpos( $icon['social_icon_link'], 'http') === false || strpos( $icon['social_icon_link'], home_url() ) === 0 ) ? '' : ' target="_blank"'; /** * @since 4.5.6 * @return string */ $aria_label = apply_filters( 'avf_social_media_icon_aria_label_value', $aria_label, $icon ); if( ! empty( $aria_label ) ) { $aria_label = 'aria-label="' . esc_attr( $aria_label ) . '"'; } /** * Change tooltip titls for icon * * @since 4.8.7 * @param string $display_name * @param array $icon * @return string */ $display_name = apply_filters( 'avf_social_media_icon_display_name', $display_name, $icon ); $html = ''; $html .= "<{$this->args['inside']} class='{$this->args['class']}_{$icon['social_icon']} av-social-link-{$icon['social_icon']} social_icon_{$this->counter}'>"; $html .= "<a {$blank} {$aria_label} href='" . esc_url( $icon['social_icon_link'] ) . "' " . av_icon_string( $icon['social_icon'], false ) . " title='{$display_name}'>"; $html .= "<span class='avia_hidden_link_text'>{$display_name}</span>"; $html .= '</a>'; $html .= "</{$this->args['inside']}>"; $html = avia_targeted_link_rel( $html ); return $html; } /** * Builds the html, based on the available icons * * @since < 4.0 * @return string */ public function html() { $this->html = ''; if( ! empty( $this->icons ) ) { $this->html .= "<{$this->args['outside']} class='noLightbox {$this->args['class']} icon_count_" . count( $this->icons ) . "'>"; foreach ( $this->icons as $icon ) { if( ! empty( $icon['social_icon'] ) ) { $this->html .= $this->build_icon( $icon ); $this->counter ++; } } $this->html .= $this->args['append']; $this->html .= "</{$this->args['outside']}>"; } return $this->html; } } } if( ! function_exists( 'avia_social_media_icons' ) ) { /** * Wrapper function for social media icons * * @since < 4.0 * @param array $args * @param boolean $echo * @param array $post_data * @return string */ function avia_social_media_icons( $args = array(), $echo = true, $post_data = array() ) { $icons = new avia_social_media_icons( $args, $post_data ); $html = $icons->html(); if( $echo ) { echo $html; } return $html; } } if( ! class_exists( 'avia_social_share_links' ) ) { /** * Share link builder class * * @since ??? * @since 4.8.3 extended to support link to social profiles and custom profile link set in ALB element "Social Buttons" */ class avia_social_share_links { /** * @since < 4.0 * @var array */ protected $args; /** * @since < 4.0 * @var array */ protected $options; /** * @since < 4.0 * @var string */ protected $title; /** * @since < 4.0 * @var array */ protected $links; /** * @since < 4.0 * @var string */ protected $html; /** * @since < 4.0 * @var int */ protected $counter; /** * * @since 4.5.7.1 * @var array */ protected $post_data; /** * * @since 4.8.3 * @var avia_social_media_icons */ protected $social_media_icons; /** * Initialize the variables necessary for all social media links * * @since < 4.0 * @param array $args * @param array|false $options * @param string|false $title */ public function __construct( $args = array(), $options = false, $title = false ) { $default_arguments = array( 'facebook' => array( 'encode' => true, 'encode_urls' => false, 'pattern' => 'https://www.facebook.com/sharer.php?u=[permalink]&t=[title]' ), 'twitter' => array( 'encode' => true, 'encode_urls' => false, 'pattern' => 'https://twitter.com/share?text=[title]&url=[shortlink]' ), 'whatsapp' => array( 'encode' => true, 'encode_urls' => false, 'pattern' => 'https://api.whatsapp.com/send?text=[permalink]', 'label' => __( 'Share on WhatsApp', 'avia_framework' ), 'label_profile' => __( 'Link to WhatsApp', 'avia_framework' ) ), 'pinterest' => array( 'encode' => true, 'encode_urls' => true, 'pattern' => 'https://pinterest.com/pin/create/button/?url=[permalink]&description=[title]&media=[thumbnail]' ), 'linkedin' => array( 'encode' => true, 'encode_urls' => false, 'pattern' => 'https://linkedin.com/shareArticle?mini=true&title=[title]&url=[permalink]' ), 'tumblr' => array( 'encode' => true, 'encode_urls' => true, 'pattern' => 'https://www.tumblr.com/share/link?url=[permalink]&name=[title]&description=[excerpt]' ), 'vk' => array( 'encode' => true, 'encode_urls' => false, 'pattern' => 'https://vk.com/share.php?url=[permalink]' ), 'reddit' => array( 'encode' => true, 'encode_urls' => false, 'pattern' => 'https://reddit.com/submit?url=[permalink]&title=[title]' ), 'telegram' => $this->default_telegram_link( $args, $options, $title ), 'mail' => array( 'encode' => true, 'encode_urls' => false, 'pattern' => 'mailto:?subject=[title]&body=[permalink]', 'label' => __( 'Share by Mail', 'avia_framework' ) ), 'yelp' => $this->default_yelp_link( $args, $options, $title ), 'five_100_px' => array( 'encode' => false, 'encode_urls' => false, 'profile_only' => true, 'label_profile' => __( 'Link to 500px', 'avia_framework' ) ), 'behance' => array( 'encode' => false, 'encode_urls' => false, 'profile_only' => true ), 'dribbble' => array( 'encode' => false, 'encode_urls' => false, 'profile_only' => true ), 'flickr' => array( 'encode' => false, 'encode_urls' => false, 'profile_only' => true ), 'instagram' => array( 'encode' => false, 'encode_urls' => false, 'profile_only' => true ), 'skype' => array( 'encode' => false, 'encode_urls' => false, 'profile_only' => true ), 'soundcloud' => array( 'encode' => false, 'encode_urls' => false, 'profile_only' => true ), 'vimeo' => array( 'encode' => false, 'encode_urls' => false, 'profile_only' => true ), 'xing' => array( 'encode' => false, 'encode_urls' => false, 'profile_only' => true ), 'youtube' => array( 'encode' => false, 'encode_urls' => false, 'profile_only' => true ) ); $this->args = apply_filters( 'avia_social_share_link_arguments', array_merge( $default_arguments, $args ) ); $this->options = ( empty( $options ) ) ? avia_get_option() : $options; $this->title = $title !== false ? $title : __( 'Share this entry', 'avia_framework' ); $this->links = array(); $this->html = ''; $this->counter = 0; $this->post_data = array(); $this->social_media_icons = new avia_social_media_icons(); /** * Create a valid options entry for theme icons in case a new checkbox option for an icon has been created and * options have not been saved - in this case we hide it. * Was introduced with adding yelp 4.7.2.1, can be removed in a future release. * * This allows to add icons via filter and show them */ if( ! isset( $this->options['share_yelp'] ) ) { $this->options['share_yelp'] = 'disabled'; } if( ! isset( $this->options['share_telegram'] ) ) { $this->options['share_telegram'] = 'disabled'; } $this->build_share_links(); } /** * @since 4.5.6 */ public function __destruct() { unset( $this->args ); unset( $this->options ); unset( $this->links ); unset( $this->post_data ); unset( $this->social_media_icons ); } /** * Initialize and filter the default yelp array. * If $options = false or no link provided in $options fallback to * link in theme options or yelp homepage * * @since 4.6.4 * @param array $args * @param array|false $options * @param string|false $title * @return array */ protected function default_yelp_link( $args, $options, $title ) { /** * Fallback URL used if no url specified in theme options "Social Profiles" or in custom social share button * * @since 4.7.1.1 * @param string * @return string */ $pattern = apply_filters( 'avf_default_yelp_url', 'https://www.yelp.com' ); $icons = apply_filters( 'avia_filter_social_icons', avia_get_option( 'social_icons' ) ); foreach( $icons as $icon ) { if( 'yelp' == $icon['social_icon'] ) { if( ! empty( $icon['social_icon_link'] ) ) { $pattern = esc_url( $icon['social_icon_link'] ); } break; } } if( is_array( $options ) && ( 'disabled' != $options['share_yelp'] ) && ( 'disabled' != $options['yelp_link'] ) ) { $pattern = esc_url( $options['yelp_link'] ); } $default = array( 'encode' => false, 'encode_urls' => false, 'pattern' => $pattern, 'label' => __( 'Visit us on Yelp','avia_framework' ) ); /** * Filter the default yelp array * e.g. allow on blogposts is_single() to change link to post specific yelp page * * @since 4.6.4 * @param array $default * @param array $args * @param array|false $options * @param string|false $title * @return array */ $default = apply_filters( 'avf_default_yelp_link', $default, $args, $options, $title ); return $default; } /** * Initialize and filter the default Telegram array. * If $options = false or no link provided in $options fallback to * link in theme options or telegram homepage * * @since 5.1.3 * @param array $args * @param array|false $options * @param string|false $title * @return array */ protected function default_telegram_link( $args, $options, $title ) { /** * Fallback URL used if no url specified in theme options "Social Profiles" or in custom social share button * * @since 5.1.3 * @param string * @return string */ $pattern = apply_filters( 'avf_default_telegram_url', 'https://telegram.org/' ); $icons = apply_filters( 'avia_filter_social_icons', avia_get_option( 'social_icons' ) ); foreach( $icons as $icon ) { if( 'telegram' == $icon['social_icon'] ) { if( ! empty( $icon['social_icon_link'] ) ) { $pattern = esc_url( $icon['social_icon_link'] ); } break; } } if( is_array( $options ) && ( 'disabled' != $options['share_telegram'] ) && ( 'disabled' != $options['telegram_link'] ) ) { $pattern = esc_url( $options['telegram_link'] ); } $default = array( 'encode' => true, 'encode_urls' => false, 'pattern' => 'https://t.me/share/url?url=[permalink]&text=[title]' ); /** * Filter the default telegram array * e.g. allow on blogposts is_single() to change link to post specific Telegram page * * @since 5.1.3 * @param array $default * @param array $args * @param array|false $options * @param string|false $title * @return array */ $default = apply_filters( 'avf_default_telegram_link', $default, $args, $options, $title ); return $default; } /** * Filter social icons that are disabled in the backend. everything that is left will be displayed. * That way the user can hook into the 'avia_social_share_link_arguments' filter above and add new social icons * without the need to add a new backend option * * @since < 4.0 */ protected function build_share_links() { $replace = array(); $thumb = wp_get_attachment_image_src( get_post_thumbnail_id(), 'masonry' ); $replace['permalink'] = ! isset( $this->post_data['permalink'] ) ? get_permalink() : $this->post_data['permalink']; $replace['title'] = ! isset( $this->post_data['title'] ) ? get_the_title() : $this->post_data['title']; $replace['excerpt'] = ! isset( $this->post_data['excerpt'] ) ? get_the_excerpt() : $this->post_data['excerpt']; $replace['shortlink'] = ! isset( $this->post_data['shortlink'] ) ? wp_get_shortlink() : $this->post_data['shortlink']; $replace['thumbnail'] = is_array( $thumb ) && isset( $thumb[0] ) ? $thumb[0] : ''; $replace['thumbnail'] = ! isset( $this->post_data['thumbnail'] ) ? $replace['thumbnail'] : $this->post_data['thumbnail']; $replace = apply_filters( 'avia_social_share_link_replace_values', $replace ); $charset = get_bloginfo( 'charset' ); foreach( $this->args as $key => $share ) { $share_key = 'share_' . $key; $profile_key = $key . '_profile'; $this->args[ $key ]['url'] = false; $this->args[ $key ]['profile'] = false; /* * 'avia_social_share_link_arguments' filter might add share links that do not exist in "Blog Layout" section as checkbox. * Therefore we only check for unchecked if the checkbox exists. */ if( isset( $this->options[ $share_key ] ) && $this->options[ $share_key ] == 'disabled' ) { continue; } $url = isset( $share['pattern'] ) ? $share['pattern'] : ''; if( ! empty( $url ) ) { foreach( $replace as $replace_key => $replace_value ) { if( ! empty( $share['encode'] ) && $replace_key != 'shortlink' && $replace_key != 'permalink' ) { $replace_value = rawurlencode( html_entity_decode( $replace_value, ENT_QUOTES, $charset ) ); } if( ! empty( $share['encode_urls'] ) && ( $replace_key == 'shortlink' || $replace_key == 'permalink') ) { $replace_value = rawurlencode( html_entity_decode( $replace_value, ENT_QUOTES, $charset ) ); } $url = str_replace( "[{$replace_key}]", $replace_value, $url ); } $this->args[ $key ]['url'] = ! empty( $url ) ? $url : false; } // set profile link if( isset( $this->options[ $profile_key ] ) && ! empty( $this->options[ $profile_key ] ) ) { $this->args[ $key ]['profile'] = trim( $this->options[ $profile_key ] ); } else { $icon = $this->social_media_icons->get_icon( $key ); if( false !== $icon ) { $this->args[ $key ]['profile'] = $icon['social_icon_link']; } } $this->counter ++; } } /** * Builds the html, based on the available urls * * @since < 4.0 * @return string */ public function html() { global $avia_config; $this->html = ''; if( $this->counter == 0 ) { return $this->html; } $this->html .= '<div class="av-share-box">'; if( $this->title ) { $default_heading = 'h5'; $args = array( 'heading' => $default_heading, 'extra_class' => '' ); $extra_args = array( $this, 'title' ); /** * @since 4.5.7.1 * @return array */ $args = apply_filters( 'avf_customize_heading_settings', $args, __CLASS__, $extra_args ); $heading = ! empty( $args['heading'] ) ? $args['heading'] : $default_heading; $css = ! empty( $args['extra_class'] ) ? $args['extra_class'] : ''; $this->html .= "<{$heading} class='av-share-link-description av-no-toc {$css}'>"; $this->html .= apply_filters( 'avia_social_share_title', $this->title , $this->args ); $this->html .= "</{$heading}>"; } $this->html .= '<ul class="av-share-box-list noLightbox">'; $buttons = $this->sort_buttons( $this->args ); foreach( $buttons as $key => $share ) { $select_profile = false; if( isset( $this->options['btn_action'] ) && 'profile' == $this->options['btn_action'] ) { $select_profile = true; } else if( isset( $share['profile_only'] ) && true === $share['profile_only'] ) { $select_profile = true; } if( $select_profile ) { $url = isset( $share['profile'] ) ? $share['profile'] : false; } else { $url = isset( $share['url'] ) ? $share['url'] : false; } if( empty( $url ) ) { continue; } $icon = isset( $share['icon'] ) ? $share['icon'] : $key; $source = ucfirst( $key ); if( ! empty( $avia_config['font_icons'][ $key ]['display_name'] ) ) { $source = $avia_config['font_icons'][ $key ]['display_name']; } $label_key = $select_profile ? 'label_profile' : 'label'; if( isset( $share[ $label_key ] ) && ! empty( $share[ $label_key ] ) ) { $name = $share[ $label_key ]; } else if( $select_profile ) { $name = __( 'Link to','avia_framework') . ' ' . $source; } else { $name = __( 'Share on','avia_framework') . ' ' . $source; } $name = esc_attr( $name ); $blank = strpos( $share['url'], 'mailto' ) !== false ? '' : 'target="_blank"'; /** * @since 4.5.6 * @return string */ $aria_label = apply_filters( 'avf_social_share_links_aria_label_value', $name, $key, $share, $this ); if( ! empty( $aria_label ) ) { $aria_label = 'aria-label="' . esc_attr( $aria_label ) . '"'; } $this->html .= "<li class='av-share-link av-social-link-{$key}' >"; $this->html .= "<a {$blank} {$aria_label} href='" . esc_url( $url ) . "' " . av_icon_string( $icon, false ) . " title='' data-avia-related-tooltip='{$name}'>"; $this->html .= "<span class='avia_hidden_link_text'>{$name}</span>"; $this->html .= '</a>'; $this->html .= '</li>'; } $this->html .= '</ul>'; $this->html .= '</div>'; $this->html = avia_targeted_link_rel( $this->html ); return $this->html; } /** * Sort buttons using a filter * * @since 4.8.3 * @param array $buttons * @return array */ protected function sort_buttons( array $buttons ) { /** * Return an array with button keys in the desired order. These buttons are placed first, then the other follow as defined in $this->args * * @since 4.8.3 * @param array $sort_array * @param array $this->options * @param avia_social_share_links $this * @return array|false */ $sort_buttons = apply_filters( 'avf_social_share_buttons_order', [], $this->options, $this ); if( ! is_array( $sort_buttons ) || empty( $sort_buttons ) ) { return $buttons; } $new_array = []; foreach( $sort_buttons as $key ) { if( ! isset( $buttons[ $key ] ) ) { continue; } $new_array[ $key ] = $buttons[ $key ]; unset( $buttons[ $key ] ); } return array_merge( $new_array, $buttons ); } } } if( ! function_exists( 'avia_social_share_links' ) ) { /** * Wrapper function for social share links * * @param array $args * @param array|false $options * @param string|false $title * @param boolean $echo * @return string */ function avia_social_share_links( $args = array(), $options = false, $title = false, $echo = true ) { $icons = new avia_social_share_links( $args, $options, $title ); $html = $icons->html(); if( $echo ) { echo $html; } return $html; } } if( ! function_exists( 'avia_social_share_links_single_post' ) ) { /** * Wrapper function for social share links on a single post page * * @since 4.8.3 * @return string */ function avia_social_share_links_single_post( $echo = true ) { $custom_class = array(); $style = avia_get_option( 'single_post_share_buttons_style' ); $alignment = avia_get_option( 'single_post_share_buttons_alignment' ); if( '' == $style ) { $style = 'av-social-sharing-box-default'; } else if( 'minimal' == $style ) { $style = 'av-social-sharing-box-minimal'; } $custom_class[] = $style; if( ! in_array( $style, array( 'av-social-sharing-box-default', 'av-social-sharing-box-minimal', 'av-social-sharing-box-icon', 'av-social-sharing-box-icon-simple' ) ) ) { $custom_class[] = 'av-social-sharing-box-color-bg'; } if( in_array( $style, array( 'av-social-sharing-box-square', 'av-social-sharing-box-circle', 'av-social-sharing-box-icon', 'av-social-sharing-box-icon-simple' ) ) ) { $custom_class[] = 'av-social-sharing-box-same-width'; $custom_class[] = $alignment; } else { $custom_class[] = 'av-social-sharing-box-fullwidth'; } $custom_class = implode( ' ', $custom_class ); $html = "<div class='av-social-sharing-box {$custom_class}'>"; $html .= avia_social_share_links( array(), false, false, false ); $html .= '</div>'; if( $echo ) { echo $html; } return $html; } }