[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /* 4 * This file is part of the Symfony package. 5 * 6 * (c) Fabien Potencier <[email protected]> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12 namespace Symfony\Component\VarDumper\Dumper; 13 14 use Symfony\Component\VarDumper\Cloner\Cursor; 15 use Symfony\Component\VarDumper\Cloner\Data; 16 17 /** 18 * HtmlDumper dumps variables as HTML. 19 * 20 * @author Nicolas Grekas <[email protected]> 21 */ 22 class HtmlDumper extends CliDumper 23 { 24 public static $defaultOutput = 'php://output'; 25 26 protected static $themes = [ 27 'dark' => [ 28 'default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all', 29 'num' => 'font-weight:bold; color:#1299DA', 30 'const' => 'font-weight:bold', 31 'str' => 'font-weight:bold; color:#56DB3A', 32 'note' => 'color:#1299DA', 33 'ref' => 'color:#A0A0A0', 34 'public' => 'color:#FFFFFF', 35 'protected' => 'color:#FFFFFF', 36 'private' => 'color:#FFFFFF', 37 'meta' => 'color:#B729D9', 38 'key' => 'color:#56DB3A', 39 'index' => 'color:#1299DA', 40 'ellipsis' => 'color:#FF8400', 41 'ns' => 'user-select:none;', 42 ], 43 'light' => [ 44 'default' => 'background:none; color:#CC7832; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all', 45 'num' => 'font-weight:bold; color:#1299DA', 46 'const' => 'font-weight:bold', 47 'str' => 'font-weight:bold; color:#629755;', 48 'note' => 'color:#6897BB', 49 'ref' => 'color:#6E6E6E', 50 'public' => 'color:#262626', 51 'protected' => 'color:#262626', 52 'private' => 'color:#262626', 53 'meta' => 'color:#B729D9', 54 'key' => 'color:#789339', 55 'index' => 'color:#1299DA', 56 'ellipsis' => 'color:#CC7832', 57 'ns' => 'user-select:none;', 58 ], 59 ]; 60 61 protected $dumpHeader; 62 protected $dumpPrefix = '<pre class=sf-dump id=%s data-indent-pad="%s">'; 63 protected $dumpSuffix = '</pre><script>Sfdump(%s)</script>'; 64 protected $dumpId = 'sf-dump'; 65 protected $colors = true; 66 protected $headerIsDumped = false; 67 protected $lastDepth = -1; 68 protected $styles; 69 70 private $displayOptions = [ 71 'maxDepth' => 1, 72 'maxStringLength' => 160, 73 'fileLinkFormat' => null, 74 ]; 75 private $extraDisplayOptions = []; 76 77 /** 78 * {@inheritdoc} 79 */ 80 public function __construct($output = null, string $charset = null, int $flags = 0) 81 { 82 AbstractDumper::__construct($output, $charset, $flags); 83 $this->dumpId = 'sf-dump-'.mt_rand(); 84 $this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); 85 $this->styles = static::$themes['dark'] ?? self::$themes['dark']; 86 } 87 88 /** 89 * {@inheritdoc} 90 */ 91 public function setStyles(array $styles) 92 { 93 $this->headerIsDumped = false; 94 $this->styles = $styles + $this->styles; 95 } 96 97 public function setTheme(string $themeName) 98 { 99 if (!isset(static::$themes[$themeName])) { 100 throw new \InvalidArgumentException(sprintf('Theme "%s" does not exist in class "%s".', $themeName, static::class)); 101 } 102 103 $this->setStyles(static::$themes[$themeName]); 104 } 105 106 /** 107 * Configures display options. 108 * 109 * @param array $displayOptions A map of display options to customize the behavior 110 */ 111 public function setDisplayOptions(array $displayOptions) 112 { 113 $this->headerIsDumped = false; 114 $this->displayOptions = $displayOptions + $this->displayOptions; 115 } 116 117 /** 118 * Sets an HTML header that will be dumped once in the output stream. 119 */ 120 public function setDumpHeader(?string $header) 121 { 122 $this->dumpHeader = $header; 123 } 124 125 /** 126 * Sets an HTML prefix and suffix that will encapse every single dump. 127 */ 128 public function setDumpBoundaries(string $prefix, string $suffix) 129 { 130 $this->dumpPrefix = $prefix; 131 $this->dumpSuffix = $suffix; 132 } 133 134 /** 135 * {@inheritdoc} 136 */ 137 public function dump(Data $data, $output = null, array $extraDisplayOptions = []) 138 { 139 $this->extraDisplayOptions = $extraDisplayOptions; 140 $result = parent::dump($data, $output); 141 $this->dumpId = 'sf-dump-'.mt_rand(); 142 143 return $result; 144 } 145 146 /** 147 * Dumps the HTML header. 148 */ 149 protected function getDumpHeader() 150 { 151 $this->headerIsDumped = $this->outputStream ?? $this->lineDumper; 152 153 if (null !== $this->dumpHeader) { 154 return $this->dumpHeader; 155 } 156 157 $line = str_replace('{$options}', json_encode($this->displayOptions, \JSON_FORCE_OBJECT), <<<'EOHTML' 158 <script> 159 Sfdump = window.Sfdump || (function (doc) { 160 161 var refStyle = doc.createElement('style'), 162 rxEsc = /([.*+?^${}()|\[\]\/\\])/g, 163 idRx = /\bsf-dump-\d+-ref[012]\w+\b/, 164 keyHint = 0 <= navigator.platform.toUpperCase().indexOf('MAC') ? 'Cmd' : 'Ctrl', 165 addEventListener = function (e, n, cb) { 166 e.addEventListener(n, cb, false); 167 }; 168 169 refStyle.innerHTML = 'pre.sf-dump .sf-dump-compact, .sf-dump-str-collapse .sf-dump-str-collapse, .sf-dump-str-expand .sf-dump-str-expand { display: none; }'; 170 (doc.documentElement.firstElementChild || doc.documentElement.children[0]).appendChild(refStyle); 171 refStyle = doc.createElement('style'); 172 (doc.documentElement.firstElementChild || doc.documentElement.children[0]).appendChild(refStyle); 173 174 if (!doc.addEventListener) { 175 addEventListener = function (element, eventName, callback) { 176 element.attachEvent('on' + eventName, function (e) { 177 e.preventDefault = function () {e.returnValue = false;}; 178 e.target = e.srcElement; 179 callback(e); 180 }); 181 }; 182 } 183 184 function toggle(a, recursive) { 185 var s = a.nextSibling || {}, oldClass = s.className, arrow, newClass; 186 187 if (/\bsf-dump-compact\b/.test(oldClass)) { 188 arrow = '▼'; 189 newClass = 'sf-dump-expanded'; 190 } else if (/\bsf-dump-expanded\b/.test(oldClass)) { 191 arrow = '▶'; 192 newClass = 'sf-dump-compact'; 193 } else { 194 return false; 195 } 196 197 if (doc.createEvent && s.dispatchEvent) { 198 var event = doc.createEvent('Event'); 199 event.initEvent('sf-dump-expanded' === newClass ? 'sfbeforedumpexpand' : 'sfbeforedumpcollapse', true, false); 200 201 s.dispatchEvent(event); 202 } 203 204 a.lastChild.innerHTML = arrow; 205 s.className = s.className.replace(/\bsf-dump-(compact|expanded)\b/, newClass); 206 207 if (recursive) { 208 try { 209 a = s.querySelectorAll('.'+oldClass); 210 for (s = 0; s < a.length; ++s) { 211 if (-1 == a[s].className.indexOf(newClass)) { 212 a[s].className = newClass; 213 a[s].previousSibling.lastChild.innerHTML = arrow; 214 } 215 } 216 } catch (e) { 217 } 218 } 219 220 return true; 221 }; 222 223 function collapse(a, recursive) { 224 var s = a.nextSibling || {}, oldClass = s.className; 225 226 if (/\bsf-dump-expanded\b/.test(oldClass)) { 227 toggle(a, recursive); 228 229 return true; 230 } 231 232 return false; 233 }; 234 235 function expand(a, recursive) { 236 var s = a.nextSibling || {}, oldClass = s.className; 237 238 if (/\bsf-dump-compact\b/.test(oldClass)) { 239 toggle(a, recursive); 240 241 return true; 242 } 243 244 return false; 245 }; 246 247 function collapseAll(root) { 248 var a = root.querySelector('a.sf-dump-toggle'); 249 if (a) { 250 collapse(a, true); 251 expand(a); 252 253 return true; 254 } 255 256 return false; 257 } 258 259 function reveal(node) { 260 var previous, parents = []; 261 262 while ((node = node.parentNode || {}) && (previous = node.previousSibling) && 'A' === previous.tagName) { 263 parents.push(previous); 264 } 265 266 if (0 !== parents.length) { 267 parents.forEach(function (parent) { 268 expand(parent); 269 }); 270 271 return true; 272 } 273 274 return false; 275 } 276 277 function highlight(root, activeNode, nodes) { 278 resetHighlightedNodes(root); 279 280 Array.from(nodes||[]).forEach(function (node) { 281 if (!/\bsf-dump-highlight\b/.test(node.className)) { 282 node.className = node.className + ' sf-dump-highlight'; 283 } 284 }); 285 286 if (!/\bsf-dump-highlight-active\b/.test(activeNode.className)) { 287 activeNode.className = activeNode.className + ' sf-dump-highlight-active'; 288 } 289 } 290 291 function resetHighlightedNodes(root) { 292 Array.from(root.querySelectorAll('.sf-dump-str, .sf-dump-key, .sf-dump-public, .sf-dump-protected, .sf-dump-private')).forEach(function (strNode) { 293 strNode.className = strNode.className.replace(/\bsf-dump-highlight\b/, ''); 294 strNode.className = strNode.className.replace(/\bsf-dump-highlight-active\b/, ''); 295 }); 296 } 297 298 return function (root, x) { 299 root = doc.getElementById(root); 300 301 var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || ' ').replace(rxEsc, '\\$1')+')+', 'm'), 302 options = {$options}, 303 elt = root.getElementsByTagName('A'), 304 len = elt.length, 305 i = 0, s, h, 306 t = []; 307 308 while (i < len) t.push(elt[i++]); 309 310 for (i in x) { 311 options[i] = x[i]; 312 } 313 314 function a(e, f) { 315 addEventListener(root, e, function (e, n) { 316 if ('A' == e.target.tagName) { 317 f(e.target, e); 318 } else if ('A' == e.target.parentNode.tagName) { 319 f(e.target.parentNode, e); 320 } else { 321 n = /\bsf-dump-ellipsis\b/.test(e.target.className) ? e.target.parentNode : e.target; 322 323 if ((n = n.nextElementSibling) && 'A' == n.tagName) { 324 if (!/\bsf-dump-toggle\b/.test(n.className)) { 325 n = n.nextElementSibling || n; 326 } 327 328 f(n, e, true); 329 } 330 } 331 }); 332 }; 333 function isCtrlKey(e) { 334 return e.ctrlKey || e.metaKey; 335 } 336 function xpathString(str) { 337 var parts = str.match(/[^'"]+|['"]/g).map(function (part) { 338 if ("'" == part) { 339 return '"\'"'; 340 } 341 if ('"' == part) { 342 return "'\"'"; 343 } 344 345 return "'" + part + "'"; 346 }); 347 348 return "concat(" + parts.join(",") + ", '')"; 349 } 350 function xpathHasClass(className) { 351 return "contains(concat(' ', normalize-space(@class), ' '), ' " + className +" ')"; 352 } 353 addEventListener(root, 'mouseover', function (e) { 354 if ('' != refStyle.innerHTML) { 355 refStyle.innerHTML = ''; 356 } 357 }); 358 a('mouseover', function (a, e, c) { 359 if (c) { 360 e.target.style.cursor = "pointer"; 361 } else if (a = idRx.exec(a.className)) { 362 try { 363 refStyle.innerHTML = 'pre.sf-dump .'+a[0]+'{background-color: #B729D9; color: #FFF !important; border-radius: 2px}'; 364 } catch (e) { 365 } 366 } 367 }); 368 a('click', function (a, e, c) { 369 if (/\bsf-dump-toggle\b/.test(a.className)) { 370 e.preventDefault(); 371 if (!toggle(a, isCtrlKey(e))) { 372 var r = doc.getElementById(a.getAttribute('href').substr(1)), 373 s = r.previousSibling, 374 f = r.parentNode, 375 t = a.parentNode; 376 t.replaceChild(r, a); 377 f.replaceChild(a, s); 378 t.insertBefore(s, r); 379 f = f.firstChild.nodeValue.match(indentRx); 380 t = t.firstChild.nodeValue.match(indentRx); 381 if (f && t && f[0] !== t[0]) { 382 r.innerHTML = r.innerHTML.replace(new RegExp('^'+f[0].replace(rxEsc, '\\$1'), 'mg'), t[0]); 383 } 384 if (/\bsf-dump-compact\b/.test(r.className)) { 385 toggle(s, isCtrlKey(e)); 386 } 387 } 388 389 if (c) { 390 } else if (doc.getSelection) { 391 try { 392 doc.getSelection().removeAllRanges(); 393 } catch (e) { 394 doc.getSelection().empty(); 395 } 396 } else { 397 doc.selection.empty(); 398 } 399 } else if (/\bsf-dump-str-toggle\b/.test(a.className)) { 400 e.preventDefault(); 401 e = a.parentNode.parentNode; 402 e.className = e.className.replace(/\bsf-dump-str-(expand|collapse)\b/, a.parentNode.className); 403 } 404 }); 405 406 elt = root.getElementsByTagName('SAMP'); 407 len = elt.length; 408 i = 0; 409 410 while (i < len) t.push(elt[i++]); 411 len = t.length; 412 413 for (i = 0; i < len; ++i) { 414 elt = t[i]; 415 if ('SAMP' == elt.tagName) { 416 a = elt.previousSibling || {}; 417 if ('A' != a.tagName) { 418 a = doc.createElement('A'); 419 a.className = 'sf-dump-ref'; 420 elt.parentNode.insertBefore(a, elt); 421 } else { 422 a.innerHTML += ' '; 423 } 424 a.title = (a.title ? a.title+'\n[' : '[')+keyHint+'+click] Expand all children'; 425 a.innerHTML += elt.className == 'sf-dump-compact' ? '<span>▶</span>' : '<span>▼</span>'; 426 a.className += ' sf-dump-toggle'; 427 428 x = 1; 429 if ('sf-dump' != elt.parentNode.className) { 430 x += elt.parentNode.getAttribute('data-depth')/1; 431 } 432 } else if (/\bsf-dump-ref\b/.test(elt.className) && (a = elt.getAttribute('href'))) { 433 a = a.substr(1); 434 elt.className += ' '+a; 435 436 if (/[\[{]$/.test(elt.previousSibling.nodeValue)) { 437 a = a != elt.nextSibling.id && doc.getElementById(a); 438 try { 439 s = a.nextSibling; 440 elt.appendChild(a); 441 s.parentNode.insertBefore(a, s); 442 if (/^[@#]/.test(elt.innerHTML)) { 443 elt.innerHTML += ' <span>▶</span>'; 444 } else { 445 elt.innerHTML = '<span>▶</span>'; 446 elt.className = 'sf-dump-ref'; 447 } 448 elt.className += ' sf-dump-toggle'; 449 } catch (e) { 450 if ('&' == elt.innerHTML.charAt(0)) { 451 elt.innerHTML = '…'; 452 elt.className = 'sf-dump-ref'; 453 } 454 } 455 } 456 } 457 } 458 459 if (doc.evaluate && Array.from && root.children.length > 1) { 460 root.setAttribute('tabindex', 0); 461 462 SearchState = function () { 463 this.nodes = []; 464 this.idx = 0; 465 }; 466 SearchState.prototype = { 467 next: function () { 468 if (this.isEmpty()) { 469 return this.current(); 470 } 471 this.idx = this.idx < (this.nodes.length - 1) ? this.idx + 1 : 0; 472 473 return this.current(); 474 }, 475 previous: function () { 476 if (this.isEmpty()) { 477 return this.current(); 478 } 479 this.idx = this.idx > 0 ? this.idx - 1 : (this.nodes.length - 1); 480 481 return this.current(); 482 }, 483 isEmpty: function () { 484 return 0 === this.count(); 485 }, 486 current: function () { 487 if (this.isEmpty()) { 488 return null; 489 } 490 return this.nodes[this.idx]; 491 }, 492 reset: function () { 493 this.nodes = []; 494 this.idx = 0; 495 }, 496 count: function () { 497 return this.nodes.length; 498 }, 499 }; 500 501 function showCurrent(state) 502 { 503 var currentNode = state.current(), currentRect, searchRect; 504 if (currentNode) { 505 reveal(currentNode); 506 highlight(root, currentNode, state.nodes); 507 if ('scrollIntoView' in currentNode) { 508 currentNode.scrollIntoView(true); 509 currentRect = currentNode.getBoundingClientRect(); 510 searchRect = search.getBoundingClientRect(); 511 if (currentRect.top < (searchRect.top + searchRect.height)) { 512 window.scrollBy(0, -(searchRect.top + searchRect.height + 5)); 513 } 514 } 515 } 516 counter.textContent = (state.isEmpty() ? 0 : state.idx + 1) + ' of ' + state.count(); 517 } 518 519 var search = doc.createElement('div'); 520 search.className = 'sf-dump-search-wrapper sf-dump-search-hidden'; 521 search.innerHTML = ' 522 <input type="text" class="sf-dump-search-input"> 523 <span class="sf-dump-search-count">0 of 0<\/span> 524 <button type="button" class="sf-dump-search-input-previous" tabindex="-1"> 525 <svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1683 1331l-166 165q-19 19-45 19t-45-19L896 965l-531 531q-19 19-45 19t-45-19l-166-165q-19-19-19-45.5t19-45.5l742-741q19-19 45-19t45 19l742 741q19 19 19 45.5t-19 45.5z"\/><\/svg> 526 <\/button> 527 <button type="button" class="sf-dump-search-input-next" tabindex="-1"> 528 <svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1683 808l-742 741q-19 19-45 19t-45-19L109 808q-19-19-19-45.5t19-45.5l166-165q19-19 45-19t45 19l531 531 531-531q19-19 45-19t45 19l166 165q19 19 19 45.5t-19 45.5z"\/><\/svg> 529 <\/button> 530 '; 531 root.insertBefore(search, root.firstChild); 532 533 var state = new SearchState(); 534 var searchInput = search.querySelector('.sf-dump-search-input'); 535 var counter = search.querySelector('.sf-dump-search-count'); 536 var searchInputTimer = 0; 537 var previousSearchQuery = ''; 538 539 addEventListener(searchInput, 'keyup', function (e) { 540 var searchQuery = e.target.value; 541 /* Don't perform anything if the pressed key didn't change the query */ 542 if (searchQuery === previousSearchQuery) { 543 return; 544 } 545 previousSearchQuery = searchQuery; 546 clearTimeout(searchInputTimer); 547 searchInputTimer = setTimeout(function () { 548 state.reset(); 549 collapseAll(root); 550 resetHighlightedNodes(root); 551 if ('' === searchQuery) { 552 counter.textContent = '0 of 0'; 553 554 return; 555 } 556 557 var classMatches = [ 558 "sf-dump-str", 559 "sf-dump-key", 560 "sf-dump-public", 561 "sf-dump-protected", 562 "sf-dump-private", 563 ].map(xpathHasClass).join(' or '); 564 565 var xpathResult = doc.evaluate('.//span[' + classMatches + '][contains(translate(child::text(), ' + xpathString(searchQuery.toUpperCase()) + ', ' + xpathString(searchQuery.toLowerCase()) + '), ' + xpathString(searchQuery.toLowerCase()) + ')]', root, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); 566 567 while (node = xpathResult.iterateNext()) state.nodes.push(node); 568 569 showCurrent(state); 570 }, 400); 571 }); 572 573 Array.from(search.querySelectorAll('.sf-dump-search-input-next, .sf-dump-search-input-previous')).forEach(function (btn) { 574 addEventListener(btn, 'click', function (e) { 575 e.preventDefault(); 576 -1 !== e.target.className.indexOf('next') ? state.next() : state.previous(); 577 searchInput.focus(); 578 collapseAll(root); 579 showCurrent(state); 580 }) 581 }); 582 583 addEventListener(root, 'keydown', function (e) { 584 var isSearchActive = !/\bsf-dump-search-hidden\b/.test(search.className); 585 if ((114 === e.keyCode && !isSearchActive) || (isCtrlKey(e) && 70 === e.keyCode)) { 586 /* F3 or CMD/CTRL + F */ 587 if (70 === e.keyCode && document.activeElement === searchInput) { 588 /* 589 * If CMD/CTRL + F is hit while having focus on search input, 590 * the user probably meant to trigger browser search instead. 591 * Let the browser execute its behavior: 592 */ 593 return; 594 } 595 596 e.preventDefault(); 597 search.className = search.className.replace(/\bsf-dump-search-hidden\b/, ''); 598 searchInput.focus(); 599 } else if (isSearchActive) { 600 if (27 === e.keyCode) { 601 /* ESC key */ 602 search.className += ' sf-dump-search-hidden'; 603 e.preventDefault(); 604 resetHighlightedNodes(root); 605 searchInput.value = ''; 606 } else if ( 607 (isCtrlKey(e) && 71 === e.keyCode) /* CMD/CTRL + G */ 608 || 13 === e.keyCode /* Enter */ 609 || 114 === e.keyCode /* F3 */ 610 ) { 611 e.preventDefault(); 612 e.shiftKey ? state.previous() : state.next(); 613 collapseAll(root); 614 showCurrent(state); 615 } 616 } 617 }); 618 } 619 620 if (0 >= options.maxStringLength) { 621 return; 622 } 623 try { 624 elt = root.querySelectorAll('.sf-dump-str'); 625 len = elt.length; 626 i = 0; 627 t = []; 628 629 while (i < len) t.push(elt[i++]); 630 len = t.length; 631 632 for (i = 0; i < len; ++i) { 633 elt = t[i]; 634 s = elt.innerText || elt.textContent; 635 x = s.length - options.maxStringLength; 636 if (0 < x) { 637 h = elt.innerHTML; 638 elt[elt.innerText ? 'innerText' : 'textContent'] = s.substring(0, options.maxStringLength); 639 elt.className += ' sf-dump-str-collapse'; 640 elt.innerHTML = '<span class=sf-dump-str-collapse>'+h+'<a class="sf-dump-ref sf-dump-str-toggle" title="Collapse"> ◀</a></span>'+ 641 '<span class=sf-dump-str-expand>'+elt.innerHTML+'<a class="sf-dump-ref sf-dump-str-toggle" title="'+x+' remaining characters"> ▶</a></span>'; 642 } 643 } 644 } catch (e) { 645 } 646 }; 647 648 })(document); 649 </script><style> 650 pre.sf-dump { 651 display: block; 652 white-space: pre; 653 padding: 5px; 654 overflow: initial !important; 655 } 656 pre.sf-dump:after { 657 content: ""; 658 visibility: hidden; 659 display: block; 660 height: 0; 661 clear: both; 662 } 663 pre.sf-dump span { 664 display: inline; 665 } 666 pre.sf-dump a { 667 text-decoration: none; 668 cursor: pointer; 669 border: 0; 670 outline: none; 671 color: inherit; 672 } 673 pre.sf-dump img { 674 max-width: 50em; 675 max-height: 50em; 676 margin: .5em 0 0 0; 677 padding: 0; 678 background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAHUlEQVQY02O8zAABilCaiQEN0EeA8QuUcX9g3QEAAjcC5piyhyEAAAAASUVORK5CYII=) #D3D3D3; 679 } 680 pre.sf-dump .sf-dump-ellipsis { 681 display: inline-block; 682 overflow: visible; 683 text-overflow: ellipsis; 684 max-width: 5em; 685 white-space: nowrap; 686 overflow: hidden; 687 vertical-align: top; 688 } 689 pre.sf-dump .sf-dump-ellipsis+.sf-dump-ellipsis { 690 max-width: none; 691 } 692 pre.sf-dump code { 693 display:inline; 694 padding:0; 695 background:none; 696 } 697 .sf-dump-public.sf-dump-highlight, 698 .sf-dump-protected.sf-dump-highlight, 699 .sf-dump-private.sf-dump-highlight, 700 .sf-dump-str.sf-dump-highlight, 701 .sf-dump-key.sf-dump-highlight { 702 background: rgba(111, 172, 204, 0.3); 703 border: 1px solid #7DA0B1; 704 border-radius: 3px; 705 } 706 .sf-dump-public.sf-dump-highlight-active, 707 .sf-dump-protected.sf-dump-highlight-active, 708 .sf-dump-private.sf-dump-highlight-active, 709 .sf-dump-str.sf-dump-highlight-active, 710 .sf-dump-key.sf-dump-highlight-active { 711 background: rgba(253, 175, 0, 0.4); 712 border: 1px solid #ffa500; 713 border-radius: 3px; 714 } 715 pre.sf-dump .sf-dump-search-hidden { 716 display: none !important; 717 } 718 pre.sf-dump .sf-dump-search-wrapper { 719 font-size: 0; 720 white-space: nowrap; 721 margin-bottom: 5px; 722 display: flex; 723 position: -webkit-sticky; 724 position: sticky; 725 top: 5px; 726 } 727 pre.sf-dump .sf-dump-search-wrapper > * { 728 vertical-align: top; 729 box-sizing: border-box; 730 height: 21px; 731 font-weight: normal; 732 border-radius: 0; 733 background: #FFF; 734 color: #757575; 735 border: 1px solid #BBB; 736 } 737 pre.sf-dump .sf-dump-search-wrapper > input.sf-dump-search-input { 738 padding: 3px; 739 height: 21px; 740 font-size: 12px; 741 border-right: none; 742 border-top-left-radius: 3px; 743 border-bottom-left-radius: 3px; 744 color: #000; 745 min-width: 15px; 746 width: 100%; 747 } 748 pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next, 749 pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous { 750 background: #F2F2F2; 751 outline: none; 752 border-left: none; 753 font-size: 0; 754 line-height: 0; 755 } 756 pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next { 757 border-top-right-radius: 3px; 758 border-bottom-right-radius: 3px; 759 } 760 pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next > svg, 761 pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous > svg { 762 pointer-events: none; 763 width: 12px; 764 height: 12px; 765 } 766 pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-count { 767 display: inline-block; 768 padding: 0 5px; 769 margin: 0; 770 border-left: none; 771 line-height: 21px; 772 font-size: 12px; 773 } 774 EOHTML 775 ); 776 777 foreach ($this->styles as $class => $style) { 778 $line .= 'pre.sf-dump'.('default' === $class ? ', pre.sf-dump' : '').' .sf-dump-'.$class.'{'.$style.'}'; 779 } 780 $line .= 'pre.sf-dump .sf-dump-ellipsis-note{'.$this->styles['note'].'}'; 781 782 return $this->dumpHeader = preg_replace('/\s+/', ' ', $line).'</style>'.$this->dumpHeader; 783 } 784 785 /** 786 * {@inheritdoc} 787 */ 788 public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut) 789 { 790 if ('' === $str && isset($cursor->attr['img-data'], $cursor->attr['content-type'])) { 791 $this->dumpKey($cursor); 792 $this->line .= $this->style('default', $cursor->attr['img-size'] ?? '', []); 793 $this->line .= $cursor->depth >= $this->displayOptions['maxDepth'] ? ' <samp class=sf-dump-compact>' : ' <samp class=sf-dump-expanded>'; 794 $this->endValue($cursor); 795 $this->line .= $this->indentPad; 796 $this->line .= sprintf('<img src="data:%s;base64,%s" /></samp>', $cursor->attr['content-type'], base64_encode($cursor->attr['img-data'])); 797 $this->endValue($cursor); 798 } else { 799 parent::dumpString($cursor, $str, $bin, $cut); 800 } 801 } 802 803 /** 804 * {@inheritdoc} 805 */ 806 public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild) 807 { 808 if (Cursor::HASH_OBJECT === $type) { 809 $cursor->attr['depth'] = $cursor->depth; 810 } 811 parent::enterHash($cursor, $type, $class, false); 812 813 if ($cursor->skipChildren || $cursor->depth >= $this->displayOptions['maxDepth']) { 814 $cursor->skipChildren = false; 815 $eol = ' class=sf-dump-compact>'; 816 } else { 817 $this->expandNextHash = false; 818 $eol = ' class=sf-dump-expanded>'; 819 } 820 821 if ($hasChild) { 822 $this->line .= '<samp data-depth='.($cursor->depth + 1); 823 if ($cursor->refIndex) { 824 $r = Cursor::HASH_OBJECT !== $type ? 1 - (Cursor::HASH_RESOURCE !== $type) : 2; 825 $r .= $r && 0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->refIndex; 826 827 $this->line .= sprintf(' id=%s-ref%s', $this->dumpId, $r); 828 } 829 $this->line .= $eol; 830 $this->dumpLine($cursor->depth); 831 } 832 } 833 834 /** 835 * {@inheritdoc} 836 */ 837 public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut) 838 { 839 $this->dumpEllipsis($cursor, $hasChild, $cut); 840 if ($hasChild) { 841 $this->line .= '</samp>'; 842 } 843 parent::leaveHash($cursor, $type, $class, $hasChild, 0); 844 } 845 846 /** 847 * {@inheritdoc} 848 */ 849 protected function style(string $style, string $value, array $attr = []) 850 { 851 if ('' === $value) { 852 return ''; 853 } 854 855 $v = esc($value); 856 857 if ('ref' === $style) { 858 if (empty($attr['count'])) { 859 return sprintf('<a class=sf-dump-ref>%s</a>', $v); 860 } 861 $r = ('#' !== $v[0] ? 1 - ('@' !== $v[0]) : 2).substr($value, 1); 862 863 return sprintf('<a class=sf-dump-ref href=#%s-ref%s title="%d occurrences">%s</a>', $this->dumpId, $r, 1 + $attr['count'], $v); 864 } 865 866 if ('const' === $style && isset($attr['value'])) { 867 $style .= sprintf(' title="%s"', esc(is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value']))); 868 } elseif ('public' === $style) { 869 $style .= sprintf(' title="%s"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property'); 870 } elseif ('str' === $style && 1 < $attr['length']) { 871 $style .= sprintf(' title="%d%s characters"', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : ''); 872 } elseif ('note' === $style && 0 < ($attr['depth'] ?? 0) && false !== $c = strrpos($value, '\\')) { 873 $style .= ' title=""'; 874 $attr += [ 875 'ellipsis' => \strlen($value) - $c, 876 'ellipsis-type' => 'note', 877 'ellipsis-tail' => 1, 878 ]; 879 } elseif ('protected' === $style) { 880 $style .= ' title="Protected property"'; 881 } elseif ('meta' === $style && isset($attr['title'])) { 882 $style .= sprintf(' title="%s"', esc($this->utf8Encode($attr['title']))); 883 } elseif ('private' === $style) { 884 $style .= sprintf(' title="Private property defined in class: `%s`"', esc($this->utf8Encode($attr['class']))); 885 } 886 $map = static::$controlCharsMap; 887 888 if (isset($attr['ellipsis'])) { 889 $class = 'sf-dump-ellipsis'; 890 if (isset($attr['ellipsis-type'])) { 891 $class = sprintf('"%s sf-dump-ellipsis-%s"', $class, $attr['ellipsis-type']); 892 } 893 $label = esc(substr($value, -$attr['ellipsis'])); 894 $style = str_replace(' title="', " title=\"$v\n", $style); 895 $v = sprintf('<span class=%s>%s</span>', $class, substr($v, 0, -\strlen($label))); 896 897 if (!empty($attr['ellipsis-tail'])) { 898 $tail = \strlen(esc(substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']))); 899 $v .= sprintf('<span class=%s>%s</span>%s', $class, substr($label, 0, $tail), substr($label, $tail)); 900 } else { 901 $v .= $label; 902 } 903 } 904 905 $v = "<span class=sf-dump-{$style}>".preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) { 906 $s = $b = '<span class="sf-dump-default'; 907 $c = $c[$i = 0]; 908 if ($ns = "\r" === $c[$i] || "\n" === $c[$i]) { 909 $s .= ' sf-dump-ns'; 910 } 911 $s .= '">'; 912 do { 913 if (("\r" === $c[$i] || "\n" === $c[$i]) !== $ns) { 914 $s .= '</span>'.$b; 915 if ($ns = !$ns) { 916 $s .= ' sf-dump-ns'; 917 } 918 $s .= '">'; 919 } 920 921 $s .= $map[$c[$i]] ?? sprintf('\x%02X', \ord($c[$i])); 922 } while (isset($c[++$i])); 923 924 return $s.'</span>'; 925 }, $v).'</span>'; 926 927 if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) { 928 $attr['href'] = $href; 929 } 930 if (isset($attr['href'])) { 931 $target = isset($attr['file']) ? '' : ' target="_blank"'; 932 $v = sprintf('<a href="%s"%s rel="noopener noreferrer">%s</a>', esc($this->utf8Encode($attr['href'])), $target, $v); 933 } 934 if (isset($attr['lang'])) { 935 $v = sprintf('<code class="%s">%s</code>', esc($attr['lang']), $v); 936 } 937 938 return $v; 939 } 940 941 /** 942 * {@inheritdoc} 943 */ 944 protected function dumpLine(int $depth, bool $endOfValue = false) 945 { 946 if (-1 === $this->lastDepth) { 947 $this->line = sprintf($this->dumpPrefix, $this->dumpId, $this->indentPad).$this->line; 948 } 949 if ($this->headerIsDumped !== ($this->outputStream ?? $this->lineDumper)) { 950 $this->line = $this->getDumpHeader().$this->line; 951 } 952 953 if (-1 === $depth) { 954 $args = ['"'.$this->dumpId.'"']; 955 if ($this->extraDisplayOptions) { 956 $args[] = json_encode($this->extraDisplayOptions, \JSON_FORCE_OBJECT); 957 } 958 // Replace is for BC 959 $this->line .= sprintf(str_replace('"%s"', '%s', $this->dumpSuffix), implode(', ', $args)); 960 } 961 $this->lastDepth = $depth; 962 963 $this->line = mb_encode_numericentity($this->line, [0x80, 0xFFFF, 0, 0xFFFF], 'UTF-8'); 964 965 if (-1 === $depth) { 966 AbstractDumper::dumpLine(0); 967 } 968 AbstractDumper::dumpLine($depth); 969 } 970 971 private function getSourceLink(string $file, int $line) 972 { 973 $options = $this->extraDisplayOptions + $this->displayOptions; 974 975 if ($fmt = $options['fileLinkFormat']) { 976 return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line); 977 } 978 979 return false; 980 } 981 } 982 983 function esc(string $str) 984 { 985 return htmlspecialchars($str, \ENT_QUOTES, 'UTF-8'); 986 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |