Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 87
0.00% covered (danger)
0.00%
0 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
Social_Links
0.00% covered (danger)
0.00%
0 / 86
0.00% covered (danger)
0.00%
0 / 10
1260
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
56
 admin_setup
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
20
 check_links
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 customize_register
0.00% covered (danger)
0.00%
0 / 29
0.00% covered (danger)
0.00%
0 / 1
20
 sanitize_link
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 has_social_links
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_social_links
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_social_link_filter
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
12
 get_customize_select
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
56
 is_customize_preview
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * Theme Tools: Social Links.
4 *
5 * This feature will only be activated for themes that declare their support.
6 * This can be done by adding code similar to the following during the
7 * 'after_setup_theme' action:
8 *
9 * add_theme_support( 'social-links', array(
10 *     'facebook', 'twitter', 'linkedin', 'tumblr',
11 * ) );
12 *
13 * @package automattic/jetpack-classic-theme-helper
14 */
15
16namespace Automattic\Jetpack\Classic_Theme_Helper;
17
18use Automattic\Jetpack\Publicize\Publicize;
19use Jetpack_Options;
20use WP_Customize_Manager;
21
22if ( ! class_exists( __NAMESPACE__ . '\Social_Links' ) ) {
23
24    /**
25     * Social_Links main class.
26     *
27     * @phan-constructor-used-for-side-effects
28     */
29    class Social_Links {
30
31        /**
32         * The links the user set for each service.
33         *
34         * @var array
35         */
36        private $links;
37
38        /**
39         * A Publicize object.
40         *
41         * @var Publicize
42         */
43        private $publicize;
44
45        /**
46         * An array with all services that are supported by both Publicize and the
47         * currently active theme.
48         *
49         * @var array
50         */
51        private $services = array();
52
53        /**
54         * An array of the services the theme supports
55         *
56         * @var array
57         */
58        private $theme_supported_services = array();
59
60        /**
61         * Constructor.
62         */
63        public function __construct() {
64            if ( ! ( ! wp_is_block_theme() && current_theme_supports( 'social-links' ) && function_exists( 'publicize_init' ) ) ) {
65                return;
66            }
67
68            $theme_support = get_theme_support( 'social-links' );
69
70            /*
71            An array of named arguments must be passed as the second parameter
72             * of add_theme_support().
73             */
74            if ( empty( $theme_support[0] ) ) {
75                return;
76            }
77
78            $this->theme_supported_services = $theme_support[0];
79            $this->links                    = class_exists( Jetpack_Options::class ) ? Jetpack_Options::get_option( 'social_links', array() ) : '';
80
81            $this->admin_setup();
82
83            add_filter( 'jetpack_has_social_links', array( $this, 'has_social_links' ) );
84            add_filter( 'jetpack_get_social_links', array( $this, 'get_social_links' ) );
85
86            foreach ( $theme_support[0] as $service ) {
87                add_filter( "pre_option_jetpack-$service", array( $this, 'get_social_link_filter' ) ); // - `get_option( 'jetpack-service' );`
88                add_filter( "theme_mod_jetpack-$service", array( $this, 'get_social_link_filter' ) ); // - `get_theme_mod( 'jetpack-service' );`
89            }
90        }
91
92        /**
93         * Init the admin setup.
94         */
95        public function admin_setup() {
96            if ( ! current_user_can( 'manage_options' ) ) {
97                return;
98            }
99
100            if ( ! is_admin() && ! $this->is_customize_preview() ) {
101                return;
102            }
103
104            // @phan-suppress-next-line PhanUndeclaredFunction -- See __construct() for the condition that ensures this function exists.
105            $this->publicize    = publicize_init();
106            $publicize_services = $this->publicize->get_services( 'connected' );
107            $this->services     = array_intersect( array_keys( $publicize_services ), $this->theme_supported_services );
108
109            add_action( 'publicize_connected', array( $this, 'check_links' ), 20 );
110            add_action( 'publicize_disconnected', array( $this, 'check_links' ), 20 );
111            add_action( 'customize_register', array( $this, 'customize_register' ) );
112            add_filter( 'sanitize_option_jetpack_options', array( $this, 'sanitize_link' ) );
113        }
114
115        /**
116         * Compares the currently saved links with the connected services and removes
117         * links from services that are no longer connected.
118         *
119         * @return void
120         */
121        public function check_links() {
122            $active_links = array_intersect_key( $this->links, array_flip( $this->services ) );
123
124            if ( $active_links !== $this->links ) {
125                $this->links = $active_links;
126                if ( class_exists( Jetpack_Options::class ) ) {
127                    Jetpack_Options::update_option( 'social_links', $active_links );
128                }
129            }
130        }
131
132        /**
133         * Add social link dropdown to the Customizer.
134         *
135         * @param WP_Customize_Manager $wp_customize Theme Customizer object.
136         */
137        public function customize_register( $wp_customize ) {
138            $wp_customize->add_section(
139                'jetpack_social_links',
140                array(
141                    'title'    => esc_html__( 'Connect', 'jetpack-classic-theme-helper' ),
142                    'priority' => 35,
143                )
144            );
145
146            if ( class_exists( Publicize::class ) ) {
147                foreach ( array_keys( $this->publicize->get_services( 'all' ) ) as $service ) {
148                    $choices = $this->get_customize_select( $service );
149
150                    if ( empty( $choices ) ) {
151                        continue;
152                    }
153
154                    $wp_customize->add_setting(
155                        "jetpack_options[social_links][$service]",
156                        array(
157                            'type'    => 'option',
158                            'default' => '',
159                        )
160                    );
161
162                    $wp_customize->add_control(
163                        "jetpack-$service",
164                        array(
165                            'label'    => $this->publicize->get_service_label( $service ),
166                            'section'  => 'jetpack_social_links',
167                            'settings' => "jetpack_options[social_links][$service]",
168                            'type'     => 'select',
169                            'choices'  => $choices,
170                        )
171                    );
172                }
173            }
174        }
175
176        /**
177         * Sanitizes social links.
178         *
179         * @param array $option The incoming values to be sanitized.
180         * @return array
181         */
182        public function sanitize_link( $option ) {
183            foreach ( $this->services as $service ) {
184                if ( ! empty( $option['social_links'][ $service ] ) ) {
185                    $option['social_links'][ $service ] = esc_url_raw( $option['social_links'][ $service ] );
186                } else {
187                    unset( $option['social_links'][ $service ] );
188                }
189            }
190
191            return $option;
192        }
193
194        /**
195         * Returns whether there are any social links set.
196         *
197         * @return bool
198         */
199        public function has_social_links() {
200            return ! empty( $this->links );
201        }
202
203        /**
204         * Return available social links.
205         *
206         * @return array
207         */
208        public function get_social_links() {
209            return $this->links;
210        }
211
212        /**
213         * Short-circuits get_option and get_theme_mod calls.
214         *
215         * @param string $link The incoming value to be replaced.
216         * @return string $link The social link that we've got.
217         */
218        public function get_social_link_filter( $link ) {
219            if ( preg_match( '/_jetpack-(.+)$/i', current_filter(), $matches ) && ! empty( $this->links[ $matches[1] ] ) ) {
220                return $this->links[ $matches[1] ];
221            }
222
223            return $link;
224        }
225
226        /**
227         * Puts together an array of choices for a specific service.
228         *
229         * @param string $service The social service.
230         * @return array An associative array with profile links and display names.
231         */
232        private function get_customize_select( $service ) {
233            $choices = array(
234                '' => __( '&mdash; Select &mdash;', 'jetpack-classic-theme-helper' ),
235            );
236
237            if ( isset( $this->links[ $service ] ) ) {
238                $choices[ $this->links[ $service ] ] = $this->links[ $service ];
239            }
240
241            if ( class_exists( Publicize::class ) ) {
242                $connected_services = $this->publicize->get_services( 'connected' );
243                if ( isset( $connected_services[ $service ] ) ) {
244                    foreach ( $connected_services[ $service ] as $c ) {
245                        $profile_link = $this->publicize->get_profile_link( $service, $c );
246
247                        if ( false === $profile_link ) {
248                            continue;
249                        }
250
251                        $choices[ $profile_link ] = $this->publicize->get_display_name( $service, $c );
252                    }
253                }
254            }
255
256            if ( 1 === count( $choices ) ) {
257                return array();
258            }
259
260            return $choices;
261        }
262
263        /**
264         * Back-compat function for versions prior to 4.0.
265         */
266        private function is_customize_preview() {
267            global $wp_customize;
268            return is_a( $wp_customize, 'WP_Customize_Manager' ) && $wp_customize->is_preview();
269        }
270    }
271
272} // - end if ( ! class_exists( 'Social_Links' )