Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
85.71% covered (warning)
85.71%
24 / 28
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
PHP_Autoloader
85.71% covered (warning)
85.71%
24 / 28
33.33% covered (danger)
33.33%
1 / 3
17.84
0.00% covered (danger)
0.00%
0 / 1
 register_autoloader
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 unregister_autoloader
92.31% covered (success)
92.31%
12 / 13
0.00% covered (danger)
0.00%
0 / 1
7.02
 load_class
75.00% covered (warning)
75.00%
9 / 12
0.00% covered (danger)
0.00%
0 / 1
10.27
1<?php
2/* HEADER */ // phpcs:ignore
3
4/**
5 * This class handles management of the actual PHP autoloader.
6 */
7class PHP_Autoloader {
8
9    /**
10     * Registers the autoloader with PHP so that it can begin autoloading classes.
11     *
12     * @param Version_Loader $version_loader The class loader to use in the autoloader.
13     */
14    public function register_autoloader( $version_loader ) {
15        // Make sure no other autoloaders are registered.
16        $this->unregister_autoloader();
17
18        // Set the global so that it can be used to load classes.
19        global $jetpack_autoloader_loader;
20        $jetpack_autoloader_loader = $version_loader;
21
22        // Ensure that the autoloader is first to avoid contention with others.
23        spl_autoload_register( array( self::class, 'load_class' ), true, true );
24    }
25
26    /**
27     * Unregisters the active autoloader so that it will no longer autoload classes.
28     */
29    public function unregister_autoloader() {
30        // Remove any v2 autoloader that we've already registered.
31        $autoload_chain = spl_autoload_functions();
32        if ( ! $autoload_chain ) {
33            return;
34        }
35        foreach ( $autoload_chain as $autoloader ) {
36            // We can identify a v2 autoloader using the namespace.
37            $namespace_check = null;
38
39            // Functions are recorded as strings.
40            if ( is_string( $autoloader ) ) {
41                $namespace_check = $autoloader;
42            } elseif ( is_array( $autoloader ) && is_string( $autoloader[0] ) ) {
43                // Static method calls have the class as the first array element.
44                $namespace_check = $autoloader[0];
45            } else {
46                // Since the autoloader has only ever been a function or a static method we don't currently need to check anything else.
47                continue;
48            }
49
50            // Check for the namespace without the generated suffix.
51            if ( 'Automattic\\Jetpack\\Autoloader\\jp' === substr( $namespace_check, 0, 32 ) ) {
52                spl_autoload_unregister( $autoloader );
53            }
54        }
55
56        // Clear the global now that the autoloader has been unregistered.
57        global $jetpack_autoloader_loader;
58        $jetpack_autoloader_loader = null;
59    }
60
61    /**
62     * Loads a class file if one could be found.
63     *
64     * Note: This function is static so that the autoloader can be easily unregistered. If
65     * it was a class method we would have to unwrap the object to check the namespace.
66     *
67     * @param string $class_name The name of the class to autoload.
68     *
69     * @return bool Indicates whether or not a class file was loaded.
70     */
71    public static function load_class( $class_name ) {
72        global $jetpack_autoloader_loader;
73        if ( ! isset( $jetpack_autoloader_loader ) ) {
74            return false;
75        }
76
77        $file = $jetpack_autoloader_loader->find_class_file( $class_name );
78        if ( ! isset( $file ) ) {
79            return false;
80        }
81
82        // A common source of strange and confusing problems is when a vendor
83        // file is autoloaded before all plugins have had a chance to register
84        // with the autoloader. Detect that, if a development constant is set.
85        if ( defined( 'JETPACK_AUTOLOAD_DEBUG_EARLY_LOADS' ) && JETPACK_AUTOLOAD_DEBUG_EARLY_LOADS &&
86            ( strpos( $file, '/vendor/' ) !== false || strpos( $file, '/jetpack_vendor/' ) !== false ) &&
87            is_callable( 'did_action' ) && ! did_action( 'plugins_loaded' )
88        ) {
89            // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_wp_debug_backtrace_summary -- This is a debug log message.
90            $msg = "Jetpack Autoloader: Autoloading `$class_name` before the plugins_loaded hook may cause strange and confusing problems. " . wp_debug_backtrace_summary( '', 1 );
91            wp_trigger_error( '', $msg );
92        }
93
94        require $file;
95        return true;
96    }
97}