Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
Shutdown_Handler
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
2 / 2
7
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 __invoke
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
6
1<?php
2/* HEADER */ // phpcs:ignore
3
4/**
5 * This class handles the shutdown of the autoloader.
6 */
7class Shutdown_Handler {
8
9    /**
10     * The Plugins_Handler instance.
11     *
12     * @var Plugins_Handler
13     */
14    private $plugins_handler;
15
16    /**
17     * The plugins cached by this autoloader.
18     *
19     * @var string[]
20     */
21    private $cached_plugins;
22
23    /**
24     * Indicates whether or not this autoloader was included by another.
25     *
26     * @var bool
27     */
28    private $was_included_by_autoloader;
29
30    /**
31     * Constructor.
32     *
33     * @param Plugins_Handler $plugins_handler The Plugins_Handler instance to use.
34     * @param string[]        $cached_plugins The plugins cached by the autoloaer.
35     * @param bool            $was_included_by_autoloader Indicates whether or not the autoloader was included by another.
36     */
37    public function __construct( $plugins_handler, $cached_plugins, $was_included_by_autoloader ) {
38        $this->plugins_handler            = $plugins_handler;
39        $this->cached_plugins             = $cached_plugins;
40        $this->was_included_by_autoloader = $was_included_by_autoloader;
41    }
42
43    /**
44     * Handles the shutdown of the autoloader.
45     */
46    public function __invoke() {
47        // Don't save a broken cache if an error happens during some plugin's initialization.
48        if ( ! did_action( 'plugins_loaded' ) ) {
49            // Ensure that the cache is emptied to prevent consecutive failures if the cache is to blame.
50            if ( ! empty( $this->cached_plugins ) ) {
51                $this->plugins_handler->cache_plugins( array() );
52            }
53
54            return;
55        }
56
57        // Load the active plugins fresh since the list we pulled earlier might not contain
58        // plugins that were activated but did not reset the autoloader. This happens
59        // when a plugin is in the cache but not "active" when the autoloader loads.
60        // We also want to make sure that plugins which are deactivating are not
61        // considered "active" so that they will be removed from the cache now.
62        try {
63            $active_plugins = $this->plugins_handler->get_active_plugins( false, ! $this->was_included_by_autoloader );
64        } catch ( \Exception $ex ) {
65            // When the package is deleted before shutdown it will throw an exception.
66            // In the event this happens we should erase the cache.
67            if ( ! empty( $this->cached_plugins ) ) {
68                $this->plugins_handler->cache_plugins( array() );
69            }
70            return;
71        }
72
73        // The paths should be sorted for easy comparisons with those loaded from the cache.
74        // Note we don't need to sort the cached entries because they're already sorted.
75        sort( $active_plugins );
76
77        // We don't want to waste time saving a cache that hasn't changed.
78        if ( $this->cached_plugins === $active_plugins ) {
79            return;
80        }
81
82        $this->plugins_handler->cache_plugins( $active_plugins );
83    }
84}