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