Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 61
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
WordAds
0.00% covered (danger)
0.00%
0 / 57
0.00% covered (danger)
0.00%
0 / 6
756
0.00% covered (danger)
0.00%
0 / 1
 is_wpcom
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 is_jetpack_module_active
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 is_available
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 register
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
20
 set_availability
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 gutenblock_render
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 1
306
1<?php //phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2/**
3 * Ads Block.
4 *
5 * @since 7.1.0
6 *
7 * @package automattic/jetpack
8 */
9
10namespace Automattic\Jetpack\Extensions;
11
12use Automattic\Jetpack\Blocks;
13use Automattic\Jetpack\Current_Plan as Jetpack_Plan;
14use Automattic\Jetpack\Modules;
15use Automattic\Jetpack\Status\Host;
16use Jetpack_Gutenberg;
17
18if ( ! defined( 'ABSPATH' ) ) {
19    exit( 0 );
20}
21
22/**
23 * Jetpack's Ads Block class.
24 *
25 * @since 7.1.0
26 */
27class WordAds {
28    /**
29     * Mapping array of gutenberg ad snippet with the WordAds_Smart formats.
30     *
31     * @var array
32     */
33    private static $gutenberg_ad_snippet_x_smart_format = array(
34        'gutenberg_300x250' => 'gutenberg_rectangle',
35        'gutenberg_728x90'  => 'gutenberg_leaderboard',
36        'gutenberg_320x50'  => 'gutenberg_mobile_leaderboard',
37        'gutenberg_160x600' => 'gutenberg_skyscraper',
38    );
39
40    /**
41     * Check if site is on WP.com Simple.
42     *
43     * @return bool
44     */
45    private static function is_wpcom() {
46        return ( new Host() )->is_wpcom_simple();
47    }
48
49    /**
50     * Check if the WordAds module is active.
51     *
52     * @return bool
53     */
54    private static function is_jetpack_module_active() {
55        return ( new Modules() )->is_active( 'wordads' );
56    }
57
58    /**
59     * Check if the site is approved for ads for WP.com Simple sites.
60     *
61     * @return bool
62     */
63    private static function is_available() {
64        if ( self::is_wpcom() ) {
65            return has_any_blog_stickers( array( 'wordads', 'wordads-approved', 'wordads-approved-misfits' ), get_current_blog_id() );
66        }
67
68        return Jetpack_Plan::supports( 'wordads' );
69    }
70
71    /**
72     * Register the WordAds block.
73     */
74    public static function register() {
75        /*
76        * The block is available even when the module is not active,
77        * so we can display a nudge to activate the module instead of the block.
78        * However, since non-admins cannot activate modules, we do not display the empty block for them.
79        */
80        if ( ! self::is_jetpack_module_active() && ! current_user_can( 'jetpack_activate_modules' ) ) {
81            return;
82        }
83
84        if ( ! self::is_available() ) {
85            return;
86        }
87
88        Blocks::jetpack_register_block(
89            __DIR__,
90            array(
91                'render_callback' => array( __CLASS__, 'gutenblock_render' ),
92            )
93        );
94    }
95
96    /**
97     * Set if the WordAds block is available.
98     */
99    public static function set_availability() {
100        $block_name = 'wordads';
101
102        if ( ! self::is_available() ) {
103            Jetpack_Gutenberg::set_extension_unavailable( $block_name, 'WordAds unavailable' );
104            return;
105        }
106        // Make the block available. Just in case it wasn't registered before.
107        Jetpack_Gutenberg::set_extension_available( $block_name );
108    }
109
110    /**
111     * Renders the WordAds block.
112     *
113     * @param array $attr Block attributes.
114     *
115     * @return string Block HTML.
116     */
117    public static function gutenblock_render( $attr ) {
118        global $wordads;
119
120        /** If the WordAds module is not active, don't render the block. */
121        if ( ! self::is_jetpack_module_active() ) {
122            return '';
123        }
124
125        /** This filter is already documented in modules/wordads/class-wordads.php `insert_ad()` */
126        if (
127            empty( $wordads )
128            || empty( $wordads->params )
129            || is_feed()
130            || apply_filters( 'wordads_inpost_disable', false )
131        ) {
132            return '';
133        }
134
135        if ( ! empty( $attr['hideMobile'] ) && $wordads->params->is_mobile() ) {
136            return '';
137        }
138
139        if ( ! self::is_wpcom() && $wordads->option( 'wordads_house' ) ) {
140            return $wordads->get_ad( 'inline', 'house' );
141        }
142
143        // section_id is mostly deprecated at this point, but it helps us (devs) keep track of which ads end up where
144        // 6 is to keep track of gutenblock ads.
145        $section_id = $wordads->params->blog_id . '6';
146        $align      = 'center';
147        if ( isset( $attr['align'] ) && in_array( $attr['align'], array( 'left', 'center', 'right' ), true ) ) {
148            $align = $attr['align'];
149        }
150        $align = 'align' . $align;
151
152        $ad_tag_ids = $wordads->get_ad_tags();
153        $format     = 'mrec';
154        if ( isset( $attr['format'] ) && isset( $ad_tag_ids[ $attr['format'] ] ) ) {
155            $format = $attr['format'];
156        }
157
158        $height   = $ad_tag_ids[ $format ]['height'];
159        $width    = $ad_tag_ids[ $format ]['width'];
160        $location = 'gutenberg';
161        $snippet  = $wordads->get_ad_snippet( $section_id, $height, $width, $location, $wordads->get_solo_unit_css() );
162
163        $key          = "{$location}_{$width}x{$height}";
164        $smart_format = self::$gutenberg_ad_snippet_x_smart_format[ $key ] ?? null;
165        // phpcs:disable WordPress.Security.NonceVerification.Recommended
166        $is_watl_enabled = $smart_format && ( isset( $_GET[ $smart_format ] ) && 'true' === $_GET[ $smart_format ] );
167        $ad_div          = $wordads->get_ad_div( 'inline', $snippet, array( $align ) );
168        // Render IPW div if WATL is not enabled.
169        if ( ! $is_watl_enabled ) {
170            return $ad_div;
171        }
172
173        // Remove linebreaks and sanitize.
174        $snippet = esc_js( str_replace( array( "\n", "\t", "\r" ), '', $ad_div ) );
175
176        // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
177        $fallback_snippet = <<<HTML
178            <script>
179                var sas_fallback = sas_fallback || [];
180                sas_fallback.push(
181                    { tag: "$snippet", type: '$smart_format' }
182                );
183            </script>
184HTML;
185
186        return $fallback_snippet . $wordads->get_watl_ad_html_tag( $smart_format );
187    }
188}
189
190add_action( 'init', array( 'Automattic\\Jetpack\\Extensions\\WordAds', 'register' ) );
191add_action( 'jetpack_register_gutenberg_extensions', array( 'Automattic\\Jetpack\\Extensions\\WordAds', 'set_availability' ) );