PluginProbe
WP Debugging / 2.12.6
WP Debugging v2.12.6
2.12.6 2.12.5 trunk 2.10.0 2.10.1 2.10.2 2.11.0 2.11.1 2.11.10 2.11.11 2.11.12 2.11.13 2.11.14 2.11.15 2.11.16 2.11.17 2.11.18 2.11.19 2.11.2 2.11.20 2.11.21 2.11.22 2.11.23 2.11.24 2.11.3 All 59 releases
wp-debugging / vendor / norcross / debug-quick-look / includes / formatting.php

formatting.php in WP Debugging 2.12.6, at vendor/norcross/debug-quick-look/includes/formatting.php

406 lines 10.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Our various formatting functions.
4 *
5 * @package DebugQuickLook
6 */
7
8 // Call our namepsace.
9 namespace DebugQuickLook\Formatting;
10
11 // Set our alias items.
12 use DebugQuickLook as Core;
13 use DebugQuickLook\Helpers as Helpers;
14
15 /**
16 * Format each line of our log data array.
17 *
18 * @param array $lines The log file lines.
19 *
20 * @return array
21 */
22 function format_parsed_lines( $lines ) {
23
24 // Filter the lines.
25 $lines = apply_filters( Core\HOOK_PREFIX . 'before_line_parse', $lines );
26
27 // Now return the lines.
28 return array_map( __NAMESPACE__ . '\format_single_line', $lines );
29 }
30
31 /**
32 * Format the single parsed line.
33 *
34 * @param string $single The single line.
35 *
36 * @return string The formatted line.
37 */
38 function format_single_line( $single ) {
39
40 // Set our block class before we start manupulating.
41 $div_class = set_parse_block_class( $single );
42
43 // Get our formatting args.
44 $formatting = Helpers\get_formatting_args();
45
46 // Do something if we have no formatting.
47 if ( ! $formatting ) {
48 return wrap_final_return( $single, $div_class );
49 }
50
51 // Loop our formatting functions.
52 foreach ( $formatting as $format => $source ) {
53
54 // Check which formatting callback is setup.
55 $format = 'native' !== sanitize_text_field( $source ) ? $format : __NAMESPACE__ . $format;
56
57 // Run each function individually.
58 $single = call_user_func( $format, $single );
59 }
60
61 // Now return the whole thing.
62 return wrap_final_return( $single, $div_class );
63 }
64
65 /**
66 * Create a class for log file block.
67 *
68 * @param string $single The single line from the log file.
69 *
70 * @return string $class The resulting class.
71 */
72 function set_parse_block_class( $single ) {
73
74 // Set the notice types we want.
75 $types = [
76 'notice' => 'PHP Notice:',
77 'warning' => 'PHP Warning:',
78 'fatal' => 'PHP Fatal error:',
79 'deprecated' => 'PHP Deprecated:',
80 'wordpress-db' => 'WordPress database error',
81 'stack-trace' => 'Stack trace:',
82 'wp-community' => 'WP_Community_Events',
83 ];
84
85 // Filter the available types.
86 $types = apply_filters( Core\HOOK_PREFIX . 'block_class_types', $types );
87
88 // Set our default class.
89 $data[] = 'log-entry-block';
90
91 // Now loop them and check each one.
92 foreach ( $types as $key => $text ) {
93
94 // Bail if we don't have it.
95 if ( strpos( $single, $text ) === false ) {
96 continue;
97 }
98
99 // Add the key to our class data array.
100 $data[] = 'log-entry-block-' . esc_attr( $key );
101 }
102
103 // Filter the array of classes.
104 $items = apply_filters( Core\HOOK_PREFIX . 'block_classes', $data );
105
106 // Make sure each one is sanitized.
107 $setup = array_map( 'sanitize_html_class', $items );
108
109 // Return the whole thing.
110 return implode( ' ', $setup );
111 }
112
113 /**
114 * Set up the date block.
115 *
116 * @param string $single The single line.
117 *
118 * @return string The formatted line.
119 */
120 function wrap_dateblock( $single ) {
121
122 // Set up our formatting rules.
123 $format = '~
124 \[( # open outer square brackets and capturing group
125 (?: # open subpattern for optional inner square brackets
126 [^[\]]* # non-square-bracket characters
127 \[ # open inner square bracket
128 [^[\]]* # non-square-bracket characters
129 ] # close inner square bracket
130 )* # end subpattern and repeat it 0 or more times
131 [^[\]]* # non-square-bracket characters
132 )] # end capturing group and outer square brackets
133 (?: # open subpattern for optional parentheses
134 \(( # open parentheses and capturing group
135 [a-z]+ # letters
136 )\) # close capturing group and parentheses
137 )? # end subpattern and make it optional
138 ~isx';
139
140 // Run the big match for the date bracket.
141 preg_match( $format, $single, $matches );
142
143 // If we don't have the dateblock, return what we had.
144 if ( empty( $matches[0] ) ) {
145 return $single;
146 }
147
148 // Format our date.
149 $fdate = date( 'c', strtotime( $matches[1] ) );
150
151 // Set the markup.
152 $markup = '<span class="log-entry-date"><time datetime="' . esc_attr( $fdate ) . '">' . $matches[0] . '</time></span>';
153
154 // Wrap the dateblock itself in a time.
155 $setup = str_replace( $matches[0], $markup, $single );
156
157 // Return it.
158 return apply_filters( Core\HOOK_PREFIX . 'dateblock_wrap', $setup, $single );
159 }
160
161 /**
162 * Set up the stack trace list.
163 *
164 * @param string $single The single line.
165 *
166 * @return string The formatted line.
167 */
168 function wrap_stacktrace( $single ) {
169
170 // Set up our formatting rules.
171 $format = "/Stack trace:\n((?:#\d*.+\n*)+)/m";
172
173 // Run the match check.
174 preg_match( $format, $single, $matches );
175
176 // If we don't have the list, return what we had.
177 if ( empty( $matches[1] ) ) {
178 return $single;
179 }
180
181 // Set our string to be modified.
182 $setup = $single;
183
184 // Create an array of the stack data.
185 $items = explode( PHP_EOL, $matches[1] );
186
187 // Set the empty list tagged items.
188 $ltags = '';
189
190 // Wrap each one with a list tag.
191 foreach ( $items as $line_item ) {
192 $ltags .= '<li class="log-entry-stack-trace-list-item">' . trim( $line_item ) . '</li>';
193 }
194
195 // Wrap the list with the ul tag.
196 $ulwrap = '<ul class="log-entry-stack-trace-list-wrap">' . $ltags . '</ul>';
197
198 // Now merge in the list.
199 $merged = str_replace( $matches[1], $ulwrap, $setup );
200
201 // Set my title.
202 $twrap = '<p class="log-entry-stack-trace-title">Stack trace:</p>';
203
204 // Wrap the stack trace word in a paragraph.
205 $setup = str_replace( 'Stack trace:', $twrap, $merged );
206
207 // Return it.
208 return apply_filters( Core\HOOK_PREFIX . 'stacktrace_wrap', $setup, $single );
209 }
210
211 /**
212 * Wrap any warning types with markup.
213 *
214 * @param string $single The single line from the log file.
215 *
216 * @return string $single The formatted line from the log file.
217 */
218 function wrap_warning_types( $single ) {
219
220 // Set the notice types we want.
221 $types = [
222 'notice' => 'PHP Notice: ',
223 'warning' => 'PHP Warning: ',
224 'fatal' => 'PHP Fatal error: ',
225 'deprecated' => 'PHP Deprecated: ',
226 'wordpress-db' => 'WordPress database error ',
227 'wp-community' => 'WP_Community_Events::maybe_log_events_response: ',
228 ];
229
230 // Filter the available types.
231 $types = apply_filters( Core\HOOK_PREFIX . 'warning_types', $types );
232
233 // Set our string to be modified.
234 $setup = $single;
235
236 // Now loop them and check each one.
237 foreach ( $types as $key => $text ) {
238
239 // Bail if we don't have it.
240 if ( strpos( $single, $text ) === false ) {
241 continue;
242 }
243
244 // Set the notice class.
245 $nclass = 'log-entry-error-label log-entry-error-' . esc_attr( $key ) . '-label';
246
247 // Set up the wrapped item.
248 $markup = '<span class="' . esc_attr( $nclass ) . '">' . esc_html( rtrim( $text, ': ' ) ) . '</span>' . PHP_EOL;
249
250 // Now wrap it in some markup.
251 $setup = str_replace( $text, $markup, $setup );
252 }
253
254 // Return it with our filter.
255 return apply_filters( Core\HOOK_PREFIX . 'warning_types_wrap', $setup, $single );
256 }
257
258 /**
259 * Wrap any JSON that may exist.
260 *
261 * @param string $single The single line from the log file.
262 *
263 * @return string $single The formatted line from the log file.
264 */
265 function wrap_json_bits( $single ) {
266
267 // Set my format for finding JSON.
268 $format = '/\{(?:[^{}]|(?R))*\}/x';
269
270 // Attempt the preg_match.
271 preg_match_all( $format, $single, $matches );
272
273 // Bail if we have none.
274 if ( empty( $matches[0] ) ) {
275 return $single;
276 }
277
278 // Escape any quotes in the JSON for proper display.
279 $matches[0] = preg_replace(
280 '/="([^"]*)"/',
281 '=\\"$1\\"',
282 $matches[0]
283 );
284 $single = preg_replace(
285 '/="([^"]*)"/',
286 '=\\"$1\\"',
287 $single
288 );
289
290 // Set our string to be modified.
291 $setup = $single;
292
293 // Loop each bit of JSON and attempt to format it.
294 foreach ( $matches[0] as $found_json ) {
295
296 // Now attempt to decode it.
297 $maybe_json = json_decode( $found_json, true );
298
299 // If we threw an error, return the single line.
300 if ( json_last_error() !== JSON_ERROR_NONE ) {
301 continue;
302 }
303
304 // Get my markup and wrap it in a div.
305 $markup = '<div class="log-entry-json-array-section">' . format_json_array( $maybe_json ) . '</div>';
306
307 // Now wrap it in some markup.
308 $setup = str_replace( $found_json, $markup, $setup );
309 }
310
311 // Return it with our filter.
312 return apply_filters( Core\HOOK_PREFIX . 'json_bits_wrap', $setup, $single );
313 }
314
315 /**************************************
316 Set the various callback formatting.
317 ***************************************/
318
319 /**
320 * Take the JSON array and make it fancy.
321 *
322 * @param array $maybe_json The array parsed from the JSON.
323 *
324 * @return string
325 */
326 function format_json_array( $maybe_json ) {
327
328 // Set my empty build.
329 $build = '';
330
331 // Wrap the whole thing in a list.
332 $build .= '<ul class="log-entry-json-array-wrap">';
333
334 // Loop my array and start checking.
335 foreach ( $maybe_json as $key => $value ) {
336
337 // Open it as a list.
338 $build .= '<li class="log-entry-json-array-item">';
339
340 // Set the key as our first label.
341 $build .= '<span class="log-entry-json-array-piece">' . esc_html( $key ) . '</span>';
342
343 // Add our splitter.
344 $build .= '<span class="log-entry-json-array-piece log-entry-json-array-splitter">&nbsp;&equals;&gt;&nbsp;</span>';
345
346 // If the value isn't an array, make a basic list item.
347 if ( ! is_array( $value ) ) {
348
349 // Make boolean a string for display.
350 $value = is_bool( $value ) ? var_export( $value, true ) : $value;
351
352 // Just wrap the piece as per usual.
353 $build .= '<span class="log-entry-json-array-piece">' . esc_html( $value ) . '</span>';
354
355 } else {
356
357 // Set the "array" holder text.
358 $build .= '<span class="log-entry-json-array-piece"><em>' . esc_html__( '(array)', 'debug-quick-look' ) . '</em></span>';
359
360 // And get recursive with it.
361 $build .= format_json_array( $value );
362 }
363
364 // Close the item inside.
365 $build .= '</li>';
366 }
367
368 // Close my list.
369 $build .= '</ul>';
370
371 // Return the entire thing.
372 return $build;
373 }
374
375 /**
376 * Handle the final markup adding.
377 *
378 * @param string $single The formatted line from the log file.
379 * @param string $class What class to include on the div.
380 *
381 * @return string $build The line wrapped in some divs.
382 */
383 function wrap_final_return( $single, $class = '' ) {
384
385 // Now set our display.
386 $build = '';
387
388 // Set the div wrapper.
389 $build .= '<div class="' . esc_attr( $class ) . '">';
390
391 // Add a second div wrapper to mimic the <pre> tag stuff.
392 $build .= '<div class="log-entry-block-pre-wrap">';
393
394 // Output to handle the text remaining.
395 $build .= wpautop( $single, false ); // . "\n";
396
397 // Close the div wrapper.
398 $build .= '</div>';
399
400 // Close the div wrapper.
401 $build .= '</div>';
402
403 // Now return the whole thing.
404 return $build;
405 }
406