Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 132
0.00% covered (danger)
0.00%
0 / 4
CRAP
n/a
0 / 0
jetpack_social_menu_include_svg_icons
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
30
jetpack_social_menu_get_svg
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
20
jetpack_social_menu_nav_menu_social_icons
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
72
jetpack_social_menu_social_links_icons
0.00% covered (danger)
0.00%
0 / 69
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * SVG icons related functions and filters
4 *
5 * @package automattic/jetpack-classic-theme-helper
6 */
7
8if ( ! defined( 'ABSPATH' ) ) {
9    exit( 0 );
10}
11
12if ( ! function_exists( 'jetpack_social_menu_include_svg_icons' ) ) {
13    /**
14     * Add SVG definitions to the footer.
15     */
16    function jetpack_social_menu_include_svg_icons() {
17        // Return early if Social Menu doesn't exist.
18        if ( ! has_nav_menu( 'jetpack-social-menu' ) ) {
19            return;
20        }
21        // Define SVG sprite file.
22        $svg_icons = __DIR__ . '/social-menu.svg';
23        // If it exists and we use the SVG menu type, include it.
24        if ( file_exists( $svg_icons ) && 'svg' === jetpack_social_menu_get_type() ) {
25            $svg_contents = file_get_contents( $svg_icons ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Only reading a local file.
26        }
27
28        if ( ! empty( $svg_contents ) ) {
29            $allowed_tags = array(
30                'svg'    => array(
31                    'style'       => true,
32                    'version'     => true,
33                    'xmlns'       => true,
34                    'xmlns:xlink' => true,
35                ),
36                'defs'   => array(),
37                'symbol' => array(
38                    'id'      => true,
39                    'viewbox' => true,
40                ),
41                'path'   => array(
42                    'd'     => true,
43                    'style' => true,
44                ),
45            );
46            echo wp_kses( $svg_contents, $allowed_tags );
47        }
48    }
49    add_action( 'wp_footer', 'jetpack_social_menu_include_svg_icons', 9999 );
50}
51
52if ( ! function_exists( 'jetpack_social_menu_get_svg' ) ) {
53    /**
54     * Return SVG markup.
55     *
56     * @param array $args {
57     *     Parameters needed to display an SVG.
58     *
59     *     @type string $icon  Required SVG icon filename.
60     * }
61     * @return string SVG markup.
62     */
63    function jetpack_social_menu_get_svg( $args = array() ) {
64        // Make sure $args are an array.
65        if ( empty( $args ) ) {
66            return esc_html__( 'Please define default parameters in the form of an array.', 'jetpack-classic-theme-helper' );
67        }
68
69        // Define an icon.
70        if ( ! ( array_key_exists( 'icon', $args ) ) ) {
71            return esc_html__( 'Please define an SVG icon filename.', 'jetpack-classic-theme-helper' );
72        }
73
74        // Set defaults.
75        $defaults = array(
76            'icon'     => '',
77            'fallback' => false,
78        );
79
80        // Parse args.
81        $args = wp_parse_args( $args, $defaults );
82
83        // Set aria hidden.
84        $aria_hidden = ' aria-hidden="true"';
85
86        // Begin SVG markup.
87        $svg = '<svg class="icon icon-' . esc_attr( $args['icon'] ) . '"' . $aria_hidden . ' role="img">';
88
89        /*
90         * Display the icon.
91         *
92         * The whitespace around `<use>` is intentional - it is a work around to a keyboard navigation bug in Safari 10.
93         *
94         * See https://core.trac.wordpress.org/ticket/38387.
95         */
96        $svg .= ' <use href="#icon-' . esc_html( $args['icon'] ) . '" xlink:href="#icon-' . esc_html( $args['icon'] ) . '"></use> ';
97
98        // Add some markup to use as a fallback for browsers that do not support SVGs.
99        if ( $args['fallback'] ) {
100            $svg .= '<span class="svg-fallback icon-' . esc_attr( $args['icon'] ) . '"></span>';
101        }
102
103        $svg .= '</svg>';
104
105        return $svg;
106    }
107}
108
109if ( ! function_exists( 'jetpack_social_menu_nav_menu_social_icons' ) ) {
110    /**
111     * Display SVG icons in social links menu.
112     *
113     * @param  string  $item_output The menu item output.
114     * @param  WP_Post $item        Menu item object.
115     * @param  int     $depth       Depth of the menu.
116     * @param  object  $args        wp_nav_menu() arguments.
117     * @return string  $item_output The menu item output with social icon.
118     */
119    function jetpack_social_menu_nav_menu_social_icons( $item_output, $item, $depth, $args ) {
120        if ( ! is_object( $args ) ) {
121            return $item_output;
122        }
123
124        // Get supported social icons.
125        $social_icons = jetpack_social_menu_social_links_icons();
126
127        // Change SVG icon inside social links menu if there is supported URL.
128        if ( 'jetpack-social-menu' === $args->theme_location ) {
129            foreach ( $social_icons as $attr => $value ) {
130                /*
131                 * attr can be a URL host, or a regex, starting with #.
132                 * Let's check for both scenarios.
133                 */
134                if (
135                    // First Regex.
136                    (
137                        str_starts_with( $attr, '#' ) && str_ends_with( $attr, '#' )
138                        && preg_match( $attr, $item_output )
139                    )
140                    // Then, regular host name.
141                    || str_contains( $item_output, $attr )
142                ) {
143                    $item_output = str_replace(
144                        $args->link_after,
145                        '</span>' . jetpack_social_menu_get_svg( array( 'icon' => esc_attr( $value ) ) ),
146                        $item_output
147                    );
148                }
149            }
150        }
151
152        return $item_output;
153    }
154    add_filter( 'walker_nav_menu_start_el', 'jetpack_social_menu_nav_menu_social_icons', 10, 4 );
155}
156
157if ( ! function_exists( 'jetpack_social_menu_social_links_icons' ) ) {
158    /**
159     * Returns an array of supported social links (URL / regex and icon name).
160     * For regex, use the # delimiter.
161     *
162     * @return array $social_links_icons
163     */
164    function jetpack_social_menu_social_links_icons() {
165        // Supported social links icons.
166        $social_links_icons = array(
167            '#https?:\/\/(www\.)?amazon\.(com|cn|in|fr|de|it|nl|es|co|ca)\/#' => 'amazon',
168            '500px.com'                         => '500px',
169            '#https?:\/\/(www\.)?apple\.com\/#' => 'apple',
170            'itunes.com'                        => 'apple',
171            'bandcamp.com'                      => 'bandcamp',
172            'behance.net'                       => 'behance',
173            'blogger.com'                       => 'blogger',
174            'blogspot.com'                      => 'blogger',
175            'bsky.app'                          => 'bluesky',
176            'codepen.io'                        => 'codepen',
177            'deviantart.com'                    => 'deviantart',
178            'discord.gg'                        => 'discord',
179            'discordapp.com'                    => 'discord',
180            'digg.com'                          => 'digg',
181            'dribbble.com'                      => 'dribbble',
182            'dropbox.com'                       => 'dropbox',
183            'etsy.com'                          => 'etsy',
184            'eventbrite.com'                    => 'eventbrite',
185            'facebook.com'                      => 'facebook',
186            '/feed/'                            => 'feed',
187            'flickr.com'                        => 'flickr',
188            'foursquare.com'                    => 'foursquare',
189            'ghost.org'                         => 'ghost',
190            'goodreads.com'                     => 'goodreads',
191            'google.com'                        => 'google',
192            'github.com'                        => 'github',
193            'instagram.com'                     => 'instagram',
194            'linkedin.com'                      => 'linkedin',
195            'mailto:'                           => 'mail',
196            'meetup.com'                        => 'meetup',
197            'medium.com'                        => 'medium',
198            'nextdoor.com'                      => 'nextdoor',
199            'patreon.com'                       => 'patreon',
200            'pinterest.'                        => 'pinterest',
201            'pocketcasts.com'                   => 'pocket-casts',
202            'podcasts.apple.com'                => 'apple-podcasts',
203            'ravelry.com'                       => 'ravelry',
204            'reddit.com'                        => 'reddit',
205            'slideshare.net'                    => 'slideshare',
206            'sms:'                              => 'sms',
207            'snapchat.com'                      => 'snapchat',
208            'soundcloud.com'                    => 'soundcloud',
209            'spotify.com'                       => 'spotify',
210            'stackoverflow.com'                 => 'stackoverflow',
211            'strava.com'                        => 'strava',
212            'stumbleupon.com'                   => 'stumbleupon',
213            'telegram.me'                       => 'telegram',
214            'threads.net'                       => 'threads',
215            'tiktok.com'                        => 'tiktok',
216            'tumblr.com'                        => 'tumblr',
217            'twitch.tv'                         => 'twitch',
218            'twitter.com'                       => 'x',
219            'vimeo.com'                         => 'vimeo',
220            'vk.com'                            => 'vk',
221            'whatsapp.com'                      => 'whatsapp',
222            'woocommerce.com'                   => 'woocommerce',
223            'wordpress.org'                     => 'wordpress',
224            'wordpress.com'                     => 'wordpress',
225            'yelp.com'                          => 'yelp',
226            'x.com'                             => 'x',
227            'xanga.com'                         => 'xanga',
228            'youtube.com'                       => 'youtube',
229        );
230
231        /*
232         * Add Mastodon instances to this array.
233         */
234        require_once __DIR__ . '../../shared-functions.php';
235        $mastodon_instance_list = jetpack_mastodon_get_instance_list();
236        foreach ( $mastodon_instance_list as $instance ) {
237            $social_links_icons[ $instance ] = 'mastodon';
238        }
239
240        return $social_links_icons;
241    }
242}