Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
67.27% covered (warning)
67.27%
37 / 55
46.15% covered (danger)
46.15%
6 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
Plugin_Logger_Actions
67.27% covered (warning)
67.27%
37 / 55
46.15% covered (danger)
46.15%
6 / 13
27.13
0.00% covered (danger)
0.00%
0 / 1
 __construct
93.75% covered (success)
93.75%
15 / 16
0.00% covered (danger)
0.00%
0 / 1
2.00
 is_wp_debug
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 add_error_handler_hooks
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 add_wordpress_error_handling_hooks
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
2.01
 add_admin_notices_hooks
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 add_admin_ui_logs_page_hooks
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 add_ajax_hooks
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 add_plugins_page_hooks
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 add_plugin_installer_page_hooks
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 add_cron_hooks
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 add_private_uploads_hooks
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 define_init_hooks
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 define_cli_hooks
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * Add the WordPress hooks and filters.
4 *
5 * @package brianhenryie/bh-wp-logger
6 */
7
8namespace BrianHenryIE\WP_Logger\WP_Includes;
9
10use BrianHenryIE\WP_Logger\Admin\Admin_Notices;
11use BrianHenryIE\WP_Logger\Admin\AJAX;
12use BrianHenryIE\WP_Logger\Admin\Logs_Page;
13use BrianHenryIE\WP_Logger\Admin\Plugin_Installer;
14use BrianHenryIE\WP_Logger\Admin\Plugins_Page;
15use BrianHenryIE\WP_Logger\API_Interface;
16use BrianHenryIE\WP_Logger\API\BH_WP_PSR_Logger;
17use BrianHenryIE\WP_Logger\Logger_Settings_Interface;
18use BrianHenryIE\WP_Logger\PHP\PHP_Error_Handler;
19use BrianHenryIE\WP_Logger\PHP\PHP_Shutdown_Handler;
20use BrianHenryIE\WP_Logger\Private_Uploads\URL_Is_Public;
21
22/**
23 * Just uses add_action and add_filter.
24 *
25 * @see WC_Logger
26 * @see https://www.php-fig.org/psr/psr-3/
27 */
28class Plugin_Logger_Actions {
29
30    /**
31     * The library object that acts as a facade to the true logger.
32     *
33     * @var BH_WP_PSR_Logger
34     */
35    protected BH_WP_PSR_Logger $wrapped_real_logger;
36
37    /**
38     * Settings object for instantiating classes.
39     *
40     * @var Logger_Settings_Interface
41     */
42    protected Logger_Settings_Interface $settings;
43
44    /**
45     * API object for instantiating classes.
46     *
47     * @var API_Interface
48     */
49    protected API_Interface $api;
50
51    /**
52     * Logger constructor.
53     *
54     * @param API_Interface             $api The main utility class.
55     * @param Logger_Settings_Interface $settings The log level etc. for this plugin.
56     * @param BH_WP_PSR_Logger          $wrapped_real_logger A facade of the real logger.
57     */
58    public function __construct( API_Interface $api, Logger_Settings_Interface $settings, BH_WP_PSR_Logger $wrapped_real_logger ) {
59        $this->wrapped_real_logger = $wrapped_real_logger;
60        $this->settings            = $settings;
61        $this->api                 = $api;
62
63        $this->add_error_handler_hooks();
64
65        $this->add_admin_ui_logs_page_hooks();
66        $this->add_admin_notices_hooks();
67        $this->add_ajax_hooks();
68        $this->add_plugins_page_hooks();
69        $this->add_plugin_installer_page_hooks();
70        $this->add_cron_hooks();
71        $this->add_private_uploads_hooks();
72        $this->define_init_hooks();
73        $this->define_cli_hooks();
74
75        if ( ! $this->is_wp_debug() ) {
76            return;
77        }
78
79        $this->add_wordpress_error_handling_hooks();
80    }
81
82    /**
83     *
84     *
85     * Defined as a protected function so it can be overridden.
86     * Caution: only consider overriding this when running on your own site. This
87     * adds significant inefficiency.
88     */
89    protected function is_wp_debug(): bool {
90        return defined( 'WP_DEBUG' ) && WP_DEBUG;
91    }
92
93    /**
94     * Add error handling for PHP errors and shutdowns.
95     */
96    protected function add_error_handler_hooks(): void {
97
98        $php_error_handler = new PHP_Error_Handler( $this->api, $this->settings, $this->wrapped_real_logger );
99        add_action( 'plugins_loaded', array( $php_error_handler, 'init' ), 2 );
100
101        $php_shutdown_handler = new PHP_Shutdown_Handler( $this->api, $this->settings, $this->wrapped_real_logger );
102        add_action( 'plugins_loaded', array( $php_shutdown_handler, 'init' ), 2 );
103    }
104
105    /**
106     * Add hooks to WordPress's handling of deprecated functions etc. in order to log it ourselves.
107     *
108     * Only runs in WP_DEBUG because this runs a backtrace on every entry to the error log, which can be significant
109     * when other plugins are not "clean".
110     */
111    protected function add_wordpress_error_handling_hooks(): void {
112
113        if ( ! $this->is_wp_debug() ) {
114            return;
115        }
116
117        $functions = new Functions( $this->api, $this->settings, $this->wrapped_real_logger );
118
119        add_action( 'deprecated_function_run', array( $functions, 'log_deprecated_functions_only_once_per_day' ), 10, 3 );
120        add_action( 'deprecated_argument_run', array( $functions, 'log_deprecated_arguments_only_once_per_day' ), 10, 3 );
121        add_action( 'doing_it_wrong_run', array( $functions, 'log_doing_it_wrong_only_once_per_day' ), 10, 3 );
122        add_action( 'deprecated_hook_run', array( $functions, 'log_deprecated_hook_only_once_per_day' ), 10, 4 );
123    }
124
125    /**
126     * Register dismissable admin notices for recorded logs.
127     */
128    protected function add_admin_notices_hooks(): void {
129
130        $admin_notices = new Admin_Notices( $this->api, $this->settings );
131        // Generate the notices from wp_options.
132        add_action( 'admin_init', array( $admin_notices, 'admin_notices' ), 9 );
133        // Add the notice.
134        add_action( 'admin_notices', array( $admin_notices, 'the_notices' ) );
135    }
136
137    /**
138     * Add an admin UI page to display the logs table.
139     * Enqueue the JavaScript for handling the buttons.
140     */
141    protected function add_admin_ui_logs_page_hooks(): void {
142
143        $logs_page = new Logs_Page( $this->api, $this->settings, $this->wrapped_real_logger );
144        add_action( 'admin_menu', array( $logs_page, 'add_page' ), 20 );
145        add_action( 'admin_enqueue_scripts', array( $logs_page, 'enqueue_scripts' ) );
146        add_action( 'admin_enqueue_scripts', array( $logs_page, 'enqueue_styles' ) );
147    }
148
149    /**
150     * Enqueue AJAX handlers for the logs page's buttons.
151     */
152    protected function add_ajax_hooks(): void {
153
154        $ajax = new AJAX( $this->api, $this->settings );
155
156        add_action( 'wp_ajax_bh_wp_logger_logs_delete', array( $ajax, 'delete' ) );
157        add_action( 'wp_ajax_bh_wp_logger_logs_delete_all', array( $ajax, 'delete_all' ) );
158    }
159
160    /**
161     * Add link on plugins.php to the logs page.
162     */
163    protected function add_plugins_page_hooks(): void {
164
165        $plugins_page = new Plugins_Page( $this->api, $this->settings );
166
167        $hook = "plugin_action_links_{$this->settings->get_plugin_basename()}";
168        add_filter( $hook, array( $plugins_page, 'add_logs_action_link' ), 99, 4 );
169    }
170
171    /**
172     * Add link to Logs on the plugin installer page (after installing a plugin via .zip file).
173     *
174     * Hooked late because the logs link should be last.
175     */
176    protected function add_plugin_installer_page_hooks(): void {
177
178        $plugin_installer = new Plugin_Installer( $this->settings );
179
180        add_filter( 'install_plugin_complete_actions', array( $plugin_installer, 'add_logs_link' ), 99, 3 );
181    }
182
183    /**
184     * Schedule a job to clean up logs.
185     */
186    protected function add_cron_hooks(): void {
187
188        $cron = new Cron( $this->api, $this->settings, $this->wrapped_real_logger );
189
190        add_action( 'init', array( $cron, 'register_delete_logs_cron_job' ) );
191        add_action( 'delete_logs_' . $this->settings->get_plugin_slug(), array( $cron, 'delete_old_logs' ) );
192    }
193
194    /**
195     * Add filter to change the admin notice when the logs directory is publicly accessible.
196     *
197     * @see \BrianHenryIE\WP_Private_Uploads\Admin\Admin_Notices::admin_notices()
198     */
199    protected function add_private_uploads_hooks(): void {
200
201        $url_is_public = new URL_Is_Public();
202
203        add_filter( "bh_wp_private_uploads_url_is_public_warning_{$this->settings->get_plugin_slug()}_logger", array( $url_is_public, 'change_warning_message' ), 10, 2 );
204    }
205
206    /**
207     * Hook in to init to download log files.
208     */
209    protected function define_init_hooks(): void {
210
211        $init = new Init( $this->api, $this->settings, $this->wrapped_real_logger );
212
213        add_action( 'init', array( $init, 'maybe_download_log' ) );
214    }
215
216    /**
217     * Add CLI commands to delete logs.
218     *
219     * Use `null` to disable CLI commands.
220     * The settings trait uses the plugin slug as the default CLI base.
221     *
222     * @see Logger_Settings_Trait::get_cli_base()
223     */
224    protected function define_cli_hooks(): void {
225
226        $cli_base = $this->settings->get_cli_base();
227
228        if ( is_null( $cli_base ) ) {
229            return;
230        }
231
232        $cli = new CLI( $this->api, $this->settings, $this->wrapped_real_logger );
233
234        add_action( 'cli_init', array( $cli, 'register_commands' ) );
235    }
236}