From 90dd6232124cdd859f73f31de26e8ec785982cc1 Mon Sep 17 00:00:00 2001 From: Brad Kent Date: Thu, 25 Jan 2024 13:46:39 -0600 Subject: [PATCH] type-hints / static analysis (primary focus on HttpMessage) Javascript fixes Update phpDoc types list --- src/Backtrace/Backtrace.php | 15 +- src/Backtrace/Context.php | 14 +- src/Backtrace/Normalizer.php | 4 +- src/Backtrace/SkipInternal.php | 7 +- src/Backtrace/Xdebug.php | 6 +- src/Container/Container.php | 25 +- src/CurlHttpMessage/Client.php | 3 + src/CurlHttpMessage/ClientAsync.php | 1 + src/CurlHttpMessage/CurlReqRes.php | 6 +- src/Debug/AbstractComponent.php | 3 +- src/Debug/AbstractDebug.php | 15 +- src/Debug/Collector/MySqli.php | 6 +- src/Debug/LogEntry.php | 4 +- src/Debug/Plugin/Channel.php | 1 + src/Debug/Plugin/Manager.php | 3 + src/Debug/Plugin/Method/Alert.php | 6 +- src/Debug/Plugin/Method/Basic.php | 11 +- src/Debug/Plugin/Method/Clear.php | 3 +- src/Debug/Plugin/Method/Count.php | 6 +- src/Debug/Plugin/Method/General.php | 3 +- src/Debug/Plugin/Method/Group.php | 12 +- src/Debug/Plugin/Method/GroupStack.php | 7 +- src/Debug/Plugin/Method/Output.php | 7 +- src/Debug/Plugin/Method/Profile.php | 19 +- src/Debug/Plugin/Method/ReqRes.php | 6 +- src/Debug/Plugin/Method/Table.php | 4 +- src/Debug/Plugin/Method/Time.php | 11 +- src/Debug/Plugin/Method/Trace.php | 5 +- src/Debug/Plugin/Prettify.php | 2 + src/Debug/Plugin/Redaction.php | 3 +- src/Debug/Plugin/Route.php | 4 +- src/Debug/Utility/ArrayUtil.php | 11 +- src/Debug/Utility/Php.php | 1 + src/Debug/Utility/PhpDoc/Type.php | 22 +- src/Debug/Utility/Profile.php | 3 +- src/Debug/Utility/StopWatch.php | 7 +- src/Debug/js/Debug.jquery.js | 73 ++- src/Debug/js/Debug.jquery.min.js | 2 +- src/Debug/js_src/enhanceEntries.js | 2 +- src/Debug/js_src/filter.js | 45 +- src/HttpMessage/AbstractServerRequest.php | 314 ---------- src/HttpMessage/AbstractStream.php | 10 +- src/HttpMessage/AbstractUri.php | 89 +-- src/HttpMessage/AssertionTrait.php | 76 ++- src/HttpMessage/HttpFoundationBridge.php | 58 +- src/HttpMessage/Message.php | 33 +- src/HttpMessage/Request.php | 2 +- src/HttpMessage/Response.php | 117 +--- src/HttpMessage/ServerRequest.php | 140 +++-- src/HttpMessage/Stream.php | 34 +- src/HttpMessage/UploadedFile.php | 49 +- src/HttpMessage/Uri.php | 39 +- src/HttpMessage/Utility/ParseStr.php | 138 +++++ src/HttpMessage/Utility/Response.php | 107 ++++ src/HttpMessage/Utility/ServerRequest.php | 238 ++++++++ src/HttpMessage/Utility/Uri.php | 186 +++++- src/Promise/Promise.php | 9 +- src/Promise/TaskQueue.php | 1 + src/Promise/Utils.php | 1 + src/PubSub/ValueStore.php | 14 +- src/Slack/AbstractBlockFactory.php | 1 + src/Slack/AbstractSlack.php | 1 + src/Slack/BlockElementsFactory.php | 14 +- src/Teams/AbstractItem.php | 1 + src/Teams/CardUtilityTrait.php | 2 +- src/Teams/ItemInterface.php | 2 +- src/Teams/Section.php | 1 + src/Teams/TeamsWebhook.php | 4 +- tests/Debug/Type/StringTest.php | 23 + tests/HttpMessage/ResponseTest.php | 5 - tests/HttpMessage/ServerRequestTest.php | 546 +++--------------- tests/HttpMessage/UriTest.php | 48 -- tests/HttpMessage/Utility/ResponseTest.php | 9 +- .../HttpMessage/Utility/ServerRequestTest.php | 392 +++++++++++++ tests/HttpMessage/Utility/UriTest.php | 74 ++- tests/HttpMessage/{ => Utility}/input.json | 0 tests/HttpMessage/{ => Utility}/input.txt | 0 77 files changed, 1807 insertions(+), 1359 deletions(-) delete mode 100644 src/HttpMessage/AbstractServerRequest.php create mode 100644 src/HttpMessage/Utility/ParseStr.php create mode 100644 src/HttpMessage/Utility/ServerRequest.php create mode 100644 tests/HttpMessage/Utility/ServerRequestTest.php rename tests/HttpMessage/{ => Utility}/input.json (100%) rename tests/HttpMessage/{ => Utility}/input.txt (100%) diff --git a/src/Backtrace/Backtrace.php b/src/Backtrace/Backtrace.php index a88a2d54..a2f6ef3a 100644 --- a/src/Backtrace/Backtrace.php +++ b/src/Backtrace/Backtrace.php @@ -4,7 +4,7 @@ * @package Backtrace * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2020-2023 Brad Kent + * @copyright 2020-2024 Brad Kent * @version v2.2 * @link http://www.github.com/bkdotcom/Backtrace */ @@ -16,7 +16,9 @@ use bdk\Backtrace\SkipInternal; use bdk\Backtrace\Xdebug; use Exception; +use InvalidArgumentException; use ParseError; +use Throwable; /** * Utility for getting backtrace @@ -31,6 +33,7 @@ class Backtrace const INCL_ARGS = 1; const INCL_OBJECT = 2; + /** @var array */ protected static $callerInfoDefault = array( 'args' => array(), 'class' => null, // where the method is defined @@ -67,7 +70,7 @@ public static function addInternalClass($classes, $level = 0) * @param int $limit limit the number of stack frames returned. * @param \Exception|\Throwable $exception (optional) Exception from which to get backtrace * - * @return array + * @return array[] */ public static function get($options = 0, $limit = 0, $exception = null) { @@ -76,7 +79,7 @@ public static function get($options = 0, $limit = 0, $exception = null) $trace = $exception ? self::getExceptionTrace($exception) : (\array_reverse(Xdebug::getFunctionStack() ?: array()) - ?: \debug_backtrace($debugBacktraceOpts, $limit ? $limit + 2 : 0)); + ?: \debug_backtrace($debugBacktraceOpts, $limit > 0 ? $limit + 2 : 0)); $trace = Normalizer::normalize($trace); $trace = SkipInternal::removeInternalFrames($trace); // keep the calling file & line, but toss the called function (what initiated trace) @@ -138,7 +141,7 @@ public static function getCallerInfo($offset = 0, $options = 0) * @param array $backtrace backtrace frames * @param int $length number of lines to include * - * @return array backtrace + * @return array[] backtrace */ public static function addContext(array $backtrace, $length = 19) { @@ -166,7 +169,7 @@ public static function getFileLines($file, $start = null, $length = null) * * @param array $backtrace backtrace * - * @return array + * @return array[] */ private static function callerInfoBuild(array $backtrace) { @@ -270,7 +273,7 @@ private static function parseFunction($function) /** * Convert our additive options to PHP's options * - * @param int $options bitmask options + * @param int|null $options bitmask options * * @return int */ diff --git a/src/Backtrace/Context.php b/src/Backtrace/Context.php index 215db13b..e8156128 100644 --- a/src/Backtrace/Context.php +++ b/src/Backtrace/Context.php @@ -4,7 +4,7 @@ * @package Backtrace * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2020-2023 Brad Kent + * @copyright 2020-2024 Brad Kent * @version v2.2 * @link http://www.github.com/bkdotcom/Backtrace */ @@ -55,9 +55,9 @@ public static function add(array $backtrace, $length = 19) * * Returns array of lineNumber => line * - * @param string $file filepath - * @param int $start line to start on (1 = first line) - * @param int $length number of lines to return + * @param string $file filepath + * @param int|null $start line to start on (1 = first line) + * @param int|null $length number of lines to return * * @return array|false false if file doesn't exist */ @@ -116,9 +116,9 @@ private static function findEvalCode(array $backtrace, $index) * * Essentially array_slice but one-based vs zero-based * - * @param array $lines lines of code - * @param int $start line to start on (1 = first line) - * @param int $length number of lines to return + * @param array $lines lines of code + * @param int|null $start line to start on (1 = first line) + * @param int|null $length number of lines to return * * @return array */ diff --git a/src/Backtrace/Normalizer.php b/src/Backtrace/Normalizer.php index 7d940f16..1f1f6884 100644 --- a/src/Backtrace/Normalizer.php +++ b/src/Backtrace/Normalizer.php @@ -4,7 +4,7 @@ * @package Backtrace * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2020-2023 Brad Kent + * @copyright 2020-2024 Brad Kent * @version v2.2 * @link http://www.github.com/bkdotcom/Backtrace */ @@ -16,8 +16,10 @@ */ class Normalizer { + /** @var array */ private static $backtraceTemp = array(); + /** @var array */ private static $frameDefault = array( 'args' => array(), 'evalLine' => null, diff --git a/src/Backtrace/SkipInternal.php b/src/Backtrace/SkipInternal.php index dbcfa256..deb01dca 100644 --- a/src/Backtrace/SkipInternal.php +++ b/src/Backtrace/SkipInternal.php @@ -4,7 +4,7 @@ * @package Backtrace * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2020-2023 Brad Kent + * @copyright 2020-2024 Brad Kent * @version v2.2 * @link http://www.github.com/bkdotcom/Backtrace */ @@ -54,7 +54,10 @@ class SkipInternal public static function addInternalClass($classes, $level = 0) { if (\is_int($level) === false) { - throw new InvalidArgumentException(\sprintf('level must be an integer')); + throw new InvalidArgumentException(\sprintf( + 'level must be an integer. %s provided.', + \gettype($level) + )); } if (\is_array($classes) === false) { $classes = array($classes => $level); diff --git a/src/Backtrace/Xdebug.php b/src/Backtrace/Xdebug.php index ce9f3a80..8e7091b1 100644 --- a/src/Backtrace/Xdebug.php +++ b/src/Backtrace/Xdebug.php @@ -4,7 +4,7 @@ * @package Backtrace * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2020-2023 Brad Kent + * @copyright 2020-2024 Brad Kent * @version v2.2 * @link http://www.github.com/bkdotcom/Backtrace */ @@ -26,7 +26,7 @@ class Xdebug * * @param int $maxDepth set xdebug.var_display_max_depth ini/config * - * @return array|false + * @return array[]|false * * @see https://bugs.xdebug.org/view.php?id=695 * @see https://bugs.xdebug.org/view.php?id=1529 @@ -39,7 +39,7 @@ public static function getFunctionStack($maxDepth = 3) } $vdmdKey = 'xdebug.var_display_max_depth'; $vdmdBak = \ini_get($vdmdKey); - \ini_set($vdmdKey, $maxDepth); + \ini_set($vdmdKey, (string) $maxDepth); $stack = \xdebug_get_function_stack(); \ini_set($vdmdKey, $vdmdBak); // phpcs:ignore SlevomatCodingStandard.Namespaces.FullyQualifiedGlobalFunctions.NonFullyQualified diff --git a/src/Container/Container.php b/src/Container/Container.php index 071920d1..0a74a7fa 100644 --- a/src/Container/Container.php +++ b/src/Container/Container.php @@ -6,7 +6,7 @@ * @package PHPDebugConsole * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2014-2022 Brad Kent + * @copyright 2014-2024 Brad Kent * @version v3.0 */ @@ -31,6 +31,7 @@ */ class Container implements \ArrayAccess { + /** @var array */ private $cfg = array( 'allowOverride' => false, // whether can update alreay built service 'onInvoke' => null, // callable @@ -43,8 +44,10 @@ class Container implements \ArrayAccess */ private $factories; + /** @var array */ private $invoked = array(); // keep track of invoked service closures + /** @var array */ private $keys = array(); /** @@ -55,8 +58,10 @@ class Container implements \ArrayAccess */ private $protected; + /** @var array */ private $raw = array(); + /** @var array */ private $values = array(); /** @@ -207,26 +212,26 @@ public function offsetGet($name) * ArrayAccess * Sets a parameter or an object. * - * @param string $name The unique identifier for the parameter or object - * @param mixed $value The value of the parameter or a closure to define an object + * @param string $offset The unique identifier for the parameter or object + * @param mixed $value The value of the parameter or a closure to define an object * * @throws \RuntimeException Prevent override of a already built service * @return void */ #[\ReturnTypeWillChange] - public function offsetSet($name, $value) + public function offsetSet($offset, $value) { - if (isset($this->invoked[$name]) && $this->cfg['allowOverride'] === false) { + if (isset($this->invoked[$offset]) && $this->cfg['allowOverride'] === false) { throw new \RuntimeException( - \sprintf('Cannot update "%s" after it has been instantiated.', $name) + \sprintf('Cannot update "%s" after it has been instantiated.', $offset) ); } - $this->keys[$name] = true; - $this->values[$name] = $value; + $this->keys[$offset] = true; + $this->values[$offset] = $value; unset( - $this->invoked[$name], - $this->raw[$name] + $this->invoked[$offset], + $this->raw[$offset] ); } diff --git a/src/CurlHttpMessage/Client.php b/src/CurlHttpMessage/Client.php index 2025b5ef..f9524c37 100644 --- a/src/CurlHttpMessage/Client.php +++ b/src/CurlHttpMessage/Client.php @@ -2,11 +2,14 @@ namespace bdk\CurlHttpMessage; +use bdk\CurlHttpMessage\Exception\NetworkException; use bdk\CurlHttpMessage\Factory; use bdk\CurlHttpMessage\HandlerStack; use bdk\Promise\PromiseInterface; use InvalidArgumentException; use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\UriInterface; /** * Lightweight PSR-7 (HttpMessage) based cURL client diff --git a/src/CurlHttpMessage/ClientAsync.php b/src/CurlHttpMessage/ClientAsync.php index deea4566..19bfed60 100644 --- a/src/CurlHttpMessage/ClientAsync.php +++ b/src/CurlHttpMessage/ClientAsync.php @@ -4,6 +4,7 @@ use bdk\Promise; use bdk\Promise\EachPromise; +use bdk\Promise\PromiseInterface; use InvalidArgumentException; use Psr\Http\Message\RequestInterface; diff --git a/src/CurlHttpMessage/CurlReqRes.php b/src/CurlHttpMessage/CurlReqRes.php index f96fd1ec..9e2cef6a 100644 --- a/src/CurlHttpMessage/CurlReqRes.php +++ b/src/CurlHttpMessage/CurlReqRes.php @@ -15,7 +15,7 @@ */ class CurlReqRes { - /** @var resource|CurlHandle */ + /** @var resource|\CurlHandle */ private $curlHandle; /** @var bool */ @@ -127,7 +127,7 @@ public function finish() * * @param bool $create (false) whether handle should be created * - * @return resource|CurlHandle|null + * @return resource|\CurlHandle|null */ public function getCurlHandle($create = false) { @@ -143,7 +143,7 @@ public function getCurlHandle($create = false) * * If setting, also sets curl options * - * @param resource|CurlHandle|null $curlHandle curlHandle + * @param resource|\CurlHandle|null $curlHandle curlHandle * * @return self */ diff --git a/src/Debug/AbstractComponent.php b/src/Debug/AbstractComponent.php index 9b55b457..27ed3938 100644 --- a/src/Debug/AbstractComponent.php +++ b/src/Debug/AbstractComponent.php @@ -6,7 +6,7 @@ * @package PHPDebugConsole * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2014-2022 Brad Kent + * @copyright 2014-2024 Brad Kent * @version v3.0 */ @@ -20,5 +20,6 @@ */ abstract class AbstractComponent extends BaseAbstractComponent implements ConfigurableInterface { + /** @var callable */ protected $setCfgMergeCallable = 'array_merge'; } diff --git a/src/Debug/AbstractDebug.php b/src/Debug/AbstractDebug.php index 1864312e..2512c6ca 100644 --- a/src/Debug/AbstractDebug.php +++ b/src/Debug/AbstractDebug.php @@ -23,23 +23,32 @@ /** * Handle underlying Debug bootstraping and config + * + * @psalm-consistent-constructor */ class AbstractDebug { /** @var \bdk\Debug\Config */ protected $config; - /** @var \bdk\Container */ + /** @var Container */ protected $container; + /** @var Container */ protected $serviceContainer; - /** @var \bdk\Debug */ + /** @var Debug|null */ protected static $instance; + /** @var array */ protected static $methodDefaultArgs = array(); + + /** @var Debug|null */ protected $parentInstance; + + /** @var Debug */ protected $rootInstance; + /** @var array */ protected $readOnly = array( 'parentInstance', 'rootInstance', @@ -50,7 +59,7 @@ class AbstractDebug * * @param array $cfg config */ - public function __construct($cfg) + public function __construct($cfg = array()) { if (!isset(self::$instance)) { // self::getInstance() will always return initial/first instance diff --git a/src/Debug/Collector/MySqli.php b/src/Debug/Collector/MySqli.php index 42a73fb8..a5613b49 100644 --- a/src/Debug/Collector/MySqli.php +++ b/src/Debug/Collector/MySqli.php @@ -6,7 +6,7 @@ * @package PHPDebugConsole * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2014-2022 Brad Kent + * @copyright 2014-2024 Brad Kent * @version v3.0 */ @@ -173,9 +173,9 @@ public function prepare($query) * {@inheritDoc} */ #[\ReturnTypeWillChange] - public function query($query, $resultmode = MYSQLI_STORE_RESULT) + public function query($query, $resultMode = MYSQLI_STORE_RESULT) { - return $this->profileCall('query', $query, array($query, $resultmode)); + return $this->profileCall('query', $query, array($query, $resultMode)); } /** diff --git a/src/Debug/LogEntry.php b/src/Debug/LogEntry.php index 08e87a9e..68dbd57a 100644 --- a/src/Debug/LogEntry.php +++ b/src/Debug/LogEntry.php @@ -6,7 +6,7 @@ * @package PHPDebugConsole * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2014-2022 Brad Kent + * @copyright 2014-2024 Brad Kent * @version v3.0 */ @@ -24,7 +24,7 @@ class LogEntry extends Event implements JsonSerializable /** * Regular expression for determining if argument contains "substitutions" * - * @var string + * @var non-empty-string */ public $subRegex = '/% (?: diff --git a/src/Debug/Plugin/Channel.php b/src/Debug/Plugin/Channel.php index 94f7a5c1..f1e091d6 100644 --- a/src/Debug/Plugin/Channel.php +++ b/src/Debug/Plugin/Channel.php @@ -25,6 +25,7 @@ class Channel implements SubscriberInterface private $channels = array(); + /** @var string[] */ protected $methods = array( 'getChannel', 'getChannels', diff --git a/src/Debug/Plugin/Manager.php b/src/Debug/Plugin/Manager.php index 0579b74d..5d8d534d 100644 --- a/src/Debug/Plugin/Manager.php +++ b/src/Debug/Plugin/Manager.php @@ -32,6 +32,7 @@ class Manager implements SubscriberInterface, PluginInterface { use CustomMethodTrait; + /** @var string[] */ protected $methods = array( 'addPlugin', 'addPlugins', @@ -43,8 +44,10 @@ class Manager implements SubscriberInterface, PluginInterface /** @var SplObjectStorage */ protected $registeredPlugins; + /** @var array */ protected $namedPlugins = array(); + /** @var bool */ private $isBootstrapped = false; /** diff --git a/src/Debug/Plugin/Method/Alert.php b/src/Debug/Plugin/Method/Alert.php index c00d20d5..06977e1b 100644 --- a/src/Debug/Plugin/Method/Alert.php +++ b/src/Debug/Plugin/Method/Alert.php @@ -6,7 +6,7 @@ * @package PHPDebugConsole * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2014-2023 Brad Kent + * @copyright 2014-2024 Brad Kent * @version v3.1 */ @@ -23,8 +23,10 @@ class Alert implements SubscriberInterface { use CustomMethodTrait; + /** @var array */ protected $levelsAllowed = array('danger', 'error', 'info', 'success', 'warn', 'warning'); + /** @var string[] */ protected $methods = array( 'alert', ); @@ -49,7 +51,7 @@ public function __construct() * "danger" and "warning" are still accepted, however deprecated * @param bool $dismissible (false) Whether to display a close icon/button * - * @return $this + * @return \bdk\Debug */ 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 6cec1964..2aa086d5 100644 --- a/src/Debug/Plugin/Method/Basic.php +++ b/src/Debug/Plugin/Method/Basic.php @@ -29,6 +29,7 @@ class Basic implements SubscriberInterface private $cliOutputStream = null; private $isCli = false; + /** @var string[] */ protected $methods = array( 'assert', 'error', @@ -47,7 +48,7 @@ class Basic implements SubscriberInterface * @param mixed ...$msg (optional) variable num of values to output if assertion fails * if none provided, will use calling file & line num * - * @return $this + * @return Debug */ public function assert($assertion, $msg = null) { @@ -84,7 +85,7 @@ public function assert($assertion, $msg = null) * * @param mixed ...$arg message / values * - * @return $this + * @return Debug */ public function error() { @@ -99,7 +100,7 @@ public function error() * * @param mixed ...$arg message / values * - * @return $this + * @return Debug */ public function info() { @@ -129,7 +130,7 @@ public function getSubscriptions() * * @param mixed ...$arg. message / values * - * @return $this + * @return Debug */ public function log() { @@ -207,7 +208,7 @@ public function varDump() * * @param mixed ...$arg message / values * - * @return $this + * @return Debug */ public function warn() { diff --git a/src/Debug/Plugin/Method/Clear.php b/src/Debug/Plugin/Method/Clear.php index 21b373fb..95b2c985 100644 --- a/src/Debug/Plugin/Method/Clear.php +++ b/src/Debug/Plugin/Method/Clear.php @@ -29,6 +29,7 @@ class Clear implements SubscriberInterface private $channelRegex; private $isRootInstance = false; + /** @var string[] */ protected $methods = array( 'clear', ); @@ -56,7 +57,7 @@ public function __construct() * `self::CLEAR_ALL` : Clear all log entries * `self::CLEAR_SILENT` : Don't add log entry * - * @return $this + * @return Debug */ 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 d185cc84..cda621dd 100644 --- a/src/Debug/Plugin/Method/Count.php +++ b/src/Debug/Plugin/Method/Count.php @@ -6,7 +6,7 @@ * @package PHPDebugConsole * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2014-2023 Brad Kent + * @copyright 2014-2024 Brad Kent * @version v3.1 */ @@ -24,8 +24,10 @@ class Count implements SubscriberInterface { use CustomMethodTrait; + /** @var array */ private $counts = array(); + /** @var string[] */ protected $methods = array( 'count', 'countReset', @@ -72,7 +74,7 @@ public function count($label = null, $flags = 0) * @param int $flags (optional) currently only one option : * \bdk\Debug::COUNT_NO_OUT` : don't output/log * - * @return $this + * @return Debug */ public function countReset($label = 'default', $flags = 0) { diff --git a/src/Debug/Plugin/Method/General.php b/src/Debug/Plugin/Method/General.php index 6d200e94..7a0c9e15 100644 --- a/src/Debug/Plugin/Method/General.php +++ b/src/Debug/Plugin/Method/General.php @@ -6,7 +6,7 @@ * @package PHPDebugConsole * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2014-2022 Brad Kent + * @copyright 2014-2024 Brad Kent * @version v3.0 */ @@ -24,6 +24,7 @@ class General implements SubscriberInterface { use CustomMethodTrait; + /** @var string[] */ protected $methods = array( 'email', 'errorStats', diff --git a/src/Debug/Plugin/Method/Group.php b/src/Debug/Plugin/Method/Group.php index 17f371ae..d568df16 100644 --- a/src/Debug/Plugin/Method/Group.php +++ b/src/Debug/Plugin/Method/Group.php @@ -32,8 +32,10 @@ class Group implements SubscriberInterface { use CustomMethodTrait; + /** @var GroupStack|null */ protected $groupStack; + /** @var string[] */ protected $methods = array( 'group', 'groupCollapsed', @@ -105,7 +107,7 @@ public function getSubscriptions() * * @param mixed ...$arg. label / values * - * @return $this + * @return Debug */ public function group() { @@ -124,7 +126,7 @@ public function group() * * @param mixed ...$arg label / values * - * @return $this + * @return Debug */ public function groupCollapsed() { @@ -145,7 +147,7 @@ public function groupCollapsed() * * @param mixed $value (optional) "return" value * - * @return $this + * @return Debug */ public function groupEnd($value = Abstracter::UNDEFINED) // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter { @@ -169,7 +171,7 @@ public function groupEnd($value = Abstracter::UNDEFINED) // @phpcs:ignore Generi * * @param int $priority (0) The higher the priority, the earlier the group will appear in output * - * @return $this + * @return Debug */ public function groupSummary($priority = 0) // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter { @@ -189,7 +191,7 @@ public function groupSummary($priority = 0) // @phpcs:ignore Generic.CodeAnalysi * * This will only occur if `cfg['collect']` is currently `true` * - * @return $this + * @return Debug */ public function groupUncollapse() { diff --git a/src/Debug/Plugin/Method/GroupStack.php b/src/Debug/Plugin/Method/GroupStack.php index ebf3f2e3..2e31b2ba 100644 --- a/src/Debug/Plugin/Method/GroupStack.php +++ b/src/Debug/Plugin/Method/GroupStack.php @@ -6,7 +6,7 @@ * @package PHPDebugConsole * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2014-2022 Brad Kent + * @copyright 2014-2024 Brad Kent * @version v3.0 */ @@ -28,6 +28,7 @@ class GroupStack 'minDepth' => 0, ); + /** @var Debug */ private $debug; /** @@ -39,11 +40,13 @@ class GroupStack */ private $priorityStack = array(); + /** @var array */ private $groupStacks = array( 'main' => array(), // array('channel' => Debug instance, 'collect' => bool)[] ); - private $groupStacksRef = null; // points to $this->data['groupStacks'][x] (where x = 'main' or (int) priority) + /** @var array{channel: Debug, collect: bool} */ + private $groupStacksRef = null; // points to $this-groupStacks[x] (where x = 'main' or (int) priority) /** * Constructor diff --git a/src/Debug/Plugin/Method/Output.php b/src/Debug/Plugin/Method/Output.php index c2f1d5fb..d2feec6d 100644 --- a/src/Debug/Plugin/Method/Output.php +++ b/src/Debug/Plugin/Method/Output.php @@ -6,7 +6,7 @@ * @package PHPDebugConsole * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2014-2023 Brad Kent + * @copyright 2014-2024 Brad Kent * @version v3.1 */ @@ -14,6 +14,7 @@ use bdk\Debug; use bdk\Debug\Plugin\CustomMethodTrait; +use bdk\PubSub\Event; use bdk\PubSub\SubscriberInterface; /** @@ -23,6 +24,7 @@ class Output implements SubscriberInterface { use CustomMethodTrait; + /** @var string[] */ protected $methods = array( 'output', ); @@ -74,7 +76,7 @@ public function output($cfg = array()) * finally ourself * This isn't outputing each channel, but for performing any per-channel "before output" activities * - * @return \bdk\PubSub\Event + * @return Event */ private function publishOutputEvent() { @@ -98,6 +100,7 @@ private function publishOutputEvent() ) ); } + /** var Event */ return $event; } } diff --git a/src/Debug/Plugin/Method/Profile.php b/src/Debug/Plugin/Method/Profile.php index 6bf0c3ad..71b4e230 100644 --- a/src/Debug/Plugin/Method/Profile.php +++ b/src/Debug/Plugin/Method/Profile.php @@ -29,16 +29,19 @@ class Profile implements SubscriberInterface { use CustomMethodTrait; + /** @var int */ protected $autoInc = 1; /** @var ProfileInstance[] */ protected $instances = array(); + /** @var string[] */ protected $methods = array( 'profile', 'profileEnd', ); + /** @var bool */ private static $profilingEnabled = false; /** @@ -124,14 +127,13 @@ public function profile($name = null) // @phpcs:ignore Generic.CodeAnalysis.Unus $callerInfo['file'], $callerInfo['line'] ); - $debug->log(new LogEntry( + return $debug->log(new LogEntry( $debug, __FUNCTION__, array($msg) )); - return $debug; } - $this->doProfile(new LogEntry( + return $this->doProfile(new LogEntry( $debug, __FUNCTION__, \func_get_args(), @@ -139,7 +141,6 @@ public function profile($name = null) // @phpcs:ignore Generic.CodeAnalysis.Unus $debug->rootInstance->getMethodDefaultArgs(__METHOD__), array('name') )); - return $debug; } /** @@ -151,7 +152,7 @@ public function profile($name = null) // @phpcs:ignore Generic.CodeAnalysis.Unus * * @param string $name Optional profile name * - * @return $this + * @return Debug */ public function profileEnd($name = null) // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter { @@ -172,7 +173,7 @@ public function profileEnd($name = null) // @phpcs:ignore Generic.CodeAnalysis.U * * @param LogEntry $logEntry LogEntry instance * - * @return void + * @return Debug */ private function doProfile(LogEntry $logEntry) { @@ -191,13 +192,13 @@ private function doProfile(LogEntry $logEntry) $this->instances[$name] = $instance; $logEntry['args'] = array('Profile \'' . $name . '\' restarted'); $debug->log($logEntry); - return; + return $debug; } $instance = new ProfileInstance(); $instance->start(); $this->instances[$name] = $instance; $logEntry['args'] = array('Profile \'' . $name . '\' started'); - $debug->log($logEntry); + return $debug->log($logEntry); } /** @@ -265,7 +266,7 @@ private function doProfileEndArgs(LogEntry $logEntry) /** * Test if we need to enable profiling * - * @param string $val config value + * @param bool $val config value * @param string $key config param name * @param Event $event The config change event * diff --git a/src/Debug/Plugin/Method/ReqRes.php b/src/Debug/Plugin/Method/ReqRes.php index c168c63d..ab1cebb6 100644 --- a/src/Debug/Plugin/Method/ReqRes.php +++ b/src/Debug/Plugin/Method/ReqRes.php @@ -15,7 +15,7 @@ use bdk\Debug; use bdk\Debug\Plugin\CustomMethodTrait; use bdk\HttpMessage\HttpFoundationBridge; -use bdk\HttpMessage\Response; +use bdk\HttpMessage\Utility\Response as ResponseUtil; use bdk\PubSub\Event; use bdk\PubSub\SubscriberInterface; use InvalidArgumentException; @@ -29,8 +29,10 @@ class ReqRes implements SubscriberInterface { use CustomMethodTrait; + /** @var array */ private $serverParams = array(); + /** @var string[] */ protected $methods = array( 'getHeaders', 'getInterface', @@ -173,7 +175,7 @@ public function getResponseHeaders($asString = false) $protocol = $this->getServerParam('SERVER_PROTOCOL') ?: 'HTTP/1.0'; $code = $this->getResponseCode(); $headersAll = array( - $protocol . ' ' . $code . ' ' . Response::codePhrase($code), + $protocol . ' ' . $code . ' ' . ResponseUtil::codePhrase($code), ); foreach ($headers as $k => $vals) { foreach ($vals as $val) { diff --git a/src/Debug/Plugin/Method/Table.php b/src/Debug/Plugin/Method/Table.php index b5927a95..e5f20084 100644 --- a/src/Debug/Plugin/Method/Table.php +++ b/src/Debug/Plugin/Method/Table.php @@ -26,8 +26,10 @@ class Table implements SubscriberInterface { use CustomMethodTrait; + /** @var LogEntry */ private $logEntry; + /** @var string[] */ protected $methods = array( 'table', 'doTable', @@ -54,7 +56,7 @@ public function __construct() * * @param mixed ...$arg traversable, [option array], [caption] in no particular order * - * @return $this + * @return Debug */ public function table() { diff --git a/src/Debug/Plugin/Method/Time.php b/src/Debug/Plugin/Method/Time.php index be4d2ee0..7c64f7d1 100644 --- a/src/Debug/Plugin/Method/Time.php +++ b/src/Debug/Plugin/Method/Time.php @@ -6,7 +6,7 @@ * @package PHPDebugConsole * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2014-2023 Brad Kent + * @copyright 2014-2024 Brad Kent * @version v3.1 */ @@ -23,6 +23,7 @@ class Time implements SubscriberInterface { use CustomMethodTrait; + /** @var string[] */ protected $methods = array( 'time', 'timeEnd', @@ -56,7 +57,7 @@ public function __construct() * @param string $label unique label * @param float $duration (optional) duration (in seconds). Use this param to log a duration obtained externally. * - * @return $this + * @return \bdk\Debug */ public function time($label = null, $duration = null) { @@ -105,7 +106,7 @@ public function time($label = null, $duration = null) * @param bool $return ('auto') whether to return the value (vs returning $this)) * 'auto' : !$log * - * @return $this|float|false The duration (in sec). + * @return \bdk\Debug|float|false The duration (in sec). * * @psalm-return ($return is true ? float|false : $this) */ @@ -137,7 +138,7 @@ public function timeEnd($label = null, $log = true, $return = 'auto') * @param bool $return ('auto') whether to return the value (vs returning $this)) * 'auto' : !$log * - * @return $this|float|false The duration (in sec). `false` if specified label does not exist + * @return \bdk\Debug|float|false The duration (in sec). `false` if specified label does not exist * * @psalm-return ($return is true ? float|false : $this) */ @@ -161,7 +162,7 @@ public function timeGet($label = null, $log = true, $return = 'auto') * @param string $label (optional) unique label * @param mixed ...$arg (optional) additional values to be logged with time * - * @return $this + * @return \bdk\Debug */ public function timeLog($label = null, $args = null) { diff --git a/src/Debug/Plugin/Method/Trace.php b/src/Debug/Plugin/Method/Trace.php index 24b19cb8..2e7a1d84 100644 --- a/src/Debug/Plugin/Method/Trace.php +++ b/src/Debug/Plugin/Method/Trace.php @@ -6,7 +6,7 @@ * @package PHPDebugConsole * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2014-2023 Brad Kent + * @copyright 2014-2024 Brad Kent * @version v3.1 */ @@ -25,6 +25,7 @@ class Trace implements SubscriberInterface { use CustomMethodTrait; + /** @var string[] */ protected $methods = array( 'trace', ); @@ -46,7 +47,7 @@ public function __construct() * @param bool $inclContext Include code snippet * @param string $caption (optional) Specify caption for the trace table * - * @return $this + * @return Debug */ public function trace($inclContext = false, $caption = 'trace') { diff --git a/src/Debug/Plugin/Prettify.php b/src/Debug/Plugin/Prettify.php index d0cdec73..aa8e1407 100644 --- a/src/Debug/Plugin/Prettify.php +++ b/src/Debug/Plugin/Prettify.php @@ -24,10 +24,12 @@ class Prettify implements SubscriberInterface { use CustomMethodTrait; + /** @var string[] */ protected $methods = array( 'prettify', ); + /** @var bool */ private $highlightAdded = false; /** diff --git a/src/Debug/Plugin/Redaction.php b/src/Debug/Plugin/Redaction.php index 41c41d9d..9ae5ce9a 100644 --- a/src/Debug/Plugin/Redaction.php +++ b/src/Debug/Plugin/Redaction.php @@ -33,7 +33,7 @@ class Redaction extends AbstractComponent implements SubscriberInterface /** * duplicate/store frequently used cfg vals * - * @var array + * @var array */ protected $cfg = array( 'enabled' => true, @@ -44,6 +44,7 @@ class Redaction extends AbstractComponent implements SubscriberInterface 'redactStrings' => array(), ); + /** @var string[] */ protected $methods = array( 'redact', 'redactHeaders', diff --git a/src/Debug/Plugin/Route.php b/src/Debug/Plugin/Route.php index 16d2d228..54603b61 100644 --- a/src/Debug/Plugin/Route.php +++ b/src/Debug/Plugin/Route.php @@ -6,7 +6,7 @@ * @package PHPDebugConsole * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2014-2023 Brad Kent + * @copyright 2014-2024 Brad Kent * @version v3.1 */ @@ -27,10 +27,12 @@ class Route extends AbstractComponent implements SubscriberInterface { use CustomMethodTrait; + /** @var string[] */ protected $methods = array( 'getDefaultRoute', ); + /** @var bool */ private $isBootstrapped = false; /** diff --git a/src/Debug/Utility/ArrayUtil.php b/src/Debug/Utility/ArrayUtil.php index 7f239460..ebc708d6 100644 --- a/src/Debug/Utility/ArrayUtil.php +++ b/src/Debug/Utility/ArrayUtil.php @@ -69,16 +69,19 @@ public static function diffAssocRecursive(array $array, $arrays) * @param mixed $val value to check * * @return bool + * + * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ public static function isList($val) { if (\is_array($val) === false) { return false; } - // iterate over keys more efficient than `$val === array_values($val)` - $keys = \array_keys($val); - foreach ($keys as $i => $key) { - if ($key !== $i) { + $i = -1; + // phpcs:ignore SlevomatCodingStandard.Variables.UnusedVariable + foreach ($val as $k => $v) { + ++$i; + if ($k !== $i) { return false; } } diff --git a/src/Debug/Utility/Php.php b/src/Debug/Utility/Php.php index e26707eb..ac0da2c2 100644 --- a/src/Debug/Utility/Php.php +++ b/src/Debug/Utility/Php.php @@ -359,6 +359,7 @@ private static function unserializeSafeModify($serialized) $regexKeys = array('full', 'prefix', 'type', 'strlen', 'classname', 'length'); $serializedNew = ''; while (\preg_match($regex, $serialized, $matches, PREG_OFFSET_CAPTURE, $offset)) { + /** @var array */ $offsets = array(); foreach ($regexKeys as $i => $key) { $matches[$key] = $matches[$i][0]; diff --git a/src/Debug/Utility/PhpDoc/Type.php b/src/Debug/Utility/PhpDoc/Type.php index e058d011..14d5758e 100644 --- a/src/Debug/Utility/PhpDoc/Type.php +++ b/src/Debug/Utility/PhpDoc/Type.php @@ -22,13 +22,23 @@ class Type { public $types = array( - 'array','bool','callable','float','int','iterable','null','object','string', - '$this','self','static', - 'array-key','double','false','mixed','non-empty-array','resource','scalar','true','void', - 'key-of', 'value-of', - 'callable-string', 'class-string', 'literal-string', 'numeric-string', 'non-empty-string', - 'negative-int', 'positive-int', + 'null', + 'mixed', 'scalar', + 'bool', 'boolean', 'true', 'false', + 'callable', 'callable-string', 'iterable', + 'int', 'integer', 'negative-int', 'positive-int', 'non-positive-int', 'non-negative-int', 'non-zero-int', 'int-mask', 'int-mask-of', + 'float', 'double', + 'numeric', // int, float, or numeric-string + 'array', 'non-empty-array', 'list', 'non-empty-list', + 'array-key', + 'void', + 'object', + 'string', 'non-falsy-string', 'numeric-string', 'non-empty-string', 'class-string', 'literal-string', + '$this', 'self', 'static', + 'resource', 'closed-resource', 'open-resource', + 'key-of', 'value-of', + 'never', 'never-return', 'never-returns', 'no-return', ); /** diff --git a/src/Debug/Utility/Profile.php b/src/Debug/Utility/Profile.php index 9b9799e4..8233aaf2 100644 --- a/src/Debug/Utility/Profile.php +++ b/src/Debug/Utility/Profile.php @@ -21,8 +21,9 @@ class Profile protected $data = array(); protected $funcStack = array(); protected $isProfiling = false; + /** @var non-empty-string */ protected $namespace = 'bdk\\Debug'; - /** @var string Ignore methods in these namespaces */ + /** @var non-empty-string Ignore methods in these namespaces */ protected $nsIgnoreRegex; protected $rootStack = array(); protected $timeLastTick = null; diff --git a/src/Debug/Utility/StopWatch.php b/src/Debug/Utility/StopWatch.php index e096ea23..459a7ec2 100644 --- a/src/Debug/Utility/StopWatch.php +++ b/src/Debug/Utility/StopWatch.php @@ -6,7 +6,7 @@ * @package PHPDebugConsole * @author Brad Kent * @license http://opensource.org/licenses/MIT MIT - * @copyright 2014-2022 Brad Kent + * @copyright 2014-2024 Brad Kent * @version v3.0 */ @@ -31,11 +31,14 @@ class StopWatch */ public function __construct($vals = array()) { + $requestTimeDefault = isset($_SERVER['REQUEST_TIME_FLOAT']) + ? $_SERVER['REQUEST_TIME_FLOAT'] + : \microtime(true); $this->timers['labels']['requestTime'] = array( 0, isset($vals['requestTime']) ? $vals['requestTime'] - : $_SERVER['REQUEST_TIME_FLOAT'], + : $requestTimeDefault, ); } diff --git a/src/Debug/js/Debug.jquery.js b/src/Debug/js/Debug.jquery.js index cb44c926..437e6b45 100644 --- a/src/Debug/js/Debug.jquery.js +++ b/src/Debug/js/Debug.jquery.js @@ -874,7 +874,7 @@ create($entry, $node); } else if ($node.is('.string-encoded.tabs-container')) { // console.warn('enhanceStringEncoded', $node) - enhanceValue$1($node, $node.find('> .tab-pane.active > *')); + enhanceValue$1($node.find('> .tab-pane.active > *'), $entry); } } @@ -1177,6 +1177,12 @@ */ var channels = []; + var tests = [ + function ($node) { + var channel = $node.data('channel') || $node.closest('.debug').data('channelNameRoot'); + return channels.indexOf(channel) > -1 + } + ]; var preFilterCallbacks = [ function ($root) { var $checkboxes = $root.find('input[data-toggle=channel]'); @@ -1200,6 +1206,7 @@ return } */ + applyFilter($delegateNode); $delegateNode.on('change', 'input[type=checkbox]', onCheckboxChange); $delegateNode.on('change', 'input[data-toggle=error]', onToggleErrorChange); $delegateNode.on('channelAdded.debug', function (e) { @@ -1210,6 +1217,18 @@ var $root = $(e.target).closest('.debug'); applyFilter($root); }); + $delegateNode.on('shown.debug.tab', function (e) { + hideSummarySeparator($(e.target)); + }); + } + + function hideSummarySeparator ($tabPane) { + $tabPane.find('> .tab-body > hr').toggleClass( + 'filter-hidden', + $tabPane.find('> .tab-body').find(' > .debug-log-summary, > .debug-log').filter(function () { + return $(this).height() < 1 + }).length > 0 + ); } function onCheckboxChange () { @@ -1242,6 +1261,10 @@ updateFilterStatus($root); } + function addTest (func) { + tests.push(func); + } + function addPreFilter (func) { preFilterCallbacks.push(func); } @@ -1273,37 +1296,34 @@ var $node = sort[i].node; applyFilterToNode($node, channelNameRoot); } - $root.find('.tab-primary > .tab-body > hr').toggleClass( - 'filter-hidden', - $root.find('.tab-primary .debug-log-summary').height() < 1 - ); + hideSummarySeparator($root.find('> .tab-panes > .tab-pane.active')); updateFilterStatus($root); } function applyFilterToNode ($node, channelNameRoot) { var hiddenWas = $node.is('.filter-hidden'); - var isFilterVis = true; + var isVis = true; if ($node.data('channel') === channelNameRoot + '.phpError') { // php Errors are filtered separately return } - isFilterVis = isFilterVis(); - $node.toggleClass('filter-hidden', !isFilterVis); - if (isFilterVis && hiddenWas) { + isVis = isFilterVis($node); + $node.toggleClass('filter-hidden', !isVis); + if (isVis && hiddenWas) { // unhiding afterUnhide($node); - } else if (!isFilterVis && !hiddenWas) { + } else if (!isVis && !hiddenWas) { // hiding afterHide($node); } - if (isFilterVis && $node.hasClass('m_group')) { + if (isVis && $node.hasClass('m_group')) { // trigger to call groupUpdate $node.trigger('collapsed.debug.group'); } } function afterUnhide ($node) { - $parentGroup = $node.parent().closest('.m_group'); + var $parentGroup = $node.parent().closest('.m_group'); if (!$parentGroup.length || $parentGroup.hasClass('expanded')) { $node.debugEnhance(); } @@ -1316,6 +1336,18 @@ } } + function isFilterVis ($node) { + var i; + var isVis = true; + for (i in tests) { + isVis = tests[i]($node); + if (!isVis) { + break + } + } + return isVis + } + function updateFilterStatus ($root) { var haveUnchecked = $root.find('.debug-sidebar input:checkbox:not(:checked)').length > 0; $root.toggleClass('filter-active', haveUnchecked); @@ -1598,6 +1630,7 @@ } addPreFilter(preFilter); + addTest(filterTest); initialized = true; } @@ -1635,6 +1668,22 @@ } } + function filterTest ($node) { + var matches = $node[0].className.match(/\bm_(\S+)\b/); + var method = matches ? matches[1] : null; + if (!options.sidebar) { + return true + } + if (method === 'group' && $node.find('> .group-body')[0].className.match(/level-(error|info|warn)/)) { + method = $node.find('> .group-body')[0].className.match(/level-(error|info|warn)/)[1]; + $node.toggleClass('filter-hidden-body', methods.indexOf(method) < 0); + } + if (['alert', 'error', 'warn', 'info'].indexOf(method) > -1) { + return methods.indexOf(method) > -1 + } + return methods.indexOf('other') > -1 + } + function preFilter ($delegateRoot) { $root$2 = $delegateRoot; options = $root$2.find('.tab-primary').data('options'); diff --git a/src/Debug/js/Debug.jquery.min.js b/src/Debug/js/Debug.jquery.min.js index 4351e514..9cd7ea6d 100644 --- a/src/Debug/js/Debug.jquery.min.js +++ b/src/Debug/js/Debug.jquery.min.js @@ -1 +1 @@ -!function(g){"use strict";var a,i;function r(n){var e=n.find("> .array-inner");0 .t_array-expand").length||(g.trim(e.html()).length<1?n.addClass("expanded").find("br").hide():(function(t){var e,n=t.find("> .array-inner");if(t.closest(".array-file-tree").length)return t.find("> .t_keyword, > .t_punct").remove(),n.find("> li > .t_operator, > li > .t_key.t_int").remove(),t.prevAll(".t_key").each(function(){var e=g(this).attr("data-toggle","array");t.prepend(e),t.prepend('')});e=g('array( ··· )'),t.find("> .t_keyword").first().wrap('').after('( ').parent().next().remove(),t.prepend(e)}(n),g.each(a.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 n(e){i=e.data("config").get(),e.on("click","[data-toggle=vis]",function(){var e,t,n,a,i,r,o,s;return e=g(this),t=e.data("vis"),n=e.closest(".t_object"),a=n.find("> .object-inner"),i=a.find("[data-toggle=vis][data-vis="+t+"]"),r="inherited"===t?"dd[data-inherited-from], .private-ancestor":"."+t,o=a.find(r),s=e.hasClass("toggle-off"),i.html(e.html().replace(s?"show ":"hide ",s?"hide ":"show ")).addClass(s?"toggle-on":"toggle-off").removeClass(s?"toggle-off":"toggle-on"),s?function(e){e.each(function(){var i=g(this),e=i.closest(".object-inner"),r=!0;e.find("> .vis-toggles [data-toggle]").each(function(){var e=g(this),t=e.hasClass("toggle-on"),n=e.data("vis"),a="inherited"===n?"dd[data-inherited-from], .private-ancestor":"."+n;if(!t&&1===i.filter(a).length)return r=!1}),r&&i.show()})}(o):o.hide(),c(n,!0),!1}),e.on("click","[data-toggle=interface]",function(){return s(this),!1})}function o(e){e.find("> .classname, > .t_const").each(function(){var e=g(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 s(e){var t=g(e),a=t.closest(".t_object");(t=t.is(".toggle-off")?t.add(t.next().find(".toggle-off")):t.add(t.next().find(".toggle-on"))).each(function(){var e=g(this),t=e.data("interface"),n=l(a,t);e.is(".toggle-off")?(e.addClass("toggle-on").removeClass("toggle-off"),n.show()):(e.addClass("toggle-off").removeClass("toggle-on"),n.hide())}),c(a)}function l(e,t){var n='> .object-inner > dd[data-implements="'+CSS.escape(t)+'"]';return e.find(n)}function c(e,t){var n=t?".object-inner > dt":"> .object-inner > dt",a=t?".object-inner > .heading":"> .object-inner > .heading";e.find(n).each(function(e,t){var n=g(t).nextUntil("dt"),a=n.not(".heading").filter(function(e,t){return"none"!==g(t).css("display")}),i=0 .object-inner"),n=t.data("accessible"),a=null;t.is(".enhanced")||(e.find("> dd > ul > li > .interface, > dd > ul > li > .interface + ul .interface").each(function(){var e=g(this).text();0!==l(t,e).length&&g(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(){s(this)}),e.find("> .private, > .protected").filter(".magic, .magic-read, .magic-write").removeClass("private protected"),"public"===n&&(e.find(".private, .protected").hide(),a="allDesc"),function(e,t){var n=0');n&&l.append(''+s+" protected");a&&l.append(''+s+" private");i&&l.append('show excluded');r&&l.append('hide inherited');if(e.find("> dd[class*=t_modifier_]").length)return e.find("> dd[class*=t_modifier_]").last().after(l);e.prepend(l)}(e,n),o=e,g.each(i.iconsObject,function(e,t){var n,a=!0,i=e.match(/(?:parent(\S+)\s)?(?:context(\S+)\s)?(.*)$/),r=t.match(/^([ap])\s*:(.+)$/);if(i){if(i[1]&&0===o.parent().filter(i[1]).length)return;i[2]&&(o=o.filter(i[2])),e=i[3]}r&&(a="p"===r[1],t=r[2]),n=o.find(e),a?n.prepend(t):n.append(t)}),e.find("> .property.forceShow").show().find("> .t_array").debugEnhance("expand"),a&&c(t,"allDesc"===a),t.addClass("enhanced"))}});function m(){var e=g(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 b(){var e=g(this).closest(".show-more-container");e.find(".show-more-wrapper").animate({height:e.find(".t_string").height()},400,"swing",function(){g(this).css("display","inline")}),e.find(".show-more-fade").fadeOut(),e.find(".show-more").hide(),e.find(".show-less").show()}function v(e){var t=g(e.target),n=t.closest("li[class*=m_]");e.stopPropagation(),t.find("> .array-inner > li > :last-child, > .array-inner > li[class]").each(function(){f(this,n)})}function y(e){var t=g(e.target);e.stopPropagation(),t.find("> .group-body").debugEnhance()}function w(e){var t=g(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(){f(this,n)}),d.enhanceInner(t))}function x(e){var t=g(e.target);(t.hasClass("t_array")?t.find("> .array-inner").find("> li > .t_string, > li.t_string"):t.hasClass("m_group")?t.find("> .group-body > li > .t_string"):t.hasClass("t_object")?t.find("> .object-inner").find(["> dd.constant > .t_string","> dd.property:visible > .t_string","> dd.method > ul > li > .t_string.return-value"].join(", ")):g()).not("[data-type-more=numeric]").each(function(){var e,t,n;35<(e=g(this)).height()-70&&((n=e.wrap('
').parent()).append('
'),(t=n.wrap('
').parent()).append(''),t.append(''))})}function C(e){var i=g(e),t=i.find("> thead");return i.is("table.sortable")&&(i.addClass("table-sort"),t.on("click","th",function(){var e=g(this),t=g(this).closest("tr").children(),n=t.index(e),a="desc"==(e.is(".sort-asc")?"asc":"desc")?"asc":"desc";t.removeClass("sort-asc sort-desc"),e.addClass("sort-"+a),e.find(".sort-arrows").length||(t.find(".sort-arrows").remove(),e.append('')),function(e,t,n){var a,i=e.tBodies[0],r=i.rows,o="function"==typeof Intl.Collator?new Intl.Collator([],{numeric:!0,sensitivity:"base"}):null;for(n="desc"===n?-1:1,r=(r=Array.prototype.slice.call(r,0)).sort(function(o,s,l){var c=/^([+-]?(?:0|[1-9]\d*)(?:\.\d*)?)(?:[eE]([+-]?\d+))?$/;return function(e,t){var n=e.cells[o].textContent.trim(),a=t.cells[o].textContent.trim(),i=n.match(c),r=a.match(c);return i&&(n=_(n,i)),r&&(a=_(a,r)),s*function(e,t,n){var a=0;if(afloat&&bfloat)return e .object-inner > .property.debug-value > .t_identifier").filter(function(){return this.innerText.match(/^file$/)}),i=!0===e.data("detectFiles")||0 *:last-child").remove()}else e.find("table thead tr > *:last-child").after("");e.find("table tbody tr").each(function(){var e=g(this),t=e.find("> td"),n={file:e.data("file")||t.eq(0).text(),line:e.data("line")||t.eq(1).text()},a=g("",{class:"file-link",href:E(n.file,n.line),html:'',style:"vertical-align: bottom",title:"Open in editor"});i?e.find(".file-link").replaceWith(a):e.hasClass("context")?t.eq(0).attr("colspan",parseInt(t.eq(0).attr("colspan"),10)+1):t.last().after(g("",{class:"text-center",html:a}))})}(e,n):e.is("[data-file]")?function(e,t){if(e.find("> .file-link").remove(),t)return;e.append(g("",{html:'',href:E(e.data("file"),e.data("line")),title:"Open in editor",class:"file-link lpad"})[0].outerHTML)}(e,n):function(e,t,n){var a=e.data("foundFiles")||[];e.is(".m_table")&&(t=e.find("> table > tbody > tr > .t_string"));t=t||[];g.each(t,function(){!function(e,t,n){var a,i=g(e),r=e.attributes,o=g.trim(i.text()),s=function(e,t){var a=[],n=g.trim(e.text());if(e.data("file"))return"boolean"==typeof e.data("file")?[null,n,1]:[null,e.data("file"),e.data("line")||1];if(0===t.indexOf(n))return[null,n,1];if(e.parent(".property.debug-value").find("> .t_identifier").text().match(/^file$/))return a={line:1},e.parent().parent().find("> .property.debug-value").each(function(){var e=g(this).find("> .t_identifier")[0].innerText,t=g(this).find("> *:last-child"),n=g.trim(t[0].innerText);a[e]=n}),[null,n,a.line];return n.match(/^(\/.+\.php)(?: \(line (\d+)(, eval'd line \d+)?\))?$/)||[]}(i,n),l=!0!==t&&i.hasClass("file-link");if(i.closest(".m_trace").length)return O(i.closest(".m_trace"));if(!s.length)return;a=function(e,t,n,a,i){var r;a?(r=g("",{text:n}),e.removeClass("file-link")):i?(r=e).prop("href",E(t[1],t[2])):r=g("",{class:"file-link",href:E(t[1],t[2]),html:n+' ',title:"Open in editor"});return r}(i,s,o,t,l),!1===l&&function(t,n,e){g.each(e,function(){if(void 0!==this){var e=this.name;if(!(-1<["html","href","title"].indexOf(e))){if("class"===e)return n.addClass(this.value),void t.removeClass("t_string");n.attr(e,this.value),t.removeAttr(e)}}}),e.style&&n.attr("style",e.style.value)}(i,a,r);if(i.is("td, th, li"))return i.html(t?o:a);i.replaceWith(a)}(this,n,a)})}(e,t,n))}function E(e,t){var n={file:e,line:t||1};return p.linkFilesTemplate.replace(/%(\w*)\b/g,function(e,t){return Object.prototype.hasOwnProperty.call(n,t)?n[t]:""})}var j,T,t,D,A=[],M=!1;function L(e){var t;u=e.data("config").get(),a=e.data("config").get(),n(e),f=I,d=h,(t=e).on("click",".close[data-dismiss=alert]",function(){g(this).parent().remove()}),t.on("click",".show-more-container .show-less",m),t.on("click",".show-more-container .show-more",b),t.on("expand.debug.array",v),t.on("expand.debug.group",y),t.on("expand.debug.object",w),t.on("expanded.debug.next",".context",function(e){f(g(e.target).find("> td > .t_array"),g(e.target).closest("li"))}),t.on("expanded.debug.array expanded.debug.group expanded.debug.object",x),k(e)}function S(e){var t=e.parent(),n=!t.hasClass("m_group")||t.hasClass("expanded");e.hide(),e.children().each(function(){P(g(this))}),n&&e.show().trigger("expanded.debug.group"),function(){if(M)return;M=!0;for(;A.length;)A.shift().debugEnhance("expand");M=!1}(),!1===e.parent().hasClass("m_group")&&e.addClass("enhanced")}function P(e){if(!e.hasClass("enhanced")){if(e.hasClass("m_group"))!function(a){var i=a.find("> .group-header"),e=i.next();if(F(a),F(i),i.attr("data-toggle","group"),i.find(".t_array, .t_object").each(function(){g(this).data("expand",!1),I(this,a)}),g.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")||e.find(".m_error, .m_warn").not(".filter-hidden").not("[data-uncollapse=false]").length)return A.push(i);i.debugEnhance("collapse",!0)}(e);else{if(e.hasClass("filter-hidden"))return;(e.is(".m_table, .m_trace")?function(e){O(e),F(e),e.hasClass("m_table")&&e.find("> table > tbody > tr > td").each(function(){I(this,e)});e.find("tbody > tr.expanded").next().trigger("expanded.debug.next"),C(e.find("> table"))}:function(e){var t;e.data("file")&&(e.attr("title")||(t=e.data("file")+": line "+e.data("line"),e.data("evalline")&&(t+=" (eval'd line "+e.data("evalline")+")"),e.attr("title",t)),O(e));F(e),e.children().each(function(){I(this,e)})})(e)}e.addClass("enhanced"),e.trigger("enhanced.debug")}}function I(e,t){var n=g(e);n.is(".t_array")?r(n):n.is(".t_object")?o(n):n.is("table")?C(n):n.is(".t_string")?O(t,n):n.is(".string-encoded.tabs-container")&&I(n,n.find("> .tab-pane.active > *"))}function F(e){var t,n=function(e){var t,n,a;if(e.data("icon"))return e.data("icon").match("<")?g(e.data("icon")):g("").addClass(e.data("icon"));if(e.hasClass("m_group"))return t;for(a in n=e.hasClass("group-header")?e.parent():e,u.iconsMethods)if(n.is(a)){t=g(u.iconsMethods[a]);break}return t}(e);!function(e){var t,n,a;for(a in u.iconsMisc)0!==(n=e.find(a)).length&&(t=g(u.iconsMisc[a]),t=(n.find("> i:first-child").hasClass(t.attr("class"))||n.prepend(t),null))}(e),n&&(e.hasClass("m_group")?e=e.find("> .group-header .group-label").eq(0):e.find("> table").length&&((t=e.find("> table > caption")).length||(t=g(""),e.find("> table").prepend(t)),e=t),e.find("> i:first-child").hasClass(n.attr("class"))||e.prepend(n))}function H(e){var t;(T=(j=e).data("config")).get("drawer")&&(j.addClass("debug-drawer debug-enhanced-ui"),(t=j.find(".debug-menu-bar")).before('
PHP
'),t.find(".float-right").append(''),j.find(".tab-panes").scrollLock(),j.find(".debug-resize-handle").on("mousedown",R),j.find(".debug-pull-tab").on("click",q),j.find(".debug-menu-bar .close").on("click",B),T.get("persistDrawer")&&T.get("openDrawer")&&q())}function q(){j.addClass("debug-drawer-open"),j.debugEnhance(),W(),g("body").css("marginBottom",j.height()+8+"px"),g(window).on("resize",W),T.get("persistDrawer")&&T.set("openDrawer",!0)}function B(){j.removeClass("debug-drawer-open"),g("body").css("marginBottom",""),g(window).off("resize",W),T.get("persistDrawer")&&T.set("openDrawer",!1)}function N(e){W(t+(D-e.pageY),!0)}function R(e){g(e.target).closest(".debug-drawer").is(".debug-drawer-open")&&(t=j.find(".tab-panes").height(),D=e.pageY,g("html").addClass("debug-resizing"),j.parents().on("mousemove",N).on("mouseup",V),e.preventDefault())}function V(){g("html").removeClass("debug-resizing"),j.parents().off("mousemove",N).off("mouseup",V),g("body").css("marginBottom",j.height()+8+"px")}function W(e,t){var n=j.find(".tab-panes"),a=j.find(".debug-menu-bar").outerHeight(),i=window.innerHeight-a-50;e=function(e){var t=j.find(".tab-panes");if(e&&"object"!=typeof e)return e;!(e=parseInt(t[0].style.height,10))&&T.get("persistDrawer")&&(e=T.get("height"));return e||100}(e),e=Math.min(e,i),e=Math.max(e,20),n.css("height",e),t&&T.get("persistDrawer")&&T.set("height",e)}g.fn.scrollLock=function(e){return(e=void 0===e||e)?void g(this).on("DOMMouseScroll mousewheel wheel",function(e){function t(){return e.stopPropagation(),e.preventDefault(),e.returnValue=!1}var n=g(this),a=this.scrollTop,i=this.scrollHeight,r=n.innerHeight(),o=e.originalEvent.wheelDelta,s=0 .tab-panes > .tab-primary > .tab-body").find(".m_alert, .group-body > *:not(.m_groupSummary)").each(function(){i.push({depth:g(this).parentsUntil(".tab_body").length,node:g(this)})}),i.sort(function(e,t){return e.depth .tab-body > hr").toggleClass("filter-hidden",e.find(".tab-primary .debug-log-summary").height()<1),Q(e)}function X(e,t){var n,a,i=e.is(".filter-hidden"),r=!0;e.data("channel")!==t+".phpError"&&(r=r(),e.toggleClass("filter-hidden",!r),r&&i?($parentGroup=(a=e).parent().closest(".m_group"),$parentGroup.length&&!$parentGroup.hasClass("expanded")||a.debugEnhance()):r||i||(n=e).hasClass("m_group")&&n.find("> .group-body").debugEnhance(),r&&e.hasClass("m_group")&&e.trigger("collapsed.debug.group"))}function Q(e){var t=0'),$.get("drawer")||t.find("input[name=persistDrawer]").closest("label").remove(),U.find(".debug-options-toggle").on("click",ce),g("input[name=debugCookie]").on("change",le).prop("checked",$.get("debugKey")&&Z("debug")===$.get("debugKey")),$.get("debugKey")||g("input[name=debugCookie]").prop("disabled",!0).closest("label").addClass("disabled"),g("input[name=persistDrawer]").on("change",pe).prop("checked",$.get("persistDrawer")),U.find("input[name=linkFiles]").on("change",de).prop("checked",$.get("linkFiles")).trigger("change"),U.find("input[name=linkFilesTemplate]").on("change",fe).val($.get("linkFilesTemplate"))}function oe(e){0===U.find(".debug-options").find(e.target).length&&ue()}function se(e){e.keyCode===ie&&ue()}function le(){g(this).is(":checked")?e("debug",$.get("debugKey"),7):e("debug","",-1)}function ce(e){var t=g(this).closest(".debug-bar").find(".debug-options").is(".show");U=g(this).closest(".debug"),t?ue():(U.find(".debug-options").addClass("show"),g("body").on("click",oe),g("body").on("keyup",se)),e.stopPropagation()}function de(){var e=g(this).prop("checked"),t=g(this).closest(".debug-options").find("input[name=linkFilesTemplate]").closest(".form-group");e?t.slideDown():t.slideUp(),$.set("linkFiles",e),g("input[name=linkFilesTemplate]").trigger("change")}function fe(){var e=g(this).val();$.set("linkFilesTemplate",e),U.trigger("config.debug.updated","linkFilesTemplate")}function pe(){var e=g(this).is(":checked");$.set({persistDrawer:e,openDrawer:e,openSidebar:!0})}function ue(){U.find(".debug-options").removeClass("show"),g("body").off("click",oe),g("body").off("keyup",se)}var ge,he,me,be=!1,ve={alert:'Alerts',error:'Error',warn:'Warning',info:'Info',other:'Other'},ye='
';function we(e){var t,n=e.find("> .tab-panes > .tab-primary");te=e.data("config")||g("body").data("config"),ae=e,n.length&&n.data("options").sidebar&&Oe(ae),te.get("persistDrawer")&&!te.get("openSidebar")&&Ee(ae),ae.on("click",".close[data-dismiss=alert]",Ce),ae.on("click",".sidebar-toggle",_e),ae.on("change",".debug-sidebar input[type=checkbox]",xe),be||(t=ke,K.push(t),be=!0)}function xe(e){var t=g(this),n=t.closest(".toggle"),a=n.next("ul").find(".toggle"),i=t.is(":checked"),r=g(".m_alert.error-summary.have-fatal");n.toggleClass("active",i),a.toggleClass("active",i),"fatal"===t.val()&&(r.find(".error-fatal").toggleClass("filter-hidden",!i),r.toggleClass("filter-hidden",0===r.children().not(".filter-hidden").length))}function Ce(e){var t=g(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 _e(){var e=g(this).closest(".debug");(e.find(".debug-sidebar").is(".show")?Ee:je)(e)}function ke(e){(ae=e).find(".tab-primary").data("options"),ne=[],ae.find("input[data-toggle=method]:checked").each(function(){ne.push(g(this).val())})}function Oe(e){var t,n,a,i,r=g(ye),o=e.find(".tab-panes > .tab-primary > .tab-body > .expand-all");e.find(".tab-panes > .tab-primary > .tab-body").before(r),t=e.closest(".debug").find(".m_alert.error-summary"),(n=t.find(".in-console")).prev().remove(),n.remove(),0===t.children().length&&t.remove(),i=(a=e).find(".debug-sidebar .php-errors ul"),g.each(["fatal","error","warning","deprecated","notice","strict"],function(e,t){var n="fatal"===t?a.find(".m_alert.error-summary.have-fatal").length:a.find(".error-"+t).filter(".m_error,.m_warn").length;0!==n&&i.append(g("
  • ").append(g('