PluginProbe ʕ •ᴥ•ʔ
Hustle – Email Marketing, Lead Generation, Optins, Popups / 5.1.1
Hustle – Email Marketing, Lead Generation, Optins, Popups v5.1.1
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 9 years ago class-thelib-core.php 9 years ago class-thelib-debug.php 9 years ago class-thelib-html.php 9 years ago class-thelib-net.php 9 years ago class-thelib-session.php 9 years ago class-thelib-ui.php 9 years ago class-thelib-updates.php 9 years ago class-thelib.php 9 years ago
class-thelib-debug.php
961 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 $last_key = end( (array_keys( $dump_data )) );
506 reset( $dump_data );
507
508 foreach ( $dump_data as $key => $value ) {
509 if ( ! $populated ) {
510 $populated = true;
511
512 $id = substr( md5( rand() . ':' . $key . ':' . count( $level ) ), 0, 8 );
513 $args['containers'][] = $id;
514 $collapse = count( $args['containers'] ) >= $default_depth;
515 if ( $collapse ) {
516 $args['collapsed'][] = $id;
517 }
518
519 $title_args = $args;
520 $title_args['toggle'] = $id;
521
522 $this->_dump_line(
523 $item_key,
524 $type_label,
525 '',
526 $level,
527 $title_args
528 );
529 unset( $args['protected'] );
530 unset( $args['private'] );
531 }
532
533 // Tree right before the item-name
534 $new_level = $level;
535
536 if ( $last_key == $key ) {
537 $new_level[] = false;
538 $args['lastkey'] = true;
539 } else {
540 $new_level[] = true;
541 $args['lastkey'] = false;
542 }
543
544 $encode_key = json_encode( $key );
545 $matches = null;
546 if ( 1 === strpos( $encode_key, '\\u0000*\\u0000' ) ) {
547 $args['protected'] = true;
548 $key = substr( $key, 3 );
549 } elseif ( 1 === preg_match( '/\\\\u0000(\w+)\\\\u0000/i', $encode_key, $matches ) ) {
550 $args['private'] = true;
551 $key = substr( $key, 2 + strlen( $matches[1] ) );
552 }
553
554 $this->_dump_var(
555 $value,
556 $key,
557 $default_depth,
558 $new_level,
559 $args
560 );
561
562 unset( $args['protected'] );
563 unset( $args['private'] );
564 } // end of array/object loop.
565
566 if ( ! $populated ) {
567 $this->_dump_line(
568 $item_key,
569 $type_label,
570 '',
571 $level,
572 $args
573 );
574 }
575 } else {
576 $this->_dump_line(
577 $item_key,
578 $type_label,
579 $type_data,
580 $level,
581 $args
582 );
583 }
584 }
585
586 /**
587 * Outputs a single line of the dump_var output.
588 *
589 * @since 1.1.4
590 * @internal
591 */
592 protected function _dump_line( $key, $type, $value, $level, $args = array() ) {
593 $type_color = '#999';
594 $type_key = strtolower( $type );
595 if ( strlen( $type_key ) > 4 ) { $type_key = substr( $type_key, 0, 4 ); }
596
597 $custom_type_colors = array(
598 'stri' => 'green',
599 'doub' => '#0099c5',
600 'floa' => '#0099c5',
601 'inte' => 'red',
602 'bool' => '#92008d',
603 'null' => '#AAA',
604 );
605
606 if ( isset( $custom_type_colors[ $type_key ] ) ) {
607 $type_color = $custom_type_colors[ $type_key ];
608 }
609
610 $collapse = array_intersect( $args['containers'], $args['collapsed'] );
611 $args['do_collapse'] = is_array( $collapse ) && count( $collapse ) > 0;
612 if ( ! empty( $args['toggle'] ) ) {
613 $args['containers'] = array_diff( $args['containers'], array( $args['toggle'] ) );
614 $args['collapsed'] = array_diff( $args['collapsed'], array( $args['toggle'] ) );
615
616 $collapse_this = array_intersect( $args['containers'], $args['collapsed'] );
617 $args['do_collapse_next'] = $args['do_collapse'];
618 $args['do_collapse'] = is_array( $collapse_this ) && count( $collapse_this ) > 0;
619 }
620
621 $row_class = '';
622 $row_attr = '';
623 if ( ! empty( $args['containers'] ) ) {
624 $row_class = implode( ' ', $args['containers'] );
625 }
626 if ( ! empty( $args['do_collapse'] ) ) {
627 $row_attr = 'style="display:none;"';
628 }
629 echo '<tr class="' . $row_class . '"' . $row_attr . '><td>';
630
631 // Property-key, if set.
632 if ( $key === null ) {
633 // Full Tree-level.
634 echo '<span class="dev-tree">';
635 for ( $i = 0; $i < count( $level ); $i += 1 ) {
636 if ( null === $level[$i] ) { continue; }
637 if ( $level[$i] ) { echo '&nbsp;│&nbsp;'; }
638 else { echo '&nbsp;&nbsp;&nbsp;'; }
639 }
640 echo '</span>';
641 } else {
642 echo '<span class="dev-tree">';
643 // Tree-level without last level.
644 for ( $i = 0; $i < count( $level ) - 1; $i += 1 ) {
645 if ( null === $level[$i] ) { continue; }
646 if ( $level[$i] ) { echo '&nbsp;│&nbsp;'; }
647 else { echo '&nbsp;&nbsp;&nbsp;'; }
648 }
649
650 if ( empty( $args['lastkey'] ) ) {
651 echo '&nbsp;├─';
652 } else {
653 echo '&nbsp;└─';
654 }
655 echo '</span>';
656
657 $key_style = '';
658 if ( ! empty( $args['protected'] ) ) {
659 $key_style .= 'color:#900;';
660 $prefix = '';
661 } elseif ( ! empty( $args['private'] ) ) {
662 $key_style .= 'color:#C00;font-style:italic;';
663 $prefix = 'PRIVATE ';
664 } else {
665 $key_style .= 'color:#000;';
666 $prefix = '';
667 }
668
669 $valid_ids = array( 'ID', 'id' );
670 $is_id = in_array( (string) $key, $valid_ids );
671 if ( $is_id ) {
672 $key_style .= 'background:#FDA;';
673 }
674
675 echo '<span class="dev-item dev-item-key" style="' . $key_style . '">[ ' . $prefix . $key . ' ]</span>';
676 echo '<span class="dev-item"> => </span>';
677 }
678
679 // Data-Type.
680 if ( ! empty( $args['toggle'] ) ) {
681 echo '<a href="javascript:toggleDisplay(\''. $args['toggle'] . '\',\'' . trim( $row_class . ' ' . $args['toggle'] ) . '\');" class="dev-item dev-toggle-item">';
682 echo '<span style="color:#666666">' . $type . '</span>&nbsp;&nbsp;';
683 echo '</a>';
684 } else {
685 echo '<span class="dev-item" style="color:#666666">' . $type . '&nbsp;&nbsp;</span>';
686 }
687
688 if ( ! empty( $args['toggle'] ) ) {
689 $collapsed = ! empty( $args['do_collapse_next'] );
690 $toggle_style = 'display: ' . ( $collapsed ? 'inline' : 'none' );
691 echo '<span id="plus' . $args['toggle'] . '" class="plus dev-item" style="' . $toggle_style . '">&nbsp;&#10549;</span>';
692 }
693
694 // Value.
695 if ( $value !== null ) {
696 $value_style = '';
697 if ( isset( $args['highlight'] ) ) {
698 $value_style = $args['highlight'];
699 }
700 echo '<span class="dev-item" style="color:' . $type_color . ';' . $value_style . '">' . $value . '</span>';
701 }
702
703 echo '</td></tr>';
704 echo "\r\n";
705 }
706
707 /**
708 * Outputs the CSS and JS scripts required to display the debug dump/trace.
709 *
710 * @since 2.0.0
711 * @internal
712 */
713 protected function add_scripts() {
714 if ( $this->is_plain_text() ) { return; }
715 if ( defined( '__DEBUG_SCRIPT' ) ) { return; }
716 define( '__DEBUG_SCRIPT', true );
717
718 if ( ! headers_sent() ) {
719 header( 'Content-type: text/html; charset=utf-8' );
720 }
721
722 ?>
723 <style>
724 .wdev-debug {
725 clear: both;
726 border: 1px solid #C00;
727 background: rgba(255, 200, 200, 1);
728 padding: 10px;
729 margin: 10px;
730 position: relative;
731 z-index: 99999;
732 box-shadow: 0 1px 5px rgba(0,0,0,0.3);
733 font-size: 12px;
734 font-family: sans-serif;
735 font-weight: 200;
736 line-height: 1;
737 }
738 .wdev-debug .dev-tree {
739 color: #000;
740 opacity: .2;
741 font-family: monospace;
742 font-size: 19px;
743 line-height: 16px;
744 float: left;
745 }
746 .wdev-debug .dev-item {
747 float: left;
748 line-height: 16px;
749 white-space: pre;
750 }
751 .wdev-debug .dev-toggle-item {
752 text-decoration: none;
753 background: rgba(255,255,255,0.2);
754 display: inline-block;
755 }
756 .wdev-debug .wdev-dump {
757 margin: 0;
758 border-collapse: collapse;
759 padding: 0;
760 border: 0;
761 }
762 .wdev-debug .wdev-trace-toggle {
763 display: block;
764 margin: 10px 0 0 0;
765 }
766 .wdev-debug .wdev-dump td {
767 font-size: 12px;
768 line-height: 1;
769 font-family: sans-serif;
770 font-weight: 200;
771 background: transparent;
772 cursor: default;
773 padding: 0;
774 border: 0;
775 }
776 .wdev-debug .wdev-dump tr:hover td {
777 background-color: #FFF;
778 background-color: rgba(255,255,255,0.3);
779 }
780 .wdev-debug-clear {
781 clear: both;
782 display: table;
783 padding: 0;
784 margin: 0;
785 }
786 .wdev-debug-label {
787 font-size: 11px;
788 float: right;
789 margin: -10px;
790 color: #FFF;
791 background-color: #D88;
792 padding: 2px 8px;
793 cursor: pointer;
794 max-width: 50%;
795 white-space: nowrap;
796 overflow: hidden;
797 text-overflow: ellipsis;
798 }
799 .wdev-debug-label:hover {
800 background-color: #E66;
801 }
802 .wdev-debug pre {
803 font-size: 12px !important;
804 margin: 1px 0 !important;
805 background: rgba(255, 200, 200, 0.8);
806 }
807 .wdev-trace td {
808 padding: 1px 2px !important;
809 font-size: 12px;
810 vertical-align: top;
811 }
812 .wdev-trace {
813 margin: 4px 0 0 0;
814 background: #EBB;
815 border-collapse: collapse;
816 }
817 .wdev-trace tr.mark td {
818 background: #EC9;
819 }
820 .wdev-trace tr td {
821 cursor: default;
822 }
823 .wdev-trace-toggle {
824 cursor: pointer;
825 }
826 .wdev-debug .trc-num {
827 width: 40px;
828 }
829 .wdev-debug .trc-loc {
830 width: 60%;
831 }
832 .wdev-debug .trc-arg {
833 width: 40%;
834 font-size: 11px;
835 white-space: nowrap;
836 }
837 .wdev-debug .trc-param {
838 padding: 0 3px;
839 display: block;
840 margin: 1px 0 1px 8px;
841 }
842 .wdev-debug .trc-param font {
843 background: rgba( 0,0,0,0.05 );
844 }
845 .wdev-debug .trc-param:after {
846 content: ',';
847 }
848 .wdev-debug .trc-param:last-child:after {
849 content: '';
850 }
851 </style>
852 <script>
853 // Toggle whole block (debug/trace)
854 function toggleBlock( clsname ) {
855 var wrap = document.getElementsByClassName( clsname );
856
857 for ( var i = 0; i < wrap.length; i += 1 ) {
858 var state = (wrap[i].style.display == 'none' ? 'block' : 'none');
859 wrap[i].style.display = state;
860 }
861 }
862 // Mark a table row
863 function _m( row ) {
864 row.classList.toggle( 'mark' );
865 }
866 // Toggle a single debug-output-level
867 function toggleDisplay( clsname, full_class ) {
868 var elements = document.getElementsByClassName( clsname ),
869 plus = document.getElementById( "plus" + clsname ),
870 plus_state = (plus.style.display == 'none' ? 'inline' : 'none'),
871 el_state = (plus_state == 'none' ? 'table-row' : 'none' ),
872 sub_id = '',
873 sub_state = el_state;
874
875 plus.style.display = plus_state;
876
877 for ( var i = 0; i < elements.length; i += 1 ) {
878 var sub_plus = elements[i].getElementsByClassName( 'plus' );
879
880 if ( elements[i].className == full_class ) {
881 if ( sub_plus.length ) { sub_plus[0].style.display = 'inline'; }
882 elements[i].style.display = el_state;
883 } else {
884 if ( sub_plus.length ) { sub_plus[0].style.display = 'inline'; }
885 elements[i].style.display = 'none';
886 }
887 }
888 }
889 </script>
890 <?php
891 }
892
893 /**
894 * Returns an HTML element that displays a colored label. By default the
895 * label is a random/unique MD5 hash.
896 * This marker is intended for debugging to identify changes in objects
897 * that are loaded via ajax.
898 *
899 * @since 2.0.1
900 * @api
901 *
902 * @param string $label Optional. The label to display. Default is a
903 * random MD5 string.
904 * @param array $styles Optional. Array of CSS styles to apply.
905 * @return object {
906 * Marker details
907 *
908 * $html
909 * $hash
910 * $text
911 * $color
912 * }
913 */
914 public function marker_html( $label = null, $styles = array() ) {
915 $hash = md5( rand( 1000, 9999 ) . time() );
916
917 if ( null === $label ) {
918 $label = $hash;
919 } else {
920 $hash = md5( $label );
921 }
922
923 $color = substr( $hash, 0, 3 );
924 $def_styles = array(
925 'background' => '#' . $color,
926 'color' => '#fff',
927 'width' => '280px',
928 'font-size' => '12px',
929 'text-transform' => 'uppercase',
930 'font-family' => 'monospace',
931 'text-align' => 'center',
932 'margin' => '0 auto 5px',
933 'border-radius' => '3px',
934 'padding' => '4px',
935 'text-shadow' => '0 0 1px #666',
936 'box-shadow' => '0 0 1px #000 inset',
937 );
938 $styles = wp_parse_args(
939 $styles,
940 $def_styles
941 );
942
943 $style = '';
944 foreach ( $styles as $key => $val ) {
945 $style .= $key . ':' . $val . ';';
946 }
947
948 $marker = sprintf(
949 '<div style="%1$s">%2$s</div>',
950 esc_attr( $style ),
951 $label
952 );
953
954 return (object) array(
955 'html' => $marker,
956 'hash' => $hash,
957 'text' => $label,
958 'color' => '#' . $color,
959 );
960 }
961 }