From ea5419452ff9139d199198412f3baf5909be56e8 Mon Sep 17 00:00:00 2001 From: Brad Kent Date: Mon, 9 Sep 2024 11:30:35 -0500 Subject: [PATCH] php 8.4 property hooks. properties now have hooks: array containing 'get' and/or 'set' and 'isVirtual': (bool) php 8.4 private/protected get new property css classes: getHook, isDeprecated, isVirtual, isWriteOnly, protected-set, private-set, setHook --- src/Debug/Abstraction/AbstractObject.php | 19 +- src/Debug/Abstraction/Abstracter.php | 3 + .../Object/AbstractInheritable.php | 34 +++ src/Debug/Abstraction/Object/Abstraction.php | 3 + src/Debug/Abstraction/Object/Constants.php | 27 +- src/Debug/Abstraction/Object/Definition.php | 2 +- src/Debug/Abstraction/Object/Helper.php | 18 -- src/Debug/Abstraction/Object/Methods.php | 16 +- src/Debug/Abstraction/Object/Properties.php | 267 +++--------------- .../Abstraction/Object/PropertiesInstance.php | 254 +++++++++++++++++ .../Abstraction/Object/PropertiesPhpDoc.php | 4 +- src/Debug/Abstraction/Object/Subscriber.php | 4 +- src/Debug/Config.php | 1 + src/Debug/Dump/Html/Object/Properties.php | 5 + src/Debug/Framework/Yii1_1/LogRoute.php | 27 +- src/Debug/Plugin/Channel.php | 2 + src/Debug/Plugin/Method/Alert.php | 4 + src/Debug/Plugin/Method/Basic.php | 17 ++ src/Debug/Plugin/Method/Clear.php | 2 + src/Debug/Plugin/Method/Count.php | 4 + src/Debug/Plugin/Method/Group.php | 4 +- src/Debug/Plugin/Method/Output.php | 3 + src/Debug/Plugin/Method/Profile.php | 4 + src/Debug/Plugin/Method/ReqRes.php | 2 + src/Debug/Plugin/Method/Table.php | 3 + src/Debug/Plugin/Method/Time.php | 10 + src/Debug/Plugin/Method/Trace.php | 2 + src/Debug/Route/Html.php | 3 - src/Debug/Route/WampHelper.php | 4 +- src/Debug/Utility/Php.php | 80 +++--- src/Debug/Utility/Table.php | 2 +- src/Debug/Utility/TableRow.php | 2 +- src/Debug/Utility/Utility.php | 21 ++ src/Debug/css/Debug.css | 2 +- src/Debug/js/Debug.jquery.js | 40 ++- src/Debug/js/Debug.jquery.min.js | 2 +- src/Debug/js_src/config.js | 27 +- src/Debug/js_src/enhanceObject.js | 13 +- src/Debug/scss/_arrayAndObject.scss | 8 + src/Promise/Utils.php | 39 ++- src/Teams/AbstractItem.php | 41 ++- .../CharReplacementAndSanitizationTest.php | 2 +- tests/Debug/ConfigTest.php | 1 + .../Debug/Fixture/PropertyAsymVisibility.php | 13 + tests/Debug/Fixture/PropertyHooks.php | 54 ++++ tests/Debug/Plugin/Method/BasicTest.php | 1 + tests/Debug/Type/EnumTest.php | 15 +- tests/Debug/Type/ObjectTest.php | 90 +++++- tests/Debug/Utility/PhpTest.php | 3 +- tests/Debug/Utility/SerializeLogTest.php | 2 + tests/Debug/data/ConfusableIdentifiers.php | 13 +- tests/Debug/data/PropertyAsymVisibility.php | 130 +++++++++ .../data/PropertyAsymVisibility_html.php | 15 + tests/Debug/data/PropertyHooks.php | 250 ++++++++++++++++ tests/Debug/data/PropertyHooks_html.php | 20 ++ 55 files changed, 1215 insertions(+), 419 deletions(-) create mode 100644 src/Debug/Abstraction/Object/PropertiesInstance.php create mode 100644 tests/Debug/Fixture/PropertyAsymVisibility.php create mode 100644 tests/Debug/Fixture/PropertyHooks.php create mode 100644 tests/Debug/data/PropertyAsymVisibility.php create mode 100644 tests/Debug/data/PropertyAsymVisibility_html.php create mode 100644 tests/Debug/data/PropertyHooks.php create mode 100644 tests/Debug/data/PropertyHooks_html.php diff --git a/src/Debug/Abstraction/AbstractObject.php b/src/Debug/Abstraction/AbstractObject.php index 0fb43242..e3bd0996 100644 --- a/src/Debug/Abstraction/AbstractObject.php +++ b/src/Debug/Abstraction/AbstractObject.php @@ -21,6 +21,7 @@ use bdk\Debug\Abstraction\Object\Helper; use bdk\Debug\Abstraction\Object\Methods; use bdk\Debug\Abstraction\Object\Properties; +use bdk\Debug\Abstraction\Object\PropertiesInstance; use bdk\Debug\Abstraction\Object\Subscriber; use ReflectionClass; use ReflectionEnumUnitCase; @@ -36,6 +37,7 @@ * @property-read Helper $helper * @property-read Methods $methods * @property-read Properties $properties + * @property-read PropertiesInstance $properties */ class AbstractObject extends AbstractComponent { @@ -66,7 +68,7 @@ class AbstractObject extends AbstractComponent const OBJ_ATTRIBUTE_OUTPUT = 8; const PARAM_ATTRIBUTE_COLLECT = 1048576; - const PARAM_ATTRIBUTE_OUTPUT = 2097152; + const PARAM_ATTRIBUTE_OUTPUT = 2097152; // 2^21 const PHPDOC_COLLECT = 1; // 2^0 const PHPDOC_OUTPUT = 2; @@ -74,6 +76,7 @@ class AbstractObject extends AbstractComponent // PROPERTIES (2^13 - 2^14) const PROP_ATTRIBUTE_COLLECT = 8192; // 2^13 const PROP_ATTRIBUTE_OUTPUT = 16384; // 2^14 + const PROP_VIRTUAL_VALUE_COLLECT = 33554432; // 2^25 const TO_STRING_OUTPUT = 16; // 2^4 @@ -114,6 +117,7 @@ class AbstractObject extends AbstractComponent // PROPERTIES 'propAttributeCollect' => self::PROP_ATTRIBUTE_COLLECT, 'propAttributeOutput' => self::PROP_ATTRIBUTE_OUTPUT, + 'propVirtualValueCollect' => self::PROP_VIRTUAL_VALUE_COLLECT, 'toStringOutput' => self::TO_STRING_OUTPUT, ); @@ -132,6 +136,8 @@ class AbstractObject extends AbstractComponent protected $methods; /** @var Properties */ protected $properties; + /** @var PropertiesInstance */ + protected $propertiesInstance; /** @var list */ protected $readOnly = array( @@ -142,6 +148,7 @@ class AbstractObject extends AbstractComponent 'helper', 'methods', 'properties', + 'propertiesInstance', ); /** @@ -164,7 +171,7 @@ class AbstractObject extends AbstractComponent * @var array Array of key/values */ protected static $values = array( - 'cfgFlags' => 0, // will default to everything sans "brief" + 'cfgFlags' => 0, // will default to everything sans "brief" & 'virtualValueCollect' 'className' => '', 'debugMethod' => '', 'interfacesCollapse' => array(), // cfg.interfacesCollapse @@ -195,6 +202,7 @@ public function __construct(Abstracter $abstracter) $this->constants = new Constants($this); $this->methods = new Methods($this); $this->properties = new Properties($this); + $this->propertiesInstance = new PropertiesInstance($this); $this->definition = new Definition($this); if ($abstracter->debug->parentInstance === null) { // we only need to subscribe to these events from root channel @@ -239,10 +247,10 @@ public function getAbstraction($obj, $method = null, array $hist = array()) public static function buildValues(array $values = array()) { if (self::$values['cfgFlags'] === 0) { - // calculate default cfgFlags (everything except for "brief") + // calculate default cfgFlags (everything except for "brief" & virtualValueCollect) self::$values['cfgFlags'] = \array_reduce(self::$cfgFlags, static function ($carry, $val) { return $carry | $val; - }, 0) & ~self::BRIEF; + }, 0) & ~self::BRIEF & ~self::PROP_VIRTUAL_VALUE_COLLECT; } return \array_merge(self::$values, $values); } @@ -297,7 +305,7 @@ private function doAbstraction(ObjectAbstraction $abs) $this->addTraverseValues($abs); } $this->methods->addInstance($abs); // method static variables - $this->properties->addInstance($abs); + $this->propertiesInstance->add($abs); /* Debug::EVENT_OBJ_ABSTRACT_END subscriber has free reign to modify abstraction values */ @@ -352,6 +360,7 @@ protected function getAbstractionValues(ReflectionClass $reflector, $obj, $metho protected function getCfgFlags() { $flagVals = \array_intersect_key(self::$cfgFlags, \array_filter($this->cfg)); + // see Abstracter::__construct which sets initial/default cfgFlags cfg vales $bitmask = \array_reduce($flagVals, static function ($carry, $val) { return $carry | $val; }, 0); diff --git a/src/Debug/Abstraction/Abstracter.php b/src/Debug/Abstraction/Abstracter.php index 81fced80..99e96d4e 100644 --- a/src/Debug/Abstraction/Abstracter.php +++ b/src/Debug/Abstraction/Abstracter.php @@ -63,6 +63,8 @@ class Abstracter extends AbstractComponent /** @var array>string,mixed> */ protected $cfg = array( 'brief' => false, // collect & output less details + // see also AbstractObject::$cfgFlags where each key + // can be set to true/false as a cfg value here 'fullyQualifyPhpDocType' => false, 'interfacesCollapse' => array( 'ArrayAccess', @@ -132,6 +134,7 @@ public function __construct(Debug $debug, $cfg = array()) ), array( 'brief' => false, + 'propVirtualValueCollect' => false, ) ); $this->setCfg(\array_merge($this->cfg, $cfg)); diff --git a/src/Debug/Abstraction/Object/AbstractInheritable.php b/src/Debug/Abstraction/Object/AbstractInheritable.php index 3c87be0e..a025cb79 100644 --- a/src/Debug/Abstraction/Object/AbstractInheritable.php +++ b/src/Debug/Abstraction/Object/AbstractInheritable.php @@ -14,6 +14,7 @@ use bdk\Debug\Abstraction\AbstractObject; use ReflectionClass; +use Reflector; /** * Base class for collecting constants, properties, & methods @@ -26,6 +27,9 @@ abstract class AbstractInheritable /** @var Helper */ protected $helper; + /** @var array */ + protected static $values = array(); + /** * Constructor * @@ -37,6 +41,36 @@ public function __construct(AbstractObject $abstractObject) $this->helper = $abstractObject->helper; } + /** + * Build (constant,method,property) info by passing values + * + * @param array $values Values to apply + * + * @return array + */ + public static function buildValues($values = array()) + { + return \array_merge(static::$values, $values); + } + + /** + * Get constant/method/property visibility + * + * @param Reflector $reflector Reflection instance + * + * @return list|'public'|'private'|'protected' + */ + protected static function getVisibility(Reflector $reflector) + { + if ($reflector->isPrivate()) { + return 'private'; + } + if ($reflector->isProtected()) { + return 'protected'; + } + return 'public'; + } + /** * Pass reflector and ancestor reflectors to callable * diff --git a/src/Debug/Abstraction/Object/Abstraction.php b/src/Debug/Abstraction/Object/Abstraction.php index 51bba6a5..048060ab 100644 --- a/src/Debug/Abstraction/Object/Abstraction.php +++ b/src/Debug/Abstraction/Object/Abstraction.php @@ -220,6 +220,9 @@ private function getCombinedValue($key) $value = isset($this->values[$key]) ? $this->values[$key] : null; + if (\in_array($key, self::$keysTemp)) { + return $value; + } $classVal = $this->inheritValue($key) ? $this->inherited[$key] : array(); diff --git a/src/Debug/Abstraction/Object/Constants.php b/src/Debug/Abstraction/Object/Constants.php index dcfd8a82..2fc8487f 100644 --- a/src/Debug/Abstraction/Object/Constants.php +++ b/src/Debug/Abstraction/Object/Constants.php @@ -36,11 +36,8 @@ class Constants extends AbstractInheritable /** @var bool */ private $attributeCollect = true; - /** @var bool */ - private $phpDocCollect = true; - /** @var array */ - private static $baseConstInfo = array( + protected static $values = array( 'attributes' => array(), 'declaredLast' => null, 'declaredOrig' => null, @@ -70,7 +67,6 @@ public function add(Abstraction $abs) $this->abs = $abs; $this->constants = array(); $this->attributeCollect = ($abs['cfgFlags'] & AbstractObject::CONST_ATTRIBUTE_COLLECT) === AbstractObject::CONST_ATTRIBUTE_COLLECT; - $this->phpDocCollect = ($abs['cfgFlags'] & AbstractObject::PHPDOC_COLLECT) === AbstractObject::PHPDOC_COLLECT; /* We trace our lineage to learn where constants are inherited from (set brief to avoid recursion with enum values) @@ -102,7 +98,6 @@ public function addCases(Abstraction $abs) return; } $this->attributeCollect = ($abs['cfgFlags'] & AbstractObject::CASE_ATTRIBUTE_COLLECT) === AbstractObject::CASE_ATTRIBUTE_COLLECT; - $this->phpDocCollect = ($abs['cfgFlags'] & AbstractObject::PHPDOC_COLLECT) === AbstractObject::PHPDOC_COLLECT; $cases = array(); foreach ($abs['reflector']->getCases() as $refCase) { $name = $refCase->getName(); @@ -111,18 +106,6 @@ public function addCases(Abstraction $abs) $abs['cases'] = $cases; } - /** - * Build constant info by passing values - * - * @param array $values Values to apply - * - * @return array - */ - public static function buildValues($values = array()) - { - return \array_merge(static::$baseConstInfo, $values); - } - /** * Get constants (php < 7.1) * @@ -192,7 +175,7 @@ private function getCaseRefInfo(ReflectionEnumUnitCase $refCase) 'value' => $refCase instanceof ReflectionEnumBackedCase ? $refCase->getBackingValue() : Abstracter::UNDEFINED, - 'visibility' => $this->helper->getVisibility($refCase), + 'visibility' => $this->getVisibility($refCase), ); } @@ -216,13 +199,11 @@ private function getConstantRefInfo(ReflectionClassConstant $refConstant) 'attributes' => $this->attributeCollect ? $this->helper->getAttributes($refConstant) : array(), - 'isFinal' => PHP_VERSION_ID >= 80100 - ? $refConstant->isFinal() - : false, + 'isFinal' => PHP_VERSION_ID >= 80100 && $refConstant->isFinal(), 'phpDoc' => $phpDoc, 'type' => $type, 'value' => $value, - 'visibility' => $this->helper->getVisibility($refConstant), + 'visibility' => $this->getVisibility($refConstant), )); } } diff --git a/src/Debug/Abstraction/Object/Definition.php b/src/Debug/Abstraction/Object/Definition.php index d4143e9d..bbbfce16 100644 --- a/src/Debug/Abstraction/Object/Definition.php +++ b/src/Debug/Abstraction/Object/Definition.php @@ -55,7 +55,7 @@ class Definition protected static $values = array( 'attributes' => array(), 'cases' => array(), - 'cfgFlags' => 0, // __constructor will set to everything sans "brief" + 'cfgFlags' => 0, // __constructor will set to everything sans "brief" and "propVirtualValueCollect" // definition will collect with all options 'className' => "\x00default\x00", 'constants' => array(), diff --git a/src/Debug/Abstraction/Object/Helper.php b/src/Debug/Abstraction/Object/Helper.php index 119b583e..a9cd2afb 100644 --- a/src/Debug/Abstraction/Object/Helper.php +++ b/src/Debug/Abstraction/Object/Helper.php @@ -178,24 +178,6 @@ public function isTraverseOnly(ObjectAbstraction $abs) return false; } - /** - * Get constant/method/property visibility - * - * @param Reflector $reflector Reflection instance - * - * @return 'public'|'private'|'protected' - */ - public static function getVisibility(Reflector $reflector) - { - if ($reflector->isPrivate()) { - return 'private'; - } - if ($reflector->isProtected()) { - return 'protected'; - } - return 'public'; - } - /** * Get Constant, Property, or Parameter's type or Method's return type * Priority given to phpDoc type, followed by reflection type (if available) diff --git a/src/Debug/Abstraction/Object/Methods.php b/src/Debug/Abstraction/Object/Methods.php index f4dae791..e573b189 100644 --- a/src/Debug/Abstraction/Object/Methods.php +++ b/src/Debug/Abstraction/Object/Methods.php @@ -35,7 +35,7 @@ class Methods extends AbstractInheritable protected $params; /** @var array */ - private static $baseMethodInfo = array( + protected static $values = array( 'attributes' => array(), 'declaredLast' => null, 'declaredOrig' => null, @@ -116,18 +116,6 @@ public function addInstance(Abstraction $abs) } } - /** - * Return method info array - * - * @param array $values values to apply - * - * @return array - */ - public static function buildValues(array $values = array()) - { - return \array_merge(static::$baseMethodInfo, $values); - } - /** * Get object's __toString value if method is not deprecated * @@ -388,7 +376,7 @@ private function addViaRefBuildInit(Abstraction $abs, ReflectionMethod $refMetho 'desc' => $returnTag['desc'], 'type' => $this->helper->getType($returnTag['type'], $refMethod), ), - 'visibility' => $this->helper->getVisibility($refMethod), + 'visibility' => $this->getVisibility($refMethod), )); } } diff --git a/src/Debug/Abstraction/Object/Properties.php b/src/Debug/Abstraction/Object/Properties.php index e79b9c92..e5686b6f 100644 --- a/src/Debug/Abstraction/Object/Properties.php +++ b/src/Debug/Abstraction/Object/Properties.php @@ -19,14 +19,15 @@ use bdk\Debug\Abstraction\Type; use ReflectionClass; use ReflectionProperty; +use Reflector; /** - * Get object property info + * Get class definition property info */ class Properties extends AbstractInheritable { /** @var array */ - private static $basePropInfo = array( + protected static $values = array( 'attributes' => array(), 'debugInfoExcluded' => false, // true if not included in __debugInfo 'declaredLast' => null, // Class where property last declared @@ -36,12 +37,14 @@ class Properties extends AbstractInheritable // populated only if overridden 'forceShow' => false, // initially show the property/value (even if protected or private) // if value is an array, expand it + 'hooks' => array(), // PHP 8.4+ 'isDeprecated' => false, // some internal php objects may raise a deprecation notice when accessing // example: `DOMDocument::$actualEncoding` // or may come from phpDoc tag 'isPromoted' => false, 'isReadOnly' => false, 'isStatic' => false, + 'isVirtual' => false, // PHP 8.4+ 'phpDoc' => array( 'desc' => '', 'summary' => '', @@ -49,8 +52,11 @@ class Properties extends AbstractInheritable 'type' => null, 'value' => Abstracter::UNDEFINED, 'valueFrom' => 'value', // 'value' | 'debugInfo' | 'debug' - 'visibility' => 'public', // public, private, protected, magic, magic-read, magic-write, debug - // may also be an array (ie: ['private', 'magic-read']) + 'visibility' => ['public'], // array + // public, private, private-set, + // protected, protected-set, + // magic, magic-read, magic-write, + // debug ); /** @var PropertiesPhpDoc */ @@ -93,13 +99,13 @@ public function add(Abstraction $abs) 'type' => Type::TYPE_STRING, 'value' => $abs['definition']['fileName'], 'valueFrom' => 'debug', - 'visibility' => 'debug', + 'visibility' => ['debug'], )); $properties['debug.line'] = static::buildValues(array( 'type' => Type::TYPE_INT, 'value' => (int) $abs['definition']['startLine'], 'valueFrom' => 'debug', - 'visibility' => 'debug', + 'visibility' => ['debug'], )); } @@ -108,213 +114,6 @@ public function add(Abstraction $abs) $this->crate($abs); } - /** - * Add property instance info/values to abstraction - * - * @param Abstraction $abs Object Abstraction instance - * - * @return void - */ - public function addInstance(Abstraction $abs) - { - if ($abs['isTraverseOnly']) { - return; - } - $this->addValues($abs); - $obj = $abs->getSubject(); - if (\is_object($obj)) { - $this->addDebug($abs); // use __debugInfo() values if useDebugInfo' && method exists - } - $this->crate($abs); - } - - /** - * Build property info by passing values - * - * @param array $values Values to apply - * - * @return array - */ - public static function buildValues($values = array()) - { - return \array_merge(static::$basePropInfo, $values); - } - - /** - * Add/Update properties with info from __debugInfo method - * - * @param Abstraction $abs Object Abstraction instance - * - * @return void - */ - private function addDebug(Abstraction $abs) - { - if (!$abs['collectPropertyValues']) { - return; - } - if (!$abs['viaDebugInfo']) { - // using __debugInfo is disabled, or object does not have __debugInfo method - return; - } - $obj = $abs->getSubject(); - // temporarily store __debugInfo values in abstraction - $abs['debugInfo'] = \call_user_func(array($obj, '__debugInfo')); - $properties = $this->addDebugWalk($abs); - /* - What remains in debugInfo are __debugInfo only values - */ - foreach ($abs['debugInfo'] as $name => $value) { - $properties[$name] = static::buildValues(array( - 'value' => $value, - 'valueFrom' => 'debugInfo', - 'visibility' => 'debug', // indicates this "property" is exclusive to debugInfo - )); - } - $abs['properties'] = $properties; - unset($abs['debugInfo']); - } - - /** - * Iterate over properties to set value & valueFrom - * - * @param Abstraction $abs Object Abstraction instance - * - * @return array - */ - private function addDebugWalk(Abstraction $abs) - { - $debugInfo = $abs['debugInfo']; - $keys = \array_keys($abs['properties']); - $properties = \array_map(static function ($info, $name) use ($abs, &$debugInfo) { - if (\array_key_exists($name, $abs['propertyOverrideValues'])) { - // we're using override value - return $info; - } - if (\array_key_exists($name, $debugInfo)) { - if ($debugInfo[$name] !== $info['value']) { - $info['value'] = $debugInfo[$name]; - $info['valueFrom'] = 'debugInfo'; - } - return $info; - } - $isInherited = $info['declaredLast'] && $info['declaredLast'] !== $abs['className']; - $isPrivateAncestor = \in_array('private', (array) $info['visibility'], true) - && $isInherited; - $info['debugInfoExcluded'] = $isPrivateAncestor === false; - return $info; - }, $abs['properties'], $keys); - $properties = \array_combine($keys, $properties); - $abs['debugInfo'] = \array_diff_key($debugInfo, $properties); - return $properties; - } - - /** - * Add property values - * - * @param Abstraction $abs Object Abstraction instance - * - * @return void - */ - private function addValues(Abstraction $abs) - { - $properties = $abs['properties']; - $valuedProps = array(); - $this->traverseAncestors($abs['reflector'], function (ReflectionClass $reflector) use ($abs, &$properties, &$valuedProps) { - $className = $this->helper->getClassName($reflector); - foreach ($reflector->getProperties() as $refProperty) { - $name = $refProperty->getName(); - if (\in_array($name, $valuedProps, true)) { - continue; - } - $valuedProps[] = $name; - $propInfo = isset($properties[$name]) - ? $properties[$name] // defined in class - : $this->buildViaRef($abs, $refProperty); // dynamic - $properties[$name] = $this->addValuesPropInfo($abs, $refProperty, $propInfo, $className); - } - }); - $abs['properties'] = $properties; - } - - /** - * Update property info with current value / declaration info - * - * @param Abstraction $abs Object Abstraction instance - * @param ReflectionProperty $refProperty ReflectionProperty instance - * @param array $propInfo Property info - * @param string $className Current level className - * - * @return array updated property info - */ - private function addValuesPropInfo(Abstraction $abs, ReflectionProperty $refProperty, array $propInfo, $className) - { - if ($abs['isAnonymous'] && $refProperty->isDefault() && $className === $abs['className']) { - // Necessary for anonymous classes - $propInfo = $this->updateDeclarationVals( - $propInfo, - $this->helper->getClassName($refProperty->getDeclaringClass()), - $className - ); - } - if ($abs['collectPropertyValues']) { - $propInfo = $this->addValue($propInfo, $abs, $refProperty); - } - return $propInfo; - } - - /** - * Add 'value' and 'valueFrom' values to property info - * - * @param array $propInfo propInfo array - * @param Abstraction $abs Object Abstraction instance - * @param ReflectionProperty $refProperty ReflectionProperty - * - * @return array updated propInfo - */ - private function addValue(array $propInfo, Abstraction $abs, ReflectionProperty $refProperty) - { - $obj = $abs->getSubject(); - $propName = $refProperty->getName(); - if (\array_key_exists($propName, $abs['propertyOverrideValues'])) { - $propInfo['valueFrom'] = 'debug'; - $value = $abs['propertyOverrideValues'][$propName]; - if (\is_array($value) && \array_intersect_key($value, static::$basePropInfo)) { - return \array_merge($propInfo, $value); - } - $propInfo['value'] = $value; - } elseif (\is_object($obj)) { - $propInfo = $this->addValueInstance($propInfo, $abs, $refProperty); - } - return $propInfo; - } - - /** - * Obtain property value from instance - * - * @param array $propInfo propInfo array - * @param Abstraction $abs Object Abstraction instance - * @param ReflectionProperty $refProperty ReflectionProperty - * - * @return array updated propInfo - */ - private function addValueInstance(array $propInfo, Abstraction $abs, ReflectionProperty $refProperty) - { - $obj = $abs->getSubject(); - $refProperty->setAccessible(true); // only accessible via reflection - $isInitialized = PHP_VERSION_ID < 70400 || $refProperty->isInitialized($obj); - \set_error_handler(static function ($errType) use (&$propInfo) { - // example: DOMDocument::$actualEncoding raises a deprecation notice when accessed - if ($errType & (E_DEPRECATED | E_USER_DEPRECATED)) { - $propInfo['isDeprecated'] = true; - } - }); - $propInfo['value'] = $isInitialized - ? $refProperty->getValue($obj) - : Abstracter::UNDEFINED; // value won't be displayed - \restore_error_handler(); - return $propInfo; - } - /** * Adds properties to abstraction via reflection * @@ -355,31 +154,30 @@ private function addViaRef(Abstraction $abs) * * @param Abstraction $abs Object Abstraction instance * @param ReflectionProperty $refProperty ReflectionProperty instance + * @param bool $isDynamic (false) Is property dynamic or defined in class * * @return array */ - private function buildViaRef(Abstraction $abs, ReflectionProperty $refProperty) + protected function buildViaRef(Abstraction $abs, ReflectionProperty $refProperty, $isDynamic = false) { $phpDoc = $this->helper->getPhpDocVar($refProperty, $abs['fullyQualifyPhpDocType']); $refProperty->setAccessible(true); // only accessible via reflection - $type = $this->helper->getType($phpDoc['type'], $refProperty); - unset($phpDoc['type']); return static::buildValues(array( 'attributes' => $abs['cfgFlags'] & AbstractObject::PROP_ATTRIBUTE_COLLECT ? $this->helper->getAttributes($refProperty) : array(), + 'hooks' => PHP_VERSION_ID >= 80400 && $isDynamic === false // https://github.com/php/php-src/issues/15718 + ? \array_keys($refProperty->getHooks()) + : array(), 'isDeprecated' => isset($phpDoc['deprecated']), // if inspecting an instance, // we will also check if ReflectionProperty::getValue throws a deprecation notice - 'isPromoted' => PHP_VERSION_ID >= 80000 - ? $refProperty->isPromoted() - : false, - 'isReadOnly' => PHP_VERSION_ID >= 80100 - ? $refProperty->isReadOnly() - : false, + 'isPromoted' => PHP_VERSION_ID >= 80000 && $refProperty->isPromoted(), + 'isReadOnly' => PHP_VERSION_ID >= 80100 && $refProperty->isReadOnly(), 'isStatic' => $refProperty->isStatic(), + 'isVirtual' => PHP_VERSION_ID >= 80400 && $refProperty->isVirtual(), // at least one hook and none of the hooks reference the property 'phpDoc' => $phpDoc, - 'type' => $type, - 'visibility' => $this->helper->getVisibility($refProperty), + 'type' => $this->helper->getType($phpDoc['type'], $refProperty), + 'visibility' => $this->getVisibility($refProperty), )); } @@ -390,7 +188,7 @@ private function buildViaRef(Abstraction $abs, ReflectionProperty $refProperty) * * @return void */ - private function crate(Abstraction $abs) + protected function crate(Abstraction $abs) { $keys = array(); $properties = $abs['properties']; @@ -403,9 +201,28 @@ private function crate(Abstraction $abs) $name = $md5; } $info['value'] = $this->abstracter->crate($info['value'], $abs['debugMethod'], $abs['hist']); + unset($info['phpDoc']['type']); $properties[$name] = $info; } $abs['keys'] = $keys; $abs['properties'] = $properties; } + + /** + * Get constant/method/property visibility + * + * @param Reflector $reflector Reflection instance + * + * @return list + */ + protected static function getVisibility(Reflector $reflector) + { + $visibility = (array) parent::getVisibility($reflector); + if (PHP_VERSION_ID >= 80400 && $reflector->isPrivateSet()) { + $visibility[] = 'private-set'; + } elseif (PHP_VERSION_ID >= 80400 && $reflector->isProtectedSet()) { + $visibility[] = 'protected-set'; + } + return $visibility; + } } diff --git a/src/Debug/Abstraction/Object/PropertiesInstance.php b/src/Debug/Abstraction/Object/PropertiesInstance.php new file mode 100644 index 00000000..aa325276 --- /dev/null +++ b/src/Debug/Abstraction/Object/PropertiesInstance.php @@ -0,0 +1,254 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @copyright 2014-2024 Brad Kent + * @since 3.3 Split from Properties + */ + +namespace bdk\Debug\Abstraction\Object; + +use bdk\Debug\Abstraction\Abstracter; +use bdk\Debug\Abstraction\Abstraction; +use bdk\Debug\Abstraction\AbstractObject; +use Error; +use ReflectionClass; +use ReflectionProperty; + + /** + * Get object property info + */ +class PropertiesInstance extends Properties +{ + /** + * Add property instance info/values to abstraction + * + * @param Abstraction $abs Object Abstraction instance + * + * @return void + */ + public function add(Abstraction $abs) + { + if ($abs['isTraverseOnly']) { + return; + } + $this->addValues($abs); + $obj = $abs->getSubject(); + if (\is_object($obj)) { + $this->addDebug($abs); // use __debugInfo() values if useDebugInfo' && method exists + } + $this->crate($abs); + } + + /** + * Add/Update properties with info from __debugInfo method + * + * @param Abstraction $abs Object Abstraction instance + * + * @return void + */ + private function addDebug(Abstraction $abs) + { + if (!$abs['collectPropertyValues']) { + return; + } + if (!$abs['viaDebugInfo']) { + // using __debugInfo is disabled, or object does not have __debugInfo method + return; + } + $obj = $abs->getSubject(); + // temporarily store __debugInfo values in abstraction + $abs['debugInfo'] = \call_user_func(array($obj, '__debugInfo')); + $properties = $this->addDebugWalk($abs); + /* + What remains in debugInfo are __debugInfo only values + */ + foreach ($abs['debugInfo'] as $name => $value) { + $properties[$name] = static::buildValues(array( + 'value' => $value, + 'valueFrom' => 'debugInfo', + 'visibility' => ['debug'], // indicates this "property" is exclusive to debugInfo + )); + } + $abs['properties'] = $properties; + unset($abs['debugInfo']); + } + + /** + * Iterate over properties to set value & valueFrom + * + * @param Abstraction $abs Object Abstraction instance + * + * @return array + */ + private function addDebugWalk(Abstraction $abs) + { + $debugInfo = $abs['debugInfo']; + $keys = \array_keys($abs['properties']); + $properties = \array_map(static function ($info, $name) use ($abs, &$debugInfo) { + if (\array_key_exists($name, $abs['propertyOverrideValues'])) { + // we used override value + return $info; + } + if (\array_key_exists($name, $debugInfo)) { + if ($debugInfo[$name] !== $info['value']) { + $info['value'] = $debugInfo[$name]; + $info['valueFrom'] = 'debugInfo'; + } + return $info; + } + $isInherited = $info['declaredLast'] && $info['declaredLast'] !== $abs['className']; + $isPrivateAncestor = \in_array('private', (array) $info['visibility'], true) + && $isInherited; + $info['debugInfoExcluded'] = $isPrivateAncestor === false; + return $info; + }, $abs['properties'], $keys); + $properties = \array_combine($keys, $properties); + $abs['debugInfo'] = \array_diff_key($debugInfo, $properties); + return $properties; + } + + /** + * Add property values + * + * @param Abstraction $abs Object Abstraction instance + * + * @return void + */ + private function addValues(Abstraction $abs) + { + $properties = $abs['properties']; + $valuedProps = array(); + $this->traverseAncestors($abs['reflector'], function (ReflectionClass $reflector) use ($abs, &$properties, &$valuedProps) { + $className = $this->helper->getClassName($reflector); + foreach ($reflector->getProperties() as $refProperty) { + $name = $refProperty->getName(); + if (\in_array($name, $valuedProps, true)) { + continue; + } + $valuedProps[] = $name; + $propInfo = isset($properties[$name]) + ? $properties[$name] // defined in class + : $this->buildViaRef($abs, $refProperty, true); // dynamic + $properties[$name] = $this->processProperty($abs, $refProperty, $propInfo, $className); + } + }); + $abs['properties'] = $properties; + } + + /** + * Update property info with current value / declaration info + * + * @param Abstraction $abs Object Abstraction instance + * @param ReflectionProperty $refProperty ReflectionProperty instance + * @param array $propInfo Property info + * @param string $className Current level className + * + * @return array updated property info + */ + private function processProperty(Abstraction $abs, ReflectionProperty $refProperty, array $propInfo, $className) + { + if ($abs['isAnonymous'] && $refProperty->isDefault() && $className === $abs['className']) { + // Necessary for anonymous classes + $propInfo = $this->updateDeclarationVals( + $propInfo, + $this->helper->getClassName($refProperty->getDeclaringClass()), + $className + ); + } + return $this->addValue($propInfo, $abs, $refProperty); + } + + /** + * Add 'value' and 'valueFrom' values to property info + * + * @param array $propInfo propInfo array + * @param Abstraction $abs Object Abstraction instance + * @param ReflectionProperty $refProperty ReflectionProperty + * + * @return array updated property info + */ + private function addValue(array $propInfo, Abstraction $abs, ReflectionProperty $refProperty) + { + $obj = $abs->getSubject(); + $propName = $refProperty->getName(); + if (\array_key_exists($propName, $abs['propertyOverrideValues'])) { + return $this->mergeOverrideValue($propInfo, $abs['propertyOverrideValues'][$propName]); + } + if ($abs['collectPropertyValues'] === false) { + return $propInfo; + } + if (\is_object($obj) === false) { + return $propInfo; + } + \set_error_handler(static function ($errType) use (&$propInfo) { + // example: `DOMDocument::$actualEncoding` raises a deprecation notice when accessed + if ($errType & (E_DEPRECATED | E_USER_DEPRECATED)) { + $propInfo['isDeprecated'] = true; + } + return true; + }); + try { + $propInfo['value'] = $this->valueFromReflection($propInfo, $abs, $refProperty); + } catch (Error $e) { + // https://github.com/php/php-src/issues/15694 + // $refProperty->isInitialized() returns true if property has a get hook + // yet getRawValue() may throw "Typed property CLassName::$property must not be accessed before initialization" + } + \restore_error_handler(); + return $propInfo; + } + + /** + * Use propertyOverrideValue for value or propInfo + * + * @param array $propInfo propInfo array + * @param mixed $overrideValue override value (or propInfo array values) + * + * @return array + */ + private function mergeOverrideValue(array $propInfo, $overrideValue) + { + $propInfo['valueFrom'] = 'debug'; + if (\is_array($overrideValue) && \array_intersect_key($overrideValue, static::$values)) { + return \array_merge($propInfo, $overrideValue); + } + $propInfo['value'] = $overrideValue; + return $propInfo; + } + + /** + * Obtain property value via `getRawValue` or `getValue` + * + * @param array $propInfo propInfo array + * @param Abstraction $abs Object Abstraction instance + * @param ReflectionProperty $refProperty ReflectionProperty + * + * @return mixed property value + */ + private function valueFromReflection(array $propInfo, Abstraction $abs, ReflectionProperty $refProperty) + { + $refProperty->setAccessible(true); // only accessible via reflection + $obj = $abs->getSubject(); + if ($propInfo['isVirtual']) { + if (\in_array('get', $propInfo['hooks'], true) === false) { + // virtual property with no getter = write-only + return $propInfo['value']; // undefined + } elseif ($abs['cfgFlags'] & AbstractObject::PROP_VIRTUAL_VALUE_COLLECT) { + return $refProperty->getValue($obj); + } + return Abstracter::NOT_INSPECTED; + } + if ($refProperty->isInitialized($obj) === false) { + return $propInfo['value']; // undefined + } + if (PHP_VERSION_ID >= 80400 && $propInfo['isStatic'] === false) { + return $refProperty->getRawValue($obj); + } + return $refProperty->getValue($obj); + } +} diff --git a/src/Debug/Abstraction/Object/PropertiesPhpDoc.php b/src/Debug/Abstraction/Object/PropertiesPhpDoc.php index 50eb306a..1019c847 100644 --- a/src/Debug/Abstraction/Object/PropertiesPhpDoc.php +++ b/src/Debug/Abstraction/Object/PropertiesPhpDoc.php @@ -144,8 +144,8 @@ private function buildViaPhpDoc(Abstraction $abs, $phpDocProp, $declaredLast, $v ), 'type' => $phpDocProp['type'], 'visibility' => $existing - ? array($vis, $existing['visibility']) // we want "magic" visibility first - : $vis, + ? \array_merge((array) $vis, (array) $existing['visibility']) // we want "magic" visibility first + : (array) $vis, ) ); } diff --git a/src/Debug/Abstraction/Object/Subscriber.php b/src/Debug/Abstraction/Object/Subscriber.php index 8fc30ffa..8fb9d463 100644 --- a/src/Debug/Abstraction/Object/Subscriber.php +++ b/src/Debug/Abstraction/Object/Subscriber.php @@ -197,13 +197,13 @@ private function onStartClosure(Abstraction $abs) 'type' => Type::TYPE_STRING, 'value' => $abs['definition']['fileName'], 'valueFrom' => 'debug', - 'visibility' => 'debug', + 'visibility' => ['debug'], )); $properties['debug.line'] = $this->abstractObject->properties->buildValues(array( 'type' => Type::TYPE_INT, 'value' => (int) $abs['definition']['startLine'], 'valueFrom' => 'debug', - 'visibility' => 'debug', + 'visibility' => ['debug'], )); $abs['properties'] = $properties; } diff --git a/src/Debug/Config.php b/src/Debug/Config.php index ceba00e4..37b172d2 100644 --- a/src/Debug/Config.php +++ b/src/Debug/Config.php @@ -63,6 +63,7 @@ class Config 'phpDocOutput', 'propAttributeCollect', 'propAttributeOutput', + 'propVirtualValueCollect', 'stringMaxLen', 'stringMaxLenBrief', 'stringMinLen', diff --git a/src/Debug/Dump/Html/Object/Properties.php b/src/Debug/Dump/Html/Object/Properties.php index 1a7963bb..775469bb 100644 --- a/src/Debug/Dump/Html/Object/Properties.php +++ b/src/Debug/Dump/Html/Object/Properties.php @@ -53,14 +53,19 @@ protected function getClasses(array $info) 'debuginfo-excluded' => $info['debugInfoExcluded'], 'debuginfo-value' => $info['valueFrom'] === 'debugInfo', 'forceShow' => $info['forceShow'], + 'getHook' => \in_array('get', $info['hooks'], true), + 'isDeprecated' => $info['isDeprecated'], 'isDynamic' => $info['declaredLast'] === null && $info['valueFrom'] === 'value' && $info['objClassName'] !== 'stdClass', 'isPromoted' => $info['isPromoted'], 'isReadOnly' => $info['isReadOnly'], 'isStatic' => $info['isStatic'], + 'isVirtual' => $info['isVirtual'], + 'isWriteOnly' => $info['isVirtual'] && \in_array('get', $info['hooks'], true) === false, 'private-ancestor' => $info['isPrivateAncestor'], 'property' => true, + 'setHook' => \in_array('set', $info['hooks'], true), ))); return \array_merge($classes, $visClasses); } diff --git a/src/Debug/Framework/Yii1_1/LogRoute.php b/src/Debug/Framework/Yii1_1/LogRoute.php index 0583d6da..00fe1296 100644 --- a/src/Debug/Framework/Yii1_1/LogRoute.php +++ b/src/Debug/Framework/Yii1_1/LogRoute.php @@ -295,16 +295,11 @@ private function processSqlCachingLogEntry(array $logEntry) // collect is/was off? return true; } + $debug = $groupLogEntry->getSubject(); $returnValue = 'saved to cache'; - if (\strpos($logEntry['message'], 'Serving') === 0) { - $regEx = '/^Serving "yii:dbquery:\S+:\S*:\S+:(.*?)(?::(a:\d+:\{.*\}))?" from cache$/s'; - \preg_match($regEx, $logEntry['message'], $matches); - $statementInfo = new StatementInfo($matches[1], $matches[2] ? \unserialize($matches[2]) : array()); - $statementInfo->appendLog($debug, array( - 'attribs' => array('class' => 'logentry-muted'), - )); + $this->processSqlCachingLogEntryServe($logEntry, $debug); $groupId = StatementInfo::lastGroupId(); $returnValue = 'from cache'; } @@ -325,6 +320,24 @@ private function processSqlCachingLogEntry(array $logEntry) return true; } + /** + * If we have a "Serving" log entry, process it as a statementInfo log entry + * + * @param array $logEntry our key/value'd log entry + * @param Debug $debug Debug instance + * + * @return void + */ + private function processSqlCachingLogEntryServe(array $logEntry, Debug $debug) + { + $regEx = '/^Serving "yii:dbquery:\S+:\S*:\S+:(.*?)(?::(a:\d+:\{.*\}))?" from cache$/s'; + \preg_match($regEx, $logEntry['message'], $matches); + $statementInfo = new StatementInfo($matches[1], $matches[2] ? \unserialize($matches[2]) : array()); + $statementInfo->appendLog($debug, array( + 'attribs' => array('class' => 'logentry-muted'), + )); + } + /** * Process Yii log entry * diff --git a/src/Debug/Plugin/Channel.php b/src/Debug/Plugin/Channel.php index f3524823..1ae21542 100644 --- a/src/Debug/Plugin/Channel.php +++ b/src/Debug/Plugin/Channel.php @@ -44,6 +44,8 @@ class Channel implements SubscriberInterface * @param array $config channel specific configuration * * @return Debug new or existing `Debug` instance + * + * @since 2.3 */ public function getChannel($name, $config = array()) { diff --git a/src/Debug/Plugin/Method/Alert.php b/src/Debug/Plugin/Method/Alert.php index ab91c066..b3157275 100644 --- a/src/Debug/Plugin/Method/Alert.php +++ b/src/Debug/Plugin/Method/Alert.php @@ -56,6 +56,10 @@ public function __construct() * @param bool $dismissible (false) Whether to display a close icon/button * * @return \bdk\Debug + * + * @since 2.0 + * @since 3.0 danger & warning levels replaced with error & warn + * @since 3.3 Now accepts arbitrary arguments (like log, info, warn, & error) */ public function alert($message, $level = 'error', $dismissible = false) { diff --git a/src/Debug/Plugin/Method/Basic.php b/src/Debug/Plugin/Method/Basic.php index bbbb550c..81102312 100644 --- a/src/Debug/Plugin/Method/Basic.php +++ b/src/Debug/Plugin/Method/Basic.php @@ -51,6 +51,9 @@ class Basic implements SubscriberInterface * if none provided, will use calling file & line num * * @return Debug + * + * 2.0 Default message used if none passed + * 2.3 Support for substitution & formatting */ public function assert($assertion, $msg = null) { @@ -88,6 +91,9 @@ public function assert($assertion, $msg = null) * @param mixed ...$arg message / values * * @return Debug + * + * @since 3.0 first param now gets `htmlspecialchar()`'d by default + * use `meta('sanitizeFirst', false)` to allow html */ public function error() { @@ -103,6 +109,9 @@ public function error() * @param mixed ...$arg message / values * * @return Debug + * + * @since 3.0 first param now gets `htmlspecialchar()`'d by default + * use `meta('sanitizeFirst', false)` to allow html */ public function info() { @@ -133,6 +142,9 @@ public function getSubscriptions() * @param mixed ...$arg. message / values * * @return Debug + * + * @since 3.0 first param now gets `htmlspecialchar()`'d by default + * use `meta('sanitizeFirst', false)` to allow html */ public function log() { @@ -179,6 +191,8 @@ public function onBootstrap(Event $event) * @param mixed ...$arg. message / values * * @return void + * + * @since 3.1 */ public function varDump() { @@ -211,6 +225,9 @@ public function varDump() * @param mixed ...$arg message / values * * @return Debug + * + * @since 3.0 first param now gets `htmlspecialchar()`'d by default + * use `meta('sanitizeFirst', false)` to allow html */ public function warn() { diff --git a/src/Debug/Plugin/Method/Clear.php b/src/Debug/Plugin/Method/Clear.php index 5fdace4b..fdd6550d 100644 --- a/src/Debug/Plugin/Method/Clear.php +++ b/src/Debug/Plugin/Method/Clear.php @@ -68,6 +68,8 @@ public function __construct() * `self::CLEAR_SILENT` : Don't add log entry * * @return Debug + * + * @since 2.2 */ public function clear($bitmask = Debug::CLEAR_LOG) // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter { diff --git a/src/Debug/Plugin/Method/Count.php b/src/Debug/Plugin/Method/Count.php index 68e5e585..42164596 100644 --- a/src/Debug/Plugin/Method/Count.php +++ b/src/Debug/Plugin/Method/Count.php @@ -55,6 +55,8 @@ public function __construct() * `\bdk\Debug::COUNT_NO_OUT` : don't output/log * * @return int The new count (or current count when using `COUNT_NO_INC`) + * + * @since 2.1 `$flags` argument added */ public function count($label = null, $flags = 0) { @@ -75,6 +77,8 @@ public function count($label = null, $flags = 0) * \bdk\Debug::COUNT_NO_OUT` : don't output/log * * @return Debug + * + * @since 2.3 */ public function countReset($label = 'default', $flags = 0) { diff --git a/src/Debug/Plugin/Method/Group.php b/src/Debug/Plugin/Method/Group.php index d80d0575..e0eb3410 100644 --- a/src/Debug/Plugin/Method/Group.php +++ b/src/Debug/Plugin/Method/Group.php @@ -118,7 +118,7 @@ public function group() /** * Create a new inline group * - * Unline `group()`, `groupCollapsed()`, will initially be collapsed + * Unlike `group()`, `groupCollapsed()`, will initially be collapsed * * @param mixed ...$arg label / values * @@ -140,6 +140,8 @@ public function groupCollapsed() * @param mixed $value (optional) "return" value * * @return Debug + * + * @since 2.3 accepts `$value` parameter */ public function groupEnd($value = Abstracter::UNDEFINED) // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter { diff --git a/src/Debug/Plugin/Method/Output.php b/src/Debug/Plugin/Method/Output.php index 84c7c62c..4bde203e 100644 --- a/src/Debug/Plugin/Method/Output.php +++ b/src/Debug/Plugin/Method/Output.php @@ -50,6 +50,9 @@ public function __construct() * @param array $cfg Override any config values * * @return string|null + * + * @since 1.2 explicitly calling output() is no longer necessary.. log will be output automatically via shutdown function + * @since 2.3 `$config` parameter */ public function output($cfg = array()) { diff --git a/src/Debug/Plugin/Method/Profile.php b/src/Debug/Plugin/Method/Profile.php index b903f5b0..7a03c11d 100644 --- a/src/Debug/Plugin/Method/Profile.php +++ b/src/Debug/Plugin/Method/Profile.php @@ -113,6 +113,8 @@ public function onStreamWrap(Event $event) * @param string $name Optional profile name * * @return Debug + * + * @since 2.3 */ public function profile($name = null) // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter { @@ -153,6 +155,8 @@ public function profile($name = null) // @phpcs:ignore Generic.CodeAnalysis.Unus * @param string $name Optional profile name * * @return Debug + * + * @since 2.3 */ public function profileEnd($name = null) // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter { diff --git a/src/Debug/Plugin/Method/ReqRes.php b/src/Debug/Plugin/Method/ReqRes.php index 8979886e..af926314 100644 --- a/src/Debug/Plugin/Method/ReqRes.php +++ b/src/Debug/Plugin/Method/ReqRes.php @@ -55,6 +55,8 @@ public function getSubscriptions() * Get and clear debug headers that need to be output * * @return array headerName => value array + * + * @since 2.3 */ public function getHeaders() { diff --git a/src/Debug/Plugin/Method/Table.php b/src/Debug/Plugin/Method/Table.php index fe1bfa8e..d6d85a5f 100644 --- a/src/Debug/Plugin/Method/Table.php +++ b/src/Debug/Plugin/Method/Table.php @@ -57,6 +57,9 @@ public function __construct() * @param mixed ...$arg traversable, [option array], [caption] in no particular order * * @return Debug + * + * @since 2.0 properly handles array of objects (objects can implement Traversable) + * @since 2.1 properly handles Traversable as param */ public function table() { diff --git a/src/Debug/Plugin/Method/Time.php b/src/Debug/Plugin/Method/Time.php index c41b5af7..290b9bd0 100644 --- a/src/Debug/Plugin/Method/Time.php +++ b/src/Debug/Plugin/Method/Time.php @@ -58,6 +58,8 @@ public function __construct() * @param float $duration (optional) duration (in seconds). Use this param to log a duration obtained externally. * * @return \bdk\Debug + * + * @since 3.0 duration argument added */ public function time($label = null, $duration = null) { @@ -98,6 +100,9 @@ public function time($label = null, $duration = null) * @return \bdk\Debug|float|false The duration (in sec). * * @psalm-return ($return is true ? float|false : \bdk\Debug) + * + * @since 3.0 returnOrTemplate & precision arguments removed. + * New meta options: precision, silent, template, & unit */ public function timeEnd($label = null, $log = true, $return = 'auto') { @@ -130,6 +135,9 @@ public function timeEnd($label = null, $log = true, $return = 'auto') * @return \bdk\Debug|float|false The duration (in sec). `false` if specified label does not exist * * @psalm-return ($return is true ? float|false : \bdk\Debug) + * + * @since 3.0 returnOrTemplate & precision arguments removed. + * New meta options: precision, silent, template, & unit */ public function timeGet($label = null, $log = true, $return = 'auto') { @@ -152,6 +160,8 @@ public function timeGet($label = null, $log = true, $return = 'auto') * @param mixed ...$arg (optional) additional values to be logged with time * * @return \bdk\Debug + * + * @since 2.3 */ public function timeLog($label = null, $args = null) { diff --git a/src/Debug/Plugin/Method/Trace.php b/src/Debug/Plugin/Method/Trace.php index f34ea76c..01455fe0 100644 --- a/src/Debug/Plugin/Method/Trace.php +++ b/src/Debug/Plugin/Method/Trace.php @@ -51,6 +51,8 @@ public function __construct() * @param int $limit (0) limit the number of stack frames returned. By default (limit = 0) all stack frames are collected * * @return Debug + * + * @since 3.3 added limit argument */ public function trace($inclContext = false, $caption = 'trace', $limit = 0) { diff --git a/src/Debug/Route/Html.php b/src/Debug/Route/Html.php index b13a22ee..8515b675 100644 --- a/src/Debug/Route/Html.php +++ b/src/Debug/Route/Html.php @@ -265,9 +265,6 @@ private function buildOutput() protected function buildChannelTree() { $channels = $this->dumper->channels; - if (empty($channels)) { - return array(); - } $tree = array(); $channelRoot = \reset($channels)->rootInstance; \ksort($channels, SORT_NATURAL | SORT_FLAG_CASE); diff --git a/src/Debug/Route/WampHelper.php b/src/Debug/Route/WampHelper.php index 1917216b..63ecceff 100644 --- a/src/Debug/Route/WampHelper.php +++ b/src/Debug/Route/WampHelper.php @@ -10,9 +10,9 @@ * @since 3.3 */ - namespace bdk\Debug\Route; +namespace bdk\Debug\Route; - use bdk\Debug; +use bdk\Debug; /** * WAMP Helper Methods diff --git a/src/Debug/Utility/Php.php b/src/Debug/Utility/Php.php index e77b66ba..91155677 100644 --- a/src/Debug/Utility/Php.php +++ b/src/Debug/Utility/Php.php @@ -34,8 +34,8 @@ class Php * Assert that a value is of a certain type * * PHPDebugConsole supports an extreme range of PHP versions : 5.4 - 8.4 (and beyond) - * `MyObj $obj = null` has been deprecated in PHP 8.4 - * must now be `?MyObj $obj = null` (which is a php 7.1 feature) + * `func(MyObj $obj = null)` has been deprecated in PHP 8.4 + * must now be `func(?MyObj $obj = null)` (which is a php 7.1 feature) * Workaround - remove type-hint when we allow null (not ideal) and call assertType * When we drop support for php < 7.1, we can remove this method and do proper type-hinting * @@ -52,21 +52,7 @@ public static function assertType($value, $type, $allowNull = true) if ($allowNull && $value === null) { return; } - $isType = false; - switch ($type) { - case 'array': - $isType = \is_array($value); - break; - case 'callable': - $isType = self::isCallable($value); - break; - case 'object': - $isType = \is_object($value); - break; - default: - $isType = \is_a($value, $type); - } - if ($isType) { + if (self::assertTypeCheck($value, $type)) { return; } throw new InvalidArgumentException(\sprintf( @@ -107,9 +93,9 @@ public static function friendlyClassName($mixed) * * @see https://github.com/symfony/polyfill/blob/main/src/Php80/Php80.php */ - public static function getDebugType($val) // phpcs:ignore Generic.Metrics.CyclomaticComplexity + public static function getDebugType($val) { - if (PHP_VERSION_ID >= 80000 && \is_array($val) === false && \is_object($val) === false) { + if (PHP_VERSION_ID >= 80000 && \in_array(\gettype($val), ['array', 'object'], true) === false) { return \get_debug_type($val); } @@ -145,7 +131,7 @@ public static function getDebugType($val) // phpcs:ignore Generic.Metrics.Cyclom public static function getIncludedFiles() { $includedFiles = \get_included_files(); - return self::sortFiles($includedFiles); + return \bdk\Debug\Utility::sortFiles($includedFiles); } /** @@ -222,29 +208,7 @@ public static function isThrowable($val) */ public static function memoryLimit() { - $iniVal = \trim(\ini_get('memory_limit') ?: \get_cfg_var('memory_limit')); - return $iniVal ?: '128M'; - } - - /** - * Sort a list of files - * - * @param list $files Files to sort - * - * @return list - */ - public static function sortFiles($files) - { - \usort($files, static function ($valA, $valB) { - $valA = \str_replace('_', '0', $valA); - $valB = \str_replace('_', '0', $valB); - $dirA = \dirname($valA); - $dirB = \dirname($valB); - return $dirA === $dirB - ? \strnatcasecmp($valA, $valB) - : \strnatcasecmp($dirA, $dirB); - }); - return $files; + return \trim(\ini_get('memory_limit') ?: \get_cfg_var('memory_limit')) ?: '128M'; } /** @@ -279,6 +243,29 @@ public static function unserializeSafe($serialized, $allowedClasses = array()) return \unserialize($serialized); } + /** + * Test if value is of a certain type + * + * @param mixed $value Value to test + * @param string $type "array", "callable", "object", or className + * + * @return bool + */ + private static function assertTypeCheck($value, $type) + { + switch ($type) { + case 'array': + return \is_array($value); + case 'callable': + return \is_callable($value); + case 'object': + return \is_object($value); + default: + return \is_a($value, $type); + } + return false; + } + /** * Get friendly class name * @@ -350,10 +337,9 @@ private static function isCallableArray(array $val, $opts) if (\is_object($val[0])) { return self::isCallableArrayObj($val, $opts); } - if ($opts & self::IS_CALLABLE_OBJ_ONLY) { - return false; - } - return self::isCallableArrayString($val, $opts); + return $opts & self::IS_CALLABLE_OBJ_ONLY + ? false + : self::isCallableArrayString($val, $opts); } /** diff --git a/src/Debug/Utility/Table.php b/src/Debug/Utility/Table.php index 9044af4a..41b289bf 100644 --- a/src/Debug/Utility/Table.php +++ b/src/Debug/Utility/Table.php @@ -331,7 +331,7 @@ static function ($info) { * @param array $prop */ static function ($prop) { - return $prop['visibility'] === 'public'; + return \in_array('public', (array) $prop['visibility'], true); } ) ); diff --git a/src/Debug/Utility/TableRow.php b/src/Debug/Utility/TableRow.php index c5c34b74..3c4503bd 100644 --- a/src/Debug/Utility/TableRow.php +++ b/src/Debug/Utility/TableRow.php @@ -191,7 +191,7 @@ static function ($info) { return $info['value']; }, \array_filter($abs['properties'], static function ($prop) { - return $prop['visibility'] === 'public'; + return \in_array('public', (array) $prop['visibility'], true); }) ); /* diff --git a/src/Debug/Utility/Utility.php b/src/Debug/Utility/Utility.php index 9b03a8a0..cfbce9b4 100644 --- a/src/Debug/Utility/Utility.php +++ b/src/Debug/Utility/Utility.php @@ -257,6 +257,27 @@ public static function isFile($val) return \is_file($val); } + /** + * Sort a list of files + * + * @param list $files Files to sort + * + * @return list + */ + public static function sortFiles($files) + { + \usort($files, static function ($valA, $valB) { + $valA = \str_replace('_', '0', $valA); + $valB = \str_replace('_', '0', $valB); + $dirA = \dirname($valA); + $dirB = \dirname($valB); + return $dirA === $dirB + ? \strnatcasecmp($valA, $valB) + : \strnatcasecmp($dirA, $dirB); + }); + return $files; + } + /** * Emit a header * diff --git a/src/Debug/css/Debug.css b/src/Debug/css/Debug.css index 714087fa..1573cf22 100644 --- a/src/Debug/css/Debug.css +++ b/src/Debug/css/Debug.css @@ -1 +1 @@ -.debug{font-size:13px}.debug{position:relative;clear:both;font-family:Arial,"Helvetica Neue",Helvetica,sans-serif;line-height:normal;text-align:left;text-shadow:none;color:#111}.debug *{font-size:inherit;line-height:normal;text-indent:0;color:inherit;margin:0}.debug *:not(i[class^=fa]){font-family:inherit}.debug a{text-decoration:none;color:#00e}.debug a:visited{color:#551a8b}.debug a:focus,.debug a:hover{border-bottom:1px dotted blue}.debug a:active,.debug a:hover{outline:0;color:#e00}.debug a.file-link{color:inherit}.debug button{color:inherit;cursor:pointer;background-color:#f0f0f0;border-color:#afafaf;font-weight:inherit;height:auto;letter-spacing:initial;line-height:initial;outline:none;padding:1px 7px 2px;text-align:center;text-transform:none;vertical-align:baseline;white-space:initial}.debug button:hover{background-color:#dde6f0}.debug code{padding:2px 4px;background-color:transparent;font-family:Menlo, Monaco, Consolas, "Courier New", monospace !important}.debug pre code{display:block}.debug,.debug div{margin:0;width:auto;height:auto;padding:0;background-color:transparent;border-radius:0}.debug dl{margin-top:0;margin-bottom:0}.debug dl dt{font-weight:bold}.debug dl.dl-horizontal{display:grid;grid-template-columns:max-content auto}.debug dl.dl-horizontal>dt{grid-column:1;text-align:right;width:auto}.debug dl.dl-horizontal>dd{grid-column:2;margin-left:0.75em}.debug dl:not(.dl-horizontal)>dd{margin-left:20px;padding-left:10px;text-indent:-10px}.debug dl:not(.dl-horizontal)>dd>ul{margin-left:-10px}.debug li.no-indent{padding-left:0;text-indent:0}.debug h3{margin-top:0.66em;margin-bottom:0.5em;font-size:1.15em;font-weight:bold}.debug h3:first-child{margin-top:0}.debug hr{color:#111;background-color:#111;border:0;height:1px}.debug img{border:0}.debug input{border-width:1px}.debug input[type=checkbox]{margin:0 0.33em 0 0;cursor:pointer}.debug label{display:block;margin:0;cursor:pointer;font-weight:bold;max-width:none}.debug label.disabled{cursor:default;pointer-events:none}.debug legend{padding:0;float:left;margin-bottom:0.5em;border:0;width:100%;font-size:144%;font-weight:bold}.debug p{margin-top:0.25em;margin-bottom:0}.debug p:first-child{margin-top:0}.debug pre{padding:0;border:0;margin:0;white-space:pre;-moz-tab-size:3;-o-tag-size:3;-tab-size:3}.debug ul{margin-top:0;margin-bottom:0}.debug ul.list-unstyled{list-style:none outside none;padding-left:0}.debug ul.list-unstyled>li{text-indent:-1em;padding-left:1em}.debug ul.list-unstyled>ul{margin-left:10px}.debug ul.no-indent>li{padding-left:0;text-indent:0}.debug fieldset{padding:0.66em;margin:0 0 10px 0;min-width:0;border:1px solid black;border-radius:4px}.debug fieldset>ul{font-size:125%}.debug .close{opacity:1;float:none}.debug ul.debug-log-summary+hr{border-top:1px dotted;background-color:transparent;margin:.5em 0}.debug .tab-pane>*>.group-body,.debug .m_groupSummary>ul{list-style:none;margin-left:0;border-left:0;padding-left:0}.debug li.php-shutdown{display:block;border-bottom:#31708f solid 1px}.debug .fa{line-height:1}.debug .alert,.debug .m_alert{padding:0.66em;margin-bottom:10px;border-radius:4px;border:1px solid transparent}.debug .m_alert{font-size:125%}.debug .m_alert h3{margin-bottom:4px}.debug .m_alert h3:last-child{margin-bottom:0}.debug .m_alert.error-summary .filter-hidden+h3{margin-top:0}.debug .m_alert.alert-dismissible{padding-right:35px}.debug .m_alert.alert-dismissible .close{float:right;position:relative;top:-7px;right:-21px;border:0;padding:0;font-size:21px;font-weight:700;line-height:1;background:none;color:#000;text-shadow:0 1px 0 #fff;opacity:0.2;cursor:pointer}.debug .m_alert.alert-dismissible .close:hover{text-decoration:none;opacity:0.5}.debug .m_alert .alert-link{font-weight:bold}.debug .alert-error{background-color:#ffbaba;border-color:#d8000c;color:#d8000c}.debug .alert-error .alert-link{color:#843534}.debug .alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.debug .alert-info .alert-link{color:#245269}.debug .alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.debug .alert-success .alert-link{color:#2b542c}.debug .alert-warn{background-color:#fefbe5;border-color:#faebcc;color:#8a6d3b}.debug .alert-warn .alert-link{color:#66512c}.debug nav[role=tablist]{display:inline-block;font-size:0;line-height:20px;vertical-align:top}.debug nav[role=tablist] .fa{margin-right:0.5em}.debug nav[role=tablist] a{display:inline-block;padding:0 13px;font-size:13px;line-height:20px;vertical-align:top;color:#111;cursor:pointer}.debug nav[role=tablist] a:hover{text-decoration:none}.debug nav[role=tablist] a:hover:not(.active){background:#e6e6e6}.debug nav[role=tablist] a.active{line-height:19px;border-bottom:#4071e1 solid 2px}.debug .tab-panes{overflow:auto}.debug .tab-panes .tab-pane{position:static;display:none}.debug .tab-panes .tab-pane.active{display:block}.debug .tab-panes .tab-pane .tab-body{padding:10px 12px 5px;background-color:#fff;overflow:auto}.debug .namespace{opacity:0.5}.debug .array-inner,.debug .object-inner{display:block;margin-left:1em}.debug .classname{font-weight:bold;color:color-mix(in lch, currentColor, #8d0c4c)}.debug .attribute .t_punct{color:inherit;font-weight:bold}.debug .t_parameter-name{color:#263}.debug .t_array>.t_array-collapse,.debug .t_array>.array-inner,.debug .t_array>.t_punct{display:none}.debug .t_array.expanded>.t_array-expand{display:none}.debug .t_array.expanded>.t_array-collapse,.debug .t_array.expanded>.t_punct{display:inline}.debug .t_array.expanded>.array-inner{display:block}.debug .t_array.array-file-tree .array-inner{margin-left:0.25em}.debug .t_array.array-file-tree .exclude-count{background:#d9edf7;color:#31708f}.debug .t_array.array-file-tree .t_key{color:#000040;font-weight:bold}.debug .t_array.array-file-tree .t_string::before,.debug .t_array.array-file-tree .t_string::after,.debug .t_array.array-file-tree .t_key::before,.debug .t_array.array-file-tree .t_key::after{display:none}.debug .array-inner>li>.t_operator{margin:0 0.25em}.debug li[class*=m_]>.t_array.array-file-tree>.array-inner{margin-left:-10px}.debug .t_object{display:inline}.debug .t_object h3{margin:0;font-size:inherit;font-style:italic;color:purple}.debug .t_object .t_modifier_abstract,.debug .t_object i.fa-circle-o{font-weight:bold;color:#9d2d2d}.debug .t_object .t_modifier_debug{color:rgba(0,11,155,0.933333)}.debug .t_object .t_modifier_final{color:rgba(255,0,0,0.933333);font-weight:bold}.debug .t_object .t_modifier_private{color:rgba(0,0,0,0.509804)}.debug .t_object .t_modifier_protected{color:rgba(0,0,0,0.776471)}.debug .t_object .t_modifier_public{color:inherit}.debug .t_object .t_modifier_static{font-style:italic;color:rgba(218,13,135,0.933333)}.debug .t_object>.object-inner>.modifiers{display:none}.debug .t_object>.object-inner>dd[class*=t_modifier_]{display:inline-block;margin-left:0;margin-right:0.5em;border-style:solid;border-width:1px;border-radius:4px;padding:0 .75em;height:1.75em;text-indent:0;line-height:1.5;font-weight:bold}.debug .t_object>.object-inner>.t_modifier_abstract{color:#333;background-color:#e6e6e6;border-color:#666}.debug .t_object>.object-inner>.t_modifier_final{color:#d8000c;background-color:#ffeded;border-color:#d8000c}.debug .t_object>.object-inner>.t_modifier_interface{color:#31708f;background-color:#d9edf7;border-color:#31708f}.debug .t_object>.object-inner>.t_modifier_readonly{color:#8a6d3b;background-color:#fefbe5;border-color:#8a6d3b}.debug .t_object>.object-inner>.t_modifier_readonly .fa-stack{font-size:0.8em;margin-right:0.33em}.debug .t_object>.object-inner>.t_modifier_readonly .fa-stack .fa-ban{opacity:0.75}.debug .t_object>.object-inner .heading{color:#4f16b0;text-decoration:underline;font-weight:bold}.debug .t_object .vis-toggles *[data-toggle]{padding:0.15em 0.5em;display:inline-block}.debug .t_object dd+.vis-toggles{margin-top:.25em}.debug .t_object .method .parameter .t_parameter-name[title],.debug .t_object .t_identifier[title],.debug .t_object .t_type[title]{border-bottom:1px dashed blue}.debug .t_object .method ul{margin-left:15px}.debug .t_object .method.deprecated{opacity:0.66}.debug .t_object .method.deprecated i{opacity:0.66;color:#d8000c;border-bottom:0}.debug .t_object .method>.t_punct:not(.t_colon){opacity:1;font-weight:bold;color:inherit}.debug .t_object .method i.fa-clone{color:#999}.debug .t_object .private-ancestor:not(:hover)>*{opacity:0.5}.debug .t_object .private-ancestor:not(:hover)>.fa-lock,.debug .t_object .private-ancestor:not(:hover)>.t_modifier_private{opacity:1}.debug .t_object i.fa-flag,.debug .t_object i.fa-warning{color:red}.debug .t_object i.fa-eye{color:rgba(0,11,155,0.933333);font-size:1.1em;border-bottom:0}.debug .t_object i.fa-magic,.debug .t_object .t_modifier_magic,.debug .t_object .t_modifier_magic-read,.debug .t_object .t_modifier_magic-write{color:rgba(255,136,0,0.933333)}.debug .t_object .debugInfo-excluded>i.fa-eye-slash{color:#999}.debug .t_object .info{display:inline-block;background-color:#d9edf7;color:#31708f}.debug td.t_object{display:table-cell}.debug .m_assert,.debug .m_clear,.debug .m_count,.debug .m_error,.debug .m_groupEndValue,.debug .m_info,.debug .m_log,.debug .m_warn{position:relative;display:table;padding-left:10px;text-indent:-10px;padding-right:0.33em;word-break:break-word}.debug .m_table td,.debug .m_trace td{word-break:break-word}.debug .m_table td.t_string,.debug .m_trace td.t_string{padding-left:1em;text-indent:-0.75em}.debug .m_assert{background-color:rgba(255,204,204,0.75)}.debug .m_assert>i{margin-right:0.33em;margin-bottom:-0.2em;display:inline-block;line-height:0.6em;vertical-align:text-bottom}.debug .m_group .group-header{display:table;white-space:nowrap}.debug .m_group .group-header i.fa-warning{color:#cdcb06;margin-left:0.33em}.debug .m_group .group-header i.fa-times-circle{color:#d8000c;margin-left:0.33em}.debug .m_group .group-body{display:none}.debug .m_group>ul{list-style:none;margin-left:1em;border-left:1px solid rgba(0,0,0,0.25);padding-left:0.25rem}.debug .m_group.expanded>.group-body{display:block}.debug .m_error,.debug .m_group.level-error>.group-body,.debug .m_group.level-error:not(.expanded)>.group-header>.level-error{background-color:#ffbaba;color:#d8000c}.debug .m_info,.debug .m_group.level-info>.group-body,.debug .m_group.level-info:not(.expanded)>.group-header>.level-info{background-color:#d9edf7;color:#31708f}.debug .m_trace .classname{color:#146314}.debug .m_warn,.debug .m_group.level-warn>.group-body,.debug .m_group.level-warn:not(.expanded)>.group-header>.level-warn{background-color:#fefbe5;color:#8a6d3b}.debug li[data-channel="general.phpError"]>i+.t_string:nth-child(2){font-weight:bold}.debug li[data-channel="general.phpError"]>.t_string:nth-child(4){opacity:0.7}.debug li[data-channel="general.phpError"]>.t_string:nth-child(4)::before{content:"\A"}.debug li[data-channel="general.phpError"]>.t_string:nth-child(4)::after{content:none}.debug li[data-channel="general.phpError"].error-fatal{padding:10px 10px 10px 20px;border-left:solid 2px #d8000c}.debug li[data-channel="general.phpError"].error-fatal>.t_string:nth-child(2){display:inline-block;margin-bottom:5px;vertical-align:top;font-size:1.2em}.debug li[data-channel="general.phpError"].error-fatal>.t_string:nth-child(3)::before{content:"\A"}.debug table{width:auto;border-collapse:collapse}.debug table caption{caption-side:top;font-weight:bold;font-style:italic;padding-bottom:0;padding-top:2px;text-align:left}.debug table th,.debug table td{padding:0 0.25em;vertical-align:top}.debug table th.t_key{white-space:nowrap}.debug table th.t_key::before,.debug table th.t_key::after{content:none}.debug table td.classname{font-weight:bold}.debug table td.t_undefined{background-color:rgba(0,0,0,0.1)}.debug table td.t_undefined::after{content:none}.debug table th,.debug table tfoot td{font-weight:bold;background-color:rgba(0,0,0,0.1)}.debug table thead th{text-align:center}.debug table thead th .classname{opacity:0.5;font-style:italic}.debug table thead th .classname::before{content:"("}.debug table thead th .classname::after{content:")"}.debug table tr[data-toggle]{cursor:default}.debug table tr[data-toggle]:hover{color:#212529;background-color:rgba(0,0,0,0.075)}.debug table tbody th.t_int,.debug table td[data-type-more=numeric],.debug table td.timestamp,.debug table td.t_int{text-align:right;white-space:nowrap}.debug table.table-bordered th,.debug table.table-bordered td{border:1px solid #7f7f7f;padding:1px 0.25em}.debug table.table-hover tbody tr{cursor:default}.debug table.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,0.075)}.debug table.table-sort>thead th{cursor:default}.debug table.table-sort>thead th:hover{background-color:rgba(0,0,0,0.25)}.debug table.table-sort .sort-arrows{text-align:center;height:1.5em;width:1.2em;margin-left:0;margin-right:1px}.debug table.table-sort .sort-arrows .fa{position:absolute;opacity:0.33}.debug table.table-sort .sort-arrows .fa-caret-down{bottom:0}.debug table.table-sort .sort-arrows .fa-caret-up{top:-1px}.debug table.table-sort .sort-asc .fa-caret-down{opacity:1}.debug table.table-sort .sort-desc .fa-caret-up{opacity:1}.debug table.trace-context{width:100%}.debug table.trace-context tr.context{display:none}.debug table.trace-context tr.context td{color:#111;max-width:1px;background-color:#f5f2f0;padding:0.75em}.debug table.trace-context tr.context td hr{margin:1em 0}.debug .t_identifier{font-weight:bold;white-space:nowrap}.debug .t_type{color:#693}.debug .t_bool[data-type-more=true]{color:#993;text-shadow:1px 1px 2px rgba(153,153,51,0.5)}.debug .t_bool[data-type-more=false]{color:#c33;text-shadow:1px 1px 2px rgba(204,51,51,0.5)}.debug .t_callable{font-weight:bold}.debug .t_callable .t_type,.debug .t_callable .namespace{font-weight:normal}.debug .t_const{color:#039;font-family:monospace}.debug .t_const .t_identifier{color:inherit}.debug .t_int,.debug .t_float,.debug .t_string[data-type-more=numeric],.debug .t_string[data-type-more=timestamp]{font-family:Courier New,monospace,Ariel !important;color:#009;font-size:1.15em;line-height:1.15em}.debug .t_int::before,.debug .t_int::after,.debug .t_float::before,.debug .t_float::after,.debug .t_string[data-type-more=numeric]::before,.debug .t_string[data-type-more=numeric]::after,.debug .t_string[data-type-more=timestamp]::before,.debug .t_string[data-type-more=timestamp]::after{font-family:Arial,"Helvetica Neue",Helvetica,sans-serif;font-size:0.8695em}.debug .t_key{opacity:0.75}.debug .t_key[data-file]{opacity:1}.debug .t_key::before,.debug .t_key::after{font-family:Arial,"Helvetica Neue",Helvetica,sans-serif;color:#999}.debug .t_key::before{content:'[';margin-right:1px}.debug .t_key::after{content:']';margin-left:1px}.debug .t_key.t_int{white-space:nowrap}.debug .t_keyword{color:#07a}.debug .t_null{opacity:0.3}.debug .t_operator{color:#a67f59;white-space:nowrap !important}.debug .t_punct{color:#999}.debug .excluded,.debug .t_maxDepth,.debug .t_notInspected,.debug .t_recursion,.debug .t_unknown{font-weight:bold;color:red}.debug .t_resource{font-style:italic}.debug .t_string{white-space:pre-wrap;word-break:break-all}.debug .t_string::before,.debug .t_string::after{font-family:Arial,"Helvetica Neue",Helvetica,sans-serif;opacity:0.33;color:#333}.debug .t_string::before{content:open-quote}.debug .t_string::after{content:close-quote}.debug .t_string.classname::before{content:none}.debug .t_string.classname::after{content:none}.debug .t_string>*{white-space:normal;word-break:break-word}.debug .t_string pre{white-space:pre}.debug .t_stringified{text-shadow:0 0 2px rgba(0,200,200,0.6)}.debug .t_undefined::after{content:"undefined";opacity:0.3}.debug.debug-drawer{position:fixed;bottom:0;left:0;width:100%;background-color:#fff;z-index:1049;height:100px;transform:translateY(100px);transition:all 0.5s}.debug.debug-drawer>*{box-sizing:border-box}.debug.debug-drawer .debug-pull-tab{display:inline-block;opacity:1;position:absolute;height:25px;top:-25px;margin-left:20px;border:1px solid #000;border-bottom-width:0;border-radius:5px 5px 0 0;padding:4px 14px;font-size:16px;background:#f3f3f3;cursor:pointer;transition:all 0.5s}.debug.debug-drawer .debug-pull-tab:hover{background:#dadada}.debug.debug-drawer .debug-pull-tab .debug-error-counts{margin-left:0.5em}.debug.debug-drawer .debug-pull-tab .badge{display:none}.debug.debug-drawer .debug-pull-tab .fa-spinner{display:none}.debug.debug-drawer .debug-resize-handle{display:block;position:absolute;top:-3px;height:4px;width:100%;opacity:0;border-top:1px solid #d0d0d0;border-bottom:1px solid #d0d0d0;background:#dadada;transition:all 0.25s ease-out}.debug.debug-drawer.debug-drawer-open{transform:translateY(0);height:auto}.debug.debug-drawer.debug-drawer-open .debug-pull-tab{opacity:0;transform:translateY(25px)}.debug.debug-drawer.debug-drawer-open .debug-pull-tab .fa-spinner{display:inline-block}.debug.debug-drawer.debug-drawer-open .debug-resize-handle{cursor:ns-resize}.debug.debug-drawer.debug-drawer-open .debug-resize-handle:hover{opacity:1}html.debug-resizing{cursor:ns-resize !important}html.debug-resizing .debug-drawer{transition:none}html.debug-resizing .debug-drawer .debug-resize-handle{opacity:1}.debug .debug-bar{position:relative;padding:5px;font-size:115%;background-color:rgba(0,0,0,0.2);margin-bottom:10px}.debug .debug-bar a{color:#6e6e6e}.debug .debug-bar button{border-radius:0;border-top-width:0;border-bottom-width:0}.debug .debug-bar button.close{font-size:21px;font-weight:300}.debug .debug-bar .float-right{position:absolute;top:0;right:6px;line-height:23px}.debug .debug-bar .float-right button{height:18px;border:0;padding:0;line-height:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent}.debug .debug-error-counts{position:relative;top:-2px;font-size:0.78em}.debug .debug-error-counts .badge{padding:0 0.4em 0 0.25em;color:inherit;background:inherit;font-size:inherit;vertical-align:unset}.debug .debug-bar{border-top:1px solid #d0d0d0;border-bottom:1px solid #d0d0d0;color:#6e6e6e;padding:0 34px 0 6px;background:#f3f3f3;font-size:16px;margin-bottom:0}.debug .debug-bar a:focus,.debug .debug-bar a:hover,.debug .debug-bar button:focus,.debug .debug-bar button:hover,.debug .debug-bar label:focus,.debug .debug-bar label:hover{color:#333;text-decoration:none}.debug .debug-bar nav{margin-left:20px;line-height:23px}.debug .debug-bar nav a{line-height:23px}.debug .debug-bar nav a.has-assert{line-height:22px;border-bottom:#da8585 solid 2px}.debug .debug-bar nav a.has-warn{line-height:22px;border-bottom:#e4cb0f solid 2px}.debug .debug-bar nav a.has-error{line-height:22px;border-bottom:red solid 2px}.debug .debug-bar nav a.active{line-height:22px;border-bottom:#4071e1 solid 2px}.debug .debug-bar>span{display:inline-block;line-height:23px}.debug .debug-options-toggle{position:relative;top:-1px}.debug .debug-options{position:absolute;top:100%;right:0;max-height:0;box-sizing:border-box;z-index:1000;float:right;min-width:12em;background:#f3f3f3;box-shadow:0 4px 8px rgba(0,0,0,0.25);transition:all 0.25s ease-out;overflow:hidden;font-size:13px}.debug .debug-options .debug-options-body{background-clip:padding-box;border:1px solid #d0d0d0;padding:0.5em 5px 0.5em 15px}.debug .debug-options.show{max-height:150px}.debug .debug-options label{font-weight:normal;padding:0.25em 0}.debug .debug-options label.disabled{color:#999}.debug .debug-options hr.dropdown-divider{margin:0.5em -5px 0.5em -15px;background:#d0d0d0;height:1px;border:none}.debug .debug-options .form-group{margin:0}.debug{transform:scale(1)}.debug .debug-sidebar{position:absolute;box-sizing:border-box;width:126px;background:#f3f3f3;height:100%;transform:translateX(-119px);transition:transform .33s}.debug .debug-sidebar button{width:100%}.debug .debug-sidebar input[type=checkbox]{display:none}.debug .debug-sidebar label{font-weight:normal}.debug .debug-sidebar+.tab-body{margin-left:6px;padding-left:10px;transition:margin-left .33s}.debug .debug-sidebar.no-transition+.tab-body{transition:none}.debug .debug-sidebar .collapse{display:none}.debug .debug-sidebar .sidebar-content{padding:0 11px 0 4px;opacity:0;overflow:hidden}.debug .debug-sidebar.show{transform:translateX(0)}.debug .debug-sidebar.show .expand{display:none}.debug .debug-sidebar.show .collapse{display:block}.debug .debug-sidebar.show+.tab-body{margin-left:126px}.debug .debug-sidebar.show .sidebar-content{opacity:1;transition:opacity 0.33s}.debug .debug-sidebar .sidebar-toggle{position:absolute;box-sizing:border-box;right:0;top:0;height:100%;width:7px;background:#f3f3f3;border-left:1px solid #d0d0d0;border-right:1px solid #d0d0d0;cursor:pointer;display:flex;color:#d0d0d0;text-align:center;z-index:1}.debug .debug-sidebar .sidebar-toggle:hover{color:#6e6e6e;background:#dadada}.debug .debug-sidebar .sidebar-toggle>div{margin:auto;padding-left:1px}.debug .debug-sidebar .debug-filters{position:relative;margin:0 -4px 10px -4px}.debug .debug-sidebar .debug-filters ul{margin-left:0}.debug .debug-sidebar .debug-filters li{text-indent:0;padding-left:10px}.debug .debug-sidebar .debug-filters>li{padding-left:4px}.debug .debug-sidebar .debug-filters>li>*:first-child{padding-top:3px;padding-bottom:3px}.debug .debug-sidebar .debug-filters>li>ul{margin-left:-10px}.debug .debug-sidebar .debug-filters>li>ul>li{padding-left:32px}.debug .debug-sidebar .debug-filters label{padding:2px 0 2px 100%;white-space:nowrap}.debug .debug-sidebar .debug-filters label.disabled span{opacity:0.5}.debug .debug-sidebar .debug-filters label,.debug .debug-sidebar .debug-filters ul ul{margin-left:-100%;padding-left:100%}.debug .debug-sidebar .fa-times-circle{color:#d8000c}.debug .debug-sidebar .fa-warning{color:#8a6d3b}.debug .debug-sidebar .fa-info-circle{color:#31708f}.debug .debug-sidebar .toggle{cursor:pointer}.debug .debug-sidebar .toggle.active{background:#dadada}.debug .debug-sidebar .toggle.active:hover{background:#bacce0}.debug .debug-sidebar .toggle:hover,.debug .debug-sidebar .toggle:hover+ul{background:#dde6f0}.debug .debug-sidebar .toggle:hover .toggle.active,.debug .debug-sidebar .toggle:hover+ul .toggle.active{background:#bacce0}.debug i.fa{margin-right:0.33em}.debug i.fa-lg{font-size:1.33em}.debug i.fa-plus-circle{opacity:0.42}.debug i.fa-calendar{font-size:1.1em}.debug .filter-hidden{display:none}.debug .filter-hidden.m_group{display:list-item}.debug .filter-hidden.m_group>.group-header{display:none}.debug .filter-hidden.m_group>.group-body{display:block !important;margin-left:0;border-left:0;padding-left:0}.debug .filter-hidden.m_group.filter-hidden-body>.group-body{display:none !important}.debug .empty.hide-if-empty{display:none}.debug .empty.m_group .group-header{cursor:auto}.debug .vis-toggles span:hover,.debug [data-toggle=interface]:hover{background-color:rgba(0,0,0,0.1)}.debug .vis-toggles .toggle-off.toggle-off,.debug .interface.toggle-off{opacity:0.5}.debug ul.list-unstyled>li:has(.show-more-container){text-indent:0;padding-left:0}.debug .show-more-container{display:inline}.debug .show-more-wrapper{display:block;position:relative;height:70px;overflow:hidden}.debug .show-more-fade{position:absolute;bottom:-1px;width:100%;height:55px;background-image:linear-gradient(to bottom, rgba(255,255,255,0), rgba(255,255,255,0.75));pointer-events:none}.debug .level-error .show-more-fade,.debug .m_error .show-more-fade{background-image:linear-gradient(to bottom, rgba(255,186,186,0), #ffbaba)}.debug .level-info .show-more-fade,.debug .m_info .show-more-fade{background-image:linear-gradient(to bottom, rgba(217,237,247,0), #d9edf7)}.debug .level-warn .show-more-fade,.debug .m_warn .show-more-fade{background-image:linear-gradient(to bottom, rgba(254,251,229,0), #fefbe5)}.debug [title]:hover .show-more-fade{background-image:linear-gradient(to bottom, rgba(201,201,201,0), #c9c9c9)}.debug .show-more,.debug .show-less{display:table;box-shadow:1px 1px 0 0 rgba(0,0,0,0.2);border:1px solid rgba(0,0,0,0.2);border-radius:2px;background-color:#eee}.debug-noti-wrap{position:fixed;display:none;top:0;width:100%;height:100%;pointer-events:none;z-index:1050}.debug-noti-wrap .debug-noti{display:table-cell;text-align:center;vertical-align:bottom;font-size:30px;transform-origin:50% 100%}.debug-noti-wrap .debug-noti.animate{animation-duration:1s;animation-name:expandAndFade;animation-timing-function:ease-in}.debug-noti-table{display:table;width:100%;height:100%}@keyframes expandAndFade{from{opacity:0.9;transform:scale(0.9, 0.94)}to{opacity:0;transform:scale(1, 1)}}.debug .badge{display:inline-block;padding:0.25em 0.4em 0.16em;font-size:82%;font-weight:500;line-height:1;text-align:center;white-space:nowrap;vertical-align:bottom;border-radius:0.25rem;color:#fff;background-color:#666}.debug .expand-all{margin-bottom:0.5em}.debug .file-link.lpad{margin-left:0.33em}.debug .file-link i{margin-right:0;vertical-align:baseline}.debug .hasTooltip:not(a),.debug *[title]:not(a){cursor:help}.debug .hasTooltip:not(a):hover,.debug *[title]:not(a):hover{background-color:rgba(0,0,0,0.05)}.debug *[data-toggle]{cursor:pointer !important}.debug .string-encoded.tabs-container>i{line-height:20px;margin-right:0}.debug .string-encoded[data-type=base64]>.string-raw .t_string{font-family:monospace}.debug .prettified{color:rgba(0,11,155,0.933333)}.debug .timestamp{color:#009}.debug .binary{padding:0 0.3em}.debug .char-ws,.debug .maxlen,.debug .unicode{padding:0 0.3em;cursor:pointer}.debug .char-ws:hover,.debug .maxlen:hover,.debug .unicode:hover{outline:0;color:#e00}.debug .binary,.debug .char-control{background-color:silver;color:#003;font-family:monospace !important;font-weight:bold}.debug .char-control{display:inline-block;vertical-align:baseline;clip-path:inset(30% 0);transform:scale(2);margin-left:0.33em}.debug .maxlen{background-color:#fc7}.debug .char-ws,.debug .unicode{background-color:#c0c0ff;font-weight:normal}.debug ul[data-type-more=binary]>li.t_string{text-indent:0;padding:0}.debug ul[data-type-more=binary]>li.t_string::before{content:""}.debug ul[data-type-more=binary]>li.t_string::after{content:""}.debug ul[data-type-more=binary]>li.t_string>.binary{padding:0;margin:0;word-spacing:-0.25em;font-size:0.8em}.debug .ws_s,.debug .ws_t,.debug .ws_r,.debug .ws_n,.debug .ws_p{opacity:0.33}.debug .ws_t::before{display:inline-block;content:"\203A";width:1em}.debug .ws_r::before{content:"\\r"}.debug .ws_n::before{content:"\\n"}.debug .tippy-box{background-color:#fff;background-clip:padding-box;border:2px solid rgba(0,8,16,0.3);border-radius:4px;outline:0;transition-property:transform, visibility, opacity;color:#333;box-shadow:0 4px 14px -2px rgba(0,8,16,0.08)}.debug .tippy-box .tippy-content{padding:5px 9px;z-index:1}.debug .tippy-box>.tippy-backdrop{background-color:#fff}.debug .tippy-box>.tippy-arrow{width:16px;height:16px;color:#333}.debug .tippy-box>.tippy-arrow::before{content:"";position:absolute;border-color:transparent;border-style:solid}.debug .tippy-box>.tippy-arrow::after,.debug .tippy-box>.tippy-svg-arrow::after{content:'';position:absolute;z-index:-1}.debug .tippy-box>.tippy-arrow::after{border-color:transparent;border-style:solid}.debug .tippy-box[data-placement^='top']>.tippy-arrow{bottom:1px}.debug .tippy-box[data-placement^='top']>.tippy-arrow::before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:#fff;transform-origin:center top}.debug .tippy-box[data-placement^='top']>.tippy-arrow::after{border-top-color:rgba(0,8,16,0.5);border-width:7px 7px 0;top:17px;left:1px}.debug .tippy-box[data-placement^='top']>.tippy-svg-arrow>svg{top:16px}.debug .tippy-box[data-placement^='top']>.tippy-svg-arrow::after{top:17px}.debug .tippy-box[data-placement^='bottom']>.tippy-arrow{top:0}.debug .tippy-box[data-placement^='bottom']>.tippy-arrow::before{top:-6px;left:0;border-width:0 8px 8px;border-bottom-color:#fff;transform-origin:center bottom}.debug .tippy-box[data-placement^='bottom']>.tippy-arrow::after{border-bottom-color:rgba(0,8,16,0.5);border-width:0 7px 7px;bottom:17px;left:1px}.debug .tippy-box[data-placement^='bottom']>.tippy-svg-arrow>svg{bottom:16px}.debug .tippy-box[data-placement^='bottom']>.tippy-svg-arrow::after{bottom:17px}.debug .tippy-box[data-placement^='left']>.tippy-arrow::before{border-left-color:#fff}.debug .tippy-box[data-placement^='left']>.tippy-arrow::after{border-left-color:rgba(0,8,16,0.5);border-width:7px 0 7px 7px;left:17px;top:1px}.debug .tippy-box[data-placement^='left']>.tippy-svg-arrow>svg{left:11px}.debug .tippy-box[data-placement^='left']>.tippy-svg-arrow::after{left:12px}.debug .tippy-box[data-placement^='right']>.tippy-arrow::before{border-right-color:#fff;right:16px}.debug .tippy-box[data-placement^='right']>.tippy-arrow::after{border-width:7px 7px 7px 0;right:17px;top:1px;border-right-color:rgba(0,8,16,0.5)}.debug .tippy-box[data-placement^='right']>.tippy-svg-arrow>svg{right:11px}.debug .tippy-box[data-placement^='right']>.tippy-svg-arrow::after{right:12px}.debug .tippy-box>.tippy-svg-arrow{fill:white}.debug .tippy-box>.tippy-svg-arrow::after{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMCA2czEuNzk2LS4wMTMgNC42Ny0zLjYxNUM1Ljg1MS45IDYuOTMuMDA2IDggMGMxLjA3LS4wMDYgMi4xNDguODg3IDMuMzQzIDIuMzg1QzE0LjIzMyA2LjAwNSAxNiA2IDE2IDZIMHoiIGZpbGw9InJnYmEoMCwgOCwgMTYsIDAuMikiIC8+PC9zdmc+);background-size:16px 6px;width:16px;height:6px}.debug .indent{padding-left:10px !important}.debug .p0{padding:0 !important}.debug .fa-inverse{color:#fff}.debug .fa-stack{line-height:2em}.debug .fa-stack-1x{line-height:inherit}.debug .fa-stack-2x{font-size:2em}.debug .float-left{float:left !important}.debug .float-right{float:right !important}.debug .font-weight-bold{font-weight:bold}.debug .no-quotes::before{content:none}.debug .no-quotes::after{content:none}.debug .bg-secondary{background-color:#666 !important;color:#fff !important}.debug .bg-success{background-color:#dff0d8 !important;color:#3c763d !important}.debug .bg-error{background-color:#ffbaba !important;color:#d8000c !important}.debug .bg-warn{background-color:#fefbe5 !important;color:#8a6d3b !important}.debug .bg-info{background-color:#d9edf7 !important;color:#31708f !important}.debug .fw-bold{font-weight:700}.debug .logentry-muted{opacity:0.5}.debug .logentry-muted.m_group.expanded{opacity:1}.debug .text-center{text-align:center}.debug .text-left{text-align:left !important}.debug .text-right{text-align:right !important}.debug .text-muted{opacity:.5}.debug .text-success{color:#3c763d}.debug .text-error{color:#d8000c}.debug .text-info{color:#31708f}.debug .text-warn{color:#8a6d3b} +.debug{font-size:13px}.debug{position:relative;clear:both;font-family:Arial,"Helvetica Neue",Helvetica,sans-serif;line-height:normal;text-align:left;text-shadow:none;color:#111}.debug *{font-size:inherit;line-height:normal;text-indent:0;color:inherit;margin:0}.debug *:not(i[class^=fa]){font-family:inherit}.debug a{text-decoration:none;color:#00e}.debug a:visited{color:#551a8b}.debug a:focus,.debug a:hover{border-bottom:1px dotted blue}.debug a:active,.debug a:hover{outline:0;color:#e00}.debug a.file-link{color:inherit}.debug button{color:inherit;cursor:pointer;background-color:#f0f0f0;border-color:#afafaf;font-weight:inherit;height:auto;letter-spacing:initial;line-height:initial;outline:none;padding:1px 7px 2px;text-align:center;text-transform:none;vertical-align:baseline;white-space:initial}.debug button:hover{background-color:#dde6f0}.debug code{padding:2px 4px;background-color:transparent;font-family:Menlo, Monaco, Consolas, "Courier New", monospace !important}.debug pre code{display:block}.debug,.debug div{margin:0;width:auto;height:auto;padding:0;background-color:transparent;border-radius:0}.debug dl{margin-top:0;margin-bottom:0}.debug dl dt{font-weight:bold}.debug dl.dl-horizontal{display:grid;grid-template-columns:max-content auto}.debug dl.dl-horizontal>dt{grid-column:1;text-align:right;width:auto}.debug dl.dl-horizontal>dd{grid-column:2;margin-left:0.75em}.debug dl:not(.dl-horizontal)>dd{margin-left:20px;padding-left:10px;text-indent:-10px}.debug dl:not(.dl-horizontal)>dd>ul{margin-left:-10px}.debug li.no-indent{padding-left:0;text-indent:0}.debug h3{margin-top:0.66em;margin-bottom:0.5em;font-size:1.15em;font-weight:bold}.debug h3:first-child{margin-top:0}.debug hr{color:#111;background-color:#111;border:0;height:1px}.debug img{border:0}.debug input{border-width:1px}.debug input[type=checkbox]{margin:0 0.33em 0 0;cursor:pointer}.debug label{display:block;margin:0;cursor:pointer;font-weight:bold;max-width:none}.debug label.disabled{cursor:default;pointer-events:none}.debug legend{padding:0;float:left;margin-bottom:0.5em;border:0;width:100%;font-size:144%;font-weight:bold}.debug p{margin-top:0.25em;margin-bottom:0}.debug p:first-child{margin-top:0}.debug pre{padding:0;border:0;margin:0;white-space:pre;-moz-tab-size:3;-o-tag-size:3;-tab-size:3}.debug ul{margin-top:0;margin-bottom:0}.debug ul.list-unstyled{list-style:none outside none;padding-left:0}.debug ul.list-unstyled>li{text-indent:-1em;padding-left:1em}.debug ul.list-unstyled>ul{margin-left:10px}.debug ul.no-indent>li{padding-left:0;text-indent:0}.debug fieldset{padding:0.66em;margin:0 0 10px 0;min-width:0;border:1px solid black;border-radius:4px}.debug fieldset>ul{font-size:125%}.debug .close{opacity:1;float:none}.debug ul.debug-log-summary+hr{border-top:1px dotted;background-color:transparent;margin:.5em 0}.debug .tab-pane>*>.group-body,.debug .m_groupSummary>ul{list-style:none;margin-left:0;border-left:0;padding-left:0}.debug li.php-shutdown{display:block;border-bottom:#31708f solid 1px}.debug .fa{line-height:1}.debug .alert,.debug .m_alert{padding:0.66em;margin-bottom:10px;border-radius:4px;border:1px solid transparent}.debug .m_alert{font-size:125%}.debug .m_alert h3{margin-bottom:4px}.debug .m_alert h3:last-child{margin-bottom:0}.debug .m_alert.error-summary .filter-hidden+h3{margin-top:0}.debug .m_alert.alert-dismissible{padding-right:35px}.debug .m_alert.alert-dismissible .close{float:right;position:relative;top:-7px;right:-21px;border:0;padding:0;font-size:21px;font-weight:700;line-height:1;background:none;color:#000;text-shadow:0 1px 0 #fff;opacity:0.2;cursor:pointer}.debug .m_alert.alert-dismissible .close:hover{text-decoration:none;opacity:0.5}.debug .m_alert .alert-link{font-weight:bold}.debug .alert-error{background-color:#ffbaba;border-color:#d8000c;color:#d8000c}.debug .alert-error .alert-link{color:#843534}.debug .alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.debug .alert-info .alert-link{color:#245269}.debug .alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.debug .alert-success .alert-link{color:#2b542c}.debug .alert-warn{background-color:#fefbe5;border-color:#faebcc;color:#8a6d3b}.debug .alert-warn .alert-link{color:#66512c}.debug nav[role=tablist]{display:inline-block;font-size:0;line-height:20px;vertical-align:top}.debug nav[role=tablist] .fa{margin-right:0.5em}.debug nav[role=tablist] a{display:inline-block;padding:0 13px;font-size:13px;line-height:20px;vertical-align:top;color:#111;cursor:pointer}.debug nav[role=tablist] a:hover{text-decoration:none}.debug nav[role=tablist] a:hover:not(.active){background:#e6e6e6}.debug nav[role=tablist] a.active{line-height:19px;border-bottom:#4071e1 solid 2px}.debug .tab-panes{overflow:auto}.debug .tab-panes .tab-pane{position:static;display:none}.debug .tab-panes .tab-pane.active{display:block}.debug .tab-panes .tab-pane .tab-body{padding:10px 12px 5px;background-color:#fff;overflow:auto}.debug .namespace{opacity:0.5}.debug .array-inner,.debug .object-inner{display:block;margin-left:1em}.debug .classname{font-weight:bold;color:color-mix(in lch, currentColor, #8d0c4c)}.debug .attribute .t_punct{color:inherit;font-weight:bold}.debug .t_parameter-name{color:#263}.debug .t_array>.t_array-collapse,.debug .t_array>.array-inner,.debug .t_array>.t_punct{display:none}.debug .t_array.expanded>.t_array-expand{display:none}.debug .t_array.expanded>.t_array-collapse,.debug .t_array.expanded>.t_punct{display:inline}.debug .t_array.expanded>.array-inner{display:block}.debug .t_array.array-file-tree .array-inner{margin-left:0.25em}.debug .t_array.array-file-tree .exclude-count{background:#d9edf7;color:#31708f}.debug .t_array.array-file-tree .t_key{color:#000040;font-weight:bold}.debug .t_array.array-file-tree .t_string::before,.debug .t_array.array-file-tree .t_string::after,.debug .t_array.array-file-tree .t_key::before,.debug .t_array.array-file-tree .t_key::after{display:none}.debug .array-inner>li>.t_operator{margin:0 0.25em}.debug li[class*=m_]>.t_array.array-file-tree>.array-inner{margin-left:-10px}.debug .t_object{display:inline}.debug .t_object h3{margin:0;font-size:inherit;font-style:italic;color:purple}.debug .t_object .t_modifier_abstract,.debug .t_object i.fa-circle-o{font-weight:bold;color:#9d2d2d}.debug .t_object .t_modifier_debug{color:rgba(0,11,155,0.933333)}.debug .t_object .t_modifier_final{color:rgba(255,0,0,0.933333);font-weight:bold}.debug .t_object .t_modifier_private{color:rgba(0,0,0,0.509804)}.debug .t_object .t_modifier_protected{color:rgba(0,0,0,0.776471)}.debug .t_object .t_modifier_public{color:inherit}.debug .t_object .t_modifier_static{font-style:italic;color:rgba(218,13,135,0.933333)}.debug .t_object>.object-inner>.modifiers{display:none}.debug .t_object>.object-inner>dd[class*=t_modifier_]{display:inline-block;margin-left:0;margin-right:0.5em;border-style:solid;border-width:1px;border-radius:4px;padding:0 .75em;height:1.75em;text-indent:0;line-height:1.5;font-weight:bold}.debug .t_object>.object-inner>.t_modifier_abstract{color:#333;background-color:#e6e6e6;border-color:#666}.debug .t_object>.object-inner>.t_modifier_final{color:#d8000c;background-color:#ffeded;border-color:#d8000c}.debug .t_object>.object-inner>.t_modifier_interface{color:#31708f;background-color:#d9edf7;border-color:#31708f}.debug .t_object>.object-inner>.t_modifier_readonly{color:#8a6d3b;background-color:#fefbe5;border-color:#8a6d3b}.debug .t_object>.object-inner>.t_modifier_readonly .fa-stack{font-size:0.8em;margin-right:0.33em}.debug .t_object>.object-inner>.t_modifier_readonly .fa-stack .fa-ban{opacity:0.75}.debug .t_object>.object-inner .heading{color:#4f16b0;text-decoration:underline;font-weight:bold}.debug .t_object .vis-toggles *[data-toggle]{padding:0.15em 0.5em;display:inline-block}.debug .t_object dd+.vis-toggles{margin-top:.25em}.debug .t_object .method .parameter .t_parameter-name[title],.debug .t_object .t_identifier[title],.debug .t_object .t_type[title]{border-bottom:1px dashed blue}.debug .t_object .method ul{margin-left:15px}.debug .t_object .method.deprecated{opacity:0.66}.debug .t_object .method.deprecated i{opacity:0.66;color:#d8000c;border-bottom:0}.debug .t_object .method>.t_punct:not(.t_colon){opacity:1;font-weight:bold;color:inherit}.debug .t_object .method i.fa-clone{color:#999}.debug .t_object .property i.isVirtual{color:#caf;text-shadow:0px 0px 1px #990099}.debug .t_object .private-ancestor:not(:hover)>*{opacity:0.5}.debug .t_object .private-ancestor:not(:hover)>.fa-lock,.debug .t_object .private-ancestor:not(:hover)>.t_modifier_private{opacity:1}.debug .t_object i.fa-flag,.debug .t_object i.fa-warning{color:red}.debug .t_object i.fa-eye{color:rgba(0,11,155,0.933333);font-size:1.1em;border-bottom:0}.debug .t_object i.fa-magic,.debug .t_object .t_modifier_magic,.debug .t_object .t_modifier_magic-read,.debug .t_object .t_modifier_magic-write{color:rgba(255,136,0,0.933333)}.debug .t_object .debugInfo-excluded>i.fa-eye-slash{color:#999}.debug .t_object .info{display:inline-block;background-color:#d9edf7;color:#31708f}.debug td.t_object{display:table-cell}.debug .m_assert,.debug .m_clear,.debug .m_count,.debug .m_error,.debug .m_groupEndValue,.debug .m_info,.debug .m_log,.debug .m_warn{position:relative;display:table;padding-left:10px;text-indent:-10px;padding-right:0.33em;word-break:break-word}.debug .m_table td,.debug .m_trace td{word-break:break-word}.debug .m_table td.t_string,.debug .m_trace td.t_string{padding-left:1em;text-indent:-0.75em}.debug .m_assert{background-color:rgba(255,204,204,0.75)}.debug .m_assert>i{margin-right:0.33em;margin-bottom:-0.2em;display:inline-block;line-height:0.6em;vertical-align:text-bottom}.debug .m_group .group-header{display:table;white-space:nowrap}.debug .m_group .group-header i.fa-warning{color:#cdcb06;margin-left:0.33em}.debug .m_group .group-header i.fa-times-circle{color:#d8000c;margin-left:0.33em}.debug .m_group .group-body{display:none}.debug .m_group>ul{list-style:none;margin-left:1em;border-left:1px solid rgba(0,0,0,0.25);padding-left:0.25rem}.debug .m_group.expanded>.group-body{display:block}.debug .m_error,.debug .m_group.level-error>.group-body,.debug .m_group.level-error:not(.expanded)>.group-header>.level-error{background-color:#ffbaba;color:#d8000c}.debug .m_info,.debug .m_group.level-info>.group-body,.debug .m_group.level-info:not(.expanded)>.group-header>.level-info{background-color:#d9edf7;color:#31708f}.debug .m_trace .classname{color:#146314}.debug .m_warn,.debug .m_group.level-warn>.group-body,.debug .m_group.level-warn:not(.expanded)>.group-header>.level-warn{background-color:#fefbe5;color:#8a6d3b}.debug li[data-channel="general.phpError"]>i+.t_string:nth-child(2){font-weight:bold}.debug li[data-channel="general.phpError"]>.t_string:nth-child(4){opacity:0.7}.debug li[data-channel="general.phpError"]>.t_string:nth-child(4)::before{content:"\A"}.debug li[data-channel="general.phpError"]>.t_string:nth-child(4)::after{content:none}.debug li[data-channel="general.phpError"].error-fatal{padding:10px 10px 10px 20px;border-left:solid 2px #d8000c}.debug li[data-channel="general.phpError"].error-fatal>.t_string:nth-child(2){display:inline-block;margin-bottom:5px;vertical-align:top;font-size:1.2em}.debug li[data-channel="general.phpError"].error-fatal>.t_string:nth-child(3)::before{content:"\A"}.debug table{width:auto;border-collapse:collapse}.debug table caption{caption-side:top;font-weight:bold;font-style:italic;padding-bottom:0;padding-top:2px;text-align:left}.debug table th,.debug table td{padding:0 0.25em;vertical-align:top}.debug table th.t_key{white-space:nowrap}.debug table th.t_key::before,.debug table th.t_key::after{content:none}.debug table td.classname{font-weight:bold}.debug table td.t_undefined{background-color:rgba(0,0,0,0.1)}.debug table td.t_undefined::after{content:none}.debug table th,.debug table tfoot td{font-weight:bold;background-color:rgba(0,0,0,0.1)}.debug table thead th{text-align:center}.debug table thead th .classname{opacity:0.5;font-style:italic}.debug table thead th .classname::before{content:"("}.debug table thead th .classname::after{content:")"}.debug table tr[data-toggle]{cursor:default}.debug table tr[data-toggle]:hover{color:#212529;background-color:rgba(0,0,0,0.075)}.debug table tbody th.t_int,.debug table td[data-type-more=numeric],.debug table td.timestamp,.debug table td.t_int{text-align:right;white-space:nowrap}.debug table.table-bordered th,.debug table.table-bordered td{border:1px solid #7f7f7f;padding:1px 0.25em}.debug table.table-hover tbody tr{cursor:default}.debug table.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,0.075)}.debug table.table-sort>thead th{cursor:default}.debug table.table-sort>thead th:hover{background-color:rgba(0,0,0,0.25)}.debug table.table-sort .sort-arrows{text-align:center;height:1.5em;width:1.2em;margin-left:0;margin-right:1px}.debug table.table-sort .sort-arrows .fa{position:absolute;opacity:0.33}.debug table.table-sort .sort-arrows .fa-caret-down{bottom:0}.debug table.table-sort .sort-arrows .fa-caret-up{top:-1px}.debug table.table-sort .sort-asc .fa-caret-down{opacity:1}.debug table.table-sort .sort-desc .fa-caret-up{opacity:1}.debug table.trace-context{width:100%}.debug table.trace-context tr.context{display:none}.debug table.trace-context tr.context td{color:#111;max-width:1px;background-color:#f5f2f0;padding:0.75em}.debug table.trace-context tr.context td hr{margin:1em 0}.debug .t_identifier{font-weight:bold;white-space:nowrap}.debug .t_type{color:#693}.debug .t_bool[data-type-more=true]{color:#993;text-shadow:1px 1px 2px rgba(153,153,51,0.5)}.debug .t_bool[data-type-more=false]{color:#c33;text-shadow:1px 1px 2px rgba(204,51,51,0.5)}.debug .t_callable{font-weight:bold}.debug .t_callable .t_type,.debug .t_callable .namespace{font-weight:normal}.debug .t_const{color:#039;font-family:monospace}.debug .t_const .t_identifier{color:inherit}.debug .t_int,.debug .t_float,.debug .t_string[data-type-more=numeric],.debug .t_string[data-type-more=timestamp]{font-family:Courier New,monospace,Ariel !important;color:#009;font-size:1.15em;line-height:1.15em}.debug .t_int::before,.debug .t_int::after,.debug .t_float::before,.debug .t_float::after,.debug .t_string[data-type-more=numeric]::before,.debug .t_string[data-type-more=numeric]::after,.debug .t_string[data-type-more=timestamp]::before,.debug .t_string[data-type-more=timestamp]::after{font-family:Arial,"Helvetica Neue",Helvetica,sans-serif;font-size:0.8695em}.debug .t_key{opacity:0.75}.debug .t_key[data-file]{opacity:1}.debug .t_key::before,.debug .t_key::after{font-family:Arial,"Helvetica Neue",Helvetica,sans-serif;color:#999}.debug .t_key::before{content:'[';margin-right:1px}.debug .t_key::after{content:']';margin-left:1px}.debug .t_key.t_int{white-space:nowrap}.debug .t_keyword{color:#07a}.debug .t_null{opacity:0.3}.debug .t_operator{color:#a67f59;white-space:nowrap !important}.debug .t_punct{color:#999}.debug .excluded,.debug .t_maxDepth,.debug .t_notInspected,.debug .t_recursion,.debug .t_unknown{font-weight:bold;color:red}.debug .t_resource{font-style:italic}.debug .t_string{white-space:pre-wrap;word-break:break-all}.debug .t_string::before,.debug .t_string::after{font-family:Arial,"Helvetica Neue",Helvetica,sans-serif;opacity:0.33;color:#333}.debug .t_string::before{content:open-quote}.debug .t_string::after{content:close-quote}.debug .t_string.classname::before{content:none}.debug .t_string.classname::after{content:none}.debug .t_string>*{white-space:normal;word-break:break-word}.debug .t_string pre{white-space:pre}.debug .t_stringified{text-shadow:0 0 2px rgba(0,200,200,0.6)}.debug .t_undefined::after{content:"undefined";opacity:0.3}.debug.debug-drawer{position:fixed;bottom:0;left:0;width:100%;background-color:#fff;z-index:1049;height:100px;transform:translateY(100px);transition:all 0.5s}.debug.debug-drawer>*{box-sizing:border-box}.debug.debug-drawer .debug-pull-tab{display:inline-block;opacity:1;position:absolute;height:25px;top:-25px;margin-left:20px;border:1px solid #000;border-bottom-width:0;border-radius:5px 5px 0 0;padding:4px 14px;font-size:16px;background:#f3f3f3;cursor:pointer;transition:all 0.5s}.debug.debug-drawer .debug-pull-tab:hover{background:#dadada}.debug.debug-drawer .debug-pull-tab .debug-error-counts{margin-left:0.5em}.debug.debug-drawer .debug-pull-tab .badge{display:none}.debug.debug-drawer .debug-pull-tab .fa-spinner{display:none}.debug.debug-drawer .debug-resize-handle{display:block;position:absolute;top:-3px;height:4px;width:100%;opacity:0;border-top:1px solid #d0d0d0;border-bottom:1px solid #d0d0d0;background:#dadada;transition:all 0.25s ease-out}.debug.debug-drawer.debug-drawer-open{transform:translateY(0);height:auto}.debug.debug-drawer.debug-drawer-open .debug-pull-tab{opacity:0;transform:translateY(25px)}.debug.debug-drawer.debug-drawer-open .debug-pull-tab .fa-spinner{display:inline-block}.debug.debug-drawer.debug-drawer-open .debug-resize-handle{cursor:ns-resize}.debug.debug-drawer.debug-drawer-open .debug-resize-handle:hover{opacity:1}html.debug-resizing{cursor:ns-resize !important}html.debug-resizing .debug-drawer{transition:none}html.debug-resizing .debug-drawer .debug-resize-handle{opacity:1}.debug .debug-bar{position:relative;padding:5px;font-size:115%;background-color:rgba(0,0,0,0.2);margin-bottom:10px}.debug .debug-bar a{color:#6e6e6e}.debug .debug-bar button{border-radius:0;border-top-width:0;border-bottom-width:0}.debug .debug-bar button.close{font-size:21px;font-weight:300}.debug .debug-bar .float-right{position:absolute;top:0;right:6px;line-height:23px}.debug .debug-bar .float-right button{height:18px;border:0;padding:0;line-height:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent}.debug .debug-error-counts{position:relative;top:-2px;font-size:0.78em}.debug .debug-error-counts .badge{padding:0 0.4em 0 0.25em;color:inherit;background:inherit;font-size:inherit;vertical-align:unset}.debug .debug-bar{border-top:1px solid #d0d0d0;border-bottom:1px solid #d0d0d0;color:#6e6e6e;padding:0 34px 0 6px;background:#f3f3f3;font-size:16px;margin-bottom:0}.debug .debug-bar a:focus,.debug .debug-bar a:hover,.debug .debug-bar button:focus,.debug .debug-bar button:hover,.debug .debug-bar label:focus,.debug .debug-bar label:hover{color:#333;text-decoration:none}.debug .debug-bar nav{margin-left:20px;line-height:23px}.debug .debug-bar nav a{line-height:23px}.debug .debug-bar nav a.has-assert{line-height:22px;border-bottom:#da8585 solid 2px}.debug .debug-bar nav a.has-warn{line-height:22px;border-bottom:#e4cb0f solid 2px}.debug .debug-bar nav a.has-error{line-height:22px;border-bottom:red solid 2px}.debug .debug-bar nav a.active{line-height:22px;border-bottom:#4071e1 solid 2px}.debug .debug-bar>span{display:inline-block;line-height:23px}.debug .debug-options-toggle{position:relative;top:-1px}.debug .debug-options{position:absolute;top:100%;right:0;max-height:0;box-sizing:border-box;z-index:1000;float:right;min-width:12em;background:#f3f3f3;box-shadow:0 4px 8px rgba(0,0,0,0.25);transition:all 0.25s ease-out;overflow:hidden;font-size:13px}.debug .debug-options .debug-options-body{background-clip:padding-box;border:1px solid #d0d0d0;padding:0.5em 5px 0.5em 15px}.debug .debug-options.show{max-height:150px}.debug .debug-options label{font-weight:normal;padding:0.25em 0}.debug .debug-options label.disabled{color:#999}.debug .debug-options hr.dropdown-divider{margin:0.5em -5px 0.5em -15px;background:#d0d0d0;height:1px;border:none}.debug .debug-options .form-group{margin:0}.debug{transform:scale(1)}.debug .debug-sidebar{position:absolute;box-sizing:border-box;width:126px;background:#f3f3f3;height:100%;transform:translateX(-119px);transition:transform .33s}.debug .debug-sidebar button{width:100%}.debug .debug-sidebar input[type=checkbox]{display:none}.debug .debug-sidebar label{font-weight:normal}.debug .debug-sidebar+.tab-body{margin-left:6px;padding-left:10px;transition:margin-left .33s}.debug .debug-sidebar.no-transition+.tab-body{transition:none}.debug .debug-sidebar .collapse{display:none}.debug .debug-sidebar .sidebar-content{padding:0 11px 0 4px;opacity:0;overflow:hidden}.debug .debug-sidebar.show{transform:translateX(0)}.debug .debug-sidebar.show .expand{display:none}.debug .debug-sidebar.show .collapse{display:block}.debug .debug-sidebar.show+.tab-body{margin-left:126px}.debug .debug-sidebar.show .sidebar-content{opacity:1;transition:opacity 0.33s}.debug .debug-sidebar .sidebar-toggle{position:absolute;box-sizing:border-box;right:0;top:0;height:100%;width:7px;background:#f3f3f3;border-left:1px solid #d0d0d0;border-right:1px solid #d0d0d0;cursor:pointer;display:flex;color:#d0d0d0;text-align:center;z-index:1}.debug .debug-sidebar .sidebar-toggle:hover{color:#6e6e6e;background:#dadada}.debug .debug-sidebar .sidebar-toggle>div{margin:auto;padding-left:1px}.debug .debug-sidebar .debug-filters{position:relative;margin:0 -4px 10px -4px}.debug .debug-sidebar .debug-filters ul{margin-left:0}.debug .debug-sidebar .debug-filters li{text-indent:0;padding-left:10px}.debug .debug-sidebar .debug-filters>li{padding-left:4px}.debug .debug-sidebar .debug-filters>li>*:first-child{padding-top:3px;padding-bottom:3px}.debug .debug-sidebar .debug-filters>li>ul{margin-left:-10px}.debug .debug-sidebar .debug-filters>li>ul>li{padding-left:32px}.debug .debug-sidebar .debug-filters label{padding:2px 0 2px 100%;white-space:nowrap}.debug .debug-sidebar .debug-filters label.disabled span{opacity:0.5}.debug .debug-sidebar .debug-filters label,.debug .debug-sidebar .debug-filters ul ul{margin-left:-100%;padding-left:100%}.debug .debug-sidebar .fa-times-circle{color:#d8000c}.debug .debug-sidebar .fa-warning{color:#8a6d3b}.debug .debug-sidebar .fa-info-circle{color:#31708f}.debug .debug-sidebar .toggle{cursor:pointer}.debug .debug-sidebar .toggle.active{background:#dadada}.debug .debug-sidebar .toggle.active:hover{background:#bacce0}.debug .debug-sidebar .toggle:hover,.debug .debug-sidebar .toggle:hover+ul{background:#dde6f0}.debug .debug-sidebar .toggle:hover .toggle.active,.debug .debug-sidebar .toggle:hover+ul .toggle.active{background:#bacce0}.debug i.fa{margin-right:0.33em}.debug i.fa-lg{font-size:1.33em}.debug i.fa-plus-circle{opacity:0.42}.debug i.fa-calendar{font-size:1.1em}.debug .filter-hidden{display:none}.debug .filter-hidden.m_group{display:list-item}.debug .filter-hidden.m_group>.group-header{display:none}.debug .filter-hidden.m_group>.group-body{display:block !important;margin-left:0;border-left:0;padding-left:0}.debug .filter-hidden.m_group.filter-hidden-body>.group-body{display:none !important}.debug .empty.hide-if-empty{display:none}.debug .empty.m_group .group-header{cursor:auto}.debug .vis-toggles span:hover,.debug [data-toggle=interface]:hover{background-color:rgba(0,0,0,0.1)}.debug .vis-toggles .toggle-off.toggle-off,.debug .interface.toggle-off{opacity:0.5}.debug ul.list-unstyled>li:has(.show-more-container){text-indent:0;padding-left:0}.debug .show-more-container{display:inline}.debug .show-more-wrapper{display:block;position:relative;height:70px;overflow:hidden}.debug .show-more-fade{position:absolute;bottom:-1px;width:100%;height:55px;background-image:linear-gradient(to bottom, rgba(255,255,255,0), rgba(255,255,255,0.75));pointer-events:none}.debug .level-error .show-more-fade,.debug .m_error .show-more-fade{background-image:linear-gradient(to bottom, rgba(255,186,186,0), #ffbaba)}.debug .level-info .show-more-fade,.debug .m_info .show-more-fade{background-image:linear-gradient(to bottom, rgba(217,237,247,0), #d9edf7)}.debug .level-warn .show-more-fade,.debug .m_warn .show-more-fade{background-image:linear-gradient(to bottom, rgba(254,251,229,0), #fefbe5)}.debug [title]:hover .show-more-fade{background-image:linear-gradient(to bottom, rgba(201,201,201,0), #c9c9c9)}.debug .show-more,.debug .show-less{display:table;box-shadow:1px 1px 0 0 rgba(0,0,0,0.2);border:1px solid rgba(0,0,0,0.2);border-radius:2px;background-color:#eee}.debug-noti-wrap{position:fixed;display:none;top:0;width:100%;height:100%;pointer-events:none;z-index:1050}.debug-noti-wrap .debug-noti{display:table-cell;text-align:center;vertical-align:bottom;font-size:30px;transform-origin:50% 100%}.debug-noti-wrap .debug-noti.animate{animation-duration:1s;animation-name:expandAndFade;animation-timing-function:ease-in}.debug-noti-table{display:table;width:100%;height:100%}@keyframes expandAndFade{from{opacity:0.9;transform:scale(0.9, 0.94)}to{opacity:0;transform:scale(1, 1)}}.debug .badge{display:inline-block;padding:0.25em 0.4em 0.16em;font-size:82%;font-weight:500;line-height:1;text-align:center;white-space:nowrap;vertical-align:bottom;border-radius:0.25rem;color:#fff;background-color:#666}.debug .expand-all{margin-bottom:0.5em}.debug .file-link.lpad{margin-left:0.33em}.debug .file-link i{margin-right:0;vertical-align:baseline}.debug .hasTooltip:not(a),.debug *[title]:not(a){cursor:help}.debug .hasTooltip:not(a):hover,.debug *[title]:not(a):hover{background-color:rgba(0,0,0,0.05)}.debug *[data-toggle]{cursor:pointer !important}.debug .string-encoded.tabs-container>i{line-height:20px;margin-right:0}.debug .string-encoded[data-type=base64]>.string-raw .t_string{font-family:monospace}.debug .prettified{color:rgba(0,11,155,0.933333)}.debug .timestamp{color:#009}.debug .binary{padding:0 0.3em}.debug .char-ws,.debug .maxlen,.debug .unicode{padding:0 0.3em;cursor:pointer}.debug .char-ws:hover,.debug .maxlen:hover,.debug .unicode:hover{outline:0;color:#e00}.debug .binary,.debug .char-control{background-color:silver;color:#003;font-family:monospace !important;font-weight:bold}.debug .char-control{display:inline-block;vertical-align:baseline;clip-path:inset(30% 0);transform:scale(2);margin-left:0.33em}.debug .maxlen{background-color:#fc7}.debug .char-ws,.debug .unicode{background-color:#c0c0ff;font-weight:normal}.debug ul[data-type-more=binary]>li.t_string{text-indent:0;padding:0}.debug ul[data-type-more=binary]>li.t_string::before{content:""}.debug ul[data-type-more=binary]>li.t_string::after{content:""}.debug ul[data-type-more=binary]>li.t_string>.binary{padding:0;margin:0;word-spacing:-0.25em;font-size:0.8em}.debug .ws_s,.debug .ws_t,.debug .ws_r,.debug .ws_n,.debug .ws_p{opacity:0.33}.debug .ws_t::before{display:inline-block;content:"\203A";width:1em}.debug .ws_r::before{content:"\\r"}.debug .ws_n::before{content:"\\n"}.debug .tippy-box{background-color:#fff;background-clip:padding-box;border:2px solid rgba(0,8,16,0.3);border-radius:4px;outline:0;transition-property:transform, visibility, opacity;color:#333;box-shadow:0 4px 14px -2px rgba(0,8,16,0.08)}.debug .tippy-box .tippy-content{padding:5px 9px;z-index:1}.debug .tippy-box>.tippy-backdrop{background-color:#fff}.debug .tippy-box>.tippy-arrow{width:16px;height:16px;color:#333}.debug .tippy-box>.tippy-arrow::before{content:"";position:absolute;border-color:transparent;border-style:solid}.debug .tippy-box>.tippy-arrow::after,.debug .tippy-box>.tippy-svg-arrow::after{content:'';position:absolute;z-index:-1}.debug .tippy-box>.tippy-arrow::after{border-color:transparent;border-style:solid}.debug .tippy-box[data-placement^='top']>.tippy-arrow{bottom:1px}.debug .tippy-box[data-placement^='top']>.tippy-arrow::before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:#fff;transform-origin:center top}.debug .tippy-box[data-placement^='top']>.tippy-arrow::after{border-top-color:rgba(0,8,16,0.5);border-width:7px 7px 0;top:17px;left:1px}.debug .tippy-box[data-placement^='top']>.tippy-svg-arrow>svg{top:16px}.debug .tippy-box[data-placement^='top']>.tippy-svg-arrow::after{top:17px}.debug .tippy-box[data-placement^='bottom']>.tippy-arrow{top:0}.debug .tippy-box[data-placement^='bottom']>.tippy-arrow::before{top:-6px;left:0;border-width:0 8px 8px;border-bottom-color:#fff;transform-origin:center bottom}.debug .tippy-box[data-placement^='bottom']>.tippy-arrow::after{border-bottom-color:rgba(0,8,16,0.5);border-width:0 7px 7px;bottom:17px;left:1px}.debug .tippy-box[data-placement^='bottom']>.tippy-svg-arrow>svg{bottom:16px}.debug .tippy-box[data-placement^='bottom']>.tippy-svg-arrow::after{bottom:17px}.debug .tippy-box[data-placement^='left']>.tippy-arrow::before{border-left-color:#fff}.debug .tippy-box[data-placement^='left']>.tippy-arrow::after{border-left-color:rgba(0,8,16,0.5);border-width:7px 0 7px 7px;left:17px;top:1px}.debug .tippy-box[data-placement^='left']>.tippy-svg-arrow>svg{left:11px}.debug .tippy-box[data-placement^='left']>.tippy-svg-arrow::after{left:12px}.debug .tippy-box[data-placement^='right']>.tippy-arrow::before{border-right-color:#fff;right:16px}.debug .tippy-box[data-placement^='right']>.tippy-arrow::after{border-width:7px 7px 7px 0;right:17px;top:1px;border-right-color:rgba(0,8,16,0.5)}.debug .tippy-box[data-placement^='right']>.tippy-svg-arrow>svg{right:11px}.debug .tippy-box[data-placement^='right']>.tippy-svg-arrow::after{right:12px}.debug .tippy-box>.tippy-svg-arrow{fill:white}.debug .tippy-box>.tippy-svg-arrow::after{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMCA2czEuNzk2LS4wMTMgNC42Ny0zLjYxNUM1Ljg1MS45IDYuOTMuMDA2IDggMGMxLjA3LS4wMDYgMi4xNDguODg3IDMuMzQzIDIuMzg1QzE0LjIzMyA2LjAwNSAxNiA2IDE2IDZIMHoiIGZpbGw9InJnYmEoMCwgOCwgMTYsIDAuMikiIC8+PC9zdmc+);background-size:16px 6px;width:16px;height:6px}.debug .indent{padding-left:10px !important}.debug .p0{padding:0 !important}.debug .fa-inverse{color:#fff}.debug .fa-stack{line-height:2em}.debug .fa-stack-1x{line-height:inherit}.debug .fa-stack-2x{font-size:2em}.debug .float-left{float:left !important}.debug .float-right{float:right !important}.debug .font-weight-bold{font-weight:bold}.debug .no-quotes::before{content:none}.debug .no-quotes::after{content:none}.debug .bg-secondary{background-color:#666 !important;color:#fff !important}.debug .bg-success{background-color:#dff0d8 !important;color:#3c763d !important}.debug .bg-error{background-color:#ffbaba !important;color:#d8000c !important}.debug .bg-warn{background-color:#fefbe5 !important;color:#8a6d3b !important}.debug .bg-info{background-color:#d9edf7 !important;color:#31708f !important}.debug .fw-bold{font-weight:700}.debug .logentry-muted{opacity:0.5}.debug .logentry-muted.m_group.expanded{opacity:1}.debug .text-center{text-align:center}.debug .text-left{text-align:left !important}.debug .text-right{text-align:right !important}.debug .text-muted{opacity:.5}.debug .text-success{color:#3c763d}.debug .text-error{color:#d8000c}.debug .text-info{color:#31708f}.debug .text-warn{color:#8a6d3b} diff --git a/src/Debug/js/Debug.jquery.js b/src/Debug/js/Debug.jquery.js index 436a67a2..ea402b0e 100644 --- a/src/Debug/js/Debug.jquery.js +++ b/src/Debug/js/Debug.jquery.js @@ -113,7 +113,9 @@ $.each(config$1.iconsObject, function (selector, v) { var prepend = true; var sMatches = selector.match(/(?:parent(\S+)\s)?(?:context(\S+)\s)?(.*)$/); - var vMatches = v.match(/^([ap])\s*:(.+)$/); + var vMatches = typeof v === 'string' + ? v.match(/^([ap])\s*:(.+)$/) + : null; var $found; var $existingIcon; if (sMatches) { @@ -132,10 +134,13 @@ $found = $node.find(selector); if (prepend === false) { $found.append(v); + return } - $existingIcon = $found.find('> i:first-child'); - $existingIcon.after(v); - $found.not($existingIcon.parent()).prepend(v); + $existingIcon = $found.find('> i:first-child + i').after(v); + $found = $found.not($existingIcon.parent()); + $existingIcon = $found.find('> i:first-child').after(v); + $found = $found.not($existingIcon.parent()); + $found.prepend(v); }); } @@ -6315,6 +6320,18 @@ '> .property.debuginfo-excluded': '', '> .property.isDynamic': '', '> .property.isPromoted': '', + '> .property.getHook, > .property.setHook': function () { + var title = 'set hook'; + if ($(this).hasClass('getHook') && $(this).hasClass('setHook')) { + title = 'get and set hooks'; + } else if ($(this).hasClass('getHook')) { + title = 'get hook'; + } + return $('🪝').prop('title', title) + }, + '> .property.isDeprecated': '', + '> .property.isVirtual': '', + '> .property.isWriteOnly': '', '> .property > .t_modifier_magic': '', '> .property > .t_modifier_magic-read': '', '> .property > .t_modifier_magic-write': '', @@ -6384,7 +6401,9 @@ Config.prototype.get = function (key) { if (typeof key === 'undefined') { - return JSON.parse(JSON.stringify(this.config)) + // unable to use JSON.parse(JSON.stringify(this.config)) + // iconsObject functions are lost + return deepCopy(this.config) } return typeof this.config[key] !== 'undefined' ? this.config[key] @@ -6429,6 +6448,17 @@ } }; + function deepCopy (src) { + let target = Array.isArray(src) ? [] : {}; + for (let prop in src) { + let value = src[prop]; + target[prop] = value && typeof value === 'object' + ? deepCopy(value) + : value; + } + return target + } + function getDebugKey () { var key = null; var queryParams = queryDecode(); diff --git a/src/Debug/js/Debug.jquery.min.js b/src/Debug/js/Debug.jquery.min.js index ba077023..03c1fccf 100644 --- a/src/Debug/js/Debug.jquery.min.js +++ b/src/Debug/js/Debug.jquery.min.js @@ -1 +1 @@ -!function(h){"use strict";var C,O;function P(n){var t,e=n.find("> .array-inner");0 .t_array-expand").length||(h.trim(e.html()).length<1?n.addClass("expanded").find("br").hide():(e=(t=n).find("> .array-inner"),t.closest(".array-file-tree").length?(t.find("> .t_keyword, > .t_punct").remove(),e.find("> li > .t_operator, > li > .t_key.t_int").remove(),t.prevAll(".t_key").each(function(){var e=h(this).attr("data-toggle","array");t.prepend(e),t.prepend('')})):(e=h('array( ··· )'),t.find("> .t_keyword").first().wrap('').after('( ').parent().next().remove(),t.prepend(e)),h.each(C.iconsArray,function(e,t){n.find(e).prepend(t)}),n.debugEnhance(function(e){var t=e.data("expand"),n=e.parentsUntil(".m_group",".t_object, .t_array").length,a=0===n;void 0===t&&0!==n&&(t=e.closest(".t_array[data-expand]").data("expand"));void 0===t&&(t=a);return t||e.hasClass("array-file-tree")}(n)?"expand":"collapse")))}function F(e){O=e.data("config").get(),e.on("click","[data-toggle=vis]",function(){(e=h(e=this),t=e.data("vis"),n=e.closest(".t_object"),a=n.find("> .object-inner"),i=a.find("[data-toggle=vis][data-vis="+t+"]"),t="inherited"===t?"dd[data-inherited-from], .private-ancestor":"."+t,a=a.find(t),t=e.hasClass("toggle-off"),i.html(e.html().replace(t?"show ":"hide ",t?"hide ":"show ")).addClass(t?"toggle-on":"toggle-off").removeClass(t?"toggle-off":"toggle-on"),t)?(i=a).each(function(){var n=h(this),e=n.closest(".object-inner"),a=!0;e.find("> .vis-toggles [data-toggle]").each(function(){var e=h(this),t=e.hasClass("toggle-on"),e=e.data("vis");if(!t&&1===n.filter("inherited"===e?"dd[data-inherited-from], .private-ancestor":"."+e).length)return a=!1}),a&&n.show()}):a.hide();var e,t,n,a,i;return R(n,!0),!1}),e.on("click","[data-toggle=interface]",function(){return H(this),!1})}function I(e){e.find("> .classname, > .t_const").each(function(){var e=h(this),t=e.next(),n="object"===e.data("toggle");t.is(".t_maxDepth, .t_recursion, .excluded")?e.addClass("empty"):n||0!==t.length&&(e.wrap('').after(' '),t.hide())})}function H(e){var e=h(e),n=e.closest(".t_object");(e=e.is(".toggle-off")?e.add(e.next().find(".toggle-off")):e.add(e.next().find(".toggle-on"))).each(function(){var e=h(this),t=e.data("interface"),t=N(n,t);e.is(".toggle-off")?(e.addClass("toggle-on").removeClass("toggle-off"),t.show()):(e.addClass("toggle-off").removeClass("toggle-on"),t.hide())}),R(n)}function N(e,t){t='> .object-inner > dd[data-implements="'+CSS.escape(t)+'"]';return e.find(t)}function R(e,t){var n=t?".object-inner > .heading":"> .object-inner > .heading";e.find(t?".object-inner > dt":"> .object-inner > dt").each(function(e,t){var n=h(t).nextUntil("dt"),a=n.not(".heading").filter(function(e,t){return"none"!==h(t).css("display")}),n=0 .object-inner"),i=e.data("accessible"),r=null;e.is(".enhanced")||(a.find("> .private, > .protected").filter(".magic, .magic-read, .magic-write").removeClass("private protected"),"public"===i&&(a.find(".private, .protected").hide(),r="allDesc"),(t=e).find("> .object-inner").find("> dd > ul > li > .interface, > dd > ul > li > .interface + ul .interface").each(function(){var e=h(this).text();0!==N(t,e).length&&h(this).addClass("toggle-on").prop("title","toggle interface methods").attr("data-toggle","interface").attr("data-interface",e)}).filter(".toggle-off").removeClass("toggle-off").each(function(){H(this)}),i=i,i=function(e,t){var n=h('
'),a="public"===t?"toggle-off":"toggle-on",t="public"===t?"show":"hide",i={hasProtected:''+t+" protected",hasPrivate:''+t+" private",hasExcluded:'show excluded',hasInherited:'hide inherited'};return h.each(e,function(e,t){t&&n.append(i[e])}),n}({hasProtected:0<(n=a).children(".protected").not(".magic, .magic-read, .magic-write").length,hasPrivate:0 dd[class*=t_modifier_]").length?n.find("> dd[class*=t_modifier_]").last().after(i):n.prepend(i),o=a,h.each(O.iconsObject,function(e,t){var n=!0,a=e.match(/(?:parent(\S+)\s)?(?:context(\S+)\s)?(.*)$/),i=t.match(/^([ap])\s*:(.+)$/);if(a){if(a[1]&&0===o.parent().filter(a[1]).length)return;a[2]&&(o=o.filter(a[2])),e=a[3]}i&&(n="p"===i[1],t=i[2]),a=o.find(e),!1===n&&a.append(t),(i=a.find("> i:first-child")).after(t),a.not(i.parent()).prepend(t)}),a.find("> .property.forceShow").show().find("> .t_array").debugEnhance("expand"),r&&R(e,"allDesc"===r),e.addClass("enhanced"))}});function W(){var e=h(this).closest(".show-more-container");e.find(".show-more-wrapper").css("display","block").animate({height:"70px"}),e.find(".show-more-fade").fadeIn(),e.find(".show-more").show(),e.find(".show-less").hide()}function $(){var e=h(this).closest(".show-more-container");e.find(".show-more-wrapper").animate({height:e.find(".t_string").height()},400,"swing",function(){h(this).css("display","inline")}),e.find(".show-more-fade").fadeOut(),e.find(".show-more").hide(),e.find(".show-less").show()}function U(e){var t="https://symbl.cc/en/"+h(this).data("codePoint");e.stopPropagation(),window.open(t,"unicode").focus()}function z(e){var t=h(e.target),n=t.closest("li[class*=m_]");e.stopPropagation(),t.find("> .array-inner > li > :last-child, > .array-inner > li[class]").each(function(){q(this,n)})}function K(e){var t=h(e.target);e.stopPropagation(),t.find("> .group-body").debugEnhance()}function J(e){var t=h(e.target),n=t.closest("li[class*=m_]");e.stopPropagation(),t.is(".enhanced")||(t.find("> .object-inner").find("> .constant > :last-child,> .property > :last-child,> .method .t_string").each(function(){q(this,n)}),B.enhanceInner(t))}function Y(e){e=h(e.target),e=e.hasClass("t_array")?e.find("> .array-inner").find("> li > .t_string, > li.t_string"):e.hasClass("m_group")?e.find("> .group-body > li > .t_string"):e.hasClass("t_object")?e.find("> .object-inner").find(["> dd.constant > .t_string","> dd.property:visible > .t_string","> dd.method > ul > li > .t_string.return-value"].join(", ")):h();e.not("[data-type-more=numeric]").each(function(){var e;35<(e=h(this)).height()-70&&((e=e.wrap('
').parent()).append('
'),(e=e.wrap('
').parent()).append(''),e.append(''))})}function G(e){var s=h(e),e=s.find("> thead");s.is("table.sortable")&&(s.addClass("table-sort"),e.on("click","th",function(){var e,t=h(this),n=h(this).closest("tr").children(),a=n.index(t),i="desc"==(t.is(".sort-asc")?"asc":"desc")?"asc":"desc",n=(n.removeClass("sort-asc sort-desc"),t.addClass("sort-"+i),t.find(".sort-arrows").length||(n.find(".sort-arrows").remove(),t.append('')),s[0]),t=a,a=i,o=n.tBodies[0],r=o.rows,n="function"==typeof Intl.Collator?new Intl.Collator([],{numeric:!0,sensitivity:"base"}):null;for(a="desc"===a?-1:1,r=(r=Array.prototype.slice.call(r,0)).sort(function(i,o,r){var s=/^([+-]?(?:0|[1-9]\d*)(?:\.\d*)?)(?:[eE]([+-]?\d+))?$/;return function(e,t){var e=e.cells[i].textContent.trim(),t=t.cells[i].textContent.trim(),n=e.match(s),a=t.match(s);return n&&a?o*function(e,t){if(e .object-inner > .property.debug-value > .t_identifier").filter(function(){return this.innerText.match(/^file$/)}),a=!0===e.data("detectFiles")||0 *:last-child").remove()}else a.find("table thead tr > *:last-child").after("");a.find("table tbody tr").each(function(){var e,t,n,a;e=h(this),t=o,n=e.find("> td"),a={file:e.data("file")||n.eq(0).text(),line:e.data("line")||n.eq(1).text()},a=h("",{class:"file-link",href:Z(a.file,a.line),html:'',style:"vertical-align: bottom",title:"Open in editor"}),t?e.find(".file-link").replaceWith(a):e.hasClass("context")?n.eq(0).attr("colspan",parseInt(n.eq(0).attr("colspan"),10)+1):n.last().after(h("",{class:"text-center",html:a}))})}else e.is("[data-file]")?(i=n,(a=e).find("> .file-link").remove(),i||a.append(h("",{html:'',href:Z(a.data("file"),a.data("line")),title:"Open in editor",class:"file-link lpad"})[0].outerHTML)):(a=t,l=n,c=(t=e).data("foundFiles")||[],a=(a=t.is(".m_table")?t.find("> table > tbody > tr > .t_string"):a)||[],h.each(a,function(){var e,t,n,a,i,o,r,s;t=l,n=c,o=h(e=this),e=e.attributes,r=h.trim(o.text()),n=function(e,t){var n=[],a=h.trim(e.text());if(e.data("file"))return"boolean"==typeof e.data("file")?[null,a,1]:[null,e.data("file"),e.data("line")||1];if(0===t.indexOf(a))return[null,a,1];if(e.parent(".property.debug-value").find("> .t_identifier").text().match(/^file$/))return n={line:1},e.parent().parent().find("> .property.debug-value").each(function(){var e=h(this).find("> .t_identifier")[0].innerText,t=h(this).find("> *:last-child"),t=h.trim(t[0].innerText);n[e]=t}),[null,a,n.line];return a.match(/^(\/.+\.php)(?: \(line (\d+)(, eval'd line \d+)?\))?$/)||[]}(o,n),s=!0!==t&&o.hasClass("file-link"),o.closest(".m_trace").length?d(o.closest(".m_trace")):n.length&&(n=function(e,t,n,a,i){var o;a?(o=h("",{text:n}),e.removeClass("file-link")):i?(o=e).prop("href",Z(t[1],t[2])):o=h("",{class:"file-link",href:Z(t[1],t[2]),html:n+' ',title:"Open in editor"});return o}(o,n,r,t,s),!1===s&&(a=o,i=n,s=e,h.each(s,function(){var e;void 0===this||(e=this.name,-1<["html","href","title"].indexOf(e))||("class"===e?(i.addClass(this.value),a.removeClass("t_string")):(i.attr(e,this.value),a.removeAttr(e)))}),s.style)&&i.attr("style",s.style.value),o.is("td, th, li")?o.html(t?r:n):o.replaceWith(n))}))}function Z(e,t){var n={file:e,line:t||1};return r.linkFilesTemplate.replace(/%(\w*)\b/g,function(e,t){return Object.prototype.hasOwnProperty.call(n,t)?n[t]:""})}var i,o,ie,oe,re=[],se=!1;function le(e){var t;s=e.data("config").get(),C=e.data("config").get(),F(e),q=l,B=V,(t=e).on("click",".close[data-dismiss=alert]",function(){h(this).parent().remove()}),t.on("click",".show-more-container .show-less",W),t.on("click",".show-more-container .show-more",$),t.on("click",".char-ws, .unicode",U),t.on("expand.debug.array",z),t.on("expand.debug.group",K),t.on("expand.debug.object",J),t.on("expanded.debug.next",".context",function(e){q(h(e.target).find("> td > .t_array"),h(e.target).closest("li"))}),t.on("expanded.debug.array expanded.debug.group expanded.debug.object",Y),Q(e)}function ce(e){var t=e.parent(),t=!t.hasClass("m_group")||t.hasClass("expanded");if(e.hide(),e.children().each(function(){de(h(this))}),t&&e.show().trigger("expanded.debug.group"),!se){for(se=!0;re.length;)re.shift().debugEnhance("expand");se=!1}!1===e.parent().hasClass("m_group")&&e.addClass("enhanced")}function de(e){if(!e.hasClass("enhanced")){if(e.hasClass("m_group"))i=(a=e).find("> .group-header"),o=i.next(),fe(a),fe(i),i.attr("data-toggle","group"),i.find(".t_array, .t_object").each(function(){h(this).data("expand",!1),l(this,a)}),h.each(["level-error","level-info","level-warn"],function(e,t){var n;a.hasClass(t)&&(n=i.children("i").eq(0),i.wrapInner(''),i.prepend(n))}),a.hasClass("expanded")||o.find(".m_error, .m_warn").not(".filter-hidden").not("[data-uncollapse=false]").length?re.push(i):i.debugEnhance("collapse",!0);else{if(e.hasClass("filter-hidden"))return;var t,n;e.is(".m_table, .m_trace")?(d(t=e),fe(t),t.hasClass("m_table")&&t.find("> table > tbody > tr > td").each(function(){l(this,t)}),t.find("tbody > tr.expanded").next().trigger("expanded.debug.next"),G(t.find("> table"))):((n=e).data("file")&&(n.attr("title")||(o=n.data("file")+": line "+n.data("line"),n.data("evalline")&&(o+=" (eval'd line "+n.data("evalline")+")"),n.attr("title",o)),d(n)),fe(n),n.children().each(function(){l(this,n)}))}var a,i,o;e.addClass("enhanced"),e.trigger("enhanced.debug")}}function l(e,t){e=h(e);e.is(".t_array")?P(e):e.is(".t_object")?I(e):e.is("table")?G(e):e.is(".t_string")?d(t,e):e.is(".string-encoded.tabs-container")&&l(e.find("> .tab-pane.active > *"),t)}function fe(e){var t,n,a,i,o=function(e){var t,n,a;if(e.data("icon"))return e.data("icon").match("<")?h(e.data("icon")):h("").addClass(e.data("icon"));if(!e.hasClass("m_group"))for(a in n=e.hasClass("group-header")?e.parent():e,s.iconsMethods)if(n.is(a)){t=h(s.iconsMethods[a]);break}return t}(e),r=e;for(i in s.iconsMisc)0!==(a=r.find(i)).length&&(n=h(s.iconsMisc[i]),n=(a.find("> i:first-child").hasClass(n.attr("class"))||a.prepend(n),null));o&&(e.hasClass("m_group")?e=e.find("> .group-header .group-label").eq(0):e.find("> table").length&&((t=e.find("> table > caption")).length||(t=h(""),e.find("> table").prepend(t)),e=t),e.find("> i:first-child").hasClass(o.attr("class"))||e.prepend(o))}function pe(e){(o=(i=e).data("config")).get("drawer")&&(i.addClass("debug-drawer debug-enhanced-ui"),(e=i.find(".debug-menu-bar")).before('
PHP
'),e.find(".float-right").append(''),i.find(".tab-panes").scrollLock(),i.find(".debug-resize-handle").on("mousedown",me),i.find(".debug-pull-tab").on("click",ue),i.find(".debug-menu-bar .close").on("click",ge),o.get("persistDrawer"))&&o.get("openDrawer")&&ue()}function ue(){i.addClass("debug-drawer-open"),i.debugEnhance(),ve(),h("body").css("marginBottom",i.height()+8+"px"),h(window).on("resize",ve),o.get("persistDrawer")&&o.set("openDrawer",!0)}function ge(){i.removeClass("debug-drawer-open"),h("body").css("marginBottom",""),h(window).off("resize",ve),o.get("persistDrawer")&&o.set("openDrawer",!1)}function he(e){ve(ie+(oe-e.pageY),!0)}function me(e){h(e.target).closest(".debug-drawer").is(".debug-drawer-open")&&(ie=i.find(".tab-panes").height(),oe=e.pageY,h("html").addClass("debug-resizing"),i.parents().on("mousemove",he).on("mouseup",be),e.preventDefault())}function be(){h("html").removeClass("debug-resizing"),i.parents().off("mousemove",he).off("mouseup",be),h("body").css("marginBottom",i.height()+8+"px")}function ve(e,t){var n=i.find(".tab-panes"),a=i.find(".debug-menu-bar").outerHeight(),a=window.innerHeight-a-50;e=function(e){var t=i.find(".tab-panes");if(e&&"object"!=typeof e)return e;!(e=parseInt(t[0].style.height,10))&&o.get("persistDrawer")&&(e=o.get("height"));return e||100}(e),e=Math.min(e,a),e=Math.max(e,20),n.css("height",e),t&&o.get("persistDrawer")&&o.set("height",e)}h.fn.scrollLock=function(e){return(e=void 0===e||e)?void h(this).on("DOMMouseScroll mousewheel wheel",function(e){function t(){return e.stopPropagation(),e.preventDefault(),e.returnValue=!1}var n=h(this),a=this.scrollTop,i=this.scrollHeight,o=n.innerHeight(),r=e.originalEvent.wheelDelta,s=0 .tab-body > hr").toggleClass("filter-hidden",0 .tab-body").find(" > .debug-log-summary, > .debug-log").filter(function(){return h(this).height()<1}).length)}function ke(){var e=h(this),t=e.is(":checked"),n=e.closest("label").next("ul").find("input"),a=e.closest(".debug");0 .tab-panes > .tab-primary > .tab-body").find(".m_alert, .group-body > *:not(.m_groupSummary)").each(function(){s.push({depth:h(this).parentsUntil(".tab_body").length,node:h(this)})}),s.sort(function(e,t){return e.depth .group-body").debugEnhance()}(l),o)&&l.hasClass("m_group")&&l.trigger("collapsed.debug.group")}_e(e.find("> .tab-panes > .tab-pane.active")),Ee(e)}function Ee(e){var t=0'),a.get("drawer")||e.find("input[name=persistDrawer]").closest("label").remove(),n.find(".debug-options-toggle").on("click",Ie),h("input[name=debugCookie]").on("change",Fe).prop("checked",a.get("debugKey")&&Te("debug")===a.get("debugKey")),a.get("debugKey")||h("input[name=debugCookie]").prop("disabled",!0).closest("label").addClass("disabled"),h("input[name=persistDrawer]").on("change",Re).prop("checked",a.get("persistDrawer")),n.find("input[name=linkFiles]").on("change",He).prop("checked",a.get("linkFiles")).trigger("change"),n.find("input[name=linkFilesTemplate]").on("change",Ne).val(a.get("linkFilesTemplate"))}function Me(e){0===n.find(".debug-options").find(e.target).length&&Be()}function Pe(e){e.keyCode===Le&&Be()}function Fe(){h(this).is(":checked")?je("debug",a.get("debugKey"),7):je("debug","",-1)}function Ie(e){var t=h(this).closest(".debug-bar").find(".debug-options").is(".show");n=h(this).closest(".debug"),t?Be():(n.find(".debug-options").addClass("show"),h("body").on("click",Me),h("body").on("keyup",Pe)),e.stopPropagation()}function He(){var e=h(this).prop("checked"),t=h(this).closest(".debug-options").find("input[name=linkFilesTemplate]").closest(".form-group");e?t.slideDown():t.slideUp(),a.set("linkFiles",e),h("input[name=linkFilesTemplate]").trigger("change")}function Ne(){var e=h(this).val();a.set("linkFilesTemplate",e),n.trigger("config.debug.updated","linkFilesTemplate")}function Re(){var e=h(this).is(":checked");a.set({persistDrawer:e,openDrawer:e,openSidebar:!0})}function Be(){n.find(".debug-options").removeClass("show"),h("body").off("click",Me),h("body").off("keyup",Pe)}var qe,f,p,Ve=!1,We={alert:'Alerts',error:'Error',warn:'Warning',info:'Info',other:'Other'},$e='
';function Ue(e){t=e.data("config")||h("body").data("config"),(De=e.find("> .tab-panes > .tab-primary").data("options")||{}).sidebar&&Xe(e),t.get("persistDrawer")&&!t.get("openSidebar")&&Qe(e),e.on("click",".close[data-dismiss=alert]",Ke),e.on("click",".sidebar-toggle",Je),e.on("change",".debug-sidebar input[type=checkbox]",ze),Ve||(xe.push(Ge),we.push(Ye),Ve=!0)}function ze(e){var t=h(this),n=t.closest(".toggle"),a=n.next("ul").find(".toggle"),i=t.is(":checked"),o=h(".m_alert.error-summary.have-fatal");n.toggleClass("active",i),a.toggleClass("active",i),"fatal"===t.val()&&(o.find(".error-fatal").toggleClass("filter-hidden",!i),o.toggleClass("filter-hidden",0===o.children().not(".filter-hidden").length))}function Ke(e){var t=h(e.delegateTarget);setTimeout(function(){0===t.find(".tab-primary > .tab-body > .m_alert").length&&t.find(".debug-sidebar input[data-toggle=method][value=alert]").parent().addClass("disabled")})}function Je(){var e=h(this).closest(".debug");(e.find(".debug-sidebar").is(".show")?Qe:Ze)(e)}function Ye(e){var t=e[0].className.match(/\bm_(\S+)\b/),t=t?t[1]:null;return!De.sidebar||("group"===t&&e.find("> .group-body")[0].className.match(/level-(error|info|warn)/)&&(t=e.find("> .group-body")[0].className.match(/level-(error|info|warn)/)[1],e.toggleClass("filter-hidden-body",c.indexOf(t)<0)),-1<["alert","error","warn","info"].indexOf(t)?-1 .tab-primary > .tab-body > .expand-all"),s=(e.find(".tab-panes > .tab-primary > .tab-body").before(o),l=(l=e).closest(".debug").find(".m_alert.error-summary"),(s=l.find(".in-console")).prev().remove(),s.remove(),0===l.children().length&&l.remove(),i=(a=e).find(".debug-sidebar .php-errors ul"),h.each(["fatal","error","warning","deprecated","notice","strict"],function(e,t){var n=("fatal"===t?a.find(".m_alert.error-summary.have-fatal"):a.find(".error-"+t).filter(".m_error,.m_warn")).length;0!==n&&i.append(h("
  • ").append(h('