Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 42
0.00% covered (danger)
0.00%
0 / 3
CRAP
n/a
0 / 0
wpcom_head_error_handler
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
wpcom_add_crossorigin_to_script_elements
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
wpcom_enqueue_error_reporting_script
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2/**
3 * Error reporting from wp-admin / Gutenberg context for Simple Sites and WoA.
4 *
5 * @package automattic/jetpack-mu-wpcom
6 */
7
8use Automattic\Jetpack\Jetpack_Mu_Wpcom;
9
10/**
11 * Inline  error handler that will capture errors before the main handler has a chance to.
12 *
13 * Errors are pushed to a global array called `_jsErr` which is then verified in the main handler.
14 *
15 * @see index.js
16 */
17function wpcom_head_error_handler() {
18    ?><script type="text/javascript">
19        window._headJsErrorHandler = function( errEvent ) {
20            window._jsErr = window._jsErr || [];
21            window._jsErr.push( errEvent );
22        }
23        window.addEventListener( 'error', window._headJsErrorHandler );
24    </script>
25    <?php
26}
27
28/**
29 * Limit the attribute to script elements that point to scripts served from s0.wp.com.
30 *
31 * We might want to add stats.wp.com and widgets.wp.com here, too. See https://wp.me/pMz3w-cCq#comment-86959.
32 * "Staticized" (aka minified or concatenaded) scripts don't go through this pipeline, so they are not processed
33 * by this filter. The attribute is added to those directly in jsconcat, see D57238-code.
34 *
35 * @param string $tag String containing the def of a script tag.
36 */
37function wpcom_add_crossorigin_to_script_elements( $tag ) {
38    $end_of_tag = strpos( $tag, '>' );
39    if ( false === $end_of_tag ) {
40        return $tag;
41    }
42
43    /*
44     * Get JUST the <script ...> tag, not anything else. $tag can include the content of the script as well.
45     * Assumes that $tag begins with <script..., which does seem to be the case in our testing.
46     */
47    $script_tag = substr( $tag, 0, $end_of_tag + 1 );
48
49    // If the src of that script tag points to an internal domain, set crossorigin=anonymous.
50    if ( preg_match( '/<script.*src=.*(s0\.wp\.com|stats\.wp\.com|widgets\.wp\.com).*>/', $script_tag ) ) { // phpcs:disable WordPress.WP.EnqueuedResources.NonEnqueuedScript
51        // Update the src of the <script...> tag.
52        $new_tag = str_replace( ' src=', " crossorigin='anonymous' src=", $script_tag );
53
54        // Then, find the original script_tag within the ENTIRE $tag, and replace it with the updated version. Now the script includes crossorigin=anonymous.
55        return str_replace( $script_tag, $new_tag, $tag );
56    }
57
58    return $tag;
59}
60
61/**
62 * Enqueue assets
63 */
64function wpcom_enqueue_error_reporting_script() {
65    // Bail if ETK has enqueued its script.
66    if ( wp_script_is( 'a8c-fse-error-reporting-script' ) ) {
67        return;
68    }
69
70    $asset_file          = include Jetpack_Mu_Wpcom::BASE_DIR . 'build/error-reporting/error-reporting.asset.php';
71    $script_dependencies = $asset_file['dependencies'] ?? array();
72    $script_version      = $asset_file['version'] ?? filemtime( Jetpack_Mu_Wpcom::BASE_DIR . 'build/error-reporting/error-reporting.js' );
73    $script_id           = 'wpcom-error-reporting-script';
74
75    wp_enqueue_script(
76        $script_id,
77        plugins_url( 'build/error-reporting/error-reporting.js', Jetpack_Mu_Wpcom::BASE_FILE ),
78        $script_dependencies,
79        $script_version,
80        true
81    );
82
83    /**
84     * Filter to enable Sentry error reporting.
85     *
86     * @param bool $enabled Whether Sentry should be activated.
87     */
88    $activate_sentry = apply_filters( 'a8c_enable_sentry_error_reporting', false );
89
90    wp_localize_script(
91        $script_id,
92        'WPcom_Error_Reporting_Config',
93        array(
94            'shouldActivateSentry' => $activate_sentry ? 'true' : 'false',
95            'releaseName'          => defined( 'WPCOM_DEPLOYED_GIT_HASH' ) ? 'WPCOM_' . WPCOM_DEPLOYED_GIT_HASH : 'WPCOM_NO_RELEASE',
96        )
97    );
98}
99
100/**
101 * Can be used to toggle the Error Reporting functionality.
102 *
103 * @param bool true if Error Reporting should be enabled, false otherwise.
104 */
105if ( apply_filters( 'a8c_enable_error_reporting', false ) ) {
106    add_action( 'admin_print_scripts', 'wpcom_head_error_handler', 0 );
107    add_filter( 'script_loader_tag', 'wpcom_add_crossorigin_to_script_elements', 99, 2 );
108
109    // We load as last as possible for performance reasons. The head handler will capture errors until the main handler is loaded.
110    add_action( 'admin_enqueue_scripts', 'wpcom_enqueue_error_reporting_script', 100 );
111}