Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
PHP_Shutdown_Handler
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
3 / 3
5
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
 init
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 handle
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2/**
3 * When PHP is shutting down, check for any errors, log if appropriate.
4 *
5 * @package brianhenryie/bh-wp-logger
6 */
7
8namespace BrianHenryIE\WP_Logger\PHP;
9
10use BrianHenryIE\WP_Logger\API_Interface;
11use BrianHenryIE\WP_Logger\Logger_Settings_Interface;
12use Psr\Log\LoggerAwareTrait;
13use Psr\Log\LoggerInterface;
14
15/**
16 * Listens for errors from register_shutdown_function and logs them to the PSR logger if they are from this plugin.
17 *
18 * @see register_shutdown_function()
19 */
20class PHP_Shutdown_Handler {
21
22    use LoggerAwareTrait;
23
24    /**
25     * Used to determine is the error related to this plugin.
26     *
27     * @var API_Interface
28     */
29    protected API_Interface $api;
30
31    /**
32     * Not used.
33     *
34     * @var Logger_Settings_Interface
35     */
36    protected Logger_Settings_Interface $settings;
37
38    /**
39     * Constructor.
40     *
41     * @param API_Interface             $api The main logger functions.
42     * @param Logger_Settings_Interface $settings The logger settings.
43     * @param LoggerInterface           $logger A PSR logger.
44     */
45    public function __construct( API_Interface $api, Logger_Settings_Interface $settings, LoggerInterface $logger ) {
46        $this->setLogger( $logger );
47        $this->settings = $settings;
48        $this->api      = $api;
49    }
50
51    /**
52     * This should maybe be run immediately rather than hooked. It _is_ hooked to enable it to be unhooked.
53     *
54     * @hooked plugins_loaded
55     */
56    public function init(): void {
57        register_shutdown_function( array( $this, 'handle' ) );
58    }
59
60    /**
61     * The handler itself. Check is the error related to this plugin, then logs an error to the PSR logger.
62     */
63    public function handle(): void {
64
65        /**
66         * The error from PHP.
67         *
68         * @var ?array{type:int, message:string, file:string, line:int} $error
69         */
70        $error = error_get_last();
71
72        if ( empty( $error ) ) {
73            return;
74        }
75
76        if ( ! $this->api->is_file_from_plugin( $error['file'] ) ) {
77            return;
78        }
79
80        // "Clears the most recent errors, making it unable to be retrieved with error_get_last().".
81        error_clear_last();
82
83        $this->logger->error( $error['message'], $error );
84    }
85}