Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
23.71% |
23 / 97 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
| Logs_Page | |
23.71% |
23 / 97 |
|
0.00% |
0 / 5 |
197.60 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
| add_page | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
30 | |||
| display_page | |
0.00% |
0 / 52 |
|
0.00% |
0 / 1 |
72 | |||
| enqueue_scripts | |
93.33% |
14 / 15 |
|
0.00% |
0 / 1 |
3.00 | |||
| enqueue_styles | |
90.00% |
9 / 10 |
|
0.00% |
0 / 1 |
3.01 | |||
| 1 | <?php |
| 2 | /** |
| 3 | * The UI around the logs table. |
| 4 | * |
| 5 | * E.g. /wp-admin/admin.php?page=bh-wp-logger-development-plugin-logs. |
| 6 | * |
| 7 | * TODO: Add "send to plugin developer" button. |
| 8 | * TODO: Add copy to clipboard button. |
| 9 | * |
| 10 | * @package brianhenryie/bh-wp-logger |
| 11 | */ |
| 12 | |
| 13 | namespace BrianHenryIE\WP_Logger\Admin; |
| 14 | |
| 15 | use BrianHenryIE\WP_Logger\API\BH_WP_PSR_Logger; |
| 16 | use BrianHenryIE\WP_Logger\API_Interface; |
| 17 | use BrianHenryIE\WP_Logger\Logger_Settings_Interface; |
| 18 | use Psr\Log\LoggerAwareTrait; |
| 19 | use Psr\Log\LogLevel; |
| 20 | use Psr\Log\NullLogger; |
| 21 | |
| 22 | /** |
| 23 | * Functions for registering a "hidden menu" item, to add the wp-admin page to display the logs. |
| 24 | */ |
| 25 | class Logs_Page { |
| 26 | |
| 27 | use LoggerAwareTrait; |
| 28 | |
| 29 | /** |
| 30 | * The logger settings. i.e. what is the plugin slug this logger is for? |
| 31 | * |
| 32 | * @uses \BrianHenryIE\WP_Logger\Logger_Settings_Interface::get_plugin_slug() |
| 33 | * @var Logger_Settings_Interface |
| 34 | */ |
| 35 | protected Logger_Settings_Interface $settings; |
| 36 | |
| 37 | /** |
| 38 | * Used to get the list of log files. |
| 39 | * Needed to instantiate the table. |
| 40 | * |
| 41 | * @var API_Interface |
| 42 | */ |
| 43 | protected API_Interface $api; |
| 44 | |
| 45 | /** |
| 46 | * Logs_Page constructor. |
| 47 | * |
| 48 | * @param API_Interface $api The main functions of the logger. |
| 49 | * @param Logger_Settings_Interface $settings The configuration used to set up the logger. |
| 50 | * @param ?BH_WP_PSR_Logger $logger The logger itself, for logging. |
| 51 | */ |
| 52 | public function __construct( API_Interface $api, Logger_Settings_Interface $settings, ?BH_WP_PSR_Logger $logger = null ) { |
| 53 | |
| 54 | $this->setLogger( $logger ?? new NullLogger() ); |
| 55 | $this->settings = $settings; |
| 56 | $this->api = $api; |
| 57 | } |
| 58 | |
| 59 | /** |
| 60 | * Add a WordPress admin UI page, but without any menu linking to it. |
| 61 | * |
| 62 | * @hooked admin_menu |
| 63 | * |
| 64 | * @see wp-admin/menu.php |
| 65 | */ |
| 66 | public function add_page(): void { |
| 67 | |
| 68 | $logs_slug = "{$this->settings->get_plugin_slug()}-logs"; |
| 69 | $menu_title = 'Logs'; |
| 70 | |
| 71 | $parent_slug = ''; |
| 72 | |
| 73 | global $menu; |
| 74 | foreach ( $menu as $menu_item ) { |
| 75 | if ( stristr( $menu_item[0], 'logs' ) || stristr( $menu_item[2], 'logs' ) || stristr( $menu_item[3], 'logs' ) ) { |
| 76 | $parent_slug = $menu_item[2]; |
| 77 | $menu_title = $this->settings->get_plugin_name(); |
| 78 | break; |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | add_submenu_page( |
| 83 | $parent_slug, |
| 84 | __( 'Logs', 'bh-wp-logger' ), |
| 85 | $menu_title, |
| 86 | 'manage_options', |
| 87 | $logs_slug, |
| 88 | array( $this, 'display_page' ) |
| 89 | ); |
| 90 | } |
| 91 | |
| 92 | /** |
| 93 | * Display the page. |
| 94 | * Record the last visited time. |
| 95 | * |
| 96 | * Registered above. |
| 97 | * |
| 98 | * @see add_page() |
| 99 | */ |
| 100 | public function display_page(): void { |
| 101 | |
| 102 | echo '<div class="wrap">'; |
| 103 | |
| 104 | echo '<h1>'; |
| 105 | echo esc_html( $this->settings->get_plugin_name() ); |
| 106 | echo '</h1>'; |
| 107 | |
| 108 | $log_files = $this->api->get_log_files(); |
| 109 | |
| 110 | if ( empty( $log_files ) ) { |
| 111 | // This will occur e.g. immediately after deleting all logs. |
| 112 | echo '<p>No logs to display.</p>'; |
| 113 | echo '</div>'; |
| 114 | return; |
| 115 | } |
| 116 | |
| 117 | $logs_table = new Logs_List_Table( $this->api, $this->settings, $this->logger ); |
| 118 | |
| 119 | // Set date here? |
| 120 | |
| 121 | // Show a list of date to switch between dates. |
| 122 | echo '<label for="log_date">Log date:</label>'; |
| 123 | echo '<select name="log_date" id="log_date">'; |
| 124 | |
| 125 | // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 126 | $chosen_date = isset( $_GET['log_date'] ) ? sanitize_key( $_GET['log_date'] ) : array_key_last( $log_files ); |
| 127 | |
| 128 | // Maybe should use set file? |
| 129 | $logs_table->set_date( $chosen_date ); |
| 130 | |
| 131 | // TODO: Allow filtering here to add external log files, e.g. from Authorize.net SDK. |
| 132 | foreach ( $log_files as $date => $path ) { |
| 133 | $date_formatted = $date; |
| 134 | echo '<option value="' . esc_attr( $date ) . '"'; |
| 135 | if ( $date === $chosen_date ) { |
| 136 | echo ' selected'; |
| 137 | } |
| 138 | echo '>' . esc_html( $date_formatted ) . '</option>'; |
| 139 | } |
| 140 | echo '</select>'; |
| 141 | |
| 142 | echo '<button name="deleteButton" id="deleteButton" data-date="' . esc_attr( $chosen_date ) . '" class="button logs-page button-primary">Delete ' . esc_html( $chosen_date ) . ' logs</button>'; |
| 143 | echo '<button name="deleteAllButton" id="deleteAllButton" class="button logs-page button-secondary">Delete all logs</button>'; |
| 144 | |
| 145 | wp_nonce_field( 'bh-wp-logger-delete', 'delete_logs_wpnonce' ); |
| 146 | |
| 147 | echo '<p>Current log level: <b>' . esc_html( ucfirst( $this->settings->get_log_level() ) ) . '</b></p>'; |
| 148 | |
| 149 | // If this is in the logger's private-uploads directory, then it already should be accessible, but if it's in the wc-logs folder, it will not be. |
| 150 | $download_url = wp_nonce_url( admin_url( 'admin.php?page=' . $this->settings->get_plugin_slug() . '&date=' . $date . '&download-log=true' ), 'bh-wp-logger-download' ); |
| 151 | $filepath = $log_files[ $chosen_date ]; |
| 152 | $filename = basename( $filepath ); |
| 153 | // TODO: Show file size here. Show number of entries. |
| 154 | echo '<p>Displaying log file at <a href="' . esc_url( $download_url ) . '" download="' . esc_attr( $filename ) . '"><code>' . esc_html( $filepath ) . '</code></a></p>'; |
| 155 | |
| 156 | echo '<p>Display levels: '; |
| 157 | |
| 158 | $log_level_counts = array( |
| 159 | LogLevel::ERROR => 0, |
| 160 | LogLevel::WARNING => 0, |
| 161 | LogLevel::NOTICE => 0, |
| 162 | LogLevel::INFO => 0, |
| 163 | LogLevel::DEBUG => 0, |
| 164 | ); |
| 165 | foreach ( $logs_table->get_data() as $datum ) { |
| 166 | ++$log_level_counts[ strtolower( $datum['level'] ) ]; |
| 167 | } |
| 168 | |
| 169 | $checkboxes = array(); |
| 170 | foreach ( $log_level_counts as $log_level => $log_level_count ) { |
| 171 | $disabled = 0 === $log_level_count ? 'disabled' : ''; |
| 172 | $friendly_level = ucfirst( $log_level ); |
| 173 | $log_level = esc_attr( $log_level ); |
| 174 | $log_level_count = intval( $log_level_count ); |
| 175 | $checkboxes[] = "<input {$disabled} class=\"log_level_display_checkbox\" type=\"checkbox\" id=\"log_level_display_checkbox_{$log_level}\" name=\"log_level_display_checkbox_{$log_level}\" checked> <label for=\"log_level_display_checkbox_{$log_level}\">$friendly_level ($log_level_count)</label>"; |
| 176 | } |
| 177 | |
| 178 | echo implode( ' • ', $checkboxes ); |
| 179 | |
| 180 | echo '</p>'; |
| 181 | |
| 182 | // TODO: Add an action here for other plugins to add controls. |
| 183 | |
| 184 | $logs_table->prepare_items(); |
| 185 | $logs_table->display(); |
| 186 | |
| 187 | echo '</div>'; |
| 188 | |
| 189 | $this->api->set_last_logs_view_time(); |
| 190 | } |
| 191 | |
| 192 | /** |
| 193 | * Enqueue the logs page javascript for changing date and deleting logs. |
| 194 | * Checks the plugin slug and only adds the script on the logs page for this plugin. |
| 195 | * |
| 196 | * @hooked admin_enqueue_scripts |
| 197 | */ |
| 198 | public function enqueue_scripts(): void { |
| 199 | |
| 200 | $slug = $this->settings->get_plugin_slug(); |
| 201 | $page_suffix = "_{$slug}-logs"; |
| 202 | |
| 203 | $current_page = get_current_screen(); |
| 204 | |
| 205 | /** |
| 206 | * `$current_page->id` will begin with `admin_page` or `$parent_slug` determined in `add_page()`. |
| 207 | * |
| 208 | * @see Logs_Page::add_page() |
| 209 | */ |
| 210 | if ( is_null( $current_page ) || substr( $current_page->id, -strlen( $page_suffix ) ) !== $page_suffix ) { |
| 211 | return; |
| 212 | } |
| 213 | |
| 214 | // This is the bh-wp-logger JavaScript version, not the plugin version. |
| 215 | $version = '1.1.0'; |
| 216 | |
| 217 | $js_path = realpath( __DIR__ . '/../../' ) . '/assets/bh-wp-logger-admin.js'; |
| 218 | $js_url = plugin_dir_url( $js_path ) . 'bh-wp-logger-admin.js'; |
| 219 | |
| 220 | wp_enqueue_script( 'bh-wp-logger-admin-logs-page-' . $slug, $js_url, array( 'jquery', 'renderjson', 'colresizable' ), $version, true ); |
| 221 | |
| 222 | $renderjson_js_path = realpath( __DIR__ . '/../../' ) . '/assets/vendor/renderjson/renderjson.js'; |
| 223 | $renderjson_js_url = plugin_dir_url( $renderjson_js_path ) . 'renderjson.js'; |
| 224 | |
| 225 | wp_enqueue_script( 'renderjson', $renderjson_js_url, array(), '1.4', true ); |
| 226 | |
| 227 | $colresizable_js_path = realpath( __DIR__ . '/../../' ) . '/assets/vendor/colresizable/colResizable-1.6.min.js'; |
| 228 | $colresizable_js_url = plugin_dir_url( $colresizable_js_path ) . 'colResizable-1.6.min.js'; |
| 229 | |
| 230 | wp_enqueue_script( 'colresizable', $colresizable_js_url, array( 'jquery' ), '1.6', true ); |
| 231 | } |
| 232 | |
| 233 | /** |
| 234 | * Register the stylesheets for the logs page. |
| 235 | * (colours the rows with the severity of the log message!). |
| 236 | * |
| 237 | * @hooked admin_enqueue_scripts |
| 238 | */ |
| 239 | public function enqueue_styles(): void { |
| 240 | |
| 241 | $slug = $this->settings->get_plugin_slug(); |
| 242 | $page_suffix = "_{$slug}-logs"; |
| 243 | |
| 244 | $current_page = get_current_screen(); |
| 245 | |
| 246 | /** |
| 247 | * `$current_page->id` will begin with `admin_page` or `$parent_slug` determined in `add_page()`. |
| 248 | * |
| 249 | * @see Logs_Page::add_page() |
| 250 | */ |
| 251 | if ( is_null( $current_page ) || substr( $current_page->id, -strlen( $page_suffix ) ) !== $page_suffix ) { |
| 252 | return; |
| 253 | } |
| 254 | |
| 255 | $handle = "{$this->settings->get_plugin_slug()}-logs"; |
| 256 | |
| 257 | $version = '1.0.0'; |
| 258 | |
| 259 | $css_path = realpath( __DIR__ . '/../../' ) . '/assets/bh-wp-logger.css'; |
| 260 | $css_url = plugin_dir_url( $css_path ) . 'bh-wp-logger.css'; |
| 261 | |
| 262 | wp_enqueue_style( $handle, $css_url, array(), $version, 'all' ); |
| 263 | } |
| 264 | } |