PluginProbe ʕ •ᴥ•ʔ
Hustle – Email Marketing, Lead Generation, Optins, Popups / 7.3.7
Hustle – Email Marketing, Lead Generation, Optins, Popups v7.3.7
7.8.13 7.8.13.1 trunk 3.0 3.1 3.1.1 3.1.2 3.1.3 3.1.4 4.3.2 4.4.4 4.4.5 4.4.5.1 4.4.5.4 4.6 4.6.1.1 4.6.1.4 4.7.0.2 4.7.0.3 4.7.0.7 4.7.0.9 4.7.1.0 4.7.1.1 4.8.0.0 5.0.0 5.0.1 5.0.1.1 5.0.1.2 5.1 5.1.1 5.1.2 5.1.3 5.1.3.1 5.1.3.2 5.1.4 5.1.5 6.0 6.0.1 6.0.2 6.0.3 6.0.4.2 6.0.5 6.0.6.1 6.0.7 6.0.8.1 6.0.9 7.0.0.1 7.0.2 7.0.3 7.0.4 7.1.0 7.1.1 7.2.0 7.2.1 7.3.0 7.3.1 7.3.3 7.3.5 7.3.6 7.3.7 7.4.0 7.4.1 7.4.11 7.4.13 7.4.13.1 7.4.2 7.4.3 7.4.4 7.4.5 7.4.5.1 7.4.5.2 7.4.6 7.4.7 7.5.0 7.6.0 7.6.1 7.6.3 7.6.4 7.6.6 7.7.0 7.7.1 7.8.0 7.8.1 7.8.10 7.8.10.1 7.8.10.2 7.8.11 7.8.12 7.8.12.1 7.8.2 7.8.3 7.8.4 7.8.5 7.8.6 7.8.7 7.8.8 7.8.9 7.8.9.1 7.8.9.2 7.8.9.3
wordpress-popup / lib / wpmu-lib / inc / class-thelib-debug.php
wordpress-popup / lib / wpmu-lib / inc Last commit date
class-thelib-array.php 5 years ago class-thelib-core.php 5 years ago class-thelib-debug.php 5 years ago class-thelib-html.php 5 years ago class-thelib-net.php 5 years ago class-thelib-session.php 5 years ago class-thelib-ui.php 5 years ago class-thelib-updates.php 5 years ago class-thelib.php 5 years ago
class-thelib-debug.php
964 lines
1 <?php
2 /**
3 * The Debug component.
4 * Access via function `lib3()->debug`.
5 *
6 * @since 1.1.4
7 */
8 class TheLib_Debug extends TheLib {
9
10 /**
11 * If set to true or false it will override the WP_DEBUG value
12 * If set to null the WP_DEBUG and WDEV_DEBUG values are used.
13 *
14 * @since 1.1.4
15 * @internal
16 * @var bool
17 */
18 protected $enabled = null;
19
20 /**
21 * If set to true each debug output will contain a stack-trace.
22 * Otherwise only the variable will be dumped.
23 *
24 * @since 1.1.4
25 * @internal
26 * @var bool
27 */
28 protected $stacktrace = true;
29
30 /**
31 * Toggles the plain-text / HTML output of the debug.
32 * All Ajax requests will ignore this flag and use plain-text format.
33 *
34 * @since 1.1.4
35 * @internal
36 * @var bool
37 */
38 protected $plain_text = false;
39
40 /**
41 * Constructor.
42 * Setup action hooks for debugger.
43 *
44 * @since 2.0.0
45 * @internal
46 */
47 public function __construct() {
48 remove_all_actions( 'wdev_debug_log' );
49 remove_all_actions( 'wdev_debug_log_trace' );
50 remove_all_actions( 'wdev_debug_dump' );
51 remove_all_actions( 'wdev_debug_trace' );
52
53 add_action(
54 'wdev_debug_log',
55 array( $this, 'log' ),
56 10, 99
57 );
58
59 add_action(
60 'wdev_debug_log_trace',
61 array( $this, 'log_trace' )
62 );
63
64 add_action(
65 'wdev_debug_dump',
66 array( $this, 'dump' ),
67 10, 99
68 );
69
70 add_action(
71 'wdev_debug_trace',
72 array( $this, 'trace' )
73 );
74 }
75
76 /**
77 * Resets all debug-output flags.
78 *
79 * @since 1.1.4
80 * @api
81 */
82 public function reset() {
83 $this->enabled = null;
84 $this->stacktrace = true;
85 }
86
87 /**
88 * Force-Enable debugging.
89 *
90 * @since 1.1.4
91 * @api
92 */
93 public function enable() {
94 $this->enabled = true;
95 }
96
97 /**
98 * Force-Disable debugging.
99 *
100 * @since 1.1.4
101 * @api
102 */
103 public function disable() {
104 $this->enabled = false;
105 }
106
107 /**
108 * Returns the debugging status. False means no debug output is made.
109 *
110 * @since 2.0.0
111 * @api
112 *
113 * @return bool
114 */
115 public function is_enabled() {
116 $enabled = $this->enabled;
117 $is_ajax = false;
118 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { $is_ajax = true; }
119 if ( defined( 'DOING_CRON' ) && DOING_CRON ) { $is_ajax = true; }
120
121 if ( null === $enabled ) {
122 if ( $is_ajax ) {
123 $enabled = WDEV_AJAX_DEBUG;
124 } else {
125 $enabled = WDEV_DEBUG;
126 }
127 }
128
129 return $enabled;
130 }
131
132 /**
133 * Enable stack-trace.
134 *
135 * @since 1.1.4
136 * @api
137 */
138 public function stacktrace_on() {
139 $this->stacktrace = true;
140 }
141
142 /**
143 * Disable stack-trace.
144 *
145 * @since 1.1.4
146 * @api
147 */
148 public function stacktrace_off() {
149 $this->stacktrace = false;
150 }
151
152 /**
153 * Do not format debug output.
154 *
155 * @since 1.1.4
156 * @api
157 */
158 public function format_text() {
159 $this->plain_text = true;
160 }
161
162 /**
163 * Use HTML to format debug output.
164 *
165 * @since 1.1.4
166 * @api
167 */
168 public function format_html() {
169 $this->plain_text = false;
170 }
171
172 /**
173 * Determines if the debug output should be made in plain text.
174 *
175 * @since 2.0.0
176 * @api
177 *
178 * @return bool
179 */
180 public function is_plain_text() {
181 $plain_text = $this->plain_text;
182
183 $is_ajax = false;
184 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { $is_ajax = true; }
185 if ( defined( 'DOING_CRON' ) && DOING_CRON ) { $is_ajax = true; }
186 if ( $is_ajax ) { $plain_text = true; }
187
188 return $plain_text;
189 }
190
191 /**
192 * Write debug information to error log file.
193 *
194 * @since 2.0.0
195 * @api
196 *
197 * @param mixed <dynamic> Each param will be dumped
198 */
199 public function log( $first_arg ) {
200 if ( $this->is_enabled() ) {
201 $plain_text = $this->plain_text;
202 $this->format_text();
203 $log_file = WP_CONTENT_DIR . '/lib3.log';
204 $time = date( "Y-m-d\tH:i:s\t" );
205
206 foreach ( func_get_args() as $param ) {
207 if ( is_scalar( $param ) ) {
208 $dump = $param;
209 } else {
210 $dump = var_export( $param, true );
211 }
212 error_log( $time . $dump . "\n", 3, $log_file );
213 }
214
215 $this->plain_text = $plain_text;
216 }
217 }
218
219 /**
220 * Write stacktrace information to error log file.
221 *
222 * @since 2.0.0
223 * @api
224 */
225 public function log_trace() {
226 if ( $this->is_enabled() ) {
227 $plain_text = $this->plain_text;
228 $this->format_text();
229 $log_file = WP_CONTENT_DIR . '/lib3.log';
230
231 // Display the backtrace.
232 $trace = $this->trace( false );
233 error_log( $trace, 3, $log_file );
234
235 $this->plain_text = $plain_text;
236 }
237 }
238
239 /**
240 * Adds a log-message to the HTTP response header.
241 * This is very useful to debug Ajax requests or redirects.
242 *
243 * @since 2.0.3
244 * @param string $message The debug message
245 */
246 public function header( $message ) {
247 static $Number = 0;
248 if ( ! $this->is_enabled() ) { return; }
249
250 $Number += 1;
251 if ( headers_sent() ) {
252 // HTTP Headers already sent, so add the response as HTML comment.
253 $message = str_replace( '-->', '--/>', $message );
254 printf( "<!-- Debug-Note[%s]: %s -->\n", $Number, $message );
255 } else {
256 // No output was sent yet so add the message to the HTTP headers.
257 $message = str_replace( array( "\n", "\r" ), ' ', $message );
258 header( "X-Debug-Note[$Number]: $message", false );
259 }
260 }
261
262 /**
263 * Displays a debug message at the current position on the page.
264 *
265 * @since 1.0.14
266 * @api
267 *
268 * @param mixed <dynamic> Each param will be dumped.
269 */
270 public function dump( $first_arg ) {
271 if ( ! $this->is_enabled() ) { return; }
272 $plain_text = $this->is_plain_text();
273
274 $this->add_scripts();
275
276 if ( ! $plain_text ) {
277 $block_id = 'wdev-debug-' . md5( rand() );
278 $block_label = '';
279 if ( is_scalar( $first_arg ) && ! empty( $first_arg ) ) {
280 $block_label = ': ' . (string) $first_arg;
281 }
282 ?>
283 <div class="wdev-debug">
284 <span class="wdev-debug-label" onclick="toggleBlock('<?php echo esc_attr( $block_id ); ?>')">
285 DEBUG<?php echo esc_html( $block_label ); ?>
286 </span>
287 <div class="<?php echo esc_attr( $block_id ); ?>">
288 <table cellspacing="0" cellpadding="0" width="100%" border="0" class="wdev-dump">
289 <?php
290 foreach ( func_get_args() as $param ) {
291 $this->_dump_var( $param );
292 }
293 ?>
294 </table>
295 <?php
296 } else {
297 foreach ( func_get_args() as $param ) {
298 $dump = var_export( $param, true );
299 echo "\r\n" . $dump;
300 }
301 }
302
303 // Display the backtrace.
304 if ( $this->stacktrace ) {
305 $this->trace();
306 }
307
308 if ( ! $plain_text ) {
309 echo '</div>';
310 echo '<div class="wdev-debug-clear"></div>';
311 echo '</div>';
312 }
313 }
314
315 /**
316 * Output a stack-trace.
317 *
318 * @since 2.0.0
319 * @api
320 *
321 * @param bool $output Optional. If false then the trace will be returned
322 * instead of echo'ed. Default: true (echo)
323 * @return string Returns the stack-trace contents.
324 */
325 public function trace( $output = true ) {
326 if ( ! $this->is_enabled() ) { return; }
327 $plain_text = $this->is_plain_text();
328
329 $this->add_scripts();
330 $trace_str = '';
331
332 if ( ! $plain_text ) {
333 $block_id = 'wdev-debug-' . md5( rand() );
334 $trace_str .= sprintf(
335 '<span class="wdev-trace-toggle" onclick="toggleBlock(\'%1$s-trace\')">
336 <b>Back-Trace</b>
337 </span>
338 <div class="%1$s-trace" style="display:none">
339 <table class="wdev-trace" width="100%%" cellspacing="0" cellpadding="3" border="1">
340 ',
341 esc_attr( $block_id )
342 );
343 }
344
345 $trace = debug_backtrace();
346 $trace_num = count( $trace );
347 $line = 0;
348
349 for ( $i = 0; $i < $trace_num; $i += 1 ) {
350 $item = $trace[$i];
351 $line_item = $item;
352 $j = $i;
353
354 while ( empty( $line_item['line'] ) && $j < $trace_num ) {
355 $line_item = $trace[$j];
356 $j += 1;
357 }
358
359 self::$core->array->equip( $line_item, 'file', 'line', 'class', 'type', 'function' );
360 self::$core->array->equip( $item, 'args', 'file', 'line', 'class', 'type', 'function' );
361 if ( 0 === strpos( $item['class'], 'TheLib_' ) ) { continue; }
362
363 $line += 1;
364 $args = '';
365 $arg_num = '';
366 $dummy = array();
367
368 if ( $i > 0 && is_array( $item['args'] ) && count( $item['args'] ) ) {
369 foreach ( $item['args'] as $arg ) {
370 if ( is_scalar( $arg ) ) {
371 if ( is_bool( $arg ) ) {
372 $dummy[] = ( $arg ? 'true' : 'false' );
373 } elseif ( is_string( $arg ) ) {
374 $dummy[] = '"' . $arg . '"';
375 } else {
376 $dummy[] = $arg;
377 }
378 } elseif ( is_array( $arg ) ) {
379 $dummy[] = '<i>[Array]</i>';
380 } elseif ( is_object( $arg ) ) {
381 $dummy[] = '<i>[' . get_class( $arg ) . ']</i>';
382 } elseif ( is_null( $arg ) ) {
383 $dummy[] = '<i>NULL</i>';
384 } else {
385 $dummy[] = '<i>[???]</i>';
386 }
387 }
388
389 $args = implode( '</font></span><span class="trc-param"><font>', $dummy );
390 $args = '<span class="trc-param"><font>' . $args . '</font></span>';
391 }
392
393 if ( $plain_text ) {
394 $file = $line_item['file'];
395 if ( strlen( $file ) > 80 ) {
396 $file = '...' . substr( $line_item['file'], -77 );
397 } else {
398 $file = str_pad( $file, 80, ' ', STR_PAD_RIGHT );
399 }
400
401 $trace_str .= sprintf(
402 "\r\n %s. \t %s \t by %s",
403 str_pad( $line, 2, ' ', STR_PAD_LEFT ),
404 $file . ': ' . str_pad( $line_item['line'], 5, ' ', STR_PAD_LEFT ),
405 $item['class'] . $item['type'] . $item['function'] . '(' . strip_tags( $args ) . ')'
406 );
407 } else {
408 $trace_str .= sprintf(
409 "<tr onclick='_m(this)'><td class='trc-num'>%s</td><td class='trc-loc'>%s</td><td class='trc-arg'>%s</td></tr>\r\n",
410 $line,
411 $line_item['file'] . ': ' . $line_item['line'],
412 $item['class'] . $item['type'] . $item['function'] . '(' . $args . ')'
413 );
414 }
415 }
416
417 if ( $plain_text ) {
418 $trace_str .= "\r\n-----\r\n";
419 } else {
420 $trace_str .= '</table>';
421 $trace_str .= '</div>';
422 }
423
424 if ( $output ) {
425 echo '' . $trace_str;
426 }
427
428 return $trace_str;
429 }
430
431 /**
432 * Outputs an advanced var dump.
433 *
434 * @since 1.1.0
435 * @internal
436 *
437 * @param any $input The variable/object/value to dump.
438 * @param int $default_depth Deeper items will be collapsed
439 * @param int $level Do not change this value!
440 */
441 protected function _dump_var( $data, $item_key = null, $default_depth = 3, $level = array( null ), $args = array() ) {
442 if ( ! is_string( $data ) && is_callable( $data ) ) {
443 $type = 'Callable';
444 } else {
445 $type = ucfirst( gettype( $data ) );
446 }
447
448 if ( empty( $level ) ) { $level = array( null ); }
449 $args['containers'] = self::$core->array->get( $args['containers'] );
450 $args['collapsed'] = self::$core->array->get( $args['collapsed'] );
451
452 $type_data = null;
453 $type_length = null;
454 $full_dump = false;
455
456 switch ( $type ) {
457 case 'String':
458 $type_length = strlen( $data );
459 $type_data = '"' . htmlentities( $data ) . '"';
460 break;
461
462 case 'Double':
463 case 'Float':
464 $type = 'Float';
465 $type_length = strlen( $data );
466 $type_data = htmlentities( $data );
467 break;
468
469 case 'Integer':
470 $type_length = strlen( $data );
471 $type_data = htmlentities( $data );
472 break;
473
474 case 'Boolean':
475 $type_length = strlen( $data );
476 $type_data = $data ? 'TRUE' : 'FALSE';
477 break;
478
479 case 'NULL':
480 $type_length = 0;
481 $type_data = 'NULL';
482 break;
483
484 case 'Array':
485 $type_length = count( $data );
486 break;
487
488 case 'Object':
489 $full_dump = true;
490 break;
491 }
492
493 $type_label = $type . ( $type_length !== null ? '(' . $type_length . ')' : '' );
494
495 if ( in_array( $type, array( 'Object', 'Array' ) ) ) {
496 $populated = false;
497
498 $dump_data = (array) $data;
499 ksort( $dump_data );
500
501 if ( 'Object' == $type ) {
502 $type_label .= ' [' . get_class( $data ) . ']';
503 }
504
505 $keys = array_keys( $dump_data );
506 $last_key = end( $keys );
507 reset( $dump_data );
508
509 foreach ( $dump_data as $key => $value ) {
510 if ( ! $populated ) {
511 $populated = true;
512
513 $id = substr( md5( rand() . ':' . $key . ':' . count( $level ) ), 0, 8 );
514 $args['containers'][] = $id;
515 $collapse = count( $args['containers'] ) >= $default_depth;
516 if ( $collapse ) {
517 $args['collapsed'][] = $id;
518 }
519
520 $title_args = $args;
521 $title_args['toggle'] = $id;
522
523 $this->_dump_line(
524 $item_key,
525 $type_label,
526 '',
527 $level,
528 $title_args
529 );
530 unset( $args['protected'] );
531 unset( $args['private'] );
532 }
533
534 // Tree right before the item-name
535 $new_level = $level;
536
537 if ( $last_key == $key ) {
538 $new_level[] = false;
539 $args['lastkey'] = true;
540 } else {
541 $new_level[] = true;
542 $args['lastkey'] = false;
543 }
544
545 $encode_key = json_encode( $key );
546 $matches = null;
547 if ( 1 === strpos( $encode_key, '\\u0000*\\u0000' ) ) {
548 $args['protected'] = true;
549 $key = substr( $key, 3 );
550 } elseif ( 1 === preg_match( '/\\\\u0000(\w+)\\\\u0000/i', $encode_key, $matches ) ) {
551 $args['private'] = true;
552 $key = substr( $key, 2 + strlen( $matches[1] ) );
553 }
554
555 $this->_dump_var(
556 $value,
557 $key,
558 $default_depth,
559 $new_level,
560 $args
561 );
562
563 unset( $args['protected'] );
564 unset( $args['private'] );
565 } // end of array/object loop.
566
567 if ( ! $populated ) {
568 $this->_dump_line(
569 $item_key,
570 $type_label,
571 '',
572 $level,
573 $args
574 );
575 }
576 } else {
577 $this->_dump_line(
578 $item_key,
579 $type_label,
580 $type_data,
581 $level,
582 $args
583 );
584 }
585 }
586
587 /**
588 * Outputs a single line of the dump_var output.
589 *
590 * @since 1.1.4
591 * @internal
592 */
593 protected function _dump_line( $key, $type, $value, $level, $args = array() ) {
594 $type_color = '#999';
595 $type_key = strtolower( $type );
596 if ( strlen( $type_key ) > 4 ) { $type_key = substr( $type_key, 0, 4 ); }
597
598 $custom_type_colors = array(
599 'stri' => 'green',
600 'doub' => '#0099c5',
601 'floa' => '#0099c5',
602 'inte' => 'red',
603 'bool' => '#92008d',
604 'null' => '#AAA',
605 );
606
607 if ( isset( $custom_type_colors[ $type_key ] ) ) {
608 $type_color = $custom_type_colors[ $type_key ];
609 }
610
611 $collapse = array_intersect( $args['containers'], $args['collapsed'] );
612 $args['do_collapse'] = is_array( $collapse ) && count( $collapse ) > 0;
613 if ( ! empty( $args['toggle'] ) ) {
614 $args['containers'] = array_diff( $args['containers'], array( $args['toggle'] ) );
615 $args['collapsed'] = array_diff( $args['collapsed'], array( $args['toggle'] ) );
616
617 $collapse_this = array_intersect( $args['containers'], $args['collapsed'] );
618 $args['do_collapse_next'] = $args['do_collapse'];
619 $args['do_collapse'] = is_array( $collapse_this ) && count( $collapse_this ) > 0;
620 }
621
622 $row_class = '';
623 $row_attr = '';
624 if ( ! empty( $args['containers'] ) ) {
625 $row_class = implode( ' ', $args['containers'] );
626 }
627 if ( ! empty( $args['do_collapse'] ) ) {
628 $row_attr = 'style="display:none;"';
629 }
630 echo '<tr class="' . $row_class . '"' . $row_attr . '><td>';
631
632 // Property-key, if set.
633 if ( $key === null ) {
634 // Full Tree-level.
635 echo '<span class="dev-tree">';
636 for ( $i = 0; $i < count( $level ); $i += 1 ) {
637 if ( null === $level[$i] ) { continue; }
638 if ( $level[$i] ) { echo '&nbsp;│&nbsp;'; }
639 else { echo '&nbsp;&nbsp;&nbsp;'; }
640 }
641 echo '</span>';
642 } else {
643 echo '<span class="dev-tree">';
644 // Tree-level without last level.
645 for ( $i = 0; $i < count( $level ) - 1; $i += 1 ) {
646 if ( null === $level[$i] ) { continue; }
647 if ( $level[$i] ) { echo '&nbsp;│&nbsp;'; }
648 else { echo '&nbsp;&nbsp;&nbsp;'; }
649 }
650
651 if ( empty( $args['lastkey'] ) ) {
652 echo '&nbsp;├─';
653 } else {
654 echo '&nbsp;└─';
655 }
656 echo '</span>';
657
658 $key_style = '';
659 if ( ! empty( $args['protected'] ) ) {
660 $key_style .= 'color:#900;';
661 $prefix = '';
662 } elseif ( ! empty( $args['private'] ) ) {
663 $key_style .= 'color:#C00;font-style:italic;';
664 $prefix = 'PRIVATE ';
665 } else {
666 $key_style .= 'color:#000;';
667 $prefix = '';
668 }
669
670 $valid_ids = array( 'ID', 'id' );
671 $is_id = in_array( (string) $key, $valid_ids );
672 if ( $is_id ) {
673 $key_style .= 'background:#FDA;';
674 }
675
676 echo '<span class="dev-item dev-item-key" style="' . $key_style . '">[ ' . $prefix . $key . ' ]</span>';
677 echo '<span class="dev-item"> => </span>';
678 }
679
680 // Data-Type.
681 if ( ! empty( $args['toggle'] ) ) {
682 echo '<a href="javascript:toggleDisplay(\''. $args['toggle'] . '\',\'' . trim( $row_class . ' ' . $args['toggle'] ) . '\');" class="dev-item dev-toggle-item">';
683 echo '<span style="color:#666666">' . $type . '</span>&nbsp;&nbsp;';
684 echo '</a>';
685 } else {
686 echo '<span class="dev-item" style="color:#666666">' . $type . '&nbsp;&nbsp;</span>';
687 }
688
689 if ( ! empty( $args['toggle'] ) ) {
690 $collapsed = ! empty( $args['do_collapse_next'] );
691 $toggle_style = 'display: ' . ( $collapsed ? 'inline' : 'none' );
692 echo '<span id="plus' . $args['toggle'] . '" class="plus dev-item" style="' . $toggle_style . '">&nbsp;&#10549;</span>';
693 }
694
695 // Value.
696 if ( $value !== null ) {
697 $value_style = '';
698 if ( isset( $args['highlight'] ) ) {
699 $value_style = $args['highlight'];
700 }
701 echo '<span class="dev-item" style="color:' . $type_color . ';' . $value_style . '">' . $value . '</span>';
702 }
703
704 echo '</td></tr>';
705 echo "\r\n";
706 }
707
708 /**
709 * Outputs the CSS and JS scripts required to display the debug dump/trace.
710 *
711 * @since 2.0.0
712 * @internal
713 */
714 protected function add_scripts() {
715 if ( $this->is_plain_text() ) { return; }
716 if ( defined( '__DEBUG_SCRIPT' ) ) { return; }
717 define( '__DEBUG_SCRIPT', true );
718
719 if ( ! headers_sent() ) {
720 header( 'Content-type: text/html; charset=utf-8' );
721 }
722
723 ?>
724 <style>
725 .wdev-debug {
726 clear: both;
727 border: 1px solid #C00;
728 background: rgba(255, 200, 200, 1);
729 padding: 10px;
730 margin: 10px;
731 position: relative;
732 z-index: 99999;
733 box-shadow: 0 1px 5px rgba(0,0,0,0.3);
734 font-size: 12px;
735 font-family: sans-serif;
736 font-weight: 200;
737 line-height: 1;
738 }
739 .wdev-debug .dev-tree {
740 color: #000;
741 opacity: .2;
742 font-family: monospace;
743 font-size: 19px;
744 line-height: 16px;
745 float: left;
746 }
747 .wdev-debug .dev-item {
748 float: left;
749 line-height: 16px;
750 white-space: pre;
751 }
752 .wdev-debug .dev-toggle-item {
753 text-decoration: none;
754 background: rgba(255,255,255,0.2);
755 display: inline-block;
756 }
757 .wdev-debug .wdev-dump {
758 margin: 0;
759 border-collapse: collapse;
760 padding: 0;
761 border: 0;
762 }
763 .wdev-debug .wdev-trace-toggle {
764 display: block;
765 margin: 10px 0 0 0;
766 }
767 .wdev-debug .wdev-dump td {
768 font-size: 12px;
769 line-height: 1;
770 font-family: sans-serif;
771 font-weight: 200;
772 background: transparent;
773 cursor: default;
774 padding: 0;
775 border: 0;
776 word-break: normal!important;
777 }
778 .wdev-debug .wdev-dump tr:hover td {
779 background-color: #FFF;
780 background-color: rgba(255,255,255,0.3);
781 }
782 .wdev-debug-clear {
783 clear: both;
784 display: table;
785 padding: 0;
786 margin: 0;
787 }
788 .wdev-debug-label {
789 font-size: 11px;
790 float: right;
791 margin: -10px;
792 color: #FFF;
793 background-color: #D88;
794 padding: 2px 8px;
795 cursor: pointer;
796 max-width: 50%;
797 white-space: nowrap;
798 overflow: hidden;
799 text-overflow: ellipsis;
800 }
801 .wdev-debug-label:hover {
802 background-color: #E66;
803 }
804 .wdev-debug pre {
805 font-size: 12px !important;
806 margin: 1px 0 !important;
807 background: rgba(255, 200, 200, 0.8);
808 }
809 .wdev-trace td {
810 padding: 1px 2px !important;
811 font-size: 12px;
812 vertical-align: top;
813 word-break: normal!important;
814 }
815 .wdev-trace {
816 margin: 4px 0 0 0;
817 background: #EBB;
818 border-collapse: collapse;
819 }
820 .wdev-trace tr.mark td {
821 background: #EC9;
822 }
823 .wdev-trace tr td {
824 cursor: default;
825 }
826 .wdev-trace-toggle {
827 cursor: pointer;
828 }
829 .wdev-debug .trc-num {
830 width: 40px;
831 }
832 .wdev-debug .trc-loc {
833 width: 60%;
834 }
835 .wdev-debug .trc-arg {
836 width: 40%;
837 font-size: 11px;
838 white-space: nowrap;
839 }
840 .wdev-debug .trc-param {
841 padding: 0 3px;
842 display: block;
843 margin: 1px 0 1px 8px;
844 }
845 .wdev-debug .trc-param font {
846 background: rgba( 0,0,0,0.05 );
847 }
848 .wdev-debug .trc-param:after {
849 content: ',';
850 }
851 .wdev-debug .trc-param:last-child:after {
852 content: '';
853 }
854 </style>
855 <script>
856 // Toggle whole block (debug/trace)
857 function toggleBlock( clsname ) {
858 var wrap = document.getElementsByClassName( clsname );
859
860 for ( var i = 0; i < wrap.length; i += 1 ) {
861 var state = (wrap[i].style.display == 'none' ? 'block' : 'none');
862 wrap[i].style.display = state;
863 }
864 }
865 // Mark a table row
866 function _m( row ) {
867 row.classList.toggle( 'mark' );
868 }
869 // Toggle a single debug-output-level
870 function toggleDisplay( clsname, full_class ) {
871 var elements = document.getElementsByClassName( clsname ),
872 plus = document.getElementById( "plus" + clsname ),
873 plus_state = (plus.style.display == 'none' ? 'inline' : 'none'),
874 el_state = (plus_state == 'none' ? 'table-row' : 'none' ),
875 sub_id = '',
876 sub_state = el_state;
877
878 plus.style.display = plus_state;
879
880 for ( var i = 0; i < elements.length; i += 1 ) {
881 var sub_plus = elements[i].getElementsByClassName( 'plus' );
882
883 if ( elements[i].className == full_class ) {
884 if ( sub_plus.length ) { sub_plus[0].style.display = 'inline'; }
885 elements[i].style.display = el_state;
886 } else {
887 if ( sub_plus.length ) { sub_plus[0].style.display = 'inline'; }
888 elements[i].style.display = 'none';
889 }
890 }
891 }
892 </script>
893 <?php
894 }
895
896 /**
897 * Returns an HTML element that displays a colored label. By default the
898 * label is a random/unique MD5 hash.
899 * This marker is intended for debugging to identify changes in objects
900 * that are loaded via ajax.
901 *
902 * @since 2.0.1
903 * @api
904 *
905 * @param string $label Optional. The label to display. Default is a
906 * random MD5 string.
907 * @param array $styles Optional. Array of CSS styles to apply.
908 * @return object {
909 * Marker details
910 *
911 * $html
912 * $hash
913 * $text
914 * $color
915 * }
916 */
917 public function marker_html( $label = null, $styles = array() ) {
918 $hash = md5( rand( 1000, 9999 ) . time() );
919
920 if ( null === $label ) {
921 $label = $hash;
922 } else {
923 $hash = md5( $label );
924 }
925
926 $color = substr( $hash, 0, 3 );
927 $def_styles = array(
928 'background' => '#' . $color,
929 'color' => '#fff',
930 'width' => '280px',
931 'font-size' => '12px',
932 'text-transform' => 'uppercase',
933 'font-family' => 'monospace',
934 'text-align' => 'center',
935 'margin' => '0 auto 5px',
936 'border-radius' => '3px',
937 'padding' => '4px',
938 'text-shadow' => '0 0 1px #666',
939 'box-shadow' => '0 0 1px #000 inset',
940 );
941 $styles = wp_parse_args(
942 $styles,
943 $def_styles
944 );
945
946 $style = '';
947 foreach ( $styles as $key => $val ) {
948 $style .= $key . ':' . $val . ';';
949 }
950
951 $marker = sprintf(
952 '<div style="%1$s">%2$s</div>',
953 esc_attr( $style ),
954 $label
955 );
956
957 return (object) array(
958 'html' => $marker,
959 'hash' => $hash,
960 'text' => $label,
961 'color' => '#' . $color,
962 );
963 }
964 }