admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('sharemypost_frontend_nonce'), ]); } static function get_networks() { $networks = [ 'twitter' => [ 'label' => __('Twitter/X', 'sharemypost'), 'url' => 'https://x.com/intent/tweet?url=%s&text=%s', 'icon' => '', ], 'pinterest' => [ 'label' => __('Pinterest', 'sharemypost'), 'url' => 'https://pinterest.com/pin/create/button/?url=%s&description=%s', 'icon' => '', ], 'reddit' => [ 'label' => __('Reddit', 'sharemypost'), 'url' => 'https://reddit.com/submit?url=%s&title=%s', 'icon' => '', ], 'mastodon' => [ 'label' => __('Mastodon', 'sharemypost'), 'url' => 'https://mastodon.social/share?text=%s', 'icon' => '', ], 'threads' => [ 'label' => __('Threads', 'sharemypost'), 'url' => 'https://www.threads.net/intent/post?text=%s', 'icon' => '', ], 'email' => [ 'label' => __('Email', 'sharemypost'), 'url' => 'mailto:?subject=%s&body=%s', 'icon' => '', ], 'print' => [ 'label' => __('Print', 'sharemypost'), 'url' => '%s', 'icon' => '', ], 'flipboard' => [ 'label' => __('Flipboard', 'sharemypost'), 'url' => 'https://share.flipboard.com/bookmarklet/popout?v=2&url=%s', 'icon' => 'Flipboard', ], 'hackernews' => [ 'label' => __('Hacker News', 'sharemypost'), 'url' => 'https://news.ycombinator.com/submitlink?u=%s&t=%s', 'icon' => '', ], 'line' => [ 'label' => __('Line', 'sharemypost'), 'url' => 'https://social-plugins.line.me/web/share?url=%s', 'icon' => '', ], 'wechat' => [ 'label' => __('WeChat', 'sharemypost'), 'url' => 'weixin://dl/moments?text=%s', 'icon' => '', ], 'snapchat' => [ 'label' => __('Snapchat', 'sharemypost'), 'url' => 'https://snapchat.com/scan?attachmentUrl=%s', 'icon' => '', ], 'mix' => [ 'label' => __('Mix', 'sharemypost'), 'url' => 'https://mix.com/save?url=%s', 'icon' => 'Mix', ], 'pocket' => [ 'label' => __('Pocket', 'sharemypost'), 'url' => 'https://getpocket.com/save?url=%s', 'icon' => '', ], 'sms' => [ 'label' => __('SMS', 'sharemypost'), 'url' => 'sms:?body=%s', 'icon' => 'Google Messages', ], 'tumblr' => [ 'label' => __('Tumblr', 'sharemypost'), 'url' => 'https://www.tumblr.com/widgets/share/tool?posttype=link&tags=blog&caption=&content=%s', 'icon' => 'Tumblr', ], 'xing' => [ 'label' => __('XING', 'sharemypost'), 'url' => 'https://www.xing.com/app/user?op=share;url=%s', 'icon' => 'Xing', ], 'vk' => [ 'label' => __('VKontakte', 'sharemypost'), 'url' => 'https://vk.com/share.php?url=%s', 'icon' => 'VK', ], 'buffer' => [ 'label' => __('Buffer', 'sharemypost'), 'url' => 'https://buffer.com/add?url=%s&text=%s', 'icon' => 'Buffer', ], 'yummly' => [ 'label' => __('Yummly', 'sharemypost'), 'url' => 'https://www.yummly.com/urb/verify-recipe?url=%s', 'icon' => '', ], 'nextdoor' => [ 'label' => __('Nextdoor', 'sharemypost'), 'url' => 'https://nextdoor.com/api/validate-share/?url=%s', 'icon' => '', ], 'gab' => [ 'label' => __('Gab', 'sharemypost'), 'url' => 'https://gab.com/compose?url=%s', 'icon' => 'Grocy', ], ]; $networks = apply_filters('sharemypost_networks', $networks); return $networks; } static function get_enabled_networks($type = 'global'){ $settings = \ShareMyPost\Util::get_settings(); $key_map = apply_filters('sharemypost_enabled_networks_key', [ 'inline' => 'inline_enabled_networks', ], $type); if(isset($key_map[$type])){ $enabled = (array) (isset($settings[$key_map[$type]]) ? $settings[$key_map[$type]] : []); }else{ $enabled = (array) (isset($settings['enabled_networks']) ? $settings['enabled_networks'] : []); } $enabled = array_map('sanitize_key', (array) $enabled); return array_intersect_key( self::get_networks(), array_flip($enabled) ); } static function normalize_network_order($order_input) { if(is_string($order_input)){ $order_input = array_map('trim', explode(',', $order_input)); } if(!is_array($order_input)){ return []; } $sanitized = array_values(array_unique(array_map('sanitize_key', $order_input))); $valid = array_keys(self::get_networks()); $order = array_values(array_intersect($sanitized, $valid)); return $order; } static function get_networks_ordered($type = 'global'){ $defaults = \ShareMyPost\Util::get_default_settings(); $settings = \ShareMyPost\Util::get_settings(); $all_networks = self::get_networks(); $order_map = apply_filters('sharemypost_network_order_key', [ 'inline' => 'inline_network_order', ], $type); if(isset($order_map[$type])){ $key = $order_map[$type]; $order = isset($settings[$key]) ? self::normalize_network_order($settings[$key]) : []; if(empty($order) && isset($defaults[$key])) { $order = $defaults[$key]; } }else{ $order = self::normalize_network_order($settings['network_order']); if(empty($order)) { $order = $defaults['network_order']; } } if($type === 'inline'){ $all_networks = apply_filters('sharemypost_inline_networks_list', $all_networks); } $ordered = []; foreach($order as $network_key){ if(isset($all_networks[$network_key])) { $ordered[$network_key] = $all_networks[$network_key]; } } foreach($all_networks as $network_key => $data){ if(!isset($ordered[$network_key])){ $ordered[$network_key] = $data; } } return $ordered; } static function sanitize_settings($input){ $defaults = \ShareMyPost\Util::get_default_settings(); $current = get_option('sharemypost_settings', []); $section = ''; if (isset($input['section'])) { $section = sanitize_key($input['section']); } $is_inline_tab = ($section !== '') ? ($section === 'inline') : isset($input['inline_position']); $checkbox_arrays = [ 'inline_post_types', 'inline_enabled_networks', ]; foreach($checkbox_arrays as $key){ $is_set_in_form = isset($input[$key]); if(!$is_set_in_form){ if($is_inline_tab && in_array($key, ['inline_post_types','inline_enabled_networks'], true)){ $input[$key] = []; }else{ $input[$key] = isset($current[$key]) ? $current[$key] : (isset($defaults[$key]) ? $defaults[$key] : []); } } } $single_checkboxes = [ 'inline_enabled', 'mobile', ]; foreach($single_checkboxes as $key){ $is_set_in_form = isset($input[$key]); if(!$is_set_in_form){ if($is_inline_tab && ($key === 'mobile' || strpos($key, 'inline_') === 0)){ $input[$key] = 0; }else{ $input[$key] = isset($current[$key]) ? $current[$key] : (isset($defaults[$key]) ? $defaults[$key] : 0); } } } $input = wp_parse_args((array)$input, wp_parse_args($current, $defaults)); $input['inline_enabled'] = !empty($input['inline_enabled']) ? 1 : 0; $input['mobile'] = !empty($input['mobile']) ? 1 : 0; $inline_position = isset($input['inline_position']) ? wp_unslash($input['inline_position']) : ''; $input['inline_position'] = in_array($inline_position, ['above', 'below', 'both'], true) ? $inline_position : $defaults['inline_position']; $raw_post_types = (array)(isset($input['inline_post_types']) ? $input['inline_post_types'] : []); $raw_post_types = wp_unslash($raw_post_types); $input['inline_post_types'] = array_values(array_filter(array_map('sanitize_key', $raw_post_types))); $inline_show_labels = isset($input['inline_show_labels']) ? wp_unslash($input['inline_show_labels']) : ''; $input['inline_show_labels'] = in_array($inline_show_labels, ['icon_only', 'label_only', 'both'], true) ? $inline_show_labels : $defaults['inline_show_labels']; $inline_button_color_type = isset($input['inline_button_color_type']) ? wp_unslash($input['inline_button_color_type']) : ''; $input['inline_button_color_type'] = in_array($inline_button_color_type, ['original', 'custom'], true) ? $inline_button_color_type : $defaults['inline_button_color_type']; $inline_button_color = isset($input['inline_button_color']) ? wp_unslash($input['inline_button_color']) : ''; $input['inline_button_color'] = sanitize_hex_color($inline_button_color); if(empty($input['inline_button_color'])){ $input['inline_button_color'] = $defaults['inline_button_color']; } $networks = array_keys(\ShareMyPost\Helpers::get_networks()); $inline_enabled_networks = (array)(isset($input['inline_enabled_networks']) ? $input['inline_enabled_networks'] : []); $inline_enabled_networks = wp_unslash($inline_enabled_networks); $input['inline_enabled_networks'] = array_values(array_intersect($networks, $inline_enabled_networks)); if(isset($input['inline_network_order'])){ $order = self::normalize_network_order(wp_unslash($input['inline_network_order'])); $input['inline_network_order'] = !empty($order) ? $order : $defaults['inline_network_order']; }else{ $input['inline_network_order'] = $defaults['inline_network_order']; } $container_width = isset($input['container_width']) ? wp_unslash($input['container_width']) : ''; $input['container_width'] = in_array($container_width, ['auto', 'full'], true) ? $container_width : $defaults['container_width']; return apply_filters('sharemypost_sanitize_settings', $input, $defaults, $current); } static function build_share_url($network, $post_id, $type = 'global') { $networks = self::get_networks(); if(!isset($networks[$network])){ return ''; } $url_template = $networks[$network]['url']; $post = get_post($post_id); $permalink = get_permalink($post_id); $settings = \ShareMyPost\Util::get_settings(); $permalink = apply_filters('sharemypost_share_url_permalink', $permalink, $post, $network, $settings); switch($network){ case 'buffer': case 'twitter': case 'pinterest': case 'reddit': case 'telegram': case 'hackernews': case 'email': return sprintf($url_template, rawurlencode($permalink), rawurlencode($post->post_title)); case 'whatsapp': case 'sms': return sprintf($url_template, rawurlencode($post->post_title . ' ' . $permalink)); case 'facebook': case 'linkedin': case 'mastodon': case 'bluesky': case 'yummly': case 'nextdoor': case 'line': case 'pocket': case 'tumblr': case 'vk': case 'xing': case 'mix': case 'flipboard': case 'messenger': case 'print': return sprintf($url_template, rawurlencode($permalink)); default: return sprintf($url_template, rawurlencode($permalink)); } } static function build_share_buttons($post_id, $type = 'global') { $enabled = array_keys(self::get_enabled_networks($type)); $ordered_networks = self::get_networks_ordered($type); $buttons = []; foreach ($ordered_networks as $network => $data) { if(!in_array($network, $enabled, true)){ continue; } $buttons[] = [ 'network' => $network, 'icon' => self::get_network_icon($network), 'label' => $data['label'], 'share_url' => self::build_share_url($network, $post_id, $type), ]; } return $buttons; } static function get_network_icon($network) { $networks = self::get_networks(); if(isset($networks[$network]) && isset($networks[$network]['icon'])){ $icon = $networks[$network]['icon']; $icon = preg_replace('/\s(width|height)=["\']?\d*["\']?\s*/i', ' ', $icon); $icon = preg_replace('/\s+style="width:\s*\d+px;\s*height:\s*\d+px;\s*"/i', ' ', $icon); if (strpos($icon, 'fill="') === false && strpos($icon, 'stroke="') === false) { $icon = str_replace(''; } static function append_sharebar($content) { if (get_the_ID() !== get_queried_object_id()) { return $content; } if (is_front_page() && !apply_filters('sharemypost_show_on_front_page', false)) { return $content; } $settings = \ShareMyPost\Util::get_settings(); if(empty($settings['inline_enabled'])){ return $content; } if(empty($settings['mobile']) && wp_is_mobile()){ return $content; } $post_type = get_post_type(); $allowed_types = (array) $settings['inline_post_types']; if(!in_array($post_type, $allowed_types, true)){ return $content; } $html = self::get_share_bar_html(get_the_ID()); if(empty($html)){ return $content; } $html = wp_kses($html, self::get_allowed_html_tags()); // Mark as run right before modifying the content so the next call is blocked $has_run = true; switch ($settings['inline_position']) { case 'above': return $html . $content; case 'below': return $content . $html; case 'both': return $html . $content . $html; default: return $content; } } static function resolve_bar_setting($settings, $primary_key, $fallback_key = null) { $defaults = \ShareMyPost\Util::get_default_settings(); $default_value = array_key_exists($primary_key, $defaults) ? $defaults[$primary_key] : null; if(array_key_exists($primary_key, $settings) && $settings[$primary_key] !== $default_value){ return $settings[$primary_key]; } if($fallback_key !== null && array_key_exists($fallback_key, $settings)){ return $settings[$fallback_key]; } if($fallback_key !== null && array_key_exists($fallback_key, $defaults)){ return $defaults[$fallback_key]; } return $default_value; } static function get_share_bar_html($post_id, $is_floating = false) { $settings = \ShareMyPost\Util::get_settings(); $type = 'inline'; $buttons = self::build_share_buttons($post_id, $type); $buttons = apply_filters('sharemypost_share_bar_buttons', $buttons, $post_id, $is_floating, $settings); $color_type = $settings['inline_button_color_type']; $button_color = $settings['inline_button_color']; $show_labels_setting = $settings['inline_show_labels']; if(empty($buttons)){ return ''; } $wrapper_classes = [ 'sharemypost-share-bar', 'sharemypost-inline-bar', 'sharemypost-color-type-' . esc_attr($color_type), 'sharemypost-shape-rounded', 'sharemypost-style-filled', 'sharemypost-size-normal', ]; $show_icon = in_array($show_labels_setting, ['icon_only', 'both'], true); $show_label = in_array($show_labels_setting, ['label_only', 'both'], true); $wrapper_classes[] = 'sharemypost-labels-' . esc_attr($show_labels_setting); $wrapper_classes = apply_filters('sharemypost_share_bar_wrapper_classes', $wrapper_classes, $post_id, $is_floating, $settings); $style_vars = [ '--sharemypost-button-color:' . esc_attr($button_color), '--sharemypost-button-gap:10px', '--sharemypost-button-size:20px', '--sharemypost-button-font-size:' . max(10, round(20 * 0.33)) . 'px', '--sharemypost-button-padding:' . max(6, round(20 * 0.22)) . 'px ' . max(10, round(20 * 0.35)) . 'px', '--sharemypost-button-icon-size:' . max(20, round(20 * 0.70)) . 'px', ]; $style_vars = apply_filters('sharemypost_share_bar_style_vars', $style_vars, $post_id, $is_floating, $settings); $html = '
'; $html .= apply_filters('sharemypost_share_bar_before_buttons', '', $post_id, $is_floating, $settings, $type); $html .= '
'; // Share Buttons foreach($buttons as $btn){ $btn_classes = ['sharemypost-share-button', 'sharemypost-network-' . esc_attr($btn['network'])]; $btn_classes = apply_filters('sharemypost_share_bar_button_classes', $btn_classes, $btn, $post_id, $is_floating, $settings); $html .= ''; if(!empty($show_icon)){ static $allowed_svg = null; if(null === $allowed_svg){ $allowed_svg = [ 'svg' => [ 'viewbox' => true, 'viewBox' => true, 'xmlns' => true, 'fill' => true, 'stroke' => true, 'stroke-width' => true, 'stroke-linecap' => true, 'stroke-linejoin' => true, 'style' => true, 'class' => true, 'role' => true, ], 'path' => [ 'd' => true, 'fill' => true, 'stroke' => true, 'stroke-width' => true, 'stroke-linecap' => true, 'stroke-linejoin' => true, 'style' => true, ], 'circle' => [ 'cx' => true, 'cy' => true, 'r' => true, 'fill' => true, 'stroke' => true, ], 'rect' => [ 'x' => true, 'y' => true, 'width' => true, 'height' => true, 'rx' => true, 'ry' => true, 'fill' => true, ], 'g' => ['fill' => true, 'stroke' => true], 'polygon' => ['points' => true, 'fill' => true], 'line' => ['x1' => true, 'y1' => true, 'x2' => true, 'y2' => true, 'stroke' => true], 'polyline' => ['points' => true, 'fill' => true, 'stroke' => true], 'ellipse' => ['cx' => true, 'cy' => true, 'rx' => true, 'ry' => true, 'fill' => true, 'stroke' => true], 'title' => [], ]; } $html .= '' . wp_kses($btn['icon'], $allowed_svg) . ''; } if(!empty($show_label)){ $html .= '' . esc_html($btn['label']) . ''; } $html = apply_filters('sharemypost_share_bar_button_inner', $html, $btn, $post_id, $is_floating, $settings); $html .= ''; } $html .= apply_filters('sharemypost_share_bar_extra_buttons', '', $post_id, $is_floating, $settings, $show_icon, $show_label); $html .= '
'; $html .= apply_filters('sharemypost_share_bar_after_buttons', '', $post_id, $is_floating, $settings, $type); $html .= '
'; return wp_kses(apply_filters('sharemypost_share_bar_html', $html, $post_id, $is_floating, $settings), self::get_allowed_html_tags()); } static function get_allowed_html_tags() { return [ 'div' => [ 'class' => true, 'style' => true, 'id' => true, ], 'p' => [ 'class' => true, ], 'span' => [ 'class' => true, 'style' => true, ], 'a' => [ 'href' => true, 'class' => true, 'target' => true, 'rel' => true, 'data-post-id' => true, 'data-network' => true, 'data-click-id' => true, 'style' => true, ], 'svg' => [ 'viewbox' => true, 'viewBox' => true, 'xmlns' => true, 'fill' => true, 'stroke' => true, 'stroke-width' => true, 'stroke-linecap' => true, 'stroke-linejoin' => true, 'style' => true, 'class' => true, 'role' => true, 'width' => true, 'height' => true, ], 'path' => [ 'd' => true, 'fill' => true, 'stroke' => true, 'stroke-width' => true, 'stroke-linecap' => true, 'stroke-linejoin' => true, 'style' => true, ], 'circle' => [ 'cx' => true, 'cy' => true, 'r' => true, 'fill' => true, 'stroke' => true, ], 'rect' => [ 'x' => true, 'y' => true, 'width' => true, 'height' => true, 'rx' => true, 'ry' => true, 'fill' => true, ], 'g' => [ 'fill' => true, 'stroke' => true, ], 'polygon' => [ 'points' => true, 'fill' => true, ], 'line' => [ 'x1' => true, 'y1' => true, 'x2' => true, 'y2' => true, 'stroke' => true, ], 'polyline' => [ 'points' => true, 'fill' => true, 'stroke' => true, ], 'ellipse' => [ 'cx' => true, 'cy' => true, 'rx' => true, 'ry' => true, 'fill' => true, 'stroke' => true, ], 'title' => [], ]; } }