Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 67
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Jetpack_Contact_Info_Block
0.00% covered (danger)
0.00%
0 / 67
0.00% covered (danger)
0.00%
0 / 6
156
0.00% covered (danger)
0.00%
0 / 1
 register_block
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
2
 render
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 render_address
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
6
 has_attributes
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
20
 render_email
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 render_phone
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * Class Jetpack_Contact_Info_Block
4 *
5 * @package automattic/jetpack
6 */
7
8use Automattic\Jetpack\Blocks;
9
10/**
11 * Helper class that lets us add schema attributes dynamically because they are not something that is store with the content.
12 * Due to the limitations of wp_kses.
13 *
14 * @since 7.1.0
15 */
16class Jetpack_Contact_Info_Block {
17
18    /**
19     * Registers the block for use in Gutenberg
20     * This is done via an action so that we can disable
21     * registration if we need to.
22     */
23    public static function register_block() {
24
25        Blocks::jetpack_register_block(
26            __DIR__,
27            array(
28                'render_callback' => __NAMESPACE__ . '\render',
29            )
30        );
31
32        Blocks::jetpack_register_block(
33            'jetpack/address',
34            array(
35                'parent'          => array( 'jetpack/contact-info' ),
36                'render_callback' => __NAMESPACE__ . '\render_adress',
37            )
38        );
39
40        Blocks::jetpack_register_block(
41            'jetpack/email',
42            array(
43                'parent'          => array( 'jetpack/contact-info' ),
44                'render_callback' => __NAMESPACE__ . '\render_email',
45            )
46        );
47
48        Blocks::jetpack_register_block(
49            'jetpack/phone',
50            array(
51                'parent'          => array( 'jetpack/contact-info' ),
52                'render_callback' => __NAMESPACE__ . '\render_phone',
53            )
54        );
55    }
56
57    /**
58     * Adds contact info schema attributes.
59     *
60     * @param array  $attr    Array containing the contact info block attributes.
61     * @param string $content String containing the contact info block content.
62     *
63     * @return string
64     */
65    public static function render( $attr, $content ) {
66        Jetpack_Gutenberg::load_assets_as_required( __DIR__ );
67        return str_replace(
68            'class="wp-block-jetpack-contact-info', // Closing " intentionally ommited to that the user can also add the className as expected.
69            'itemprop="location" itemscope itemtype="http://schema.org/Organization" class="wp-block-jetpack-contact-info',
70            $content
71        );
72    }
73
74    /**
75     * Adds address schema attributes.
76     *
77     * @param array  $attr    Array containing the address block attributes.
78     * @param string $content String containing the address block content.
79     *
80     * @return string
81     */
82    public static function render_address( $attr, $content ) {
83        // Returns empty content if the only attribute set is linkToGoogleMaps.
84        if ( ! self::has_attributes( $attr, array( 'linkToGoogleMaps', 'className' ) ) ) {
85            return '';
86        }
87        $find    = array(
88            'class="wp-block-jetpack-address"',
89            'class="jetpack-address__address',
90            // Closing " left out on purpose - there are multiple address fields and they all need to be updated with the same itemprop.
91            'class="jetpack-address__region"',
92            'class="jetpack-address__city"',
93            'class="jetpack-address__postal"',
94            'class="jetpack-address__country"',
95        );
96        $replace = array(
97            'itemprop="address" itemscope itemtype="http://schema.org/PostalAddress" class="wp-block-jetpack-address" ',
98            'itemprop="streetAddress" class="jetpack-address__address', // Closing " left out on purpose.
99            'itemprop="addressRegion" class="jetpack-address__region"',
100            'itemprop="addressLocality" class="jetpack-address__city"',
101            'itemprop="postalCode" class="jetpack-address__postal"',
102            'itemprop="addressCountry" class="jetpack-address__country"',
103        );
104
105        return str_replace( $find, $replace, $content );
106    }
107
108    /**
109     * Helper function that lets us determine if a block has any valid attributes.
110     *
111     * @param array $attr Array containing the block attributes.
112     * @param array $omit Array containing the block attributes that we ignore.
113     *
114     * @return bool
115     */
116    public static function has_attributes( $attr, $omit = array() ) {
117        foreach ( $attr as $attribute => $value ) {
118            if ( ! in_array( $attribute, $omit, true ) && ! empty( $value ) ) {
119                return true;
120            }
121        }
122
123        return false;
124    }
125
126    /**
127     * Adds email schema attributes.
128     *
129     * @param array  $attr    Array containing the email block attributes.
130     * @param string $content String containing the email block content.
131     *
132     * @return string
133     */
134    public static function render_email( $attr, $content ) {
135        $content = self::has_attributes( $attr, array( 'className' ) ) ?
136            str_replace( 'href="mailto:', 'itemprop="email" href="mailto:', $content ) :
137            '';
138        return $content;
139    }
140
141    /**
142     * Adds phone schema attributes. Also wraps the tel link in a span so that
143     * it's recognized as a telephone number in Google's Structured Data.
144     *
145     * @param array  $attr    Array containing the phone block attributes.
146     * @param string $content String containing the phone block content.
147     *
148     * @return string
149     */
150    public static function render_phone( $attr, $content ) {
151        if ( self::has_attributes( $attr, array( 'className' ) ) ) {
152            return str_replace(
153                array( '<a href="tel:', '</a>' ),
154                array( '<span itemprop="telephone"><a href="tel:', '</a></span>' ),
155                $content
156            );
157        }
158
159        return '';
160    }
161}