diff --git a/app/Config/App.php b/app/Config/App.php index 2da765fa6b8e..b91c058e951f 100644 --- a/app/Config/App.php +++ b/app/Config/App.php @@ -265,5 +265,4 @@ class App extends BaseConfig | - http://www.w3.org/TR/CSP/ */ public $CSPEnabled = false; - } diff --git a/app/Config/Kint.php b/app/Config/Kint.php new file mode 100644 index 000000000000..9562447ecac1 --- /dev/null +++ b/app/Config/Kint.php @@ -0,0 +1,62 @@ +detectEnvironment(); $this->bootstrapEnvironment(); - if (CI_DEBUG) + $this->initializeKint(); + + if (! CI_DEBUG) { - require_once SYSTEMPATH . 'ThirdParty/Kint/kint.php'; + \Kint::$enabled_mode = false; } } //-------------------------------------------------------------------- + /** + * Initializes Kint + */ + protected function initializeKint() + { + // If we have KINT_DIR it means it's already loaded via composer + if (! defined('KINT_DIR')) + { + spl_autoload_register(function ($class) { + $class = explode('\\', $class); + + if ('Kint' !== array_shift($class)) + { + return; + } + + $file = SYSTEMPATH . 'ThirdParty/Kint/' . implode('/', $class) . '.php'; + + file_exists($file) && require_once $file; + }); + + require_once SYSTEMPATH . 'ThirdParty/Kint/init.php'; + } + + /** + * Config\Kint + */ + $config = config('Config\Kint'); + + \Kint::$max_depth = $config->maxDepth; + \Kint::$display_called_from = $config->displayCalledFrom; + \Kint::$expanded = $config->expanded; + + if (! empty($config->plugins) && is_array($config->plugins)) + { + \Kint::$plugins = $config->plugins; + } + + \Kint\Renderer\RichRenderer::$theme = $config->richTheme; + \Kint\Renderer\RichRenderer::$folder = $config->richFolder; + \Kint\Renderer\RichRenderer::$sort = $config->richSort; + if (! empty($config->richObjectPlugins) && is_array($config->richObjectPlugins)) + { + \Kint\Renderer\RichRenderer::$object_plugins = $config->richObjectPlugins; + } + if (! empty($config->richTabPlugins) && is_array($config->richTabPlugins)) + { + \Kint\Renderer\RichRenderer::$tab_plugins = $config->richTabPlugins; + } + + \Kint\Renderer\CliRenderer::$cli_colors = $config->cliColors; + \Kint\Renderer\CliRenderer::$force_utf8 = $config->cliForceUTF8; + \Kint\Renderer\CliRenderer::$detect_width = $config->cliDetectWidth; + \Kint\Renderer\CliRenderer::$min_terminal_width = $config->cliMinWidth; + } + + //-------------------------------------------------------------------- + /** * Launch the application! * diff --git a/system/ComposerScripts.php b/system/ComposerScripts.php index 9666d00fe955..d53108f46a23 100644 --- a/system/ComposerScripts.php +++ b/system/ComposerScripts.php @@ -149,6 +149,29 @@ protected static function removeDir($dir) } } + protected static function copyDir($source, $dest) + { + $dir = opendir($source); + @mkdir($dest); + + while (false !== ( $file = readdir($dir))) + { + if (( $file !== '.' ) && ( $file !== '..' )) + { + if (is_dir($source . '/' . $file)) + { + static::copyDir($source . '/' . $file, $dest . '/' . $file); + } + else + { + copy($source . '/' . $file, $dest . '/' . $file); + } + } + } + + closedir($dir); + } + /** * Moves the Laminas Escaper files into our base repo so that it's * available for packaged releases where the users don't user Composer. @@ -194,9 +217,9 @@ public static function moveEscaper() */ public static function moveKint() { - $filename = 'vendor/kint-php/kint/build/kint-aante-light.php'; + $dir = 'vendor/kint-php/kint/src'; - if (is_file($filename)) + if (is_dir($dir)) { $base = basename(__DIR__) . '/' . static::$basePath . 'Kint'; @@ -212,10 +235,10 @@ public static function moveKint() mkdir($base, 0755); } - if (! static::moveFile($filename, $base . '/kint.php')) - { - die('Error moving: ' . $filename); - } + static::copyDir($dir, $base); + static::copyDir($dir . '/../resources', $base . '/resources'); + copy($dir . '/../init.php', $base . '/init.php'); + copy($dir . '/../init_helpers.php', $base . '/init_helpers.php'); } } } diff --git a/system/ThirdParty/Kint/CallFinder.php b/system/ThirdParty/Kint/CallFinder.php new file mode 100644 index 000000000000..e7192a815284 --- /dev/null +++ b/system/ThirdParty/Kint/CallFinder.php @@ -0,0 +1,473 @@ + true, + T_COMMENT => true, + T_DOC_COMMENT => true, + T_INLINE_HTML => true, + T_OPEN_TAG => true, + T_OPEN_TAG_WITH_ECHO => true, + T_WHITESPACE => true, + ); + + /** + * Things we need to do specially for operator tokens: + * - Refuse to strip spaces around them + * - Wrap the access path in parentheses if there + * are any of these in the final short parameter. + */ + private static $operator = array( + T_AND_EQUAL => true, + T_BOOLEAN_AND => true, + T_BOOLEAN_OR => true, + T_ARRAY_CAST => true, + T_BOOL_CAST => true, + T_CLONE => true, + T_CONCAT_EQUAL => true, + T_DEC => true, + T_DIV_EQUAL => true, + T_DOUBLE_CAST => true, + T_INC => true, + T_INCLUDE => true, + T_INCLUDE_ONCE => true, + T_INSTANCEOF => true, + T_INT_CAST => true, + T_IS_EQUAL => true, + T_IS_GREATER_OR_EQUAL => true, + T_IS_IDENTICAL => true, + T_IS_NOT_EQUAL => true, + T_IS_NOT_IDENTICAL => true, + T_IS_SMALLER_OR_EQUAL => true, + T_LOGICAL_AND => true, + T_LOGICAL_OR => true, + T_LOGICAL_XOR => true, + T_MINUS_EQUAL => true, + T_MOD_EQUAL => true, + T_MUL_EQUAL => true, + T_NEW => true, + T_OBJECT_CAST => true, + T_OR_EQUAL => true, + T_PLUS_EQUAL => true, + T_REQUIRE => true, + T_REQUIRE_ONCE => true, + T_SL => true, + T_SL_EQUAL => true, + T_SR => true, + T_SR_EQUAL => true, + T_STRING_CAST => true, + T_UNSET_CAST => true, + T_XOR_EQUAL => true, + '!' => true, + '%' => true, + '&' => true, + '*' => true, + '+' => true, + '-' => true, + '.' => true, + '/' => true, + ':' => true, + '<' => true, + '=' => true, + '>' => true, + '?' => true, + '^' => true, + '|' => true, + '~' => true, + ); + + private static $strip = array( + '(' => true, + ')' => true, + '[' => true, + ']' => true, + '{' => true, + '}' => true, + T_OBJECT_OPERATOR => true, + T_DOUBLE_COLON => true, + T_NS_SEPARATOR => true, + ); + + public static function getFunctionCalls($source, $line, $function) + { + static $up = array( + '(' => true, + '[' => true, + '{' => true, + T_CURLY_OPEN => true, + T_DOLLAR_OPEN_CURLY_BRACES => true, + ); + static $down = array( + ')' => true, + ']' => true, + '}' => true, + ); + static $modifiers = array( + '!' => true, + '@' => true, + '~' => true, + '+' => true, + '-' => true, + ); + static $identifier = array( + T_DOUBLE_COLON => true, + T_STRING => true, + T_NS_SEPARATOR => true, + ); + + if (KINT_PHP56) { + self::$operator[T_POW] = true; + self::$operator[T_POW_EQUAL] = true; + } + + if (KINT_PHP70) { + self::$operator[T_SPACESHIP] = true; + } + + if (KINT_PHP74) { + self::$operator[T_COALESCE_EQUAL] = true; + } + + $tokens = \token_get_all($source); + $cursor = 1; + $function_calls = array(); + /** @var array Performance optimization preventing backwards loops */ + $prev_tokens = array(null, null, null); + + if (\is_array($function)) { + $class = \explode('\\', $function[0]); + $class = \strtolower(\end($class)); + $function = \strtolower($function[1]); + } else { + $class = null; + $function = \strtolower($function); + } + + // Loop through tokens + foreach ($tokens as $index => $token) { + if (!\is_array($token)) { + continue; + } + + // Count newlines for line number instead of using $token[2] + // since certain situations (String tokens after whitespace) may + // not have the correct line number unless you do this manually + $cursor += \substr_count($token[1], "\n"); + if ($cursor > $line) { + break; + } + + // Store the last real tokens for later + if (isset(self::$ignore[$token[0]])) { + continue; + } + + $prev_tokens = array($prev_tokens[1], $prev_tokens[2], $token); + + // Check if it's the right type to be the function we're looking for + if (T_STRING !== $token[0] || \strtolower($token[1]) !== $function) { + continue; + } + + // Check if it's a function call + $nextReal = self::realTokenIndex($tokens, $index); + if (!isset($nextReal, $tokens[$nextReal]) || '(' !== $tokens[$nextReal]) { + continue; + } + + // Check if it matches the signature + if (null === $class) { + if ($prev_tokens[1] && \in_array($prev_tokens[1][0], array(T_DOUBLE_COLON, T_OBJECT_OPERATOR), true)) { + continue; + } + } else { + if (!$prev_tokens[1] || T_DOUBLE_COLON !== $prev_tokens[1][0]) { + continue; + } + + if (!$prev_tokens[0] || T_STRING !== $prev_tokens[0][0] || \strtolower($prev_tokens[0][1]) !== $class) { + continue; + } + } + + $inner_cursor = $cursor; + $depth = 1; // The depth respective to the function call + $offset = $nextReal + 1; // The start of the function call + $instring = false; // Whether we're in a string or not + $realtokens = false; // Whether the current scope contains anything meaningful or not + $paramrealtokens = false; // Whether the current parameter contains anything meaningful + $params = array(); // All our collected parameters + $shortparam = array(); // The short version of the parameter + $param_start = $offset; // The distance to the start of the parameter + + // Loop through the following tokens until the function call ends + while (isset($tokens[$offset])) { + $token = $tokens[$offset]; + + // Ensure that the $inner_cursor is correct and + // that $token is either a T_ constant or a string + if (\is_array($token)) { + $inner_cursor += \substr_count($token[1], "\n"); + } + + if (!isset(self::$ignore[$token[0]]) && !isset($down[$token[0]])) { + $paramrealtokens = $realtokens = true; + } + + // If it's a token that makes us to up a level, increase the depth + if (isset($up[$token[0]])) { + if (1 === $depth) { + $shortparam[] = $token; + $realtokens = false; + } + + ++$depth; + } elseif (isset($down[$token[0]])) { + --$depth; + + // If this brings us down to the parameter level, and we've had + // real tokens since going up, fill the $shortparam with an ellipsis + if (1 === $depth) { + if ($realtokens) { + $shortparam[] = '...'; + } + $shortparam[] = $token; + } + } elseif ('"' === $token[0]) { + // Strings use the same symbol for up and down, but we can + // only ever be inside one string, so just use a bool for that + if ($instring) { + --$depth; + if (1 === $depth) { + $shortparam[] = '...'; + } + } else { + ++$depth; + } + + $instring = !$instring; + + $shortparam[] = '"'; + } elseif (1 === $depth) { + if (',' === $token[0]) { + $params[] = array( + 'full' => \array_slice($tokens, $param_start, $offset - $param_start), + 'short' => $shortparam, + ); + $shortparam = array(); + $paramrealtokens = false; + $param_start = $offset + 1; + } elseif (T_CONSTANT_ENCAPSED_STRING === $token[0] && \strlen($token[1]) > 2) { + $shortparam[] = $token[1][0].'...'.$token[1][0]; + } else { + $shortparam[] = $token; + } + } + + // Depth has dropped to 0 (So we've hit the closing paren) + if ($depth <= 0) { + if ($paramrealtokens) { + $params[] = array( + 'full' => \array_slice($tokens, $param_start, $offset - $param_start), + 'short' => $shortparam, + ); + } + + break; + } + + ++$offset; + } + + // If we're not passed (or at) the line at the end + // of the function call, we're too early so skip it + if ($inner_cursor < $line) { + continue; + } + + // Format the final output parameters + foreach ($params as &$param) { + $name = self::tokensFormatted($param['short']); + $expression = false; + foreach ($name as $token) { + if (self::tokenIsOperator($token)) { + $expression = true; + break; + } + } + + $param = array( + 'name' => self::tokensToString($name), + 'path' => self::tokensToString(self::tokensTrim($param['full'])), + 'expression' => $expression, + ); + } + + // Get the modifiers + --$index; + + while (isset($tokens[$index])) { + if (!isset(self::$ignore[$tokens[$index][0]]) && !isset($identifier[$tokens[$index][0]])) { + break; + } + + --$index; + } + + $mods = array(); + + while (isset($tokens[$index])) { + if (isset(self::$ignore[$tokens[$index][0]])) { + --$index; + continue; + } + + if (isset($modifiers[$tokens[$index][0]])) { + $mods[] = $tokens[$index]; + --$index; + continue; + } + + break; + } + + $function_calls[] = array( + 'parameters' => $params, + 'modifiers' => $mods, + ); + } + + return $function_calls; + } + + private static function realTokenIndex(array $tokens, $index) + { + ++$index; + + while (isset($tokens[$index])) { + if (!isset(self::$ignore[$tokens[$index][0]])) { + return $index; + } + + ++$index; + } + + return null; + } + + /** + * We need a separate method to check if tokens are operators because we + * occasionally add "..." to short parameter versions. If we simply check + * for `$token[0]` then "..." will incorrectly match the "." operator. + * + * @param array|string $token The token to check + * + * @return bool + */ + private static function tokenIsOperator($token) + { + return '...' !== $token && isset(self::$operator[$token[0]]); + } + + private static function tokensToString(array $tokens) + { + $out = ''; + + foreach ($tokens as $token) { + if (\is_string($token)) { + $out .= $token; + } elseif (\is_array($token)) { + $out .= $token[1]; + } + } + + return $out; + } + + private static function tokensTrim(array $tokens) + { + foreach ($tokens as $index => $token) { + if (isset(self::$ignore[$token[0]])) { + unset($tokens[$index]); + } else { + break; + } + } + + $tokens = \array_reverse($tokens); + + foreach ($tokens as $index => $token) { + if (isset(self::$ignore[$token[0]])) { + unset($tokens[$index]); + } else { + break; + } + } + + return \array_reverse($tokens); + } + + private static function tokensFormatted(array $tokens) + { + $space = false; + + $tokens = self::tokensTrim($tokens); + + $output = array(); + $last = null; + + foreach ($tokens as $index => $token) { + if (isset(self::$ignore[$token[0]])) { + if ($space) { + continue; + } + + $next = $tokens[self::realTokenIndex($tokens, $index)]; + + if (isset(self::$strip[$last[0]]) && !self::tokenIsOperator($next)) { + continue; + } + + if (isset(self::$strip[$next[0]]) && $last && !self::tokenIsOperator($last)) { + continue; + } + + $token = ' '; + $space = true; + } else { + $space = false; + $last = $token; + } + + $output[] = $token; + } + + return $output; + } +} diff --git a/system/ThirdParty/Kint/Object/BasicObject.php b/system/ThirdParty/Kint/Object/BasicObject.php new file mode 100644 index 000000000000..d69347eb8dfc --- /dev/null +++ b/system/ThirdParty/Kint/Object/BasicObject.php @@ -0,0 +1,248 @@ +representations[$rep->getName()])) { + return false; + } + + if (null === $pos) { + $this->representations[$rep->getName()] = $rep; + } else { + $this->representations = \array_merge( + \array_slice($this->representations, 0, $pos), + array($rep->getName() => $rep), + \array_slice($this->representations, $pos) + ); + } + + return true; + } + + public function replaceRepresentation(Representation $rep, $pos = null) + { + if (null === $pos) { + $this->representations[$rep->getName()] = $rep; + } else { + $this->removeRepresentation($rep); + $this->addRepresentation($rep, $pos); + } + } + + public function removeRepresentation($rep) + { + if ($rep instanceof Representation) { + unset($this->representations[$rep->getName()]); + } elseif (\is_string($rep)) { + unset($this->representations[$rep]); + } + } + + public function getRepresentation($name) + { + if (isset($this->representations[$name])) { + return $this->representations[$name]; + } + } + + public function getRepresentations() + { + return $this->representations; + } + + public function clearRepresentations() + { + $this->representations = array(); + } + + public function getType() + { + return $this->type; + } + + public function getModifiers() + { + $out = $this->getAccess(); + + if ($this->const) { + $out .= ' const'; + } + + if ($this->static) { + $out .= ' static'; + } + + if (\strlen($out)) { + return \ltrim($out); + } + } + + public function getAccess() + { + switch ($this->access) { + case self::ACCESS_PRIVATE: + return 'private'; + case self::ACCESS_PROTECTED: + return 'protected'; + case self::ACCESS_PUBLIC: + return 'public'; + } + } + + public function getName() + { + return $this->name; + } + + public function getOperator() + { + switch ($this->operator) { + case self::OPERATOR_ARRAY: + return '=>'; + case self::OPERATOR_OBJECT: + return '->'; + case self::OPERATOR_STATIC: + return '::'; + } + } + + public function getSize() + { + return $this->size; + } + + public function getValueShort() + { + if ($rep = $this->value) { + if ('boolean' === $this->type) { + return $rep->contents ? 'true' : 'false'; + } + + if ('integer' === $this->type || 'double' === $this->type) { + return $rep->contents; + } + } + } + + public function getAccessPath() + { + return $this->access_path; + } + + public function transplant(BasicObject $old) + { + $this->name = $old->name; + $this->size = $old->size; + $this->access_path = $old->access_path; + $this->access = $old->access; + $this->static = $old->static; + $this->const = $old->const; + $this->type = $old->type; + $this->depth = $old->depth; + $this->owner_class = $old->owner_class; + $this->operator = $old->operator; + $this->reference = $old->reference; + $this->value = $old->value; + $this->representations += $old->representations; + $this->hints = \array_merge($this->hints, $old->hints); + } + + /** + * Creates a new basic object with a name and access path. + * + * @param null|string $name + * @param null|string $access_path + * + * @return \Kint\Object\BasicObject + */ + public static function blank($name = null, $access_path = null) + { + $o = new self(); + $o->name = $name; + $o->access_path = $access_path; + + return $o; + } + + public static function sortByAccess(BasicObject $a, BasicObject $b) + { + static $sorts = array( + self::ACCESS_PUBLIC => 1, + self::ACCESS_PROTECTED => 2, + self::ACCESS_PRIVATE => 3, + self::ACCESS_NONE => 4, + ); + + return $sorts[$a->access] - $sorts[$b->access]; + } + + public static function sortByName(BasicObject $a, BasicObject $b) + { + $ret = \strnatcasecmp($a->name, $b->name); + + if (0 === $ret) { + return (int) \is_int($b->name) - (int) \is_int($a->name); + } + + return $ret; + } +} diff --git a/system/ThirdParty/Kint/Object/BlobObject.php b/system/ThirdParty/Kint/Object/BlobObject.php new file mode 100644 index 000000000000..66d508ff70db --- /dev/null +++ b/system/ThirdParty/Kint/Object/BlobObject.php @@ -0,0 +1,177 @@ +encoding) { + return 'binary '.$this->type; + } + + if ('ASCII' === $this->encoding) { + return $this->type; + } + + return $this->encoding.' '.$this->type; + } + + public function getValueShort() + { + if ($rep = $this->value) { + return '"'.$rep->contents.'"'; + } + } + + public function transplant(BasicObject $old) + { + parent::transplant($old); + + if ($old instanceof self) { + $this->encoding = $old->encoding; + } + } + + public static function strlen($string, $encoding = false) + { + if (\function_exists('mb_strlen')) { + if (false === $encoding) { + $encoding = self::detectEncoding($string); + } + + if ($encoding && 'ASCII' !== $encoding) { + return \mb_strlen($string, $encoding); + } + } + + return \strlen($string); + } + + public static function substr($string, $start, $length = null, $encoding = false) + { + if (\function_exists('mb_substr')) { + if (false === $encoding) { + $encoding = self::detectEncoding($string); + } + + if ($encoding && 'ASCII' !== $encoding) { + return \mb_substr($string, $start, $length, $encoding); + } + } + + // Special case for substr/mb_substr discrepancy + if ('' === $string) { + return ''; + } + + return \substr($string, $start, isset($length) ? $length : PHP_INT_MAX); + } + + public static function detectEncoding($string) + { + if (\function_exists('mb_detect_encoding')) { + if ($ret = \mb_detect_encoding($string, self::$char_encodings, true)) { + return $ret; + } + } + + // Pretty much every character encoding uses first 32 bytes as control + // characters. If it's not a multi-byte format it's safe to say matching + // any control character besides tab, nl, and cr means it's binary. + if (\preg_match('/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/', $string)) { + return false; + } + + if (\function_exists('iconv')) { + foreach (self::$legacy_encodings as $encoding) { + if (@\iconv($encoding, $encoding, $string) === $string) { + return $encoding; + } + } + } elseif (!\function_exists('mb_detect_encoding')) { // @codeCoverageIgnore + // If a user has neither mb_detect_encoding, nor iconv, nor the + // polyfills, there's not much we can do about it... + // Pretend it's ASCII and pray the browser renders it properly. + return 'ASCII'; // @codeCoverageIgnore + } + + return false; + } +} diff --git a/system/ThirdParty/Kint/Object/ClosureObject.php b/system/ThirdParty/Kint/Object/ClosureObject.php new file mode 100644 index 000000000000..344eceb21e77 --- /dev/null +++ b/system/ThirdParty/Kint/Object/ClosureObject.php @@ -0,0 +1,68 @@ +access_path) { + return parent::getAccessPath().'('.$this->getParams().')'; + } + } + + public function getSize() + { + } + + public function getParams() + { + if (null !== $this->paramcache) { + return $this->paramcache; + } + + $out = array(); + + foreach ($this->parameters as $p) { + $type = $p->getType(); + + $ref = $p->reference ? '&' : ''; + + if ($type) { + $out[] = $type.' '.$ref.$p->getName(); + } else { + $out[] = $ref.$p->getName(); + } + } + + return $this->paramcache = \implode(', ', $out); + } +} diff --git a/system/ThirdParty/Kint/Object/DateTimeObject.php b/system/ThirdParty/Kint/Object/DateTimeObject.php new file mode 100644 index 000000000000..f8b1b3fd164f --- /dev/null +++ b/system/ThirdParty/Kint/Object/DateTimeObject.php @@ -0,0 +1,53 @@ +dt = clone $dt; + } + + public function getValueShort() + { + $stamp = $this->dt->format('Y-m-d H:i:s'); + if ((int) ($micro = $this->dt->format('u'))) { + $stamp .= '.'.$micro; + } + $stamp .= $this->dt->format('P T'); + + return $stamp; + } +} diff --git a/system/ThirdParty/Kint/Object/InstanceObject.php b/system/ThirdParty/Kint/Object/InstanceObject.php new file mode 100644 index 000000000000..943b33d8eabb --- /dev/null +++ b/system/ThirdParty/Kint/Object/InstanceObject.php @@ -0,0 +1,78 @@ +classname; + } + + public function transplant(BasicObject $old) + { + parent::transplant($old); + + if ($old instanceof self) { + $this->classname = $old->classname; + $this->hash = $old->hash; + $this->filename = $old->filename; + $this->startline = $old->startline; + } + } + + public static function sortByHierarchy($a, $b) + { + if (\is_string($a) && \is_string($b)) { + $aclass = $a; + $bclass = $b; + } elseif (!($a instanceof BasicObject) || !($b instanceof BasicObject)) { + return 0; + } elseif ($a instanceof self && $b instanceof self) { + $aclass = $a->classname; + $bclass = $b->classname; + } else { + return 0; + } + + if (\is_subclass_of($aclass, $bclass)) { + return -1; + } + + if (\is_subclass_of($bclass, $aclass)) { + return 1; + } + + return 0; + } +} diff --git a/system/ThirdParty/Kint/Object/MethodObject.php b/system/ThirdParty/Kint/Object/MethodObject.php new file mode 100644 index 000000000000..78d49de22264 --- /dev/null +++ b/system/ThirdParty/Kint/Object/MethodObject.php @@ -0,0 +1,253 @@ +name = $method->getName(); + $this->filename = $method->getFileName(); + $this->startline = $method->getStartLine(); + $this->endline = $method->getEndLine(); + $this->internal = $method->isInternal(); + $this->docstring = $method->getDocComment(); + $this->return_reference = $method->returnsReference(); + + foreach ($method->getParameters() as $param) { + $this->parameters[] = new ParameterObject($param); + } + + if (KINT_PHP70) { + $this->returntype = $method->getReturnType(); + if ($this->returntype) { + $this->returntype = Utils::getTypeString($this->returntype); + } + } + + if ($method instanceof ReflectionMethod) { + $this->static = $method->isStatic(); + $this->operator = $this->static ? BasicObject::OPERATOR_STATIC : BasicObject::OPERATOR_OBJECT; + $this->abstract = $method->isAbstract(); + $this->final = $method->isFinal(); + $this->owner_class = $method->getDeclaringClass()->name; + $this->access = BasicObject::ACCESS_PUBLIC; + if ($method->isProtected()) { + $this->access = BasicObject::ACCESS_PROTECTED; + } elseif ($method->isPrivate()) { + $this->access = BasicObject::ACCESS_PRIVATE; + } + } + + if ($this->internal) { + return; + } + + $docstring = new DocstringRepresentation( + $this->docstring, + $this->filename, + $this->startline + ); + + $docstring->implicit_label = true; + $this->addRepresentation($docstring); + $this->value = $docstring; + } + + public function setAccessPathFrom(InstanceObject $parent) + { + static $magic = array( + '__call' => true, + '__callstatic' => true, + '__clone' => true, + '__construct' => true, + '__debuginfo' => true, + '__destruct' => true, + '__get' => true, + '__invoke' => true, + '__isset' => true, + '__set' => true, + '__set_state' => true, + '__sleep' => true, + '__tostring' => true, + '__unset' => true, + '__wakeup' => true, + ); + + $name = \strtolower($this->name); + + if ('__construct' === $name) { + $this->access_path = 'new \\'.$parent->getType(); + } elseif ('__invoke' === $name) { + $this->access_path = $parent->access_path; + } elseif ('__clone' === $name) { + $this->access_path = 'clone '.$parent->access_path; + $this->showparams = false; + } elseif ('__tostring' === $name) { + $this->access_path = '(string) '.$parent->access_path; + $this->showparams = false; + } elseif (isset($magic[$name])) { + $this->access_path = null; + } elseif ($this->static) { + $this->access_path = '\\'.$this->owner_class.'::'.$this->name; + } else { + $this->access_path = $parent->access_path.'->'.$this->name; + } + } + + public function getValueShort() + { + if (!$this->value || !($this->value instanceof DocstringRepresentation)) { + return parent::getValueShort(); + } + + $ds = $this->value->getDocstringWithoutComments(); + + if (!$ds) { + return null; + } + + $ds = \explode("\n", $ds); + + $out = ''; + + foreach ($ds as $line) { + if (0 === \strlen(\trim($line)) || '@' === $line[0]) { + break; + } + + $out .= $line.' '; + } + + if (\strlen($out)) { + return \rtrim($out); + } + } + + public function getModifiers() + { + $mods = array( + $this->abstract ? 'abstract' : null, + $this->final ? 'final' : null, + $this->getAccess(), + $this->static ? 'static' : null, + ); + + $out = ''; + + foreach ($mods as $word) { + if (null !== $word) { + $out .= $word.' '; + } + } + + if (\strlen($out)) { + return \rtrim($out); + } + } + + public function getAccessPath() + { + if (null !== $this->access_path) { + if ($this->showparams) { + return parent::getAccessPath().'('.$this->getParams().')'; + } + + return parent::getAccessPath(); + } + } + + public function getParams() + { + if (null !== $this->paramcache) { + return $this->paramcache; + } + + $out = array(); + + foreach ($this->parameters as $p) { + $type = $p->getType(); + if ($type) { + $type .= ' '; + } + + $default = $p->getDefault(); + if ($default) { + $default = ' = '.$default; + } + + $ref = $p->reference ? '&' : ''; + + $out[] = $type.$ref.$p->getName().$default; + } + + return $this->paramcache = \implode(', ', $out); + } + + public function getPhpDocUrl() + { + if (!$this->internal) { + return null; + } + + if ($this->owner_class) { + $class = \strtolower($this->owner_class); + } else { + $class = 'function'; + } + + $funcname = \str_replace('_', '-', \strtolower($this->name)); + + if (0 === \strpos($funcname, '--') && 0 !== \strpos($funcname, '-', 2)) { + $funcname = \substr($funcname, 2); + } + + return 'https://secure.php.net/'.$class.'.'.$funcname; + } +} diff --git a/system/ThirdParty/Kint/Object/ParameterObject.php b/system/ThirdParty/Kint/Object/ParameterObject.php new file mode 100644 index 000000000000..4bed551f548b --- /dev/null +++ b/system/ThirdParty/Kint/Object/ParameterObject.php @@ -0,0 +1,100 @@ +getType()) { + $this->type_hint = Utils::getTypeString($type); + } + } else { + if ($param->isArray()) { + $this->type_hint = 'array'; + } else { + try { + if ($this->type_hint = $param->getClass()) { + $this->type_hint = $this->type_hint->name; + } + } catch (ReflectionException $e) { + \preg_match('/\\[\\s\\<\\w+?>\\s([\\w]+)/s', $param->__toString(), $matches); + $this->type_hint = isset($matches[1]) ? $matches[1] : ''; + } + } + } + + $this->reference = $param->isPassedByReference(); + $this->name = $param->getName(); + $this->position = $param->getPosition(); + + if ($param->isDefaultValueAvailable()) { + /** @var mixed Psalm bug workaround */ + $default = $param->getDefaultValue(); + switch (\gettype($default)) { + case 'NULL': + $this->default = 'null'; + break; + case 'boolean': + $this->default = $default ? 'true' : 'false'; + break; + case 'array': + $this->default = \count($default) ? 'array(...)' : 'array()'; + break; + default: + $this->default = \var_export($default, true); + break; + } + } + } + + public function getType() + { + return $this->type_hint; + } + + public function getName() + { + return '$'.$this->name; + } + + public function getDefault() + { + return $this->default; + } +} diff --git a/system/ThirdParty/Kint/Object/Representation/ColorRepresentation.php b/system/ThirdParty/Kint/Object/Representation/ColorRepresentation.php new file mode 100644 index 000000000000..d6a072f50891 --- /dev/null +++ b/system/ThirdParty/Kint/Object/Representation/ColorRepresentation.php @@ -0,0 +1,576 @@ + 'f0f8ff', + 'antiquewhite' => 'faebd7', + 'aqua' => '00ffff', + 'aquamarine' => '7fffd4', + 'azure' => 'f0ffff', + 'beige' => 'f5f5dc', + 'bisque' => 'ffe4c4', + 'black' => '000000', + 'blanchedalmond' => 'ffebcd', + 'blue' => '0000ff', + 'blueviolet' => '8a2be2', + 'brown' => 'a52a2a', + 'burlywood' => 'deb887', + 'cadetblue' => '5f9ea0', + 'chartreuse' => '7fff00', + 'chocolate' => 'd2691e', + 'coral' => 'ff7f50', + 'cornflowerblue' => '6495ed', + 'cornsilk' => 'fff8dc', + 'crimson' => 'dc143c', + 'cyan' => '00ffff', + 'darkblue' => '00008b', + 'darkcyan' => '008b8b', + 'darkgoldenrod' => 'b8860b', + 'darkgray' => 'a9a9a9', + 'darkgreen' => '006400', + 'darkgrey' => 'a9a9a9', + 'darkkhaki' => 'bdb76b', + 'darkmagenta' => '8b008b', + 'darkolivegreen' => '556b2f', + 'darkorange' => 'ff8c00', + 'darkorchid' => '9932cc', + 'darkred' => '8b0000', + 'darksalmon' => 'e9967a', + 'darkseagreen' => '8fbc8f', + 'darkslateblue' => '483d8b', + 'darkslategray' => '2f4f4f', + 'darkslategrey' => '2f4f4f', + 'darkturquoise' => '00ced1', + 'darkviolet' => '9400d3', + 'deeppink' => 'ff1493', + 'deepskyblue' => '00bfff', + 'dimgray' => '696969', + 'dimgrey' => '696969', + 'dodgerblue' => '1e90ff', + 'firebrick' => 'b22222', + 'floralwhite' => 'fffaf0', + 'forestgreen' => '228b22', + 'fuchsia' => 'ff00ff', + 'gainsboro' => 'dcdcdc', + 'ghostwhite' => 'f8f8ff', + 'gold' => 'ffd700', + 'goldenrod' => 'daa520', + 'gray' => '808080', + 'green' => '008000', + 'greenyellow' => 'adff2f', + 'grey' => '808080', + 'honeydew' => 'f0fff0', + 'hotpink' => 'ff69b4', + 'indianred' => 'cd5c5c', + 'indigo' => '4b0082', + 'ivory' => 'fffff0', + 'khaki' => 'f0e68c', + 'lavender' => 'e6e6fa', + 'lavenderblush' => 'fff0f5', + 'lawngreen' => '7cfc00', + 'lemonchiffon' => 'fffacd', + 'lightblue' => 'add8e6', + 'lightcoral' => 'f08080', + 'lightcyan' => 'e0ffff', + 'lightgoldenrodyellow' => 'fafad2', + 'lightgray' => 'd3d3d3', + 'lightgreen' => '90ee90', + 'lightgrey' => 'd3d3d3', + 'lightpink' => 'ffb6c1', + 'lightsalmon' => 'ffa07a', + 'lightseagreen' => '20b2aa', + 'lightskyblue' => '87cefa', + 'lightslategray' => '778899', + 'lightslategrey' => '778899', + 'lightsteelblue' => 'b0c4de', + 'lightyellow' => 'ffffe0', + 'lime' => '00ff00', + 'limegreen' => '32cd32', + 'linen' => 'faf0e6', + 'magenta' => 'ff00ff', + 'maroon' => '800000', + 'mediumaquamarine' => '66cdaa', + 'mediumblue' => '0000cd', + 'mediumorchid' => 'ba55d3', + 'mediumpurple' => '9370db', + 'mediumseagreen' => '3cb371', + 'mediumslateblue' => '7b68ee', + 'mediumspringgreen' => '00fa9a', + 'mediumturquoise' => '48d1cc', + 'mediumvioletred' => 'c71585', + 'midnightblue' => '191970', + 'mintcream' => 'f5fffa', + 'mistyrose' => 'ffe4e1', + 'moccasin' => 'ffe4b5', + 'navajowhite' => 'ffdead', + 'navy' => '000080', + 'oldlace' => 'fdf5e6', + 'olive' => '808000', + 'olivedrab' => '6b8e23', + 'orange' => 'ffa500', + 'orangered' => 'ff4500', + 'orchid' => 'da70d6', + 'palegoldenrod' => 'eee8aa', + 'palegreen' => '98fb98', + 'paleturquoise' => 'afeeee', + 'palevioletred' => 'db7093', + 'papayawhip' => 'ffefd5', + 'peachpuff' => 'ffdab9', + 'peru' => 'cd853f', + 'pink' => 'ffc0cb', + 'plum' => 'dda0dd', + 'powderblue' => 'b0e0e6', + 'purple' => '800080', + 'rebeccapurple' => '663399', + 'red' => 'ff0000', + 'rosybrown' => 'bc8f8f', + 'royalblue' => '4169e1', + 'saddlebrown' => '8b4513', + 'salmon' => 'fa8072', + 'sandybrown' => 'f4a460', + 'seagreen' => '2e8b57', + 'seashell' => 'fff5ee', + 'sienna' => 'a0522d', + 'silver' => 'c0c0c0', + 'skyblue' => '87ceeb', + 'slateblue' => '6a5acd', + 'slategray' => '708090', + 'slategrey' => '708090', + 'snow' => 'fffafa', + 'springgreen' => '00ff7f', + 'steelblue' => '4682b4', + 'tan' => 'd2b48c', + 'teal' => '008080', + 'thistle' => 'd8bfd8', + 'tomato' => 'ff6347', + // To quote MDN: + // "Technically, transparent is a shortcut for rgba(0,0,0,0)." + 'transparent' => '00000000', + 'turquoise' => '40e0d0', + 'violet' => 'ee82ee', + 'wheat' => 'f5deb3', + 'white' => 'ffffff', + 'whitesmoke' => 'f5f5f5', + 'yellow' => 'ffff00', + 'yellowgreen' => '9acd32', + ); + + public $r = 0; + public $g = 0; + public $b = 0; + public $a = 1.0; + public $variant; + public $implicit_label = true; + public $hints = array('color'); + + public function __construct($value) + { + parent::__construct('Color'); + + $this->contents = $value; + $this->setValues($value); + } + + public function getColor($variant = null) + { + if (!$variant) { + $variant = $this->variant; + } + + switch ($variant) { + case self::COLOR_NAME: + $hex = \sprintf('%02x%02x%02x', $this->r, $this->g, $this->b); + $hex_alpha = \sprintf('%02x%02x%02x%02x', $this->r, $this->g, $this->b, \round($this->a * 0xFF)); + + return \array_search($hex, self::$color_map, true) ?: \array_search($hex_alpha, self::$color_map, true); + case self::COLOR_HEX_3: + if (0 === $this->r % 0x11 && 0 === $this->g % 0x11 && 0 === $this->b % 0x11) { + return \sprintf( + '#%1X%1X%1X', + \round($this->r / 0x11), + \round($this->g / 0x11), + \round($this->b / 0x11) + ); + } + + return false; + case self::COLOR_HEX_6: + return \sprintf('#%02X%02X%02X', $this->r, $this->g, $this->b); + case self::COLOR_RGB: + if (1.0 === $this->a) { + return \sprintf('rgb(%d, %d, %d)', $this->r, $this->g, $this->b); + } + + return \sprintf('rgb(%d, %d, %d, %s)', $this->r, $this->g, $this->b, \round($this->a, 4)); + case self::COLOR_RGBA: + return \sprintf('rgba(%d, %d, %d, %s)', $this->r, $this->g, $this->b, \round($this->a, 4)); + case self::COLOR_HSL: + $val = self::rgbToHsl($this->r, $this->g, $this->b); + if (1.0 === $this->a) { + return \vsprintf('hsl(%d, %d%%, %d%%)', $val); + } + + return \sprintf('hsl(%d, %d%%, %d%%, %s)', $val[0], $val[1], $val[2], \round($this->a, 4)); + case self::COLOR_HSLA: + $val = self::rgbToHsl($this->r, $this->g, $this->b); + + return \sprintf('hsla(%d, %d%%, %d%%, %s)', $val[0], $val[1], $val[2], \round($this->a, 4)); + case self::COLOR_HEX_4: + if (0 === $this->r % 0x11 && 0 === $this->g % 0x11 && 0 === $this->b % 0x11 && 0 === ($this->a * 255) % 0x11) { + return \sprintf( + '#%1X%1X%1X%1X', + \round($this->r / 0x11), + \round($this->g / 0x11), + \round($this->b / 0x11), + \round($this->a * 0xF) + ); + } + + return false; + + case self::COLOR_HEX_8: + return \sprintf('#%02X%02X%02X%02X', $this->r, $this->g, $this->b, \round($this->a * 0xFF)); + } + + return false; + } + + public function hasAlpha($variant = null) + { + if (null === $variant) { + $variant = $this->variant; + } + + switch ($variant) { + case self::COLOR_NAME: + case self::COLOR_RGB: + case self::COLOR_HSL: + return \abs($this->a - 1) >= 0.0001; + case self::COLOR_RGBA: + case self::COLOR_HSLA: + case self::COLOR_HEX_4: + case self::COLOR_HEX_8: + return true; + default: + return false; + } + } + + protected function setValues($value) + { + $value = \strtolower(\trim($value)); + // Find out which variant of color input it is + if (isset(self::$color_map[$value])) { + if (!$this->setValuesFromHex(self::$color_map[$value])) { + return; + } + + $variant = self::COLOR_NAME; + } elseif ('#' === $value[0]) { + $variant = $this->setValuesFromHex(\substr($value, 1)); + + if (!$variant) { + return; + } + } else { + $variant = $this->setValuesFromFunction($value); + + if (!$variant) { + return; + } + } + + // If something has gone horribly wrong + if ($this->r > 0xFF || $this->g > 0xFF || $this->b > 0xFF || $this->a > 1) { + $this->variant = null; // @codeCoverageIgnore + } else { + $this->variant = $variant; + $this->r = (int) $this->r; + $this->g = (int) $this->g; + $this->b = (int) $this->b; + $this->a = (float) $this->a; + } + } + + protected function setValuesFromHex($hex) + { + if (!\ctype_xdigit($hex)) { + return null; + } + + switch (\strlen($hex)) { + case 3: + $variant = self::COLOR_HEX_3; + break; + case 6: + $variant = self::COLOR_HEX_6; + break; + case 4: + $variant = self::COLOR_HEX_4; + break; + case 8: + $variant = self::COLOR_HEX_8; + break; + default: + return null; + } + + switch ($variant) { + case self::COLOR_HEX_4: + $this->a = \hexdec($hex[3]) / 0xF; + // no break + case self::COLOR_HEX_3: + $this->r = \hexdec($hex[0]) * 0x11; + $this->g = \hexdec($hex[1]) * 0x11; + $this->b = \hexdec($hex[2]) * 0x11; + break; + case self::COLOR_HEX_8: + $this->a = \hexdec(\substr($hex, 6, 2)) / 0xFF; + // no break + case self::COLOR_HEX_6: + $hex = \str_split($hex, 2); + $this->r = \hexdec($hex[0]); + $this->g = \hexdec($hex[1]); + $this->b = \hexdec($hex[2]); + break; + } + + return $variant; + } + + protected function setValuesFromFunction($value) + { + if (!\preg_match('/^((?:rgb|hsl)a?)\\s*\\(([0-9\\.%,\\s\\/\\-]+)\\)$/i', $value, $match)) { + return null; + } + + switch (\strtolower($match[1])) { + case 'rgb': + $variant = self::COLOR_RGB; + break; + case 'rgba': + $variant = self::COLOR_RGBA; + break; + case 'hsl': + $variant = self::COLOR_HSL; + break; + case 'hsla': + $variant = self::COLOR_HSLA; + break; + default: + return null; // @codeCoverageIgnore + } + + $params = \preg_replace('/[,\\s\\/]+/', ',', \trim($match[2])); + $params = \explode(',', $params); + $params = \array_map('trim', $params); + + if (\count($params) < 3 || \count($params) > 4) { + return null; + } + + foreach ($params as $i => &$color) { + if (false !== \strpos($color, '%')) { + $color = (float) \str_replace('%', '', $color); + + if (3 === $i) { + $color = $color / 100; + } elseif (\in_array($variant, array(self::COLOR_RGB, self::COLOR_RGBA), true)) { + $color = \round($color / 100 * 0xFF); + } + } + + $color = (float) $color; + + if (0 === $i && \in_array($variant, array(self::COLOR_HSL, self::COLOR_HSLA), true)) { + $color = ($color % 360 + 360) % 360; + } + } + + /** @var float[] Psalm bug workaround */ + $params = \array_map('floatval', $params); + + switch ($variant) { + case self::COLOR_RGBA: + case self::COLOR_RGB: + if (\min($params) < 0 || \max($params) > 0xFF) { + return null; + } + break; + case self::COLOR_HSLA: + case self::COLOR_HSL: + if (\min($params) < 0 || $params[0] > 360 || \max($params[1], $params[2]) > 100) { + return null; + } + break; + } + + if (4 === \count($params)) { + if ($params[3] > 1) { + return null; + } + + $this->a = $params[3]; + } + + if (self::COLOR_HSLA === $variant || self::COLOR_HSL === $variant) { + $params = self::hslToRgb($params[0], $params[1], $params[2]); + } + + list($this->r, $this->g, $this->b) = $params; + + return $variant; + } + + /** + * Turns HSL color to RGB. Black magic. + * + * @param float $h Hue + * @param float $s Saturation + * @param float $l Lightness + * + * @return int[] RGB array + */ + public static function hslToRgb($h, $s, $l) + { + if (\min($h, $s, $l) < 0) { + throw new InvalidArgumentException('The parameters for hslToRgb should be no less than 0'); + } + + if ($h > 360 || \max($s, $l) > 100) { + throw new InvalidArgumentException('The parameters for hslToRgb should be no more than 360, 100, and 100 respectively'); + } + + $h /= 360; + $s /= 100; + $l /= 100; + + $m2 = ($l <= 0.5) ? $l * ($s + 1) : $l + $s - $l * $s; + $m1 = $l * 2 - $m2; + + return array( + (int) \round(self::hueToRgb($m1, $m2, $h + 1 / 3) * 0xFF), + (int) \round(self::hueToRgb($m1, $m2, $h) * 0xFF), + (int) \round(self::hueToRgb($m1, $m2, $h - 1 / 3) * 0xFF), + ); + } + + /** + * Converts RGB to HSL. Color inversion of previous black magic is white magic? + * + * @param float|int $red Red + * @param float|int $green Green + * @param float|int $blue Blue + * + * @return float[] HSL array + */ + public static function rgbToHsl($red, $green, $blue) + { + if (\min($red, $green, $blue) < 0) { + throw new InvalidArgumentException('The parameters for rgbToHsl should be no less than 0'); + } + + if (\max($red, $green, $blue) > 0xFF) { + throw new InvalidArgumentException('The parameters for rgbToHsl should be no more than 255'); + } + + $clrMin = \min($red, $green, $blue); + $clrMax = \max($red, $green, $blue); + $deltaMax = $clrMax - $clrMin; + + $L = ($clrMax + $clrMin) / 510; + + if (0 == $deltaMax) { + $H = 0; + $S = 0; + } else { + if (0.5 > $L) { + $S = $deltaMax / ($clrMax + $clrMin); + } else { + $S = $deltaMax / (510 - $clrMax - $clrMin); + } + + if ($clrMax === $red) { + $H = ($green - $blue) / (6.0 * $deltaMax); + + if (0 > $H) { + $H += 1.0; + } + } elseif ($clrMax === $green) { + $H = 1 / 3 + ($blue - $red) / (6.0 * $deltaMax); + } else { + $H = 2 / 3 + ($red - $green) / (6.0 * $deltaMax); + } + } + + return array( + (float) ($H * 360 % 360), + (float) ($S * 100), + (float) ($L * 100), + ); + } + + /** + * Helper function for hslToRgb. Even blacker magic. + * + * + * @param float $m1 + * @param float $m2 + * @param float $hue + * + * @return float Color value + */ + private static function hueToRgb($m1, $m2, $hue) + { + $hue = ($hue < 0) ? $hue + 1 : (($hue > 1) ? $hue - 1 : $hue); + if ($hue * 6 < 1) { + return $m1 + ($m2 - $m1) * $hue * 6; + } + if ($hue * 2 < 1) { + return $m2; + } + if ($hue * 3 < 2) { + return $m1 + ($m2 - $m1) * (2 / 3 - $hue) * 6; + } + + return $m1; + } +} diff --git a/system/ThirdParty/Kint/Object/Representation/DocstringRepresentation.php b/system/ThirdParty/Kint/Object/Representation/DocstringRepresentation.php new file mode 100644 index 000000000000..488d8d6e0748 --- /dev/null +++ b/system/ThirdParty/Kint/Object/Representation/DocstringRepresentation.php @@ -0,0 +1,73 @@ +file = $file; + $this->line = $line; + $this->class = $class; + $this->contents = $docstring; + } + + /** + * Returns the representation's docstring without surrounding comments. + * + * Note that this will not work flawlessly. + * + * On comments with whitespace after the stars the lines will begin with + * whitespace, since we can't accurately guess how much of an indentation + * is required. + * + * And on lines without stars on the left this may eat bullet points. + * + * Long story short: If you want the docstring read the contents. If you + * absolutely must have it without comments (ie renderValueShort) this will + * probably do. + * + * @return null|string Docstring with comments stripped + */ + public function getDocstringWithoutComments() + { + if (!$this->contents) { + return null; + } + + $string = \substr($this->contents, 3, -2); + $string = \preg_replace('/^\\s*\\*\\s*?(\\S|$)/m', '\\1', $string); + + return \trim($string); + } +} diff --git a/system/ThirdParty/Kint/Object/Representation/MicrotimeRepresentation.php b/system/ThirdParty/Kint/Object/Representation/MicrotimeRepresentation.php new file mode 100644 index 000000000000..b9f4dacb314b --- /dev/null +++ b/system/ThirdParty/Kint/Object/Representation/MicrotimeRepresentation.php @@ -0,0 +1,71 @@ +seconds = (int) $seconds; + $this->microseconds = (int) $microseconds; + + $this->group = $group; + $this->lap = $lap; + $this->total = $total; + $this->i = $i; + + if ($i) { + $this->avg = $total / $i; + } + + $this->mem = \memory_get_usage(); + $this->mem_real = \memory_get_usage(true); + $this->mem_peak = \memory_get_peak_usage(); + $this->mem_peak_real = \memory_get_peak_usage(true); + } + + public function getDateTime() + { + return DateTime::createFromFormat('U u', $this->seconds.' '.\str_pad($this->microseconds, 6, '0', STR_PAD_LEFT)); + } +} diff --git a/system/ThirdParty/Kint/Object/Representation/Representation.php b/system/ThirdParty/Kint/Object/Representation/Representation.php new file mode 100644 index 000000000000..0c911a4eaa98 --- /dev/null +++ b/system/ThirdParty/Kint/Object/Representation/Representation.php @@ -0,0 +1,71 @@ +label = $label; + + if (null === $name) { + $name = $label; + } + + $this->setName($name); + } + + public function getLabel() + { + if (\is_array($this->contents) && \count($this->contents) > 1) { + return $this->label.' ('.\count($this->contents).')'; + } + + return $this->label; + } + + public function getName() + { + return $this->name; + } + + public function setName($name) + { + $this->name = \preg_replace('/[^a-z0-9]+/', '_', \strtolower($name)); + } + + public function labelIsImplicit() + { + return $this->implicit_label; + } +} diff --git a/system/ThirdParty/Kint/Object/Representation/SourceRepresentation.php b/system/ThirdParty/Kint/Object/Representation/SourceRepresentation.php new file mode 100644 index 000000000000..c2cf1204f1a9 --- /dev/null +++ b/system/ThirdParty/Kint/Object/Representation/SourceRepresentation.php @@ -0,0 +1,72 @@ +filename = $filename; + $this->line = $line; + + $start_line = \max($line - $padding, 1); + $length = $line + $padding + 1 - $start_line; + $this->source = self::getSource($filename, $start_line, $length); + if (null !== $this->source) { + $this->contents = \implode("\n", $this->source); + } + } + + /** + * Gets section of source code. + * + * @param string $filename Full path to file + * @param int $start_line The first line to display (1 based) + * @param null|int $length Amount of lines to show + * + * @return null|array + */ + public static function getSource($filename, $start_line = 1, $length = null) + { + if (!$filename || !\file_exists($filename) || !\is_readable($filename)) { + return null; + } + + $source = \preg_split("/\r\n|\n|\r/", \file_get_contents($filename)); + $source = \array_combine(\range(1, \count($source)), $source); + $source = \array_slice($source, $start_line - 1, $length, true); + + return $source; + } +} diff --git a/system/ThirdParty/Kint/Object/Representation/SplFileInfoRepresentation.php b/system/ThirdParty/Kint/Object/Representation/SplFileInfoRepresentation.php new file mode 100644 index 000000000000..3df50e6a1284 --- /dev/null +++ b/system/ThirdParty/Kint/Object/Representation/SplFileInfoRepresentation.php @@ -0,0 +1,177 @@ +getRealPath()) { + $this->realpath = $fileInfo->getRealPath(); + $this->perms = $fileInfo->getPerms(); + $this->size = $fileInfo->getSize(); + $this->owner = $fileInfo->getOwner(); + $this->group = $fileInfo->getGroup(); + $this->ctime = $fileInfo->getCTime(); + $this->mtime = $fileInfo->getMTime(); + } + + $this->path = $fileInfo->getPathname(); + + $this->is_dir = $fileInfo->isDir(); + $this->is_file = $fileInfo->isFile(); + $this->is_link = $fileInfo->isLink(); + + if ($this->is_link) { + $this->linktarget = $fileInfo->getLinkTarget(); + } + + switch ($this->perms & 0xF000) { + case 0xC000: + $this->typename = 'Socket'; + $this->typeflag = 's'; + break; + case 0x6000: + $this->typename = 'Block device'; + $this->typeflag = 'b'; + break; + case 0x2000: + $this->typename = 'Character device'; + $this->typeflag = 'c'; + break; + case 0x1000: + $this->typename = 'Named pipe'; + $this->typeflag = 'p'; + break; + default: + if ($this->is_file) { + if ($this->is_link) { + $this->typename = 'File symlink'; + $this->typeflag = 'l'; + } else { + $this->typename = 'File'; + $this->typeflag = '-'; + } + } elseif ($this->is_dir) { + if ($this->is_link) { + $this->typename = 'Directory symlink'; + $this->typeflag = 'l'; + } else { + $this->typename = 'Directory'; + $this->typeflag = 'd'; + } + } + break; + } + + $this->flags = array($this->typeflag); + + // User + $this->flags[] = (($this->perms & 0400) ? 'r' : '-'); + $this->flags[] = (($this->perms & 0200) ? 'w' : '-'); + if ($this->perms & 0100) { + $this->flags[] = ($this->perms & 04000) ? 's' : 'x'; + } else { + $this->flags[] = ($this->perms & 04000) ? 'S' : '-'; + } + + // Group + $this->flags[] = (($this->perms & 0040) ? 'r' : '-'); + $this->flags[] = (($this->perms & 0020) ? 'w' : '-'); + if ($this->perms & 0010) { + $this->flags[] = ($this->perms & 02000) ? 's' : 'x'; + } else { + $this->flags[] = ($this->perms & 02000) ? 'S' : '-'; + } + + // Other + $this->flags[] = (($this->perms & 0004) ? 'r' : '-'); + $this->flags[] = (($this->perms & 0002) ? 'w' : '-'); + if ($this->perms & 0001) { + $this->flags[] = ($this->perms & 01000) ? 's' : 'x'; + } else { + $this->flags[] = ($this->perms & 01000) ? 'S' : '-'; + } + + $this->contents = \implode($this->flags).' '.$this->owner.' '.$this->group; + $this->contents .= ' '.$this->getSize().' '.$this->getMTime().' '; + + if ($this->is_link && $this->linktarget) { + $this->contents .= $this->path.' -> '.$this->linktarget; + } elseif (null !== $this->realpath && \strlen($this->realpath) < \strlen($this->path)) { + $this->contents .= $this->realpath; + } else { + $this->contents .= $this->path; + } + } + + public function getLabel() + { + return $this->typename.' ('.$this->getSize().')'; + } + + public function getSize() + { + if ($this->size) { + $size = Utils::getHumanReadableBytes($this->size); + + return \round($size['value'], 2).$size['unit']; + } + } + + public function getMTime() + { + $year = \date('Y', $this->mtime); + + if ($year !== \date('Y')) { + return \date('M d Y', $this->mtime); + } + + return \date('M d H:i', $this->mtime); + } +} diff --git a/system/ThirdParty/Kint/Object/ResourceObject.php b/system/ThirdParty/Kint/Object/ResourceObject.php new file mode 100644 index 000000000000..a43f85d900ee --- /dev/null +++ b/system/ThirdParty/Kint/Object/ResourceObject.php @@ -0,0 +1,49 @@ +resource_type) { + return $this->resource_type.' resource'; + } + + return 'resource'; + } + + public function transplant(BasicObject $old) + { + parent::transplant($old); + + if ($old instanceof self) { + $this->resource_type = $old->resource_type; + } + } +} diff --git a/system/ThirdParty/Kint/Object/StreamObject.php b/system/ThirdParty/Kint/Object/StreamObject.php new file mode 100644 index 000000000000..358f2743e94f --- /dev/null +++ b/system/ThirdParty/Kint/Object/StreamObject.php @@ -0,0 +1,54 @@ +stream_meta = $meta; + } + + public function getValueShort() + { + if (empty($this->stream_meta['uri'])) { + return; + } + + $uri = $this->stream_meta['uri']; + + if (\stream_is_local($uri)) { + return Kint::shortenPath($uri); + } + + return $uri; + } +} diff --git a/system/ThirdParty/Kint/Object/ThrowableObject.php b/system/ThirdParty/Kint/Object/ThrowableObject.php new file mode 100644 index 000000000000..2a86d57538df --- /dev/null +++ b/system/ThirdParty/Kint/Object/ThrowableObject.php @@ -0,0 +1,54 @@ +message = $throw->getMessage(); + } + + public function getValueShort() + { + if (\strlen($this->message)) { + return '"'.$this->message.'"'; + } + } +} diff --git a/system/ThirdParty/Kint/Object/TraceFrameObject.php b/system/ThirdParty/Kint/Object/TraceFrameObject.php new file mode 100644 index 000000000000..4259aeeec1aa --- /dev/null +++ b/system/ThirdParty/Kint/Object/TraceFrameObject.php @@ -0,0 +1,100 @@ +transplant($base); + + $this->trace = array( + 'function' => isset($raw_frame['function']) ? $raw_frame['function'] : null, + 'line' => isset($raw_frame['line']) ? $raw_frame['line'] : null, + 'file' => isset($raw_frame['file']) ? $raw_frame['file'] : null, + 'class' => isset($raw_frame['class']) ? $raw_frame['class'] : null, + 'type' => isset($raw_frame['type']) ? $raw_frame['type'] : null, + 'object' => null, + 'args' => null, + ); + + if ($this->trace['class'] && \method_exists($this->trace['class'], $this->trace['function'])) { + $func = new ReflectionMethod($this->trace['class'], $this->trace['function']); + $this->trace['function'] = new MethodObject($func); + } elseif (!$this->trace['class'] && \function_exists($this->trace['function'])) { + $func = new ReflectionFunction($this->trace['function']); + $this->trace['function'] = new MethodObject($func); + } + + foreach ($this->value->contents as $frame_prop) { + if ('object' === $frame_prop->name) { + $this->trace['object'] = $frame_prop; + $this->trace['object']->name = null; + $this->trace['object']->operator = BasicObject::OPERATOR_NONE; + } + if ('args' === $frame_prop->name) { + $this->trace['args'] = $frame_prop->value->contents; + + if ($this->trace['function'] instanceof MethodObject) { + foreach (\array_values($this->trace['function']->parameters) as $param) { + if (isset($this->trace['args'][$param->position])) { + $this->trace['args'][$param->position]->name = $param->getName(); + } + } + } + } + } + + $this->clearRepresentations(); + + if (isset($this->trace['file'], $this->trace['line']) && \is_readable($this->trace['file'])) { + $this->addRepresentation(new SourceRepresentation($this->trace['file'], $this->trace['line'])); + } + + if ($this->trace['args']) { + $args = new Representation('Arguments'); + $args->contents = $this->trace['args']; + $this->addRepresentation($args); + } + + if ($this->trace['object']) { + $callee = new Representation('object'); + $callee->label = 'Callee object ['.$this->trace['object']->classname.']'; + $callee->contents[] = $this->trace['object']; + $this->addRepresentation($callee); + } + } +} diff --git a/system/ThirdParty/Kint/Object/TraceObject.php b/system/ThirdParty/Kint/Object/TraceObject.php new file mode 100644 index 000000000000..a780b082bf9c --- /dev/null +++ b/system/ThirdParty/Kint/Object/TraceObject.php @@ -0,0 +1,45 @@ +size) { + return 'empty'; + } + + return parent::getSize(); + } +} diff --git a/system/ThirdParty/Kint/Parser/ArrayObjectPlugin.php b/system/ThirdParty/Kint/Parser/ArrayObjectPlugin.php new file mode 100644 index 000000000000..286d255b16b9 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/ArrayObjectPlugin.php @@ -0,0 +1,63 @@ +getFlags(); + + if (ArrayObject::STD_PROP_LIST === $flags) { + return; + } + + $var->setFlags(ArrayObject::STD_PROP_LIST); + + $o = $this->parser->parse($var, $o); + + $var->setFlags($flags); + + $this->parser->haltParse(); + } +} diff --git a/system/ThirdParty/Kint/Parser/Base64Plugin.php b/system/ThirdParty/Kint/Parser/Base64Plugin.php new file mode 100644 index 000000000000..3d7d6bc29011 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/Base64Plugin.php @@ -0,0 +1,95 @@ +depth = $o->depth + 1; + $base_obj->name = 'base64_decode('.$o->name.')'; + + if ($o->access_path) { + $base_obj->access_path = 'base64_decode('.$o->access_path.')'; + } + + $r = new Representation('Base64'); + $r->contents = $this->parser->parse($data, $base_obj); + + if (\strlen($var) > self::$min_length_soft) { + $o->addRepresentation($r, 0); + } else { + $o->addRepresentation($r); + } + } +} diff --git a/system/ThirdParty/Kint/Parser/BinaryPlugin.php b/system/ThirdParty/Kint/Parser/BinaryPlugin.php new file mode 100644 index 000000000000..327c297cd560 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/BinaryPlugin.php @@ -0,0 +1,49 @@ +encoding, array('ASCII', 'UTF-8'), true)) { + $o->value->hints[] = 'binary'; + } + } +} diff --git a/system/ThirdParty/Kint/Parser/BlacklistPlugin.php b/system/ThirdParty/Kint/Parser/BlacklistPlugin.php new file mode 100644 index 000000000000..b37e45ff6fbf --- /dev/null +++ b/system/ThirdParty/Kint/Parser/BlacklistPlugin.php @@ -0,0 +1,143 @@ +parseObject($var, $o); + } + if (\is_array($var)) { + return $this->parseArray($var, $o); + } + } + + protected function parseObject(&$var, BasicObject &$o) + { + foreach (self::$blacklist as $class) { + if ($var instanceof $class) { + return $this->blacklistObject($var, $o); + } + } + + if ($o->depth <= 0) { + return; + } + + foreach (self::$shallow_blacklist as $class) { + if ($var instanceof $class) { + return $this->blacklistObject($var, $o); + } + } + } + + protected function blacklistObject(&$var, BasicObject &$o) + { + $object = new InstanceObject(); + $object->transplant($o); + $object->classname = \get_class($var); + $object->hash = \spl_object_hash($var); + $object->clearRepresentations(); + $object->value = null; + $object->size = null; + $object->hints[] = 'blacklist'; + + $o = $object; + + $this->parser->haltParse(); + } + + protected function parseArray(array &$var, BasicObject &$o) + { + if (\count($var) > self::$array_limit) { + return $this->blacklistArray($var, $o); + } + + if ($o->depth <= 0) { + return; + } + + if (\count($var) > self::$shallow_array_limit) { + return $this->blacklistArray($var, $o); + } + } + + protected function blacklistArray(array &$var, BasicObject &$o) + { + $object = new BasicObject(); + $object->transplant($o); + $object->value = null; + $object->size = \count($var); + $object->hints[] = 'blacklist'; + + $o = $object; + + $this->parser->haltParse(); + } +} diff --git a/system/ThirdParty/Kint/Parser/ClassMethodsPlugin.php b/system/ThirdParty/Kint/Parser/ClassMethodsPlugin.php new file mode 100644 index 000000000000..e4c23716186a --- /dev/null +++ b/system/ThirdParty/Kint/Parser/ClassMethodsPlugin.php @@ -0,0 +1,113 @@ +getMethods() as $method) { + $methods[] = new MethodObject($method); + } + + \usort($methods, array('Kint\\Parser\\ClassMethodsPlugin', 'sort')); + + self::$cache[$class] = $methods; + } + + if (!empty(self::$cache[$class])) { + $rep = new Representation('Available methods', 'methods'); + + // Can't cache access paths + foreach (self::$cache[$class] as $m) { + $method = clone $m; + $method->depth = $o->depth + 1; + + if (!$this->parser->childHasPath($o, $method)) { + $method->access_path = null; + } else { + $method->setAccessPathFrom($o); + } + + if ($method->owner_class !== $class && $ds = $method->getRepresentation('docstring')) { + $ds = clone $ds; + $ds->class = $method->owner_class; + $method->replaceRepresentation($ds); + } + + $rep->contents[] = $method; + } + + $o->addRepresentation($rep); + } + } + + private static function sort(MethodObject $a, MethodObject $b) + { + $sort = ((int) $a->static) - ((int) $b->static); + if ($sort) { + return $sort; + } + + $sort = BasicObject::sortByAccess($a, $b); + if ($sort) { + return $sort; + } + + $sort = InstanceObject::sortByHierarchy($a->owner_class, $b->owner_class); + if ($sort) { + return $sort; + } + + return $a->startline - $b->startline; + } +} diff --git a/system/ThirdParty/Kint/Parser/ClassStaticsPlugin.php b/system/ThirdParty/Kint/Parser/ClassStaticsPlugin.php new file mode 100644 index 000000000000..0ba58ca24874 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/ClassStaticsPlugin.php @@ -0,0 +1,122 @@ +getConstants() as $name => $val) { + $const = BasicObject::blank($name, '\\'.$class.'::'.$name); + $const->const = true; + $const->depth = $o->depth + 1; + $const->owner_class = $class; + $const->operator = BasicObject::OPERATOR_STATIC; + $const = $this->parser->parse($val, $const); + + $consts[] = $const; + } + + self::$cache[$class] = $consts; + } + + $statics = new Representation('Static class properties', 'statics'); + $statics->contents = self::$cache[$class]; + + foreach ($reflection->getProperties(ReflectionProperty::IS_STATIC) as $static) { + $prop = new BasicObject(); + $prop->name = '$'.$static->getName(); + $prop->depth = $o->depth + 1; + $prop->static = true; + $prop->operator = BasicObject::OPERATOR_STATIC; + $prop->owner_class = $static->getDeclaringClass()->name; + + $prop->access = BasicObject::ACCESS_PUBLIC; + if ($static->isProtected()) { + $prop->access = BasicObject::ACCESS_PROTECTED; + } elseif ($static->isPrivate()) { + $prop->access = BasicObject::ACCESS_PRIVATE; + } + + if ($this->parser->childHasPath($o, $prop)) { + $prop->access_path = '\\'.$prop->owner_class.'::'.$prop->name; + } + + $static->setAccessible(true); + $static = $static->getValue(); + $statics->contents[] = $this->parser->parse($static, $prop); + } + + if (empty($statics->contents)) { + return; + } + + \usort($statics->contents, array('Kint\\Parser\\ClassStaticsPlugin', 'sort')); + + $o->addRepresentation($statics); + } + + private static function sort(BasicObject $a, BasicObject $b) + { + $sort = ((int) $a->const) - ((int) $b->const); + if ($sort) { + return $sort; + } + + $sort = BasicObject::sortByAccess($a, $b); + if ($sort) { + return $sort; + } + + return InstanceObject::sortByHierarchy($a->owner_class, $b->owner_class); + } +} diff --git a/system/ThirdParty/Kint/Parser/ClosurePlugin.php b/system/ThirdParty/Kint/Parser/ClosurePlugin.php new file mode 100644 index 000000000000..73e367b22b03 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/ClosurePlugin.php @@ -0,0 +1,94 @@ +transplant($o); + $o = $object; + $object->removeRepresentation('properties'); + + $closure = new ReflectionFunction($var); + + $o->filename = $closure->getFileName(); + $o->startline = $closure->getStartLine(); + + foreach ($closure->getParameters() as $param) { + $o->parameters[] = new ParameterObject($param); + } + + $p = new Representation('Parameters'); + $p->contents = &$o->parameters; + $o->addRepresentation($p, 0); + + $statics = array(); + + if (\method_exists($closure, 'getClosureThis') && $v = $closure->getClosureThis()) { + $statics = array('this' => $v); + } + + if (\count($statics = $statics + $closure->getStaticVariables())) { + $statics_parsed = array(); + + foreach ($statics as $name => &$static) { + $obj = BasicObject::blank('$'.$name); + $obj->depth = $o->depth + 1; + $statics_parsed[$name] = $this->parser->parse($static, $obj); + if (null === $statics_parsed[$name]->value) { + $statics_parsed[$name]->access_path = null; + } + } + + $r = new Representation('Uses'); + $r->contents = $statics_parsed; + $o->addRepresentation($r, 0); + } + } +} diff --git a/system/ThirdParty/Kint/Parser/ColorPlugin.php b/system/ThirdParty/Kint/Parser/ColorPlugin.php new file mode 100644 index 000000000000..0d748f2c35f2 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/ColorPlugin.php @@ -0,0 +1,63 @@ + 32) { + return; + } + + $trimmed = \strtolower(\trim($var)); + + if (!isset(ColorRepresentation::$color_map[$trimmed]) && !\preg_match('/^(?:(?:rgb|hsl)[^\\)]{6,}\\)|#[0-9a-fA-F]{3,8})$/', $trimmed)) { + return; + } + + $rep = new ColorRepresentation($var); + + if ($rep->variant) { + $o->removeRepresentation($o->value); + $o->addRepresentation($rep, 0); + $o->hints[] = 'color'; + } + } +} diff --git a/system/ThirdParty/Kint/Parser/DOMDocumentPlugin.php b/system/ThirdParty/Kint/Parser/DOMDocumentPlugin.php new file mode 100644 index 000000000000..ec08d311ffef --- /dev/null +++ b/system/ThirdParty/Kint/Parser/DOMDocumentPlugin.php @@ -0,0 +1,328 @@ + 'DOMNode', + 'firstChild' => 'DOMNode', + 'lastChild' => 'DOMNode', + 'previousSibling' => 'DOMNode', + 'nextSibling' => 'DOMNode', + 'ownerDocument' => 'DOMDocument', + ); + + /** + * Show all properties and methods. + * + * @var bool + */ + public static $verbose = false; + + public function getTypes() + { + return array('object'); + } + + public function getTriggers() + { + return Parser::TRIGGER_SUCCESS; + } + + public function parse(&$var, BasicObject &$o, $trigger) + { + if (!$o instanceof InstanceObject) { + return; + } + + if ($var instanceof DOMNamedNodeMap || $var instanceof DOMNodeList) { + return $this->parseList($var, $o, $trigger); + } + + if ($var instanceof DOMNode) { + return $this->parseNode($var, $o); + } + } + + protected function parseList(&$var, InstanceObject &$o, $trigger) + { + // Recursion should never happen, should always be stopped at the parent + // DOMNode. Depth limit on the other hand we're going to skip since + // that would show an empty iterator and rather useless. Let the depth + // limit hit the children (DOMNodeList only has DOMNode as children) + if ($trigger & Parser::TRIGGER_RECURSION) { + return; + } + + $o->size = $var->length; + if (0 === $o->size) { + $o->replaceRepresentation(new Representation('Iterator')); + $o->size = null; + + return; + } + + // Depth limit + // Make empty iterator representation since we need it in DOMNode to point out depth limits + if ($this->parser->getDepthLimit() && $o->depth + 1 >= $this->parser->getDepthLimit()) { + $b = new BasicObject(); + $b->name = $o->classname.' Iterator Contents'; + $b->access_path = 'iterator_to_array('.$o->access_path.')'; + $b->depth = $o->depth + 1; + $b->hints[] = 'depth_limit'; + + $r = new Representation('Iterator'); + $r->contents = array($b); + $o->replaceRepresentation($r, 0); + + return; + } + + $data = \iterator_to_array($var); + + $r = new Representation('Iterator'); + $o->replaceRepresentation($r, 0); + + foreach ($data as $key => $item) { + $base_obj = new BasicObject(); + $base_obj->depth = $o->depth + 1; + $base_obj->name = $item->nodeName; + + if ($o->access_path) { + if ($var instanceof DOMNamedNodeMap) { + $base_obj->access_path = $o->access_path.'->getNamedItem('.\var_export($key, true).')'; + } elseif ($var instanceof DOMNodeList) { + $base_obj->access_path = $o->access_path.'->item('.\var_export($key, true).')'; + } else { + $base_obj->access_path = 'iterator_to_array('.$o->access_path.')'; + } + } + + $r->contents[] = $this->parser->parse($item, $base_obj); + } + } + + protected function parseNode(&$var, InstanceObject &$o) + { + // Fill the properties + // They can't be enumerated through reflection or casting, + // so we have to trust the docs and try them one at a time + $known_properties = array( + 'nodeValue', + 'childNodes', + 'attributes', + ); + + if (self::$verbose) { + $known_properties = array( + 'nodeName', + 'nodeValue', + 'nodeType', + 'parentNode', + 'childNodes', + 'firstChild', + 'lastChild', + 'previousSibling', + 'nextSibling', + 'attributes', + 'ownerDocument', + 'namespaceURI', + 'prefix', + 'localName', + 'baseURI', + 'textContent', + ); + } + + $childNodes = array(); + $attributes = array(); + + $rep = $o->value; + + foreach ($known_properties as $prop) { + $prop_obj = $this->parseProperty($o, $prop, $var); + $rep->contents[] = $prop_obj; + + if ('childNodes' === $prop) { + $childNodes = $prop_obj->getRepresentation('iterator'); + } elseif ('attributes' === $prop) { + $attributes = $prop_obj->getRepresentation('iterator'); + } + } + + if (!self::$verbose) { + $o->removeRepresentation('methods'); + $o->removeRepresentation('properties'); + } + + // Attributes and comments and text nodes don't + // need children or attributes of their own + if (\in_array($o->classname, array('DOMAttr', 'DOMText', 'DOMComment'), true)) { + return; + } + + // Set the attributes + if ($attributes) { + $a = new Representation('Attributes'); + foreach ($attributes->contents as $attribute) { + $a->contents[] = self::textualNodeToString($attribute); + } + $o->addRepresentation($a, 0); + } + + // Set the children + if ($childNodes) { + $c = new Representation('Children'); + + if (1 === \count($childNodes->contents) && ($node = \reset($childNodes->contents)) && \in_array('depth_limit', $node->hints, true)) { + $n = new InstanceObject(); + $n->transplant($node); + $n->name = 'childNodes'; + $n->classname = 'DOMNodeList'; + $c->contents = array($n); + } else { + foreach ($childNodes->contents as $index => $node) { + // Shortcircuit text nodes to plain strings + if ('DOMText' === $node->classname || 'DOMComment' === $node->classname) { + $node = self::textualNodeToString($node); + + // And remove them if they're empty + if (\ctype_space($node->value->contents) || '' === $node->value->contents) { + continue; + } + } + + $c->contents[] = $node; + } + } + + $o->addRepresentation($c, 0); + } + + if (isset($c) && \count($c->contents)) { + $o->size = \count($c->contents); + } + + if (!$o->size) { + $o->size = null; + } + } + + protected function parseProperty(InstanceObject $o, $prop, &$var) + { + // Duplicating (And slightly optimizing) the Parser::parseObject() code here + $base_obj = new BasicObject(); + $base_obj->depth = $o->depth + 1; + $base_obj->owner_class = $o->classname; + $base_obj->name = $prop; + $base_obj->operator = BasicObject::OPERATOR_OBJECT; + $base_obj->access = BasicObject::ACCESS_PUBLIC; + + if (null !== $o->access_path) { + $base_obj->access_path = $o->access_path; + + if (\preg_match('/^[A-Za-z0-9_]+$/', $base_obj->name)) { + $base_obj->access_path .= '->'.$base_obj->name; + } else { + $base_obj->access_path .= '->{'.\var_export($base_obj->name, true).'}'; + } + } + + if (!isset($var->{$prop})) { + $base_obj->type = 'null'; + } elseif (isset(self::$blacklist[$prop])) { + $b = new InstanceObject(); + $b->transplant($base_obj); + $base_obj = $b; + + $base_obj->hints[] = 'blacklist'; + $base_obj->classname = self::$blacklist[$prop]; + } elseif ('attributes' === $prop) { + $base_obj = $this->parser->parseDeep($var->{$prop}, $base_obj); + } else { + $base_obj = $this->parser->parse($var->{$prop}, $base_obj); + } + + return $base_obj; + } + + protected static function textualNodeToString(InstanceObject $o) + { + if (empty($o->value) || empty($o->value->contents) || empty($o->classname)) { + return; + } + + if (!\in_array($o->classname, array('DOMText', 'DOMAttr', 'DOMComment'), true)) { + return; + } + + foreach ($o->value->contents as $property) { + if ('nodeValue' === $property->name) { + $ret = clone $property; + $ret->name = $o->name; + + return $ret; + } + } + } +} diff --git a/system/ThirdParty/Kint/Parser/DateTimePlugin.php b/system/ThirdParty/Kint/Parser/DateTimePlugin.php new file mode 100644 index 000000000000..f2cebb643cb9 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/DateTimePlugin.php @@ -0,0 +1,55 @@ +transplant($o); + + $o = $object; + } +} diff --git a/system/ThirdParty/Kint/Parser/FsPathPlugin.php b/system/ThirdParty/Kint/Parser/FsPathPlugin.php new file mode 100644 index 000000000000..3a8d1e0538c2 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/FsPathPlugin.php @@ -0,0 +1,72 @@ + 2048) { + return; + } + + if (!\preg_match('/[\\/\\'.DIRECTORY_SEPARATOR.']/', $var)) { + return; + } + + if (\preg_match('/[?<>"*|]/', $var)) { + return; + } + + if (!@\file_exists($var)) { + return; + } + + if (\in_array($var, self::$blacklist, true)) { + return; + } + + $r = new SplFileInfoRepresentation(new SplFileInfo($var)); + $r->hints[] = 'fspath'; + $o->addRepresentation($r, 0); + } +} diff --git a/system/ThirdParty/Kint/Parser/IteratorPlugin.php b/system/ThirdParty/Kint/Parser/IteratorPlugin.php new file mode 100644 index 000000000000..0487a381f5b9 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/IteratorPlugin.php @@ -0,0 +1,110 @@ +name = $class.' Iterator Contents'; + $b->access_path = 'iterator_to_array('.$o->access_path.', true)'; + $b->depth = $o->depth + 1; + $b->hints[] = 'blacklist'; + + $r = new Representation('Iterator'); + $r->contents = array($b); + + $o->addRepresentation($r); + + return; + } + } + + /** @var array|false */ + $data = \iterator_to_array($var); + + if (false === $data) { + return; + } + + $base_obj = new BasicObject(); + $base_obj->depth = $o->depth; + + if ($o->access_path) { + $base_obj->access_path = 'iterator_to_array('.$o->access_path.')'; + } + + $r = new Representation('Iterator'); + $r->contents = $this->parser->parse($data, $base_obj); + $r->contents = $r->contents->value->contents; + + $primary = $o->getRepresentations(); + $primary = \reset($primary); + if ($primary && $primary === $o->value && $primary->contents === array()) { + $o->addRepresentation($r, 0); + } else { + $o->addRepresentation($r); + } + } +} diff --git a/system/ThirdParty/Kint/Parser/JsonPlugin.php b/system/ThirdParty/Kint/Parser/JsonPlugin.php new file mode 100644 index 000000000000..84b251955383 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/JsonPlugin.php @@ -0,0 +1,73 @@ +depth = $o->depth; + + if ($o->access_path) { + $base_obj->access_path = 'json_decode('.$o->access_path.', true)'; + } + + $r = new Representation('Json'); + $r->contents = $this->parser->parse($json, $base_obj); + + if (!\in_array('depth_limit', $r->contents->hints, true)) { + $r->contents = $r->contents->value->contents; + } + + $o->addRepresentation($r, 0); + } +} diff --git a/system/ThirdParty/Kint/Parser/MicrotimePlugin.php b/system/ThirdParty/Kint/Parser/MicrotimePlugin.php new file mode 100644 index 000000000000..5062b59ad224 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/MicrotimePlugin.php @@ -0,0 +1,105 @@ +depth) { + return; + } + + if (\is_string($var)) { + if ('microtime()' !== $o->name || !\preg_match('/^0\\.[0-9]{8} [0-9]{10}$/', $var)) { + return; + } + + $usec = (int) \substr($var, 2, 6); + $sec = (int) \substr($var, 11, 10); + } else { + if ('microtime(...)' !== $o->name) { + return; + } + + $sec = \floor($var); + $usec = $var - $sec; + $usec = \floor($usec * 1000000); + } + + $time = $sec + ($usec / 1000000); + + if (null !== self::$last) { + $last_time = self::$last[0] + (self::$last[1] / 1000000); + $lap = $time - $last_time; + ++self::$times; + } else { + $lap = null; + self::$start = $time; + } + + self::$last = array($sec, $usec); + + if (null !== $lap) { + $total = $time - self::$start; + $r = new MicrotimeRepresentation($sec, $usec, self::$group, $lap, $total, self::$times); + } else { + $r = new MicrotimeRepresentation($sec, $usec, self::$group); + } + $r->contents = $var; + $r->implicit_label = true; + + $o->removeRepresentation($o->value); + $o->addRepresentation($r); + $o->hints[] = 'microtime'; + } + + public static function clean() + { + self::$last = null; + self::$start = null; + self::$times = 0; + ++self::$group; + } +} diff --git a/system/ThirdParty/Kint/Parser/MysqliPlugin.php b/system/ThirdParty/Kint/Parser/MysqliPlugin.php new file mode 100644 index 000000000000..265299bec6ee --- /dev/null +++ b/system/ThirdParty/Kint/Parser/MysqliPlugin.php @@ -0,0 +1,129 @@ + true, + 'connect_errno' => true, + 'connect_error' => true, + ); + + // These are readable on empty mysqli objects, but not on failed connections + protected $empty_readable = array( + 'client_info' => true, + 'errno' => true, + 'error' => true, + ); + + // These are only readable on connected mysqli objects + protected $connected_readable = array( + 'affected_rows' => true, + 'error_list' => true, + 'field_count' => true, + 'host_info' => true, + 'info' => true, + 'insert_id' => true, + 'server_info' => true, + 'server_version' => true, + 'stat' => true, + 'sqlstate' => true, + 'protocol_version' => true, + 'thread_id' => true, + 'warning_count' => true, + ); + + public function getTypes() + { + return array('object'); + } + + public function getTriggers() + { + return Parser::TRIGGER_COMPLETE; + } + + public function parse(&$var, BasicObject &$o, $trigger) + { + if (!$var instanceof Mysqli) { + return; + } + + $connected = false; + $empty = false; + + if (\is_string(@$var->sqlstate)) { + $connected = true; + } elseif (\is_string(@$var->client_info)) { + $empty = true; + } + + foreach ($o->value->contents as $key => $obj) { + if (isset($this->connected_readable[$obj->name])) { + if (!$connected) { + continue; + } + } elseif (isset($this->empty_readable[$obj->name])) { + if (!$connected && !$empty) { + continue; + } + } elseif (!isset($this->always_readable[$obj->name])) { + continue; + } + + if ('null' !== $obj->type) { + continue; + } + + $param = $var->{$obj->name}; + + if (null === $param) { + continue; + } + + $base = BasicObject::blank($obj->name, $obj->access_path); + + $base->depth = $obj->depth; + $base->owner_class = $obj->owner_class; + $base->operator = $obj->operator; + $base->access = $obj->access; + $base->reference = $obj->reference; + + $o->value->contents[$key] = $this->parser->parse($param, $base); + } + } +} diff --git a/system/ThirdParty/Kint/Parser/Parser.php b/system/ThirdParty/Kint/Parser/Parser.php new file mode 100644 index 000000000000..b7f81c62186f --- /dev/null +++ b/system/ThirdParty/Kint/Parser/Parser.php @@ -0,0 +1,604 @@ +marker = \uniqid("kint\0", true); + + $this->caller_class = $caller; + + if ($depth_limit) { + $this->depth_limit = $depth_limit; + } + } + + /** + * Set the caller class. + * + * @param null|string $caller Caller class name + */ + public function setCallerClass($caller = null) + { + $this->noRecurseCall(); + + $this->caller_class = $caller; + } + + public function getCallerClass() + { + return $this->caller_class; + } + + /** + * Set the depth limit. + * + * @param false|int $depth_limit Maximum depth to parse data + */ + public function setDepthLimit($depth_limit = false) + { + $this->noRecurseCall(); + + $this->depth_limit = $depth_limit; + } + + public function getDepthLimit() + { + return $this->depth_limit; + } + + /** + * Disables the depth limit and parses a variable. + * + * This should not be used unless you know what you're doing! + * + * @param mixed $var The input variable + * @param BasicObject $o The base object + * + * @return BasicObject + */ + public function parseDeep(&$var, BasicObject $o) + { + $depth_limit = $this->depth_limit; + $this->depth_limit = false; + + $out = $this->parse($var, $o); + + $this->depth_limit = $depth_limit; + + return $out; + } + + /** + * Parses a variable into a Kint object structure. + * + * @param mixed $var The input variable + * @param BasicObject $o The base object + * + * @return BasicObject + */ + public function parse(&$var, BasicObject $o) + { + $o->type = \strtolower(\gettype($var)); + + if (!$this->applyPlugins($var, $o, self::TRIGGER_BEGIN)) { + return $o; + } + + switch ($o->type) { + case 'array': + return $this->parseArray($var, $o); + case 'boolean': + case 'double': + case 'integer': + case 'null': + return $this->parseGeneric($var, $o); + case 'object': + return $this->parseObject($var, $o); + case 'resource': + return $this->parseResource($var, $o); + case 'string': + return $this->parseString($var, $o); + default: + return $this->parseUnknown($var, $o); + } + } + + public function addPlugin(Plugin $p) + { + if (!$types = $p->getTypes()) { + return false; + } + + if (!$triggers = $p->getTriggers()) { + return false; + } + + $p->setParser($this); + + foreach ($types as $type) { + if (!isset($this->plugins[$type])) { + $this->plugins[$type] = array( + self::TRIGGER_BEGIN => array(), + self::TRIGGER_SUCCESS => array(), + self::TRIGGER_RECURSION => array(), + self::TRIGGER_DEPTH_LIMIT => array(), + ); + } + + foreach ($this->plugins[$type] as $trigger => &$pool) { + if ($triggers & $trigger) { + $pool[] = $p; + } + } + } + + return true; + } + + public function clearPlugins() + { + $this->plugins = array(); + } + + public function haltParse() + { + $this->parse_break = true; + } + + public function childHasPath(InstanceObject $parent, BasicObject $child) + { + if ('object' === $parent->type && (null !== $parent->access_path || $child->static || $child->const)) { + if (BasicObject::ACCESS_PUBLIC === $child->access) { + return true; + } + + if (BasicObject::ACCESS_PRIVATE === $child->access && $this->caller_class) { + if ($this->caller_class === $child->owner_class) { + return true; + } + } elseif (BasicObject::ACCESS_PROTECTED === $child->access && $this->caller_class) { + if ($this->caller_class === $child->owner_class) { + return true; + } + + if (\is_subclass_of($this->caller_class, $child->owner_class)) { + return true; + } + + if (\is_subclass_of($child->owner_class, $this->caller_class)) { + return true; + } + } + } + + return false; + } + + /** + * Returns an array without the recursion marker in it. + * + * DO NOT pass an array that has had it's marker removed back + * into the parser, it will result in an extra recursion + * + * @param array $array Array potentially containing a recursion marker + * + * @return array Array with recursion marker removed + */ + public function getCleanArray(array $array) + { + unset($array[$this->marker]); + + return $array; + } + + protected function noRecurseCall() + { + $bt = \debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS); + + $caller_frame = array( + 'function' => __FUNCTION__, + ); + + while (isset($bt[0]['object']) && $bt[0]['object'] === $this) { + $caller_frame = \array_shift($bt); + } + + foreach ($bt as $frame) { + if (isset($frame['object']) && $frame['object'] === $this) { + throw new DomainException(__CLASS__.'::'.$caller_frame['function'].' cannot be called from inside a parse'); + } + } + } + + private function parseGeneric(&$var, BasicObject $o) + { + $rep = new Representation('Contents'); + $rep->contents = $var; + $rep->implicit_label = true; + $o->addRepresentation($rep); + $o->value = $rep; + + $this->applyPlugins($var, $o, self::TRIGGER_SUCCESS); + + return $o; + } + + /** + * Parses a string into a Kint BlobObject structure. + * + * @param string $var The input variable + * @param BasicObject $o The base object + * + * @return BasicObject + */ + private function parseString(&$var, BasicObject $o) + { + $string = new BlobObject(); + $string->transplant($o); + $string->encoding = BlobObject::detectEncoding($var); + $string->size = BlobObject::strlen($var, $string->encoding); + + $rep = new Representation('Contents'); + $rep->contents = $var; + $rep->implicit_label = true; + + $string->addRepresentation($rep); + $string->value = $rep; + + $this->applyPlugins($var, $string, self::TRIGGER_SUCCESS); + + return $string; + } + + /** + * Parses an array into a Kint object structure. + * + * @param array $var The input variable + * @param BasicObject $o The base object + * + * @return BasicObject + */ + private function parseArray(array &$var, BasicObject $o) + { + $array = new BasicObject(); + $array->transplant($o); + $array->size = \count($var); + + if (isset($var[$this->marker])) { + --$array->size; + $array->hints[] = 'recursion'; + + $this->applyPlugins($var, $array, self::TRIGGER_RECURSION); + + return $array; + } + + $rep = new Representation('Contents'); + $rep->implicit_label = true; + $array->addRepresentation($rep); + $array->value = $rep; + + if (!$array->size) { + $this->applyPlugins($var, $array, self::TRIGGER_SUCCESS); + + return $array; + } + + if ($this->depth_limit && $o->depth >= $this->depth_limit) { + $array->hints[] = 'depth_limit'; + + $this->applyPlugins($var, $array, self::TRIGGER_DEPTH_LIMIT); + + return $array; + } + + $copy = \array_values($var); + + // It's really really hard to access numeric string keys in arrays, + // and it's really really hard to access integer properties in + // objects, so we just use array_values and index by counter to get + // at it reliably for reference testing. This also affects access + // paths since it's pretty much impossible to access these things + // without complicated stuff you should never need to do. + $i = 0; + + // Set the marker for recursion + $var[$this->marker] = $array->depth; + + $refmarker = new stdClass(); + + foreach ($var as $key => &$val) { + if ($key === $this->marker) { + continue; + } + + $child = new BasicObject(); + $child->name = $key; + $child->depth = $array->depth + 1; + $child->access = BasicObject::ACCESS_NONE; + $child->operator = BasicObject::OPERATOR_ARRAY; + + if (null !== $array->access_path) { + if (\is_string($key) && (string) (int) $key === $key) { + $child->access_path = 'array_values('.$array->access_path.')['.$i.']'; // @codeCoverageIgnore + } else { + $child->access_path = $array->access_path.'['.\var_export($key, true).']'; + } + } + + $stash = $val; + $copy[$i] = $refmarker; + if ($val === $refmarker) { + $child->reference = true; + $val = $stash; + } + + $rep->contents[] = $this->parse($val, $child); + ++$i; + } + + $this->applyPlugins($var, $array, self::TRIGGER_SUCCESS); + unset($var[$this->marker]); + + return $array; + } + + /** + * Parses an object into a Kint InstanceObject structure. + * + * @param object $var The input variable + * @param BasicObject $o The base object + * + * @return BasicObject + */ + private function parseObject(&$var, BasicObject $o) + { + $hash = \spl_object_hash($var); + $values = (array) $var; + + $object = new InstanceObject(); + $object->transplant($o); + $object->classname = \get_class($var); + $object->hash = $hash; + $object->size = \count($values); + + if (isset($this->object_hashes[$hash])) { + $object->hints[] = 'recursion'; + + $this->applyPlugins($var, $object, self::TRIGGER_RECURSION); + + return $object; + } + + $this->object_hashes[$hash] = $object; + + if ($this->depth_limit && $o->depth >= $this->depth_limit) { + $object->hints[] = 'depth_limit'; + + $this->applyPlugins($var, $object, self::TRIGGER_DEPTH_LIMIT); + unset($this->object_hashes[$hash]); + + return $object; + } + + $reflector = new ReflectionObject($var); + + if ($reflector->isUserDefined()) { + $object->filename = $reflector->getFileName(); + $object->startline = $reflector->getStartLine(); + } + + $rep = new Representation('Properties'); + + $copy = \array_values($values); + $refmarker = new stdClass(); + $i = 0; + + // Reflection will not show parent classes private properties, and if a + // property was unset it will happly trigger a notice looking for it. + foreach ($values as $key => &$val) { + // Casting object to array: + // private properties show in the form "\0$owner_class_name\0$property_name"; + // protected properties show in the form "\0*\0$property_name"; + // public properties show in the form "$property_name"; + // http://www.php.net/manual/en/language.types.array.php#language.types.array.casting + + $child = new BasicObject(); + $child->depth = $object->depth + 1; + $child->owner_class = $object->classname; + $child->operator = BasicObject::OPERATOR_OBJECT; + $child->access = BasicObject::ACCESS_PUBLIC; + + $split_key = \explode("\0", $key, 3); + + if (3 === \count($split_key) && '' === $split_key[0]) { + $child->name = $split_key[2]; + if ('*' === $split_key[1]) { + $child->access = BasicObject::ACCESS_PROTECTED; + } else { + $child->access = BasicObject::ACCESS_PRIVATE; + $child->owner_class = $split_key[1]; + } + } elseif (KINT_PHP72) { + $child->name = (string) $key; + } else { + $child->name = $key; // @codeCoverageIgnore + } + + if ($this->childHasPath($object, $child)) { + $child->access_path = $object->access_path; + + if (!KINT_PHP72 && \is_int($child->name)) { + $child->access_path = 'array_values((array) '.$child->access_path.')['.$i.']'; // @codeCoverageIgnore + } elseif (\preg_match('/^[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*$/', $child->name)) { + $child->access_path .= '->'.$child->name; + } else { + $child->access_path .= '->{'.\var_export((string) $child->name, true).'}'; + } + } + + $stash = $val; + $copy[$i] = $refmarker; + if ($val === $refmarker) { + $child->reference = true; + $val = $stash; + } + + $rep->contents[] = $this->parse($val, $child); + ++$i; + } + + $object->addRepresentation($rep); + $object->value = $rep; + $this->applyPlugins($var, $object, self::TRIGGER_SUCCESS); + unset($this->object_hashes[$hash]); + + return $object; + } + + /** + * Parses a resource into a Kint ResourceObject structure. + * + * @param resource $var The input variable + * @param BasicObject $o The base object + * + * @return BasicObject + */ + private function parseResource(&$var, BasicObject $o) + { + $resource = new ResourceObject(); + $resource->transplant($o); + $resource->resource_type = \get_resource_type($var); + + $this->applyPlugins($var, $resource, self::TRIGGER_SUCCESS); + + return $resource; + } + + /** + * Parses an unknown into a Kint object structure. + * + * @param mixed $var The input variable + * @param BasicObject $o The base object + * + * @return BasicObject + */ + private function parseUnknown(&$var, BasicObject $o) + { + $o->type = 'unknown'; + $this->applyPlugins($var, $o, self::TRIGGER_SUCCESS); + + return $o; + } + + /** + * Applies plugins for an object type. + * + * @param mixed $var variable + * @param BasicObject $o Kint object parsed so far + * @param int $trigger The trigger to check for the plugins + * + * @return bool Continue parsing + */ + private function applyPlugins(&$var, BasicObject &$o, $trigger) + { + $break_stash = $this->parse_break; + + /** @var bool Psalm bug workaround */ + $this->parse_break = false; + + $plugins = array(); + + if (isset($this->plugins[$o->type][$trigger])) { + $plugins = $this->plugins[$o->type][$trigger]; + } + + foreach ($plugins as $plugin) { + try { + $plugin->parse($var, $o, $trigger); + } catch (Exception $e) { + \trigger_error( + 'An exception ('.\get_class($e).') was thrown in '.$e->getFile().' on line '.$e->getLine().' while executing Kint Parser Plugin "'.\get_class($plugin).'". Error message: '.$e->getMessage(), + E_USER_WARNING + ); + } + + if ($this->parse_break) { + $this->parse_break = $break_stash; + + return false; + } + } + + $this->parse_break = $break_stash; + + return true; + } +} diff --git a/system/ThirdParty/Kint/Parser/Plugin.php b/system/ThirdParty/Kint/Parser/Plugin.php new file mode 100644 index 000000000000..51d5f0b1440b --- /dev/null +++ b/system/ThirdParty/Kint/Parser/Plugin.php @@ -0,0 +1,55 @@ +parser = $p; + } + + /** + * An array of types (As returned by gettype) for all data this plugin can operate on. + * + * @return array List of types + */ + public function getTypes() + { + return array(); + } + + public function getTriggers() + { + return Parser::TRIGGER_NONE; + } + + abstract public function parse(&$variable, BasicObject &$o, $trigger); +} diff --git a/system/ThirdParty/Kint/Parser/ProxyPlugin.php b/system/ThirdParty/Kint/Parser/ProxyPlugin.php new file mode 100644 index 000000000000..3376d3aa9016 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/ProxyPlugin.php @@ -0,0 +1,66 @@ +types = $types; + $this->triggers = $triggers; + $this->callback = $callback; + } + + public function getTypes() + { + return $this->types; + } + + public function getTriggers() + { + return $this->triggers; + } + + public function parse(&$var, BasicObject &$o, $trigger) + { + return \call_user_func_array($this->callback, array(&$var, &$o, $trigger, $this->parser)); + } +} diff --git a/system/ThirdParty/Kint/Parser/SerializePlugin.php b/system/ThirdParty/Kint/Parser/SerializePlugin.php new file mode 100644 index 000000000000..c5dadb88d9de --- /dev/null +++ b/system/ThirdParty/Kint/Parser/SerializePlugin.php @@ -0,0 +1,108 @@ + Unserialization can result in code being loaded and executed due to + * > object instantiation and autoloading, and a malicious user may be able + * > to exploit this. + * + * The natural way to stop that from happening is to just refuse to unserialize + * stuff by default. Which is what we're doing for anything that's not scalar. + * + * @var bool + */ + public static $safe_mode = true; + public static $options = array(true); + + public function getTypes() + { + return array('string'); + } + + public function getTriggers() + { + return Parser::TRIGGER_SUCCESS; + } + + public function parse(&$var, BasicObject &$o, $trigger) + { + $trimmed = \rtrim($var); + + if ('N;' !== $trimmed && !\preg_match('/^(?:[COabis]:\\d+[:;]|d:\\d+(?:\\.\\d+);)/', $trimmed)) { + return; + } + + if (!self::$safe_mode || !\in_array($trimmed[0], array('C', 'O', 'a'), true)) { + // Second parameter only supported on PHP 7 + if (KINT_PHP70) { + // Suppress warnings on unserializeable variable + $data = @\unserialize($trimmed, self::$options); + } else { + $data = @\unserialize($trimmed); + } + + if (false === $data && 'b:0;' !== \substr($trimmed, 0, 4)) { + return; + } + } + + $base_obj = new BasicObject(); + $base_obj->depth = $o->depth + 1; + $base_obj->name = 'unserialize('.$o->name.')'; + + if ($o->access_path) { + $base_obj->access_path = 'unserialize('.$o->access_path; + if (!KINT_PHP70 || self::$options === array(true)) { + $base_obj->access_path .= ')'; + } elseif (self::$options === array(false)) { + $base_obj->access_path .= ', false)'; + } else { + $base_obj->access_path .= ', Serialize::$options)'; + } + } + + $r = new Representation('Serialized'); + + if (isset($data)) { + $r->contents = $this->parser->parse($data, $base_obj); + } else { + $base_obj->hints[] = 'blacklist'; + $r->contents = $base_obj; + } + + $o->addRepresentation($r, 0); + } +} diff --git a/system/ThirdParty/Kint/Parser/SimpleXMLElementPlugin.php b/system/ThirdParty/Kint/Parser/SimpleXMLElementPlugin.php new file mode 100644 index 000000000000..b90c863f8873 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/SimpleXMLElementPlugin.php @@ -0,0 +1,154 @@ +hints[] = 'simplexml_element'; + + if (!self::$verbose) { + $o->removeRepresentation('properties'); + $o->removeRepresentation('iterator'); + $o->removeRepresentation('methods'); + } + + // Attributes + $a = new Representation('Attributes'); + + $base_obj = new BasicObject(); + $base_obj->depth = $o->depth; + + if ($o->access_path) { + $base_obj->access_path = '(string) '.$o->access_path; + } + + if ($attribs = $var->attributes()) { + $attribs = \iterator_to_array($attribs); + $attribs = \array_map('strval', $attribs); + } else { + $attribs = array(); + } + + // XML attributes are by definition strings and don't have children, + // so up the depth limit in case we're just below the limit since + // there won't be any recursive stuff anyway. + $a->contents = $this->parser->parseDeep($attribs, $base_obj)->value->contents; + + $o->addRepresentation($a, 0); + + // Children + // We need to check children() separately from the values we already parsed because + // text contents won't show up in children() but they will show up in properties. + // + // Why do we still need to check for attributes if we already have an attributes() + // method? Hell if I know! + $children = $var->children(); + + if ($o->value) { + $c = new Representation('Children'); + + foreach ($o->value->contents as $value) { + if ('@attributes' === $value->name) { + continue; + } + + if (isset($children->{$value->name})) { + $i = 0; + + while (isset($children->{$value->name}[$i])) { + $base_obj = new BasicObject(); + $base_obj->depth = $o->depth + 1; + $base_obj->name = $value->name; + if ($value->access_path) { + $base_obj->access_path = $value->access_path.'['.$i.']'; + } + + $value = $this->parser->parse($children->{$value->name}[$i], $base_obj); + + if ($value->access_path && 'string' === $value->type) { + $value->access_path = '(string) '.$value->access_path; + } + + $c->contents[] = $value; + + ++$i; + } + } + } + + $o->size = \count($c->contents); + + if (!$o->size) { + $o->size = null; + + if (\strlen((string) $var)) { + $base_obj = new BlobObject(); + $base_obj->depth = $o->depth + 1; + $base_obj->name = $o->name; + if ($o->access_path) { + $base_obj->access_path = '(string) '.$o->access_path; + } + + $value = (string) $var; + + $c = new Representation('Contents'); + $c->implicit_label = true; + $c->contents = array($this->parser->parseDeep($value, $base_obj)); + } + } + + $o->addRepresentation($c, 0); + } + } +} diff --git a/system/ThirdParty/Kint/Parser/SplFileInfoPlugin.php b/system/ThirdParty/Kint/Parser/SplFileInfoPlugin.php new file mode 100644 index 000000000000..8b72193bc369 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/SplFileInfoPlugin.php @@ -0,0 +1,55 @@ +addRepresentation($r, 0); + $o->size = $r->getSize(); + } +} diff --git a/system/ThirdParty/Kint/Parser/SplObjectStoragePlugin.php b/system/ThirdParty/Kint/Parser/SplObjectStoragePlugin.php new file mode 100644 index 000000000000..03ff301d3477 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/SplObjectStoragePlugin.php @@ -0,0 +1,54 @@ +getRepresentation('iterator'))) { + return; + } + + $r = $o->getRepresentation('iterator'); + if ($r) { + $o->size = !\is_array($r->contents) ? null : \count($r->contents); + } + } +} diff --git a/system/ThirdParty/Kint/Parser/StreamPlugin.php b/system/ThirdParty/Kint/Parser/StreamPlugin.php new file mode 100644 index 000000000000..464a3fff12c5 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/StreamPlugin.php @@ -0,0 +1,78 @@ +resource_type) { + return; + } + + if (!$meta = \stream_get_meta_data($var)) { + return; + } + + $rep = new Representation('Stream'); + $rep->implicit_label = true; + + $base_obj = new BasicObject(); + $base_obj->depth = $o->depth; + + if ($o->access_path) { + $base_obj->access_path = 'stream_get_meta_data('.$o->access_path.')'; + } + + $rep->contents = $this->parser->parse($meta, $base_obj); + + if (!\in_array('depth_limit', $rep->contents->hints, true)) { + $rep->contents = $rep->contents->value->contents; + } + + $o->addRepresentation($rep, 0); + $o->value = $rep; + + $stream = new StreamObject($meta); + $stream->transplant($o); + $o = $stream; + } +} diff --git a/system/ThirdParty/Kint/Parser/TablePlugin.php b/system/ThirdParty/Kint/Parser/TablePlugin.php new file mode 100644 index 000000000000..510c4ff0ef86 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/TablePlugin.php @@ -0,0 +1,87 @@ +value->contents)) { + return; + } + + $array = $this->parser->getCleanArray($var); + + if (\count($array) < 2) { + return; + } + + // Ensure this is an array of arrays and that all child arrays have the + // same keys. We don't care about their children - if there's another + // "table" inside we'll just make another one down the value tab + $keys = null; + foreach ($array as $elem) { + if (!\is_array($elem) || \count($elem) < 2) { + return; + } + + if (null === $keys) { + $keys = \array_keys($elem); + } elseif (\array_keys($elem) !== $keys) { + return; + } + } + + // Ensure none of the child arrays are recursion or depth limit. We + // don't care if their children are since they are the table cells + foreach ($o->value->contents as $childarray) { + if (empty($childarray->value->contents)) { + return; + } + } + + // Objects by reference for the win! We can do a copy-paste of the value + // representation contents and just slap a new hint on there and hey + // presto we have our table representation with no extra memory used! + $table = new Representation('Table'); + $table->contents = $o->value->contents; + $table->hints[] = 'table'; + $o->addRepresentation($table, 0); + } +} diff --git a/system/ThirdParty/Kint/Parser/ThrowablePlugin.php b/system/ThirdParty/Kint/Parser/ThrowablePlugin.php new file mode 100644 index 000000000000..8490d1d41a1a --- /dev/null +++ b/system/ThirdParty/Kint/Parser/ThrowablePlugin.php @@ -0,0 +1,60 @@ +transplant($o); + $r = new SourceRepresentation($var->getFile(), $var->getLine()); + $r->showfilename = true; + $throw->addRepresentation($r, 0); + + $o = $throw; + } +} diff --git a/system/ThirdParty/Kint/Parser/TimestampPlugin.php b/system/ThirdParty/Kint/Parser/TimestampPlugin.php new file mode 100644 index 000000000000..72958d6465c0 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/TimestampPlugin.php @@ -0,0 +1,71 @@ +value->label = 'Timestamp'; + $o->value->hints[] = 'timestamp'; + } + } +} diff --git a/system/ThirdParty/Kint/Parser/ToStringPlugin.php b/system/ThirdParty/Kint/Parser/ToStringPlugin.php new file mode 100644 index 000000000000..8b7a65fe60f5 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/ToStringPlugin.php @@ -0,0 +1,67 @@ +hasMethod('__toString')) { + return; + } + + foreach (self::$blacklist as $class) { + if ($var instanceof $class) { + return; + } + } + + $r = new Representation('toString'); + $r->contents = (string) $var; + + $o->addRepresentation($r); + } +} diff --git a/system/ThirdParty/Kint/Parser/TracePlugin.php b/system/ThirdParty/Kint/Parser/TracePlugin.php new file mode 100644 index 000000000000..3554993dd2e1 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/TracePlugin.php @@ -0,0 +1,92 @@ +value) { + return; + } + + $trace = $this->parser->getCleanArray($var); + + if (\count($trace) !== \count($o->value->contents) || !Utils::isTrace($trace)) { + return; + } + + $traceobj = new TraceObject(); + $traceobj->transplant($o); + $rep = $traceobj->value; + + $old_trace = $rep->contents; + + Utils::normalizeAliases(self::$blacklist); + + $rep->contents = array(); + + foreach ($old_trace as $frame) { + $index = $frame->name; + + if (!isset($trace[$index]['function'])) { + // Something's very very wrong here, but it's probably a plugin's fault + continue; + } + + if (Utils::traceFrameIsListed($trace[$index], self::$blacklist)) { + continue; + } + + $rep->contents[$index] = new TraceFrameObject($frame, $trace[$index]); + } + + \ksort($rep->contents); + $rep->contents = \array_values($rep->contents); + + $traceobj->clearRepresentations(); + $traceobj->addRepresentation($rep); + $traceobj->size = \count($rep->contents); + $o = $traceobj; + } +} diff --git a/system/ThirdParty/Kint/Parser/XmlPlugin.php b/system/ThirdParty/Kint/Parser/XmlPlugin.php new file mode 100644 index 000000000000..0947e9a6cb14 --- /dev/null +++ b/system/ThirdParty/Kint/Parser/XmlPlugin.php @@ -0,0 +1,150 @@ +access_path); + + if (empty($xml)) { + return; + } + + list($xml, $access_path, $name) = $xml; + + $base_obj = new BasicObject(); + $base_obj->depth = $o->depth + 1; + $base_obj->name = $name; + $base_obj->access_path = $access_path; + + $r = new Representation('XML'); + $r->contents = $this->parser->parse($xml, $base_obj); + + $o->addRepresentation($r, 0); + } + + protected static function xmlToSimpleXML($var, $parent_path) + { + try { + $errors = \libxml_use_internal_errors(true); + $xml = \simplexml_load_string($var); + \libxml_use_internal_errors($errors); + } catch (Exception $e) { + if (isset($errors)) { + \libxml_use_internal_errors($errors); + } + + return; + } + + if (!$xml) { + return; + } + + if (null === $parent_path) { + $access_path = null; + } else { + $access_path = 'simplexml_load_string('.$parent_path.')'; + } + + $name = $xml->getName(); + + return array($xml, $access_path, $name); + } + + /** + * Get the DOMDocument info. + * + * The documentation of DOMDocument::loadXML() states that while you can + * call it statically, it will give an E_STRICT warning. On my system it + * actually gives an E_DEPRECATED warning, but it works so we'll just add + * an error-silencing '@' to the access path. + * + * If it errors loading then we wouldn't have gotten this far in the first place. + * + * @param string $var The XML string + * @param null|string $parent_path The path to the parent, in this case the XML string + * + * @return null|array The root element DOMNode, the access path, and the root element name + */ + protected static function xmlToDOMDocument($var, $parent_path) + { + // There's no way to check validity in DOMDocument without making errors. For shame! + if (!self::xmlToSimpleXML($var, $parent_path)) { + return null; + } + + $xml = new DOMDocument(); + $xml->loadXML($var); + $xml = $xml->firstChild; + + if (null === $parent_path) { + $access_path = null; + } else { + $access_path = '@\\DOMDocument::loadXML('.$parent_path.')->firstChild'; + } + + $name = $xml->nodeName; + + return array($xml, $access_path, $name); + } +} diff --git a/system/ThirdParty/Kint/Renderer/CliRenderer.php b/system/ThirdParty/Kint/Renderer/CliRenderer.php new file mode 100644 index 000000000000..0d0846a411c3 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/CliRenderer.php @@ -0,0 +1,152 @@ +windows_output = KINT_WIN; + } + + if (!self::$terminal_width) { + if (!KINT_WIN && self::$detect_width) { + self::$terminal_width = \exec('tput cols'); + } + + if (self::$terminal_width < self::$min_terminal_width) { + self::$terminal_width = self::$default_width; + } + } + + $this->colors = $this->windows_output ? false : self::$cli_colors; + + $this->header_width = self::$terminal_width; + } + + public function colorValue($string) + { + if (!$this->colors) { + return $string; + } + + return "\x1b[32m".\str_replace("\n", "\x1b[0m\n\x1b[32m", $string)."\x1b[0m"; + } + + public function colorType($string) + { + if (!$this->colors) { + return $string; + } + + return "\x1b[35;1m".\str_replace("\n", "\x1b[0m\n\x1b[35;1m", $string)."\x1b[0m"; + } + + public function colorTitle($string) + { + if (!$this->colors) { + return $string; + } + + return "\x1b[36m".\str_replace("\n", "\x1b[0m\n\x1b[36m", $string)."\x1b[0m"; + } + + public function renderTitle(BasicObject $o) + { + if ($this->windows_output) { + return $this->utf8ToWindows(parent::renderTitle($o)); + } + + return parent::renderTitle($o); + } + + public function preRender() + { + return PHP_EOL; + } + + public function postRender() + { + if ($this->windows_output) { + return $this->utf8ToWindows(parent::postRender()); + } + + return parent::postRender(); + } + + public function escape($string, $encoding = false) + { + return \str_replace("\x1b", '\\x1b', $string); + } + + protected function utf8ToWindows($string) + { + return \str_replace( + array('┌', '═', '┐', '│', '└', '─', '┘'), + array("\xda", "\xdc", "\xbf", "\xb3", "\xc0", "\xc4", "\xd9"), + $string + ); + } +} diff --git a/system/ThirdParty/Kint/Renderer/PlainRenderer.php b/system/ThirdParty/Kint/Renderer/PlainRenderer.php new file mode 100644 index 000000000000..493a7743bed4 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/PlainRenderer.php @@ -0,0 +1,237 @@ + array( + array('Kint\\Renderer\\PlainRenderer', 'renderJs'), + array('Kint\\Renderer\\Text\\MicrotimePlugin', 'renderJs'), + ), + 'style' => array( + array('Kint\\Renderer\\PlainRenderer', 'renderCss'), + ), + 'raw' => array(), + ); + + /** + * Path to the CSS file to load by default. + * + * @var string + */ + public static $theme = 'plain.css'; + + /** + * Output htmlentities instead of utf8. + * + * @var bool + */ + public static $disable_utf8 = false; + + public static $needs_pre_render = true; + + public static $always_pre_render = false; + + protected $force_pre_render = false; + protected $pre_render; + + public function __construct() + { + parent::__construct(); + + $this->pre_render = self::$needs_pre_render; + + if (self::$always_pre_render) { + $this->setPreRender(true); + } + } + + public function setCallInfo(array $info) + { + parent::setCallInfo($info); + + if (\in_array('@', $this->call_info['modifiers'], true)) { + $this->setPreRender(true); + } + } + + public function setStatics(array $statics) + { + parent::setStatics($statics); + + if (!empty($statics['return'])) { + $this->setPreRender(true); + } + } + + public function setPreRender($pre_render) + { + $this->pre_render = $pre_render; + $this->force_pre_render = true; + } + + public function getPreRender() + { + return $this->pre_render; + } + + public function colorValue($string) + { + return ''.$string.''; + } + + public function colorType($string) + { + return ''.$string.''; + } + + public function colorTitle($string) + { + return ''.$string.''; + } + + public function renderTitle(BasicObject $o) + { + if (self::$disable_utf8) { + return $this->utf8ToHtmlentity(parent::renderTitle($o)); + } + + return parent::renderTitle($o); + } + + public function preRender() + { + $output = ''; + + if ($this->pre_render) { + foreach (self::$pre_render_sources as $type => $values) { + $contents = ''; + foreach ($values as $v) { + $contents .= \call_user_func($v, $this); + } + + if (!\strlen($contents)) { + continue; + } + + switch ($type) { + case 'script': + $output .= ''; + break; + case 'style': + $output .= ''; + break; + default: + $output .= $contents; + } + } + + // Don't pre-render on every dump + if (!$this->force_pre_render) { + self::$needs_pre_render = false; + } + } + + return $output.'
'; + } + + public function postRender() + { + if (self::$disable_utf8) { + return $this->utf8ToHtmlentity(parent::postRender()).'
'; + } + + return parent::postRender().''; + } + + public function ideLink($file, $line) + { + $path = $this->escape(Kint::shortenPath($file)).':'.$line; + $ideLink = Kint::getIdeLink($file, $line); + + if (!$ideLink) { + return $path; + } + + $class = ''; + + if (\preg_match('/https?:\\/\\//i', $ideLink)) { + $class = 'class="kint-ide-link" '; + } + + return ''.$path.''; + } + + public function escape($string, $encoding = false) + { + if (false === $encoding) { + $encoding = BlobObject::detectEncoding($string); + } + + $original_encoding = $encoding; + + if (false === $encoding || 'ASCII' === $encoding) { + $encoding = 'UTF-8'; + } + + $string = \htmlspecialchars($string, ENT_NOQUOTES, $encoding); + + // this call converts all non-ASCII characters into numeirc htmlentities + if (\function_exists('mb_encode_numericentity') && 'ASCII' !== $original_encoding) { + $string = \mb_encode_numericentity($string, array(0x80, 0xffff, 0, 0xffff), $encoding); + } + + return $string; + } + + protected function utf8ToHtmlentity($string) + { + return \str_replace( + array('┌', '═', '┐', '│', '└', '─', '┘'), + array('┌', '═', '┐', '│', '└', '─', '┘'), + $string + ); + } + + protected static function renderJs() + { + return \file_get_contents(KINT_DIR.'/resources/compiled/shared.js').\file_get_contents(KINT_DIR.'/resources/compiled/plain.js'); + } + + protected static function renderCss() + { + if (\file_exists(KINT_DIR.'/resources/compiled/'.self::$theme)) { + return \file_get_contents(KINT_DIR.'/resources/compiled/'.self::$theme); + } + + return \file_get_contents(self::$theme); + } +} diff --git a/system/ThirdParty/Kint/Renderer/Renderer.php b/system/ThirdParty/Kint/Renderer/Renderer.php new file mode 100644 index 000000000000..cf8b0a781179 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Renderer.php @@ -0,0 +1,185 @@ +call_info = array( + 'params' => $info['params'], + 'modifiers' => $info['modifiers'], + 'callee' => $info['callee'], + 'caller' => $info['caller'], + 'trace' => $info['trace'], + ); + } + + public function getCallInfo() + { + return $this->call_info; + } + + public function setStatics(array $statics) + { + $this->statics = $statics; + $this->setShowTrace(!empty($statics['display_called_from'])); + } + + public function getStatics() + { + return $this->statics; + } + + public function setShowTrace($show_trace) + { + $this->show_trace = $show_trace; + } + + public function getShowTrace() + { + return $this->show_trace; + } + + /** + * Returns the first compatible plugin available. + * + * @param array $plugins Array of hints to class strings + * @param array $hints Array of object hints + * + * @return array Array of hints to class strings filtered and sorted by object hints + */ + public function matchPlugins(array $plugins, array $hints) + { + $out = array(); + + foreach ($hints as $key) { + if (isset($plugins[$key])) { + $out[$key] = $plugins[$key]; + } + } + + return $out; + } + + public function filterParserPlugins(array $plugins) + { + return $plugins; + } + + public function preRender() + { + return ''; + } + + public function postRender() + { + return ''; + } + + public static function sortPropertiesFull(BasicObject $a, BasicObject $b) + { + $sort = BasicObject::sortByAccess($a, $b); + if ($sort) { + return $sort; + } + + $sort = BasicObject::sortByName($a, $b); + if ($sort) { + return $sort; + } + + return InstanceObject::sortByHierarchy($a->owner_class, $b->owner_class); + } + + /** + * Sorts an array of BasicObject. + * + * @param BasicObject[] $contents Object properties to sort + * @param int $sort + * + * @return BasicObject[] + */ + public static function sortProperties(array $contents, $sort) + { + switch ($sort) { + case self::SORT_VISIBILITY: + /** @var array Containers to quickly stable sort by type */ + $containers = array( + BasicObject::ACCESS_PUBLIC => array(), + BasicObject::ACCESS_PROTECTED => array(), + BasicObject::ACCESS_PRIVATE => array(), + BasicObject::ACCESS_NONE => array(), + ); + + foreach ($contents as $item) { + $containers[$item->access][] = $item; + } + + return \call_user_func_array('array_merge', $containers); + case self::SORT_FULL: + \usort($contents, array('Kint\\Renderer\\Renderer', 'sortPropertiesFull')); + // no break + default: + return $contents; + } + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/BinaryPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/BinaryPlugin.php new file mode 100644 index 000000000000..5b4d613fdce6 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/BinaryPlugin.php @@ -0,0 +1,51 @@ +'; + + $chunks = \str_split($r->contents, self::$line_length); + + foreach ($chunks as $index => $chunk) { + $out .= \sprintf('%08X', $index * self::$line_length).":\t"; + $out .= \implode(' ', \str_split(\str_pad(\bin2hex($chunk), 2 * self::$line_length, ' '), self::$chunk_length)); + $out .= "\t".\preg_replace('/[^\\x20-\\x7E]/', '.', $chunk)."\n"; + } + + $out .= ''; + + return $out; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/BlacklistPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/BlacklistPlugin.php new file mode 100644 index 000000000000..fcfedc1a00be --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/BlacklistPlugin.php @@ -0,0 +1,36 @@ +'.$this->renderLockedHeader($o, 'Blacklisted').''; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/CallablePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/CallablePlugin.php new file mode 100644 index 000000000000..5834017ba550 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/CallablePlugin.php @@ -0,0 +1,174 @@ +renderMethod($o); + } + + if ($o instanceof ClosureObject) { + return $this->renderClosure($o); + } + + return $this->renderCallable($o); + } + + protected function renderClosure(ClosureObject $o) + { + $children = $this->renderer->renderChildren($o); + + $header = ''; + + if (null !== ($s = $o->getModifiers())) { + $header .= ''.$s.' '; + } + + if (null !== ($s = $o->getName())) { + $header .= ''.$this->renderer->escape($s).'('.$this->renderer->escape($o->getParams()).')'; + } + + if (null !== ($s = $o->getValueShort())) { + if (RichRenderer::$strlen_max && BlobObject::strlen($s) > RichRenderer::$strlen_max) { + $s = \substr($s, 0, RichRenderer::$strlen_max).'...'; + } + $header .= ' '.$this->renderer->escape($s); + } + + return '
'.$this->renderer->renderHeaderWrapper($o, (bool) \strlen($children), $header).$children.'
'; + } + + protected function renderCallable(BasicObject $o) + { + $children = $this->renderer->renderChildren($o); + + $header = ''; + + if (null !== ($s = $o->getModifiers())) { + $header .= ''.$s.' '; + } + + if (null !== ($s = $o->getName())) { + $header .= ''.$this->renderer->escape($s).''; + } + + if (null !== ($s = $o->getValueShort())) { + if (RichRenderer::$strlen_max && BlobObject::strlen($s) > RichRenderer::$strlen_max) { + $s = \substr($s, 0, RichRenderer::$strlen_max).'...'; + } + $header .= ' '.$this->renderer->escape($s); + } + + return '
'.$this->renderer->renderHeaderWrapper($o, (bool) \strlen($children), $header).$children.'
'; + } + + protected function renderMethod(MethodObject $o) + { + if (!empty(self::$method_cache[$o->owner_class][$o->name])) { + $children = self::$method_cache[$o->owner_class][$o->name]['children']; + + $header = $this->renderer->renderHeaderWrapper( + $o, + (bool) \strlen($children), + self::$method_cache[$o->owner_class][$o->name]['header'] + ); + + return '
'.$header.$children.'
'; + } + + $children = $this->renderer->renderChildren($o); + + $header = ''; + + if (null !== ($s = $o->getModifiers()) || $o->return_reference) { + $header .= ''.$s; + + if ($o->return_reference) { + if ($s) { + $header .= ' '; + } + $header .= $this->renderer->escape('&'); + } + + $header .= ' '; + } + + if (null !== ($s = $o->getName())) { + $function = $this->renderer->escape($s).'('.$this->renderer->escape($o->getParams()).')'; + + if (null !== ($url = $o->getPhpDocUrl())) { + $function = ''.$function.''; + } + + $header .= ''.$function.''; + } + + if (!empty($o->returntype)) { + $header .= ': '; + + if ($o->return_reference) { + $header .= $this->renderer->escape('&'); + } + + $header .= $this->renderer->escape($o->returntype).''; + } elseif ($o->docstring) { + if (\preg_match('/@return\\s+(.*)\\r?\\n/m', $o->docstring, $matches)) { + if (\trim($matches[1])) { + $header .= ': '.$this->renderer->escape(\trim($matches[1])).''; + } + } + } + + if (null !== ($s = $o->getValueShort())) { + if (RichRenderer::$strlen_max && BlobObject::strlen($s) > RichRenderer::$strlen_max) { + $s = \substr($s, 0, RichRenderer::$strlen_max).'...'; + } + $header .= ' '.$this->renderer->escape($s); + } + + if (\strlen($o->owner_class) && \strlen($o->name)) { + self::$method_cache[$o->owner_class][$o->name] = array( + 'header' => $header, + 'children' => $children, + ); + } + + $header = $this->renderer->renderHeaderWrapper($o, (bool) \strlen($children), $header); + + return '
'.$header.$children.'
'; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/ClosurePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/ClosurePlugin.php new file mode 100644 index 000000000000..79a9926cab7f --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/ClosurePlugin.php @@ -0,0 +1,59 @@ +renderer->renderChildren($o); + + if (!($o instanceof ClosureObject)) { + $header = $this->renderer->renderHeader($o); + } else { + $header = ''; + + if (null !== ($s = $o->getModifiers())) { + $header .= ''.$s.' '; + } + + if (null !== ($s = $o->getName())) { + $header .= ''.$this->renderer->escape($s).'('.$this->renderer->escape($o->getParams()).') '; + } + + $header .= 'Closure '; + $header .= $this->renderer->escape(Kint::shortenPath($o->filename)).':'.(int) $o->startline; + } + + $header = $this->renderer->renderHeaderWrapper($o, (bool) \strlen($children), $header); + + return '
'.$header.$children.'
'; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/ColorPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/ColorPlugin.php new file mode 100644 index 000000000000..241a8154f430 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/ColorPlugin.php @@ -0,0 +1,100 @@ +getRepresentation('color'); + + if (!$r instanceof ColorRepresentation) { + return; + } + + $children = $this->renderer->renderChildren($o); + + $header = $this->renderer->renderHeader($o); + $header .= '
'; + + $header = $this->renderer->renderHeaderWrapper($o, (bool) \strlen($children), $header); + + return '
'.$header.$children.'
'; + } + + public function renderTab(Representation $r) + { + if (!$r instanceof ColorRepresentation) { + return; + } + + $out = ''; + + if ($color = $r->getColor(ColorRepresentation::COLOR_NAME)) { + $out .= ''.$color."\n"; + } + if ($color = $r->getColor(ColorRepresentation::COLOR_HEX_3)) { + $out .= ''.$color."\n"; + } + if ($color = $r->getColor(ColorRepresentation::COLOR_HEX_6)) { + $out .= ''.$color."\n"; + } + + if ($r->hasAlpha()) { + if ($color = $r->getColor(ColorRepresentation::COLOR_HEX_4)) { + $out .= ''.$color."\n"; + } + if ($color = $r->getColor(ColorRepresentation::COLOR_HEX_8)) { + $out .= ''.$color."\n"; + } + if ($color = $r->getColor(ColorRepresentation::COLOR_RGBA)) { + $out .= ''.$color."\n"; + } + if ($color = $r->getColor(ColorRepresentation::COLOR_HSLA)) { + $out .= ''.$color."\n"; + } + } else { + if ($color = $r->getColor(ColorRepresentation::COLOR_RGB)) { + $out .= ''.$color."\n"; + } + if ($color = $r->getColor(ColorRepresentation::COLOR_HSL)) { + $out .= ''.$color."\n"; + } + } + + if (!\strlen($out)) { + return false; + } + + return '
'.$out.'
'; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/DepthLimitPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/DepthLimitPlugin.php new file mode 100644 index 000000000000..cd92b417985c --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/DepthLimitPlugin.php @@ -0,0 +1,36 @@ +'.$this->renderLockedHeader($o, 'Depth Limit').''; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/DocstringPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/DocstringPlugin.php new file mode 100644 index 000000000000..19c530951c4d --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/DocstringPlugin.php @@ -0,0 +1,70 @@ +contents) as $line) { + $docstring[] = \trim($line); + } + + $docstring = \implode("\n", $docstring); + + $location = array(); + + if ($r->class) { + $location[] = 'Inherited from '.$this->renderer->escape($r->class); + } + if ($r->file && $r->line) { + $location[] = 'Defined in '.$this->renderer->escape(Kint::shortenPath($r->file)).':'.((int) $r->line); + } + + $location = \implode("\n", $location); + + if ($location) { + if (\strlen($docstring)) { + $docstring .= "\n\n"; + } + + $location = ''.$location.''; + } elseif (0 === \strlen($docstring)) { + return ''; + } + + return '
'.$this->renderer->escape($docstring).$location.'
'; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/MicrotimePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/MicrotimePlugin.php new file mode 100644 index 000000000000..a56bb23ef53a --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/MicrotimePlugin.php @@ -0,0 +1,68 @@ +getDateTime()->format('Y-m-d H:i:s.u'); + if (null !== $r->lap) { + $out .= '
SINCE LAST CALL: '.\round($r->lap, 4).'s.'; + } + if (null !== $r->total) { + $out .= '
SINCE START: '.\round($r->total, 4).'s.'; + } + if (null !== $r->avg) { + $out .= '
AVERAGE DURATION: '.\round($r->avg, 4).'s.'; + } + + $bytes = Utils::getHumanReadableBytes($r->mem); + $out .= '
MEMORY USAGE: '.$r->mem.' bytes ('.\round($bytes['value'], 3).' '.$bytes['unit'].')'; + $bytes = Utils::getHumanReadableBytes($r->mem_real); + $out .= ' (real '.\round($bytes['value'], 3).' '.$bytes['unit'].')'; + + $bytes = Utils::getHumanReadableBytes($r->mem_peak); + $out .= '
PEAK MEMORY USAGE: '.$r->mem_peak.' bytes ('.\round($bytes['value'], 3).' '.$bytes['unit'].')'; + $bytes = Utils::getHumanReadableBytes($r->mem_peak_real); + $out .= ' (real '.\round($bytes['value'], 3).' '.$bytes['unit'].')'; + + return '
'.$out.'
'; + } + + public static function renderJs() + { + return \file_get_contents(KINT_DIR.'/resources/compiled/microtime.js'); + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/ObjectPluginInterface.php b/system/ThirdParty/Kint/Renderer/Rich/ObjectPluginInterface.php new file mode 100644 index 000000000000..f46aa2946ea3 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/ObjectPluginInterface.php @@ -0,0 +1,33 @@ +renderer = $r; + } + + /** + * Renders a locked header. + * + * @param BasicObject $o + * @param string $content + */ + public function renderLockedHeader(BasicObject $o, $content) + { + $header = '
'; + + if (RichRenderer::$access_paths && $o->depth > 0 && $ap = $o->getAccessPath()) { + $header .= ''; + } + + $header .= ''; + + if (null !== ($s = $o->getModifiers())) { + $header .= ''.$s.' '; + } + + if (null !== ($s = $o->getName())) { + $header .= ''.$this->renderer->escape($s).' '; + + if ($s = $o->getOperator()) { + $header .= $this->renderer->escape($s, 'ASCII').' '; + } + } + + if (null !== ($s = $o->getType())) { + $s = $this->renderer->escape($s); + + if ($o->reference) { + $s = '&'.$s; + } + + $header .= ''.$s.' '; + } + + if (null !== ($s = $o->getSize())) { + $header .= '('.$this->renderer->escape($s).') '; + } + + $header .= $content; + + if (!empty($ap)) { + $header .= '
'.$this->renderer->escape($ap).'
'; + } + + return $header.'
'; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/PluginInterface.php b/system/ThirdParty/Kint/Renderer/Rich/PluginInterface.php new file mode 100644 index 000000000000..79828e7d5e26 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/PluginInterface.php @@ -0,0 +1,33 @@ +'.$this->renderLockedHeader($o, 'Recursion').''; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/SimpleXMLElementPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/SimpleXMLElementPlugin.php new file mode 100644 index 000000000000..6c18931ee7af --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/SimpleXMLElementPlugin.php @@ -0,0 +1,81 @@ +renderer->renderChildren($o); + + $header = ''; + + if (null !== ($s = $o->getModifiers())) { + $header .= ''.$s.' '; + } + + if (null !== ($s = $o->getName())) { + $header .= ''.$this->renderer->escape($s).' '; + + if ($s = $o->getOperator()) { + $header .= $this->renderer->escape($s, 'ASCII').' '; + } + } + + if (null !== ($s = $o->getType())) { + $s = $this->renderer->escape($s); + + if ($o->reference) { + $s = '&'.$s; + } + + $header .= ''.$this->renderer->escape($s).' '; + } + + if (null !== ($s = $o->getSize())) { + $header .= '('.$this->renderer->escape($s).') '; + } + + if (null === $s && $c = $o->getRepresentation('contents')) { + $c = \reset($c->contents); + + if ($c && null !== ($s = $c->getValueShort())) { + if (RichRenderer::$strlen_max && BlobObject::strlen($s) > RichRenderer::$strlen_max) { + $s = \substr($s, 0, RichRenderer::$strlen_max).'...'; + } + $header .= $this->renderer->escape($s); + } + } + + $header = $this->renderer->renderHeaderWrapper($o, (bool) \strlen($children), $header); + + return '
'.$header.$children.'
'; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/SourcePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/SourcePlugin.php new file mode 100644 index 000000000000..5443dbfd9a8e --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/SourcePlugin.php @@ -0,0 +1,79 @@ +source)) { + return false; + } + + $source = $r->source; + + // Trim empty lines from the start and end of the source + foreach ($source as $linenum => $line) { + if (\strlen(\trim($line)) || $linenum === $r->line) { + break; + } + + unset($source[$linenum]); + } + + foreach (\array_reverse($source, true) as $linenum => $line) { + if (\strlen(\trim($line)) || $linenum === $r->line) { + break; + } + + unset($source[$linenum]); + } + + $output = ''; + + foreach ($source as $linenum => $line) { + if ($linenum === $r->line) { + $output .= '
'.$this->renderer->escape($line)."\n".'
'; + } else { + $output .= '
'.$this->renderer->escape($line)."\n".'
'; + } + } + + if ($output) { + \reset($source); + + $data = ''; + if ($r->showfilename) { + $data = ' data-kint-filename="'.$this->renderer->escape($r->filename).'"'; + } + + return '
'.$output.'
'; + } + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/TabPluginInterface.php b/system/ThirdParty/Kint/Renderer/Rich/TabPluginInterface.php new file mode 100644 index 000000000000..7cdbde72d2ad --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/TabPluginInterface.php @@ -0,0 +1,33 @@ +'; + + $firstrow = \reset($r->contents); + + foreach ($firstrow->value->contents as $field) { + $out .= ''; + } + + $out .= ''; + + foreach ($r->contents as $row) { + $out .= ''; + + foreach ($row->value->contents as $field) { + $out .= 'getType())) { + $type = $this->renderer->escape($s); + + if ($field->reference) { + $ref = '&'; + $type = $ref.$type; + } + + if (null !== ($s = $field->getSize())) { + $size .= ' ('.$this->renderer->escape($s).')'; + } + } + + if ($type) { + $out .= ' title="'.$type.$size.'"'; + } + + $out .= '>'; + + switch ($field->type) { + case 'boolean': + $out .= $field->value->contents ? ''.$ref.'true' : ''.$ref.'false'; + break; + case 'integer': + case 'double': + $out .= (string) $field->value->contents; + break; + case 'null': + $out .= ''.$ref.'null'; + break; + case 'string': + if ($field->encoding) { + $val = $field->value->contents; + if (RichRenderer::$strlen_max && self::$respect_str_length && BlobObject::strlen($val) > RichRenderer::$strlen_max) { + $val = \substr($val, 0, RichRenderer::$strlen_max).'...'; + } + + $out .= $this->renderer->escape($val); + } else { + $out .= ''.$type.''; + } + break; + case 'array': + $out .= ''.$ref.'array'.$size; + break; + case 'object': + $out .= ''.$ref.$this->renderer->escape($field->classname).''.$size; + break; + case 'resource': + $out .= ''.$ref.'resource'; + break; + default: + $out .= ''.$ref.'unknown'; + break; + } + + if (\in_array('blacklist', $field->hints, true)) { + $out .= ' Blacklisted'; + } elseif (\in_array('recursion', $field->hints, true)) { + $out .= ' Recursion'; + } elseif (\in_array('depth_limit', $field->hints, true)) { + $out .= ' Depth Limit'; + } + + $out .= ''; + } + + $out .= ''; + } + + $out .= '
'.$this->renderer->escape($field->name).'
'; + $out .= $this->renderer->escape($row->name); + $out .= '
'; + + return $out; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/TimestampPlugin.php b/system/ThirdParty/Kint/Renderer/Rich/TimestampPlugin.php new file mode 100644 index 000000000000..6e3a2f8c5c83 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/TimestampPlugin.php @@ -0,0 +1,42 @@ +contents); + + if ($dt) { + return '
'.$dt->setTimeZone(new DateTimeZone('UTC'))->format('Y-m-d H:i:s T').'
'; + } + } +} diff --git a/system/ThirdParty/Kint/Renderer/Rich/TraceFramePlugin.php b/system/ThirdParty/Kint/Renderer/Rich/TraceFramePlugin.php new file mode 100644 index 000000000000..6ca19bb67157 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Rich/TraceFramePlugin.php @@ -0,0 +1,68 @@ +trace['file']) && !empty($o->trace['line'])) { + $header = ''.$this->renderer->ideLink($o->trace['file'], (int) $o->trace['line']).' '; + } else { + $header = 'PHP internal call '; + } + + if ($o->trace['class']) { + $header .= $this->renderer->escape($o->trace['class'].$o->trace['type']); + } + + if (\is_string($o->trace['function'])) { + $function = $this->renderer->escape($o->trace['function'].'()'); + } else { + $function = $this->renderer->escape( + $o->trace['function']->getName().'('.$o->trace['function']->getParams().')' + ); + + if (null !== ($url = $o->trace['function']->getPhpDocUrl())) { + $function = ''.$function.''; + } + } + + $header .= ''.$function.''; + + $children = $this->renderer->renderChildren($o); + $header = $this->renderer->renderHeaderWrapper($o, (bool) \strlen($children), $header); + + return '
'.$header.$children.'
'; + } +} diff --git a/system/ThirdParty/Kint/Renderer/RichRenderer.php b/system/ThirdParty/Kint/Renderer/RichRenderer.php new file mode 100644 index 000000000000..dcd39eec8c53 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/RichRenderer.php @@ -0,0 +1,612 @@ + 'Kint\\Renderer\\Rich\\BlacklistPlugin', + 'callable' => 'Kint\\Renderer\\Rich\\CallablePlugin', + 'closure' => 'Kint\\Renderer\\Rich\\ClosurePlugin', + 'color' => 'Kint\\Renderer\\Rich\\ColorPlugin', + 'depth_limit' => 'Kint\\Renderer\\Rich\\DepthLimitPlugin', + 'recursion' => 'Kint\\Renderer\\Rich\\RecursionPlugin', + 'simplexml_element' => 'Kint\\Renderer\\Rich\\SimpleXMLElementPlugin', + 'trace_frame' => 'Kint\\Renderer\\Rich\\TraceFramePlugin', + ); + + /** + * RichRenderer tab plugins should implement Kint\Renderer\Rich\TabPluginInterface. + */ + public static $tab_plugins = array( + 'binary' => 'Kint\\Renderer\\Rich\\BinaryPlugin', + 'color' => 'Kint\\Renderer\\Rich\\ColorPlugin', + 'docstring' => 'Kint\\Renderer\\Rich\\DocstringPlugin', + 'microtime' => 'Kint\\Renderer\\Rich\\MicrotimePlugin', + 'source' => 'Kint\\Renderer\\Rich\\SourcePlugin', + 'table' => 'Kint\\Renderer\\Rich\\TablePlugin', + 'timestamp' => 'Kint\\Renderer\\Rich\\TimestampPlugin', + ); + + public static $pre_render_sources = array( + 'script' => array( + array('Kint\\Renderer\\RichRenderer', 'renderJs'), + array('Kint\\Renderer\\Rich\\MicrotimePlugin', 'renderJs'), + ), + 'style' => array( + array('Kint\\Renderer\\RichRenderer', 'renderCss'), + ), + 'raw' => array(), + ); + + /** + * Whether or not to render access paths. + * + * Access paths can become incredibly heavy with very deep and wide + * structures. Given mostly public variables it will typically make + * up one quarter of the output HTML size. + * + * If this is an unacceptably large amount and your browser is groaning + * under the weight of the access paths - your first order of buisiness + * should be to get a new browser. Failing that, use this to turn them off. + * + * @var bool + */ + public static $access_paths = true; + + /** + * The maximum length of a string before it is truncated. + * + * Falsey to disable + * + * @var int + */ + public static $strlen_max = 80; + + /** + * Path to the CSS file to load by default. + * + * @var string + */ + public static $theme = 'original.css'; + + /** + * Assume types and sizes don't need to be escaped. + * + * Turn this off if you use anything but ascii in your class names, + * but it'll cause a slowdown of around 10% + * + * @var bool + */ + public static $escape_types = false; + + /** + * Move all dumps to a folder at the bottom of the body. + * + * @var bool + */ + public static $folder = true; + + /** + * Sort mode for object properties. + * + * @var int + */ + public static $sort = self::SORT_NONE; + + public static $needs_pre_render = true; + public static $needs_folder_render = true; + + public static $always_pre_render = false; + + protected $plugin_objs = array(); + protected $expand = false; + protected $force_pre_render = false; + protected $pre_render; + protected $use_folder; + + public function __construct() + { + $this->pre_render = self::$needs_pre_render; + $this->use_folder = self::$folder; + + if (self::$always_pre_render) { + $this->setForcePreRender(); + } + } + + public function setCallInfo(array $info) + { + parent::setCallInfo($info); + + if (\in_array('!', $this->call_info['modifiers'], true)) { + $this->setExpand(true); + $this->use_folder = false; + } + + if (\in_array('@', $this->call_info['modifiers'], true)) { + $this->setForcePreRender(); + } + } + + public function setStatics(array $statics) + { + parent::setStatics($statics); + + if (!empty($statics['expanded'])) { + $this->setExpand(true); + } + + if (!empty($statics['return'])) { + $this->setForcePreRender(); + } + } + + public function setExpand($expand) + { + $this->expand = $expand; + } + + public function getExpand() + { + return $this->expand; + } + + public function setForcePreRender() + { + $this->force_pre_render = true; + $this->pre_render = true; + } + + public function setPreRender($pre_render) + { + $this->setForcePreRender(); // TODO: Remove line in next major version + $this->pre_render = $pre_render; + } + + public function getPreRender() + { + return $this->pre_render; + } + + public function setUseFolder($use_folder) + { + $this->use_folder = $use_folder; + } + + public function getUseFolder() + { + return $this->use_folder; + } + + public function render(BasicObject $o) + { + if ($plugin = $this->getPlugin(self::$object_plugins, $o->hints)) { + if (\strlen($output = $plugin->renderObject($o))) { + return $output; + } + } + + $children = $this->renderChildren($o); + $header = $this->renderHeaderWrapper($o, (bool) \strlen($children), $this->renderHeader($o)); + + return '
'.$header.$children.'
'; + } + + public function renderNothing() + { + return '
No argument
'; + } + + public function renderHeaderWrapper(BasicObject $o, $has_children, $contents) + { + $out = 'expand) { + $out .= ' kint-show'; + } + + $out .= '"'; + } + + $out .= '>'; + + if (self::$access_paths && $o->depth > 0 && $ap = $o->getAccessPath()) { + $out .= ''; + } + + if ($has_children) { + $out .= ''; + + if (0 === $o->depth) { + $out .= ''; + $out .= ''; + } + + $out .= ''; + } + + $out .= $contents; + + if (!empty($ap)) { + $out .= '
'.$this->escape($ap).'
'; + } + + return $out.''; + } + + public function renderHeader(BasicObject $o) + { + $output = ''; + + if (null !== ($s = $o->getModifiers())) { + $output .= ''.$s.' '; + } + + if (null !== ($s = $o->getName())) { + $output .= ''.$this->escape($s).' '; + + if ($s = $o->getOperator()) { + $output .= $this->escape($s, 'ASCII').' '; + } + } + + if (null !== ($s = $o->getType())) { + if (self::$escape_types) { + $s = $this->escape($s); + } + + if ($o->reference) { + $s = '&'.$s; + } + + $output .= ''.$s.' '; + } + + if (null !== ($s = $o->getSize())) { + if (self::$escape_types) { + $s = $this->escape($s); + } + $output .= '('.$s.') '; + } + + if (null !== ($s = $o->getValueShort())) { + $s = \preg_replace('/\\s+/', ' ', $s); + + if (self::$strlen_max) { + $s = Utils::truncateString($s, self::$strlen_max); + } + + $output .= $this->escape($s); + } + + return \trim($output); + } + + public function renderChildren(BasicObject $o) + { + $contents = array(); + $tabs = array(); + + foreach ($o->getRepresentations() as $rep) { + $result = $this->renderTab($o, $rep); + if (\strlen($result)) { + $contents[] = $result; + $tabs[] = $rep; + } + } + + if (empty($tabs)) { + return ''; + } + + $output = '
'; + + if (1 === \count($tabs) && $tabs[0]->labelIsImplicit()) { + $output .= \reset($contents); + } else { + $output .= '
    '; + + foreach ($tabs as $i => $tab) { + if (0 === $i) { + $output .= '
  • '; + } else { + $output .= '
  • '; + } + + $output .= $this->escape($tab->getLabel()).'
  • '; + } + + $output .= '
    '; + + foreach ($contents as $tab) { + $output .= '
  • '.$tab.'
  • '; + } + + $output .= '
'; + } + + return $output.'
'; + } + + public function preRender() + { + $output = ''; + + if ($this->pre_render) { + foreach (self::$pre_render_sources as $type => $values) { + $contents = ''; + foreach ($values as $v) { + $contents .= \call_user_func($v, $this); + } + + if (!\strlen($contents)) { + continue; + } + + switch ($type) { + case 'script': + $output .= ''; + break; + case 'style': + $output .= ''; + break; + default: + $output .= $contents; + } + } + + // Don't pre-render on every dump + if (!$this->force_pre_render) { + self::$needs_pre_render = false; + } + } + + $output .= '
'; + + return $output; + } + + public function postRender() + { + if (!$this->show_trace) { + return '
'; + } + + $output = '
'; + $output .= ' '; + + if (!empty($this->call_info['trace']) && \count($this->call_info['trace']) > 1) { + $output .= ''; + } + + if (isset($this->call_info['callee']['file'])) { + $output .= 'Called from '.$this->ideLink( + $this->call_info['callee']['file'], + $this->call_info['callee']['line'] + ); + } + + if (isset($this->call_info['callee']['function']) && ( + !empty($this->call_info['callee']['class']) || + !\in_array( + $this->call_info['callee']['function'], + array('include', 'include_once', 'require', 'require_once'), + true + ) + ) + ) { + $output .= ' ['; + if (isset($this->call_info['callee']['class'])) { + $output .= $this->call_info['callee']['class']; + } + if (isset($this->call_info['callee']['type'])) { + $output .= $this->call_info['callee']['type']; + } + $output .= $this->call_info['callee']['function'].'()]'; + } + + if (!empty($this->call_info['trace']) && \count($this->call_info['trace']) > 1) { + $output .= '
    '; + foreach ($this->call_info['trace'] as $index => $step) { + if (!$index) { + continue; + } + + $output .= '
  1. '.$this->ideLink($step['file'], $step['line']); // closing tag not required + if (isset($step['function']) + && !\in_array($step['function'], array('include', 'include_once', 'require', 'require_once'), true) + ) { + $output .= ' ['; + if (isset($step['class'])) { + $output .= $step['class']; + } + if (isset($step['type'])) { + $output .= $step['type']; + } + $output .= $step['function'].'()]'; + } + } + $output .= '
'; + } + + $output .= '
'; + + return $output; + } + + public function escape($string, $encoding = false) + { + if (false === $encoding) { + $encoding = BlobObject::detectEncoding($string); + } + + $original_encoding = $encoding; + + if (false === $encoding || 'ASCII' === $encoding) { + $encoding = 'UTF-8'; + } + + $string = \htmlspecialchars($string, ENT_NOQUOTES, $encoding); + + // this call converts all non-ASCII characters into numeirc htmlentities + if (\function_exists('mb_encode_numericentity') && 'ASCII' !== $original_encoding) { + $string = \mb_encode_numericentity($string, array(0x80, 0xffff, 0, 0xffff), $encoding); + } + + return $string; + } + + public function ideLink($file, $line) + { + $path = $this->escape(Kint::shortenPath($file)).':'.$line; + $ideLink = Kint::getIdeLink($file, $line); + + if (!$ideLink) { + return $path; + } + + $class = ''; + + if (\preg_match('/https?:\\/\\//i', $ideLink)) { + $class = 'class="kint-ide-link" '; + } + + return ''.$path.''; + } + + protected function renderTab(BasicObject $o, Representation $rep) + { + if ($plugin = $this->getPlugin(self::$tab_plugins, $rep->hints)) { + if (\strlen($output = $plugin->renderTab($rep))) { + return $output; + } + } + + if (\is_array($rep->contents)) { + $output = ''; + + if ($o instanceof InstanceObject && 'properties' === $rep->getName()) { + foreach (self::sortProperties($rep->contents, self::$sort) as $obj) { + $output .= $this->render($obj); + } + } else { + foreach ($rep->contents as $obj) { + $output .= $this->render($obj); + } + } + + return $output; + } + + if (\is_string($rep->contents)) { + $show_contents = false; + + // If it is the value representation of a string and its whitespace + // was truncated in the header, always display the full string + if ('string' !== $o->type || $o->value !== $rep) { + $show_contents = true; + } else { + if (\preg_match('/(:?[\\r\\n\\t\\f\\v]| {2})/', $rep->contents)) { + $show_contents = true; + } elseif (self::$strlen_max && BlobObject::strlen($o->getValueShort()) > self::$strlen_max) { + $show_contents = true; + } + + if (empty($o->encoding)) { + $show_contents = false; + } + } + + if ($show_contents) { + return '
'.$this->escape($rep->contents)."\n
"; + } + } + + if ($rep->contents instanceof BasicObject) { + return $this->render($rep->contents); + } + } + + protected function getPlugin(array $plugins, array $hints) + { + if ($plugins = $this->matchPlugins($plugins, $hints)) { + $plugin = \end($plugins); + + if (!isset($this->plugin_objs[$plugin])) { + $this->plugin_objs[$plugin] = new $plugin($this); + } + + return $this->plugin_objs[$plugin]; + } + } + + protected static function renderJs() + { + return \file_get_contents(KINT_DIR.'/resources/compiled/shared.js').\file_get_contents(KINT_DIR.'/resources/compiled/rich.js'); + } + + protected static function renderCss() + { + if (\file_exists(KINT_DIR.'/resources/compiled/'.self::$theme)) { + return \file_get_contents(KINT_DIR.'/resources/compiled/'.self::$theme); + } + + return \file_get_contents(self::$theme); + } + + protected static function renderFolder() + { + return '
Kint
'; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Text/BlacklistPlugin.php b/system/ThirdParty/Kint/Renderer/Text/BlacklistPlugin.php new file mode 100644 index 000000000000..127d32a197f9 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Text/BlacklistPlugin.php @@ -0,0 +1,44 @@ +depth) { + $out .= $this->renderer->colorTitle($this->renderer->renderTitle($o)).PHP_EOL; + } + + $out .= $this->renderer->renderHeader($o).' '.$this->renderer->colorValue('BLACKLISTED').PHP_EOL; + + return $out; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Text/DepthLimitPlugin.php b/system/ThirdParty/Kint/Renderer/Text/DepthLimitPlugin.php new file mode 100644 index 000000000000..310b87e417b0 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Text/DepthLimitPlugin.php @@ -0,0 +1,44 @@ +depth) { + $out .= $this->renderer->colorTitle($this->renderer->renderTitle($o)).PHP_EOL; + } + + $out .= $this->renderer->renderHeader($o).' '.$this->renderer->colorValue('DEPTH LIMIT').PHP_EOL; + + return $out; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Text/MicrotimePlugin.php b/system/ThirdParty/Kint/Renderer/Text/MicrotimePlugin.php new file mode 100644 index 000000000000..9128032c4ae0 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Text/MicrotimePlugin.php @@ -0,0 +1,128 @@ +renderer instanceof PlainRenderer) { + $this->useJs = true; + } + } + + public function render(BasicObject $o) + { + $r = $o->getRepresentation('microtime'); + + if (!$r instanceof MicrotimeRepresentation) { + return false; + } + + $out = ''; + + if (0 == $o->depth) { + $out .= $this->renderer->colorTitle($this->renderer->renderTitle($o)).PHP_EOL; + } + + $out .= $this->renderer->renderHeader($o); + $out .= $this->renderer->renderChildren($o).PHP_EOL; + + $indent = \str_repeat(' ', ($o->depth + 1) * $this->renderer->indent_width); + + if ($this->useJs) { + $out .= ''; + } + + $out .= $indent.$this->renderer->colorType('TIME:').' '; + $out .= $this->renderer->colorValue($r->getDateTime()->format('Y-m-d H:i:s.u')).PHP_EOL; + + if (null !== $r->lap) { + $out .= $indent.$this->renderer->colorType('SINCE LAST CALL:').' '; + + $lap = \round($r->lap, 4); + + if ($this->useJs) { + $lap = ''.$lap.''; + } + + $out .= $this->renderer->colorValue($lap.'s').'.'.PHP_EOL; + } + if (null !== $r->total) { + $out .= $indent.$this->renderer->colorType('SINCE START:').' '; + $out .= $this->renderer->colorValue(\round($r->total, 4).'s').'.'.PHP_EOL; + } + if (null !== $r->avg) { + $out .= $indent.$this->renderer->colorType('AVERAGE DURATION:').' '; + + $avg = \round($r->avg, 4); + + if ($this->useJs) { + $avg = ''.$avg.''; + } + + $out .= $this->renderer->colorValue($avg.'s').'.'.PHP_EOL; + } + + $bytes = Utils::getHumanReadableBytes($r->mem); + $mem = $r->mem.' bytes ('.\round($bytes['value'], 3).' '.$bytes['unit'].')'; + $bytes = Utils::getHumanReadableBytes($r->mem_real); + $mem .= ' (real '.\round($bytes['value'], 3).' '.$bytes['unit'].')'; + + $out .= $indent.$this->renderer->colorType('MEMORY USAGE:').' '; + $out .= $this->renderer->colorValue($mem).'.'.PHP_EOL; + + $bytes = Utils::getHumanReadableBytes($r->mem_peak); + $mem = $r->mem_peak.' bytes ('.\round($bytes['value'], 3).' '.$bytes['unit'].')'; + $bytes = Utils::getHumanReadableBytes($r->mem_peak_real); + $mem .= ' (real '.\round($bytes['value'], 3).' '.$bytes['unit'].')'; + + $out .= $indent.$this->renderer->colorType('PEAK MEMORY USAGE:').' '; + $out .= $this->renderer->colorValue($mem).'.'.PHP_EOL; + + if ($this->useJs) { + $out .= ''; + } + + return $out; + } + + public static function renderJs() + { + return RichPlugin::renderJs(); + } +} diff --git a/system/ThirdParty/Kint/Renderer/Text/Plugin.php b/system/ThirdParty/Kint/Renderer/Text/Plugin.php new file mode 100644 index 000000000000..9de25c1a1147 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Text/Plugin.php @@ -0,0 +1,41 @@ +renderer = $r; + } + + abstract public function render(BasicObject $o); +} diff --git a/system/ThirdParty/Kint/Renderer/Text/RecursionPlugin.php b/system/ThirdParty/Kint/Renderer/Text/RecursionPlugin.php new file mode 100644 index 000000000000..72c2257ca8fc --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Text/RecursionPlugin.php @@ -0,0 +1,44 @@ +depth) { + $out .= $this->renderer->colorTitle($this->renderer->renderTitle($o)).PHP_EOL; + } + + $out .= $this->renderer->renderHeader($o).' '.$this->renderer->colorValue('RECURSION').PHP_EOL; + + return $out; + } +} diff --git a/system/ThirdParty/Kint/Renderer/Text/TracePlugin.php b/system/ThirdParty/Kint/Renderer/Text/TracePlugin.php new file mode 100644 index 000000000000..5833840cdf8f --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/Text/TracePlugin.php @@ -0,0 +1,111 @@ +depth) { + $out .= $this->renderer->colorTitle($this->renderer->renderTitle($o)).PHP_EOL; + } + + $out .= $this->renderer->renderHeader($o).':'.PHP_EOL; + + $indent = \str_repeat(' ', ($o->depth + 1) * $this->renderer->indent_width); + + $i = 1; + foreach ($o->value->contents as $frame) { + $framedesc = $indent.\str_pad($i.': ', 4, ' '); + + if ($frame->trace['file']) { + $framedesc .= $this->renderer->ideLink($frame->trace['file'], $frame->trace['line']).PHP_EOL; + } else { + $framedesc .= 'PHP internal call'.PHP_EOL; + } + + $framedesc .= $indent.' '; + + if ($frame->trace['class']) { + $framedesc .= $this->renderer->escape($frame->trace['class']); + + if ($frame->trace['object']) { + $framedesc .= $this->renderer->escape('->'); + } else { + $framedesc .= '::'; + } + } + + if (\is_string($frame->trace['function'])) { + $framedesc .= $this->renderer->escape($frame->trace['function']).'(...)'; + } elseif ($frame->trace['function'] instanceof MethodObject) { + $framedesc .= $this->renderer->escape($frame->trace['function']->getName()); + $framedesc .= '('.$this->renderer->escape($frame->trace['function']->getParams()).')'; + } + + $out .= $this->renderer->colorType($framedesc).PHP_EOL.PHP_EOL; + + if ($source = $frame->getRepresentation('source')) { + $line_wanted = $source->line; + $source = $source->source; + + // Trim empty lines from the start and end of the source + foreach ($source as $linenum => $line) { + if (\trim($line) || $linenum === $line_wanted) { + break; + } + + unset($source[$linenum]); + } + + foreach (\array_reverse($source, true) as $linenum => $line) { + if (\trim($line) || $linenum === $line_wanted) { + break; + } + + unset($source[$linenum]); + } + + foreach ($source as $lineno => $line) { + if ($lineno == $line_wanted) { + $out .= $indent.$this->renderer->colorValue($this->renderer->escape($line)).PHP_EOL; + } else { + $out .= $indent.$this->renderer->escape($line).PHP_EOL; + } + } + } + + ++$i; + } + + return $out; + } +} diff --git a/system/ThirdParty/Kint/Renderer/TextRenderer.php b/system/ThirdParty/Kint/Renderer/TextRenderer.php new file mode 100644 index 000000000000..43b6c40d63b8 --- /dev/null +++ b/system/ThirdParty/Kint/Renderer/TextRenderer.php @@ -0,0 +1,346 @@ + 'Kint\\Renderer\\Text\\BlacklistPlugin', + 'depth_limit' => 'Kint\\Renderer\\Text\\DepthLimitPlugin', + 'microtime' => 'Kint\\Renderer\\Text\\MicrotimePlugin', + 'recursion' => 'Kint\\Renderer\\Text\\RecursionPlugin', + 'trace' => 'Kint\\Renderer\\Text\\TracePlugin', + ); + + /** + * Parser plugins must be instanceof one of these or + * it will be removed for performance reasons. + */ + public static $parser_plugin_whitelist = array( + 'Kint\\Parser\\BlacklistPlugin', + 'Kint\\Parser\\MicrotimePlugin', + 'Kint\\Parser\\StreamPlugin', + 'Kint\\Parser\\TracePlugin', + ); + + /** + * The maximum length of a string before it is truncated. + * + * Falsey to disable + * + * @var int + */ + public static $strlen_max = 0; + + /** + * The default width of the terminal for headers. + * + * @var int + */ + public static $default_width = 80; + + /** + * Indentation width. + * + * @var int + */ + public static $default_indent = 4; + + /** + * Decorate the header and footer. + * + * @var bool + */ + public static $decorations = true; + + /** + * Sort mode for object properties. + * + * @var int + */ + public static $sort = self::SORT_NONE; + + public $header_width = 80; + public $indent_width = 4; + + protected $plugin_objs = array(); + + public function __construct() + { + $this->header_width = self::$default_width; + $this->indent_width = self::$default_indent; + } + + public function render(BasicObject $o) + { + if ($plugin = $this->getPlugin(self::$plugins, $o->hints)) { + if (\strlen($output = $plugin->render($o))) { + return $output; + } + } + + $out = ''; + + if (0 == $o->depth) { + $out .= $this->colorTitle($this->renderTitle($o)).PHP_EOL; + } + + $out .= $this->renderHeader($o); + $out .= $this->renderChildren($o).PHP_EOL; + + return $out; + } + + public function renderNothing() + { + if (self::$decorations) { + return $this->colorTitle( + $this->boxText('No argument', $this->header_width) + ).PHP_EOL; + } + + return $this->colorTitle('No argument').PHP_EOL; + } + + public function boxText($text, $width) + { + $out = '┌'.\str_repeat('─', $width - 2).'┐'.PHP_EOL; + + if (\strlen($text)) { + $text = Utils::truncateString($text, $width - 4); + $text = \str_pad($text, $width - 4); + + $out .= '│ '.$this->escape($text).' │'.PHP_EOL; + } + + $out .= '└'.\str_repeat('─', $width - 2).'┘'; + + return $out; + } + + public function renderTitle(BasicObject $o) + { + $name = (string) $o->getName(); + + if (self::$decorations) { + return $this->boxText($name, $this->header_width); + } + + return Utils::truncateString($name, $this->header_width); + } + + public function renderHeader(BasicObject $o) + { + $output = array(); + + if ($o->depth) { + if (null !== ($s = $o->getModifiers())) { + $output[] = $s; + } + + if (null !== $o->name) { + $output[] = $this->escape(\var_export($o->name, true)); + + if (null !== ($s = $o->getOperator())) { + $output[] = $this->escape($s); + } + } + } + + if (null !== ($s = $o->getType())) { + if ($o->reference) { + $s = '&'.$s; + } + + $output[] = $this->colorType($this->escape($s)); + } + + if (null !== ($s = $o->getSize())) { + $output[] = '('.$this->escape($s).')'; + } + + if (null !== ($s = $o->getValueShort())) { + if (self::$strlen_max) { + $s = Utils::truncateString($s, self::$strlen_max); + } + $output[] = $this->colorValue($this->escape($s)); + } + + return \str_repeat(' ', $o->depth * $this->indent_width).\implode(' ', $output); + } + + public function renderChildren(BasicObject $o) + { + if ('array' === $o->type) { + $output = ' ['; + } elseif ('object' === $o->type) { + $output = ' ('; + } else { + return ''; + } + + $children = ''; + + if ($o->value && \is_array($o->value->contents)) { + if ($o instanceof InstanceObject && 'properties' === $o->value->getName()) { + foreach (self::sortProperties($o->value->contents, self::$sort) as $obj) { + $children .= $this->render($obj); + } + } else { + foreach ($o->value->contents as $child) { + $children .= $this->render($child); + } + } + } + + if ($children) { + $output .= PHP_EOL.$children; + $output .= \str_repeat(' ', $o->depth * $this->indent_width); + } + + if ('array' === $o->type) { + $output .= ']'; + } else { + $output .= ')'; + } + + return $output; + } + + public function colorValue($string) + { + return $string; + } + + public function colorType($string) + { + return $string; + } + + public function colorTitle($string) + { + return $string; + } + + public function postRender() + { + if (self::$decorations) { + $output = \str_repeat('═', $this->header_width); + } else { + $output = ''; + } + + if (!$this->show_trace) { + return $this->colorTitle($output); + } + + if ($output) { + $output .= PHP_EOL; + } + + return $this->colorTitle($output.$this->calledFrom().PHP_EOL); + } + + public function filterParserPlugins(array $plugins) + { + $return = array(); + + foreach ($plugins as $index => $plugin) { + foreach (self::$parser_plugin_whitelist as $whitelist) { + if ($plugin instanceof $whitelist) { + $return[] = $plugin; + continue 2; + } + } + } + + return $return; + } + + public function ideLink($file, $line) + { + return $this->escape(Kint::shortenPath($file)).':'.$line; + } + + public function escape($string, $encoding = false) + { + return $string; + } + + protected function calledFrom() + { + $output = ''; + + if (isset($this->call_info['callee']['file'])) { + $output .= 'Called from '.$this->ideLink( + $this->call_info['callee']['file'], + $this->call_info['callee']['line'] + ); + } + + if (isset($this->call_info['callee']['function']) && ( + !empty($this->call_info['callee']['class']) || + !\in_array( + $this->call_info['callee']['function'], + array('include', 'include_once', 'require', 'require_once'), + true + ) + ) + ) { + $output .= ' ['; + if (isset($this->call_info['callee']['class'])) { + $output .= $this->call_info['callee']['class']; + } + if (isset($this->call_info['callee']['type'])) { + $output .= $this->call_info['callee']['type']; + } + $output .= $this->call_info['callee']['function'].'()]'; + } + + return $output; + } + + protected function getPlugin(array $plugins, array $hints) + { + if ($plugins = $this->matchPlugins($plugins, $hints)) { + $plugin = \end($plugins); + + if (!isset($this->plugin_objs[$plugin])) { + $this->plugin_objs[$plugin] = new $plugin($this); + } + + return $this->plugin_objs[$plugin]; + } + } +} diff --git a/system/ThirdParty/Kint/Utils.php b/system/ThirdParty/Kint/Utils.php new file mode 100644 index 000000000000..27a24913fdb1 --- /dev/null +++ b/system/ThirdParty/Kint/Utils.php @@ -0,0 +1,240 @@ + (float) ($value / \pow(1024, $i)), + 'unit' => $unit[$i], + ); + } + + public static function isSequential(array $array) + { + return \array_keys($array) === \range(0, \count($array) - 1); + } + + public static function composerGetExtras($key = 'kint') + { + $extras = array(); + + if (0 === \strpos(KINT_DIR, 'phar://')) { + // Only run inside phar file, so skip for code coverage + return $extras; // @codeCoverageIgnore + } + + $folder = KINT_DIR.'/vendor'; + + for ($i = 0; $i < 4; ++$i) { + $installed = $folder.'/composer/installed.json'; + + if (\file_exists($installed) && \is_readable($installed)) { + $packages = \json_decode(\file_get_contents($installed), true); + + foreach ($packages as $package) { + if (isset($package['extra'][$key]) && \is_array($package['extra'][$key])) { + $extras = \array_replace($extras, $package['extra'][$key]); + } + } + + $folder = \dirname($folder); + + if (\file_exists($folder.'/composer.json') && \is_readable($folder.'/composer.json')) { + $composer = \json_decode(\file_get_contents($folder.'/composer.json'), true); + + if (isset($composer['extra'][$key]) && \is_array($composer['extra'][$key])) { + $extras = \array_replace($extras, $composer['extra'][$key]); + } + } + + break; + } + + $folder = \dirname($folder); + } + + return $extras; + } + + /** + * @codeCoverageIgnore + */ + public static function composerSkipFlags() + { + $extras = self::composerGetExtras(); + + if (!empty($extras['disable-facade']) && !\defined('KINT_SKIP_FACADE')) { + \define('KINT_SKIP_FACADE', true); + } + + if (!empty($extras['disable-helpers']) && !\defined('KINT_SKIP_HELPERS')) { + \define('KINT_SKIP_HELPERS', true); + } + } + + public static function isTrace(array $trace) + { + if (!self::isSequential($trace)) { + return false; + } + + static $bt_structure = array( + 'function' => 'string', + 'line' => 'integer', + 'file' => 'string', + 'class' => 'string', + 'object' => 'object', + 'type' => 'string', + 'args' => 'array', + ); + + $file_found = false; + + foreach ($trace as $frame) { + if (!\is_array($frame) || !isset($frame['function'])) { + return false; + } + + foreach ($frame as $key => $val) { + if (!isset($bt_structure[$key])) { + return false; + } + + if (\gettype($val) !== $bt_structure[$key]) { + return false; + } + + if ('file' === $key) { + $file_found = true; + } + } + } + + return $file_found; + } + + public static function traceFrameIsListed(array $frame, array $matches) + { + if (isset($frame['class'])) { + $called = array(\strtolower($frame['class']), \strtolower($frame['function'])); + } else { + $called = \strtolower($frame['function']); + } + + return \in_array($called, $matches, true); + } + + public static function normalizeAliases(array &$aliases) + { + static $name_regex = '[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*'; + + foreach ($aliases as $index => &$alias) { + if (\is_array($alias) && 2 === \count($alias)) { + $alias = \array_values(\array_filter($alias, 'is_string')); + + if (2 === \count($alias) && + \preg_match('/^'.$name_regex.'$/', $alias[1]) && + \preg_match('/^\\\\?('.$name_regex.'\\\\)*'.$name_regex.'$/', $alias[0]) + ) { + $alias = array( + \strtolower(\ltrim($alias[0], '\\')), + \strtolower($alias[1]), + ); + } else { + unset($aliases[$index]); + continue; + } + } elseif (\is_string($alias)) { + if (\preg_match('/^\\\\?('.$name_regex.'\\\\)*'.$name_regex.'$/', $alias)) { + $alias = \explode('\\', \strtolower($alias)); + $alias = \end($alias); + } else { + unset($aliases[$index]); + continue; + } + } else { + unset($aliases[$index]); + } + } + + $aliases = \array_values($aliases); + } + + public static function truncateString($input, $length = PHP_INT_MAX, $end = '...', $encoding = false) + { + $length = (int) $length; + $endlength = BlobObject::strlen($end); + + if ($endlength >= $length) { + throw new InvalidArgumentException('Can\'t truncate a string to '.$length.' characters if ending with string '.$endlength.' characters long'); + } + + if (BlobObject::strlen($input, $encoding) > $length) { + return BlobObject::substr($input, 0, $length - $endlength, $encoding).$end; + } + + return $input; + } + + public static function getTypeString(ReflectionType $type) + { + if ($type instanceof ReflectionNamedType) { + return $type->getName(); + } + + return (string) $type; // @codeCoverageIgnore + } +} diff --git a/system/ThirdParty/Kint/init.php b/system/ThirdParty/Kint/init.php new file mode 100644 index 000000000000..952e041400ff --- /dev/null +++ b/system/ThirdParty/Kint/init.php @@ -0,0 +1,62 @@ += 0)); +\define('KINT_PHP70', (\version_compare(PHP_VERSION, '7.0') >= 0)); +\define('KINT_PHP72', (\version_compare(PHP_VERSION, '7.2') >= 0)); +\define('KINT_PHP73', (\version_compare(PHP_VERSION, '7.3') >= 0)); +\define('KINT_PHP74', (\version_compare(PHP_VERSION, '7.4') >= 0)); + +// Dynamic default settings +Kint::$file_link_format = \ini_get('xdebug.file_link_format'); +if (isset($_SERVER['DOCUMENT_ROOT'])) { + Kint::$app_root_dirs = array( + $_SERVER['DOCUMENT_ROOT'] => '', + \realpath($_SERVER['DOCUMENT_ROOT']) => '', + ); +} + +Utils::composerSkipFlags(); + +if ((!\defined('KINT_SKIP_FACADE') || !KINT_SKIP_FACADE) && !\class_exists('Kint')) { + \class_alias('Kint\\Kint', 'Kint'); +} + +if (!\defined('KINT_SKIP_HELPERS') || !KINT_SKIP_HELPERS) { + require_once __DIR__.'/init_helpers.php'; +} diff --git a/system/ThirdParty/Kint/init_helpers.php b/system/ThirdParty/Kint/init_helpers.php new file mode 100644 index 000000000000..b961d67f1af5 --- /dev/null +++ b/system/ThirdParty/Kint/init_helpers.php @@ -0,0 +1,84 @@ + '', + * app_path() => '', + * config_path() => '', + * database_path() => '', + * public_path() => '', + * resource_path() => '', + * storage_path() => '', + * ]; + * + * Defaults to [$_SERVER['DOCUMENT_ROOT'] => ''] + */ + public static $app_root_dirs = array(); + + /** + * @var int max array/object levels to go deep, if zero no limits are applied + */ + public static $max_depth = 6; + + /** + * @var bool expand all trees by default for rich view + */ + public static $expanded = false; + + /** + * @var bool enable detection when Kint is command line. + * + * Formats output with whitespace only; does not HTML-escape it + */ + public static $cli_detection = true; + + /** + * @var array Kint aliases. Add debug functions in Kint wrappers here to fix modifiers and backtraces + */ + public static $aliases = array( + array('Kint\\Kint', 'dump'), + array('Kint\\Kint', 'trace'), + array('Kint\\Kint', 'dumpArray'), + ); + + /** + * @var array Array of modes to renderer class names + */ + public static $renderers = array( + self::MODE_RICH => 'Kint\\Renderer\\RichRenderer', + self::MODE_PLAIN => 'Kint\\Renderer\\PlainRenderer', + self::MODE_TEXT => 'Kint\\Renderer\\TextRenderer', + self::MODE_CLI => 'Kint\\Renderer\\CliRenderer', + ); + + public static $plugins = array( + 'Kint\\Parser\\ArrayObjectPlugin', + 'Kint\\Parser\\Base64Plugin', + 'Kint\\Parser\\BlacklistPlugin', + 'Kint\\Parser\\ClassMethodsPlugin', + 'Kint\\Parser\\ClassStaticsPlugin', + 'Kint\\Parser\\ClosurePlugin', + 'Kint\\Parser\\ColorPlugin', + 'Kint\\Parser\\DateTimePlugin', + 'Kint\\Parser\\FsPathPlugin', + 'Kint\\Parser\\IteratorPlugin', + 'Kint\\Parser\\JsonPlugin', + 'Kint\\Parser\\MicrotimePlugin', + 'Kint\\Parser\\SimpleXMLElementPlugin', + 'Kint\\Parser\\SplFileInfoPlugin', + 'Kint\\Parser\\SplObjectStoragePlugin', + 'Kint\\Parser\\StreamPlugin', + 'Kint\\Parser\\TablePlugin', + 'Kint\\Parser\\ThrowablePlugin', + 'Kint\\Parser\\TimestampPlugin', + 'Kint\\Parser\\TracePlugin', + 'Kint\\Parser\\XmlPlugin', + ); + + protected static $plugin_pool = array(); + + protected $parser; + protected $renderer; + + public function __construct(Parser $p, Renderer $r) + { + $this->parser = $p; + $this->renderer = $r; + } + + public function setParser(Parser $p) + { + $this->parser = $p; + } + + public function getParser() + { + return $this->parser; + } + + public function setRenderer(Renderer $r) + { + $this->renderer = $r; + } + + public function getRenderer() + { + return $this->renderer; + } + + public function setStatesFromStatics(array $statics) + { + $this->renderer->setStatics($statics); + + $this->parser->setDepthLimit(isset($statics['max_depth']) ? $statics['max_depth'] : false); + $this->parser->clearPlugins(); + + if (!isset($statics['plugins'])) { + return; + } + + $plugins = array(); + + foreach ($statics['plugins'] as $plugin) { + if ($plugin instanceof Plugin) { + $plugins[] = $plugin; + } elseif (\is_string($plugin) && \is_subclass_of($plugin, 'Kint\\Parser\\Plugin')) { + if (!isset(self::$plugin_pool[$plugin])) { + $p = new $plugin(); + self::$plugin_pool[$plugin] = $p; + } + $plugins[] = self::$plugin_pool[$plugin]; + } + } + + $plugins = $this->renderer->filterParserPlugins($plugins); + + foreach ($plugins as $plugin) { + $this->parser->addPlugin($plugin); + } + } + + public function setStatesFromCallInfo(array $info) + { + $this->renderer->setCallInfo($info); + + if (isset($info['modifiers']) && \is_array($info['modifiers']) && \in_array('+', $info['modifiers'], true)) { + $this->parser->setDepthLimit(false); + } + + $this->parser->setCallerClass(isset($info['caller']['class']) ? $info['caller']['class'] : null); + } + + /** + * Renders a list of vars including the pre and post renders. + * + * @param array $vars Data to dump + * @param BasicObject[] $base Base objects + * + * @return string + */ + public function dumpAll(array $vars, array $base) + { + if (\array_keys($vars) !== \array_keys($base)) { + throw new InvalidArgumentException('Kint::dumpAll requires arrays of identical size and keys as arguments'); + } + + $output = $this->renderer->preRender(); + + if ($vars === array()) { + $output .= $this->renderer->renderNothing(); + } + + foreach ($vars as $key => $arg) { + if (!$base[$key] instanceof BasicObject) { + throw new InvalidArgumentException('Kint::dumpAll requires all elements of the second argument to be BasicObject instances'); + } + $output .= $this->dumpVar($arg, $base[$key]); + } + + $output .= $this->renderer->postRender(); + + return $output; + } + + /** + * Dumps and renders a var. + * + * @param mixed $var Data to dump + * @param BasicObject $base Base object + * + * @return string + */ + public function dumpVar(&$var, BasicObject $base) + { + return $this->renderer->render( + $this->parser->parse($var, $base) + ); + } + + /** + * Gets all static settings at once. + * + * @return array Current static settings + */ + public static function getStatics() + { + return array( + 'aliases' => self::$aliases, + 'app_root_dirs' => self::$app_root_dirs, + 'cli_detection' => self::$cli_detection, + 'display_called_from' => self::$display_called_from, + 'enabled_mode' => self::$enabled_mode, + 'expanded' => self::$expanded, + 'file_link_format' => self::$file_link_format, + 'max_depth' => self::$max_depth, + 'mode_default' => self::$mode_default, + 'mode_default_cli' => self::$mode_default_cli, + 'plugins' => self::$plugins, + 'renderers' => self::$renderers, + 'return' => self::$return, + ); + } + + /** + * Creates a Kint instances based on static settings. + * + * Also calls setStatesFromStatics for you + * + * @param array $statics array of statics as returned by getStatics + * + * @return null|\Kint\Kint + */ + public static function createFromStatics(array $statics) + { + $mode = false; + + if (isset($statics['enabled_mode'])) { + $mode = $statics['enabled_mode']; + + if (true === $statics['enabled_mode'] && isset($statics['mode_default'])) { + $mode = $statics['mode_default']; + + if (PHP_SAPI === 'cli' && !empty($statics['cli_detection']) && isset($statics['mode_default_cli'])) { + $mode = $statics['mode_default_cli']; + } + } + } + + if (!$mode) { + return null; + } + + if (!isset($statics['renderers'][$mode])) { + $renderer = new TextRenderer(); + } else { + /** @var Renderer */ + $renderer = new $statics['renderers'][$mode](); + } + + return new self(new Parser(), $renderer); + } + + /** + * Creates base objects given parameter info. + * + * @param array $params Parameters as returned from getCallInfo + * @param int $argc Number of arguments the helper was called with + * + * @return BasicObject[] Base objects for the arguments + */ + public static function getBasesFromParamInfo(array $params, $argc) + { + static $blacklist = array( + 'null', + 'true', + 'false', + 'array(...)', + 'array()', + '[...]', + '[]', + '(...)', + '()', + '"..."', + 'b"..."', + "'...'", + "b'...'", + ); + + $params = \array_values($params); + $bases = array(); + + for ($i = 0; $i < $argc; ++$i) { + if (isset($params[$i])) { + $param = $params[$i]; + } else { + $param = null; + } + + if (!isset($param['name']) || \is_numeric($param['name'])) { + $name = null; + } elseif (\in_array(\strtolower($param['name']), $blacklist, true)) { + $name = null; + } else { + $name = $param['name']; + } + + if (isset($param['path'])) { + $access_path = $param['path']; + + if (!empty($param['expression'])) { + $access_path = '('.$access_path.')'; + } + } else { + $access_path = '$'.$i; + } + + $bases[] = BasicObject::blank($name, $access_path); + } + + return $bases; + } + + /** + * Gets call info from the backtrace, alias, and argument count. + * + * Aliases must be normalized beforehand (Utils::normalizeAliases) + * + * @param array $aliases Call aliases as found in Kint::$aliases + * @param array[] $trace Backtrace + * @param int $argc Number of arguments + * + * @return array{params:null|array, modifiers:array, callee:null|array, caller:null|array, trace:array[]} Call info + */ + public static function getCallInfo(array $aliases, array $trace, $argc) + { + $found = false; + $callee = null; + $caller = null; + $miniTrace = array(); + + foreach ($trace as $index => $frame) { + if (Utils::traceFrameIsListed($frame, $aliases)) { + $found = true; + $miniTrace = array(); + } + + if (!Utils::traceFrameIsListed($frame, array('spl_autoload_call'))) { + $miniTrace[] = $frame; + } + } + + if ($found) { + $callee = \reset($miniTrace) ?: null; + + /** @var null|array Psalm bug workaround */ + $caller = \next($miniTrace) ?: null; + } + + foreach ($miniTrace as $index => $frame) { + if ((0 === $index && $callee === $frame) || isset($frame['file'], $frame['line'])) { + unset($frame['object'], $frame['args']); + $miniTrace[$index] = $frame; + } else { + unset($miniTrace[$index]); + } + } -define('KINT_DIR', dirname(__FILE__)); -define('KINT_WIN', DIRECTORY_SEPARATOR !== '/'); -define('KINT_PHP52', (version_compare(PHP_VERSION, '5.2') >= 0)); -define('KINT_PHP522', (version_compare(PHP_VERSION, '5.2.2') >= 0)); -define('KINT_PHP523', (version_compare(PHP_VERSION, '5.2.3') >= 0)); -define('KINT_PHP524', (version_compare(PHP_VERSION, '5.2.4') >= 0)); -define('KINT_PHP525', (version_compare(PHP_VERSION, '5.2.5') >= 0)); -define('KINT_PHP53', (version_compare(PHP_VERSION, '5.3') >= 0)); -define('KINT_PHP56', (version_compare(PHP_VERSION, '5.6') >= 0)); -define('KINT_PHP70', (version_compare(PHP_VERSION, '7.0') >= 0)); -define('KINT_PHP72', (version_compare(PHP_VERSION, '7.2') >= 0)); -eval(gzuncompress('xmw mE&MZ,9ly%94ɦĘd3ݤeǣ={p?<}K. -/&)3dm6P(' . "\0" . 'BP(:(?Gs4NTLg9%Am nF|0ꦽd:"\'/[Gf:]+i>{AG[,&Pw{P~1$Zd' . "\0" . 'ٰ#xʳlB' . "\0" . '%y|T$EƓɨvEf/~5Ϣ$L٨-~R)Eqw:՚<ɓNH}H~hY\'Yq&\\\'y sO^M3Dpfd}t|ry!q ,dla.(3dPo:"QhwQ!|[M -g^)asKD($߮x4-9-7, }:' . "\0" . 'TQXΦN)Q]tn -8)@ +,Nt{ރ]CHo .tibE!Y3 TT.!H(le 06]&8zsz&vEu-5 -5gVL6zl-ہPPAuE5IY*V QsS51؊\\-%FӡhH!8 ZbƋ(R#O+N\'+\\E̞^$8/~yݏ8??8lY\\{l|5jƺ%d -P Nu' . "\0" . '/S,&tB!X C_R H|-PXE?b>y8ʧdBҏbtaL Ii.\\v~KjT-fA!T0C삂i2RfB-(ɩ}ia9[Mf|WƢ8<U}:܍uΦrLSմĜ%DMqD},%S03Oqw|eQ og$r\'ɨf=k}ZC\'P*PliۏVSYKU-vT/ͥWJ#Tl{2' . "\0" . 'q=#柕1^nRuơZPYvF; jQ:OĚOs#+| eq&<ۥ_jXqqu - O@lD+1|)r[)eTr@8R|oY Dr"K?Fg' . "\0" . '/bWZiI$_Ԭ“Oc5@`/W7eLڢC@5aZ.9vV0L_Sʞ9hRZ@C&4WfUsXnE1j}*EosM6Z3ӛ|bڢH3b ,{SbBv̯U?Dh_u) %3+`Gub5R;R -q-IXG22f2l yN9HĪSՖ% \'$d\\ ^롩n3v<Qi lrI5\\<F<@C/9! -6!dq%z ~YfC2$`xUjs[V8+&fYfIYj%ԮӖ 2do(o7Y>IG`OR~hчd0M}%r&bBď4KƗ0/!Б&Rи -3Fi1i IG4nY|e>@vO1Y 5e;UB7%"֢FM4`:`f]gE{Qp\\2bDa -`RTGw0kjˣSFc3vhǠ,/jx٧@<Ś8JhCn3DZ%X/!NKQ7=@Qt-SHN !UVH,o}"Z4fhӗCay-P5yaĒBk%SXf.#+q4;97f -wf~EدUA4D@UuUP#;ѣGլ`A tx?ӶhhPvZqH# `8AH˵+Gp[Dv3 -Zbmq8`^}Ē=Gݶ$e`@٫("$uN`Ke_- /lWy46l(&WN?5#T{b_i]VS{ c ]\\锢X;,WY)ח\'ᢡ 5Uc_iQlV%힝5(V7nܚ[VUv>a3T*L A#!EC@5PR P` )kQYaL;4R ϣ9Qڧf IN6eh4lBA-FɲDJ-h0AZ>?_ t0Ns Kl醊\\ ]A+fuDgg7\'oj}' . "\0" . 'ڰ{zr~xp~A qӮuCm8y{x~rj?=3 O] 䞝SM㗷L6mn%G\\&^21v$:8nA`11i| \\<4BMI[,b&.e[<\\7B[-U>L<=--; [ -0N(LzLnX\\@=hkoa6ˢ\\2 ÇQ?àBec;K$ZdLZЋ/T)I ෥0636yϴ϶pf]nKNX/Png5Ci>B 3ih!y|VQT,fMjr8DW% -UR}p!#V7f^}Ge$Eކ)ҧZ/Kإd$<1LE|5dy0fV$)}oXh!%\'h35AiU֪U:΂&TAҔRPJQc:".y,DDaxR2/GNRgҁڔWFGbẉf r %uAtvb:d#>U2^;IkAdN|ƓB;c^4*ЅlGAFwLYbeOhbe]fnJerjH}w5FKU%CFeV>FCXM~0 H8UVVxy 5 yڙx :@XХ^Pha/_᥽鮳4gJ/3F05/[CԲoɃ\'y.ҧ/W`s"(܇j. -wwms]dq\'yfUV xۢG AV#(?Y -| / H( -W&ȐG]Z]@SA_(.F~q$42Q^(]FCFg%PTCUNR,#+\',`I_iQ&QV鴝jo~Y-mw j0- r -xJWDȶ8=' . "\0" . ':)YP "MofZe%5Hd\\Y^eS[WXҪ,}e}PR )KGܖYYhd &8:Ad+uIocw%S+OYxdFw΁hT䳥HcxfyYſdM!2kH),ޖ(P cEVnPBE4_ \\=rXY:idU2' . "\0" . 'p' . "\0" . 'jIC0~VVˉk -ʂ:ujQ3x&c!)屾{>(ǨGKJQ)u${' . "\0" . 'ᚮ) *"S¥' . "\0" . 'Hp=oga-(:m#go  =s^+z3 1L)uàp\':{$YI?P' . "\0" . '=L[҆L|::K.[ V L\'fBGmޮLSRN U;[pIɠeˈh+;BEP H+,DH -jt+0T* p_sh+ r("RQlG&7ǩR,Yʎzt틆BHӦR[iћqf6OݣP$@Fe x\\W -DI$ЄCGC죗b7\' -2gK:>JS?ɯ޼ tI[^;_z 5qSrtzH򑝝__|wo^w#~C=x?VG<M=?H00(+l\\+Ŝc@hV44bY0V܋xZڹ.xwzgvOI |f5^GՇZJ8X^G`H l.ư0 -Ix^3YH÷8 -W]! eF}{\'S$M F/ug˓}&A5x|5 \\Jʫ()Z/ZŇF$CLDoy#]a`+ DQx4sJю2xV:!]WڵzQ(LL~ -1GK!hm-Z-)_BW quU>Ͱ zdl#%[U -)QWCPZe$kj*\'l;V/l -R@Ll"5 }5Ty$yU>ռAqh+Ar!* rǺz޲' . "\0" . ' wWAa@5i({d Zt[@ -P2J2Ro|쐋0WVkw~"L' . "\0" . 'ɦÂZZVv*4E(- PM!0)J=**;8mLҮ(PDjF"JLK)4X.źŢT' . "\0" . '=9 8?;>x _͘V ܮ5:v%2;47XLZ*CF< 2>[Qݝ=;|<8!}3\'I:L\'eoxf͝*/8͒Gόbe6V,,|K≚Fx20LL|Sb? -1GB% !ls ƛx8 eoqh1ύSEu{k~dta]M.b`Cت-Rx5r2ZF5^hT -~ʁ\'%%iNz9 -U4.xgj%Xyϐ5+@uJ/wyi%|vY8CYQFRbmf%D ɫ5X{1F#,S8 o,).S0&Cd{F07 ʼgVRyV\\T2eK8RzZWB_q]|emJwq|2 ϼNc*xC)1->hX\' 2 ow>1[' . "\0" . ' Z+ʰB5=)x " 39*A +DWQ׍>&|)7]+1.+\'=ydN<:;\\*8呟+q3vıZ+WT(z|Tgb.t_9FTD48FE#]1:$h-/ۊ4ycqG$r߭w4' . "\0" . 'e 8CU҉%maTdDePmDk蟕Z;WNr1+, o)*5#x:vEއEpihKkP{j%YXIJbeums-V}%EɨC~Y=K׶B9EWş!«H!d[ٍ2֍>aBp}9N 4n2tqV%PK47ɱǚ 2]C:ωo$ 1ҢL1io[6~Rd!d}U19w$m0ک JWt^]7ѻ"G8dG>ңxQ0Mu +՗oO믩ޜJs/M>WxЈR~]bNK/ \\.gbx^2hRJAI6 Ld' . "\0" . 's0z({wr~xf glX&aIR @䓼R[THJv5>0- !`< 5˲ǎ*}勯~=WHYɰ#=yFC[4Pj/騧oѐTwf *vXԖ&9`:cA -sTs9z4B-fq6R"twQ.ֳ2p' . "\0" . 'ꮴ~JpE-bq_l <Ȥ7k' . "\0" . '/{!YA{0o>Q%ߦM}y&h4Si$e0Hn`߁z N*q`bnI/`y|PU#An2f.t)WxYH)mZ;]!Z\\KLOY&qwBj -6{OsӂQ!s2ADt}\'\'͆LHԲt3ܢ?xJv?,@nSdU7nt6p(WjLF{ -4ض62#XM/k趟l5Ŕ#-)issaKEiCwn;Ou:*\'O"S@^ӭ\'Iր^PjolwM1Po!s2`fBb\'LOٻ똓q9guN/Vm=tr\'gkδS9zt˳ē\'OiI$Ms:ע_*>Ԓ@-aZ/ew]va0ZLPd8z)t[[.ч؈r o\'4L7,tI6yxwOVY-ӔeaaX #7P6h3nn|#{v>]}(%TyZq ŞSLwJ/YIoc-C̒]Yf;_ m0kYyҖNpD8ٔ m 3D V9N#4&NL6Jt[e8DTe:!t-d|Jƚ.p {Tp"`~JTu|./:rx0&.vnrJqN#T0Z_\'OLET<098y2ub.n' . "\0" . 'h} ܉ 6 M_b9Wߤ =Xt Gb' . "\0" . ' -W, j\\n5(0\\۱&QMG]i)]TZ+Z=֫esZ[н iI&pd6jN"J[*G}MכQ2`D74Aі(MWb$DUb^9bmJ9[9\\1yUW.\\˝ABL``0t0IJ("CfiH;HDgԗ -iI:mS? EMp\\(JhY1B(ê2Ѓ]Y> KL$%n pՎɚmei*L *MM-\\Y-+V*[im|x c*2ЫJV -sx(Y52c;WA^P Vh GhU0S[ᵌ+<[)gYZG7j*7i>=]>QM|=gC 80= QӡcҬh8-&౑4(z_@Ln7`MjupLf3P+L G]N1G2vy~|u!P>f o5ߊFﱫG1޺2uyy9GkKwcjތSPDܔ(Ccú̡/hni)ƶ<~Oe.G0yUQtWN C"3A3Lc\'=/ X-n΋g-+T`)jYS6[;9c"~!F͎ U*|Cr>ekgꭗ -K[|[QU?A4?pfTC7L_F c M h\'Idvr7mCh^&S\'? & nP\\.8EAI&}jTCc\'&)/>z+F}ˣ@ --ıZ&t"վB>Z$%@u#o- z[3ϻW_"fߞ/~u6G Ί4lT|SbBeAoD˓S -rTww3\\ː"Jp()yE^5^R.)O]% yDk/mh8nBRS;S6j`Z @AUe}!nA \\#E䎳@X: -hkz6 _~d2.BWZߌtEu ϪpQM&:"ZihDԛle-@홢 K|}mJOyVؠΥJ-{+,Cc -&O@F' . "\0" . ' e 19)Nlf vЈ 6I4h6I6W98k_u>%"0q$,G.գl 2DZvBz6q!m1OO/>\\fPvAC,e<ϥ̦+VVɩn\\OP#+/>/' . "\0" . ';r"{|Pͻ㸩-f‡u-q^7H[ť w%.BFjӫs [U\'tQ?!oTl<0 zd[eC2VдeU-HFmXAMbJSիٛW , ֫㋿$+oU5{evߣ*`je Z' . "\0" . ']b+:t;jw"XHdt74.%Vdc2hr\';!...{.iޏy(({"]pwڐ17:`!@.ctD#D`d%v9?Xb/-2Q,#$$3E1o8$' . "\0" . ';f$S75+bcX8I&T]сԞ̅"%KՆ1@VaJ1`*T3$۵b)$tL2ead$ʯH)I~]oIm:jA"Qh:7Ҭ,uc|AϔGyٯk6uZ53%KR^fIf u[r,ߗ' . "\0" . '}nɛC o/&;hcqgIYl?]R[ivh ݶu5t־N=$7|EH9`dT)s9N$}iG9qm Y' . "\0" . 'Q655 oܥ x2f\'.L:w.jDzf[c -=YBS-מa.Qj馀?\'lPV$\'pɼNFXȮׇTO}uSk]$["yN>HEꦃ[["N">+~H~TKq`*ETm!C iqD#b7Uk㔖Mme@+z9(98 -M˚}5>cՆJ՟ j{eNuIz[q"˭fYԟd -wZD_v?7aşbrvI-ڨ ``5n(C;[,**i7loE4COTFǪ/,H9 tлZy[N15?mϙy ̾pS~c"=n;[pΆl}Zj@)(.B&)$ [dn7z P=!` J[6)?L6F9X1Z( 0z  O$m3۠BmÈ`P{B 4E)vPJ, -@9.W5pَ V7 czDRGt捷*kF.Cn, ,qSS\'sЗO~ -U/j2$ -' . "\0" . 'F$X6CEk9nUՄ@>PZc@|ujV.~Kzl$P -*v~1=&HٔMrZ:Gl5z?SʪŪ{4AVB7_;{ScLD~R&l5ѹ\'_fB* ?.=Vi\'Ȗa~ -a^^n^$d_NTWD鞱8p#  8Ǟ5qXԢZBC:B{UQ_Bl-[e k0)QSb!Lil;5pAm0z `c1=t*CCEL=NdOJ5KIOBo8+47!T3~-|0H,OpT98' . "\0" . 'E>J.0b60,H>TaxY)l!dh-re!QDve>(s8]Sbutex\'l |x"(;kK&b8&qӾڼ!CL' . "\0" . 'k#2E R Dr1{%O 0"|GGU ݋;֋R̝n)QNj(-6? - txh%^Ԛ,u{RT*W q"jW>N~AE\'}\\[k_Ɨ%}l?G v1U;\\s,8r Mжʤʞ? JTgTAM31yEQspFQD%_kGrR -h4YW5[F 4xfꦖ }{GJ{u@qy' . "\0" . 'jCΆmizֆ9YoltEÖX[rr"@olzJ{9 ^J7G?xx:{Bh' . "\0" . 'Zy6z/z -ƹIĀKO' . "\0" . 'T7/W;]}x]wt➻{!1pqiu -<' . "\0" . 'T14KC1>|^Z7Jֽ,#P%!wPst_%yFRU2+&JIl桐DUCRmZ.% T"6tнF%Iֆ5t+K)B (B@2BkMMtE\'uT_[_"6^-!Eʧ1G/- -!n676+[{K{P*2d}х(eUx =o{' . "\0" . '3AeHoZ7N v)!%|("0+0ҳ -ͻO1w eAϚ$2 㵀MM69}O)!Y*-wyZVWMg+' . "\0" . 'YCJlIRй G@ A1*$wS`hּ S1t@?X%`!;`o3Ծ1HH(anP܅ڥȣ>>I!y딳o4k Ct' . "\0" . 'or\\ٞ3>rec)0B,PxIIy51Re$4cr| $"k TJ,޺zmBKϪWQg --2U4+yb&VJ --y:]gZzccuNR&1Y?Owk3E(9a[ZȜ8ޖQc8Ȍ\'/{jy2vեeLG/LꇥV&9vBlhK<RŏGRWjX78"pAHEjUBD -#< -&v@Q]̓@Ŕ几kjigmK 6r9Gv]JDW_9]_s#\\C"w*ZH\\˽_zyvwYwp=Ypy}W]~tcE,-H0ۅfY ;>8_>]ݷoe:8y0z ӳʬ$[50 n4-' . "\0" . ' tŢvrrԪ6i/L!~ ?e`ؽ941=\'B,AˆǹŠr~ ' . "\0" . 'Tp8LB:+8"QbWXi1x`U - #\\:^>Y($JQf,OGԏ=bs`lz Ÿ=$tԅ{TV=U[F"#O U pWYnzkh*8HvAyMƼ_X8+l0|%~pNH~HFo;\'\\zuz̟!w|?w|=ws`[۵ߘ]P\'Lh]="]T|[.2_}DoؓF -s̊ʗKvخ"1.*L2?]E]IT -HZv7Q9s 6VbU4{eT%ESא/e|偲3Q;i|6zP*̃zSToրA5N%@B:NoGxbhS-}N&gj*{]URhJG/Dg4tō@nߊI8PgCFu3˴ 5DwQ-ֿ1җ(dH/oz"{X׷=F)oU=%/8]{XֿXvsdBMjq!qWf;D]lyN؃-,$Fj[IkQ51X.1DX;O QraWwʿl=)n t܏Mh{fx(6K/) \'>1SoxDK뜻=G5r;n%3iofTMTVU[?빠c+!b7[ ҂}l%|hgBuwL[`g6' . "\0" . '^gx}$O]_獆:RvG~Cܟ~l 8$MF_bYTx~2o۱+9X ljN̤d1eT?̒5N>$^ˤ]q"`ḍ>@6/]e+0܍oB*&X -KW.,,y/6ޥ(^DNwzeU*/P,uAWǘ6oQWҮDsDNYr!a6 -Eѿ>*\\Jg' . "\0" . 'fb2#ڿovQ:K)w9,T\'ZLZF*ŧTf b8IiJODI&ʥ So;$Ivᢉz96!0mLGK,S[Qdz>8M/' . "\0" . '0UmtTnf GEE*' . "\0" . ';`S^r&J_"PZeӕ@  nɂ(Ljk˰˲F35 ="&2<\\Nz6hZL&̀L]CuHp%}ĘUB]d+uIocw%SBIn#U -%.ldp7k<| WMu$D [DZ}njԾjU^˿ͳQVr}؟{ikCf:{*$Q63HUW0g,ʝgq]Onb* Aw25Ch/ypUn(4 taSFd~Y݋:xRX mC}s|C0٠c2}1?tH<ˡU~|Ĩ@GɠEb{EnٙEVE `ly˩K`H]{NZ=!1\'Hx ק<ڊ%y~fQKF9$玠L' . "\0" . '^HX -(DK(D=kH -#a-\\bJs|Io/]:KWgoaP:ik:m{> -On]J 7,GLZԥ9}VmʦtKdeB)cL 04X&ʺ\'WC v5k ^펙=;' . "\0" . ')ʮ yI?JՊQdW֔բK*uHId.ǖz,+AuВq}+JU?/_E?WeˏdݓӿwC=]Zu3?k=x3X$%#j]m_ K#jl /GJ7ZWKal9aC7wVj*ݷ۶vknݧ9XjNC7ɠ@ s@U)- |+qpאVtcJZtb^#G]ŏ،uvGZ\\[4 -rSA~N}P.E \'i^`*% AQyrkcz &\\cRE/}%JNQ+B0CeMnokRX|LĐEL U;b^3Kc -U 9-֛p' . "\0" . '&rz)[[ㇿ{>' . "\0" . 'O Ne RJBz=~X|"qBmh.QF2 #z(rQ[-{>-C^?V~N6 cmAd' . "\0" . '4HS0z-Z[uZdž+8, NFʞ CC[ T' . "\0" . 'l`.~BUAݳ-Q{-78X@K˃[iC5̄W%4;(ݥbPu4dKJtX!F -)>NHe(V¶aިʶp1VTڇRXR "ً,p}oR7Y.vJ{&Rr M CoVɊi' . "\0" . 'x^~U/VEtb(88މ~WTYRL&qU=\\Q+и(8w&Y}&w7y۽\\].}͹{8[ -B -0j&f•,_avD1i%gGGۘ+d-n\\N?tn0>+ěQAAk/n%?|Yi 6t])}qQ{xzB?v߹ >U&@1 -\\R -}' . "\0" . ',' . "\0" . ' -S9 wʀ_̱s2!ԓ772wOi^hǏ' . "\0" . '𩆨ח A£r\'$iT0n|<){1L\'I/t"5\\kwQ) )\\KIxjqWˡ-ςm摃Y`Wx?;' . "\0" . ';V(&`(%(6\'w/6\'$- (>9U7PxY - Xo[\\FJp>TG>M܀!_iCvfj7HxXsW60P! \'"OW,/ЮDP ĜigׄepFg1IfruS%Zo P\\")DU 4,ɖ -S\'1S*,TZ Fm\'`?JUuY^ fٌfش$bHd5}U Ϻ*HA`moOQ֨2Oi-8xdV\\Mk]}݋(\'t6ĪUBj:!^+i)kwL42' . "\0" . '| γǀa6 -x::n t,{dtYXamg\'y/0}K{/+(|HrB;wBF,3t{#u[dE\'eqG" 2f2={ȲySnDuR ?:PKq}H*A#yZR\' @˩:_  ثstT -0L.Q9;Yq^^ 9ʓT -݈m`@| -0̓eDx&&Q&+mrdTL) ñED];NPļcH4ǣHXz_3Ę,I .X' . "\0" . 'ѕSk/}&:C:;ͤ!KE)7Dyc4J`Otu/]vk@rfuׇ\\"r _zIŔDMWGKDʂ}_ KV@z .\'ZWu83Z>,-QЦ##P,DJi!uJe~9\\.?\\}^( 4|OnP.Kjhc)SFQ%vX!=/]=%Ɔh9y}Jqw=M_>_t 3oA3%tL|Rpz}=ڸH4ieqh%"- wZ$ub͙q#3t4g*Dc, &0 GW@GRFydi??)*TWC.{DTW1m1ZX@I ѧf26<t4oA|nX,̈́q -RAN6퀤4ӲW/-:ïB ݨe3Db -/Hz,f #/Z^H@&/ϊ Ch~ S;)hWX+A`+ǜW@ѣ&AW%g\'̌GuS˫<*| -]B@w#' . "\0" . 'D=eyv,;WX˄\\μ,Eį}T(;u>׸W/Ju؁a~fYN̉17ӳ' . "\0" . 'auv)Z"t;bKJ]{pI ->,!Q?44j~̅PL䋙gNyv#WTƶ&FZL<)\\M -A?`V\\' . "\0" . 'QB-}F -L}V>&d/Z1T#Au>T4)wZ@/:$7p/:,)~_6jއ$ \'Kסܡ`1&e_' . "\0" . '݀s.s8^<}-eeAG\'y0H(2z>W&n!O(KAÎ*S񵗎pӒhER\'k?:% c5_v!G2Nw\'>a-{ M3r=-VruFWϰveYwf`TB6%f5)d#T_њa!n\'ȶ1IoR&+L 숡r~M#9J&_7Ea:FYc$gI|A[fִ-$](伹wX4AظetB"' . "\0" . 'oTNA\'7`pfs-j+Oo0wB_}3̙ѻZ:s' . "\0" . 'Gfu}MKP;\\tgo/3w.mG~}~&hK$~{uSk׮p`|T7cY!N_g>ڎO7?H-1꜌W m<3EJGu]GGFr 5bY ANH1ֹ.k`ϋtu*QGRgJ=:۾"Pz0UC&D>5.iA3DOu[Ʈe]T=wJJJG7BUzuc4DHHg0' . "\0" . '3;DUU6zU@ҫOj+_tjT5 -=(5-\\I;p[qn2' . "\0" . '^tW~ez,S»V6#Y{atv7!u-uKRuTriojBQ|y1&`ngT1G 6p=O<^;??:y#.z^+j([<+/~ h\'ޝBEtXIZ ĕzL"A ~b*8' . "\0" . ' ]:c{/Wd #o 9=k -d,V]hjĠ8MaSReA}{h D9Ԥ~Iu!ÂUے4""Yqcax)-nt}[ٳd7X_+` HӤ3)oalY-`o/`{DU -ordl{!y DqlĴ"_[u}XI߾txfM_ٌG , tOfxfOٳ#Wb , \'}~&It偾b+W&@MBo[cTXMF"f,v!!Rm_Tx} zH un ʼ}vs=zޝ^==V}9ZN$0RݵL2>(pp]M@b+O?*pyЮetk~}3tB퀁 Pg EtM" {eC͚Сjݴz%AD:ʐժ^ ؋lӟz!9Rdt-t>HO~-2Mn22|qsބ&;\\"з\'1A,a]x@r)-/^?J/8g*T3Ͱt#ZR{+ -Ǫ;Mms@}KQX\'/lˎՂt ӭVP-oI$qי$[o5dZup!ӘJ! %;)ﶻ ay:uު6SWF#!Sk`h= ;^:KUyœuܐ_Z[4^_o|)&f@[@B(/:8WR藼KwtU5D Ђ1 ʢ#]HԃX`_fr-|yUt|(9d5l(*o݆F -&#XvQ7X ~sGpߦmõ, -TBYKs>isԫGG/dQX<i{z]Mi"~yr5,6 ~h(.- ԔV/]UZaRCⓂ"bvkr(E|a:C-ą-P"[n\\޶iyD\\m .ؑgMP' . "\0" . '*P듗ß٠Y7lZ 2CAE/頵bwWU,WK8l%c䐊HXT@<E&D dY5m+ʀÊR$: -b3YQHҸGԐi3Nv8~C0DSKvY7feNQ:a{#@EIBU38xF6`(%Ib6~a]!Zэ4?Q\\օ\\:+&)@rӈ>x 0Bqš1Q7R 8\'qRUX(-%"76Z!!8k]m]_RpRK_\'՝ Q֒iS5Ӻ?Ը*Jfuu:2+qeU>due5\'' . "\0" . 'K~{2s):ZTkn.#%>;NU75(DsTkV?#B6kTFr uZ\\dW\\Nϓl<`g}]*w|vCKUi$>tw*H:ÇG5];ɮբt2֎"r!zQiM8 Fjn(vnSZS;KC3.͋l6j7z)j+i!KGZ@ey&%j} BvVP]yzr=\'W) s!LON`% oAT{"HJ\'1F U[A}2Zlԫ63b̄@A߁q\'gGAI6C"Տhg0' . "\0" . 'vd"5<4@c!XoC 1F*Ѩ~T KvY hJ.B#Nx@{eiЗؒV j6G{FP@C|&l{K5o+"BYeb{} -ˈ)B\\ -o#aY>fz{!ޫF2sya_s* -~z}j2b9YI~<<_ Z.8VSTsƎ!*,' . "\0" . '-tBd0p6 ;TTQs#xU.{]g%i:yc& -0YW0-P;lKfKZ85f#X=XՋK6h)lJ $`RO!Xfk%0H ]1Z(S;zV=uFB:kE F T.n= &V+[\'ºm4DBDxIo#p/ez%2ݺpuqC/ yYCZJؕ|Z5z3U7-2Y4C)ˎZ֟>`p>zSF6;qc-&6b]ix *ժѩe\\t !+E.-tyeq*x޴t Rz(TQyFI?v}Jƃ,鲝q塿6"ҐWKS3j ' . "\0" . '8JKwi"ݞNR+VԚSŪpH|ɇkEz%*VN}W%(|>tQA\'1#@oєN ^l`51CD#ǾFS֑? . ӡ(UDlw+JR}\\kyl^t])pzXh|V-(mm~W]]n7d%TCl勺"ݧf %?7jvRYܬ?>RN#&2\'Ss2cD] plVsn t@8\\1vpOo(lg]&<\\GdTJ!k;bM{vc3N2"6O;xg%ԕa۴?1|~$Ɏjw5]MYeu}\\)np{hnEkOvYv -VRjK>e KQ[q1|#I?- 7;= 8уpd4 P0jt4?(~7(?vJ e,2E"4F<@P?ͣ7m-ҼOhgn - -}@X,ab5iohYBohN84|8[9\' I7WE}4b] >0ہ;z:ɦ 1WմI1h7y3O' . "\0" . '% h`; eE4@خ?6 []s{Xg=8ehi>\\ưd6:}\\|~q8ؙNz۵g+_Bɸmv׏/E ًuѲ3l$֜[ѓS!@Xbյv=\\4oDb.}تkum+TOWwTGٻVWDg -@ǰNFa$sӡSq4G8MdY/oʔ~;HGص|;ZqkDkߕck0v;B5]<èP9C=I!zh%|=+gGg-\\zZ,.qݤIsH"^HlwjghuWZ+ktfu{^ -+UE_zt;B)$ZN܊+x,@9 yM",Y`l`kThA9՗ҦIICsx18;|Ϛ"rjn' . "\0" . '`fbKd!"8JZ}V¬aY#XC6 ~^g/7^X.䱅fK&lHMOೣt *4ϋK`y%[(v!TQFHK &j܃gja\\ʎ9kh6bp=vM;er -EIA3M\'7m g C`Gb84nfOUg⭠ky -[({AN[o@ǣ~uy,Y jmᩨlZTo#K k7\\};WyyhtQKN JS-"dɸHF[;VX^Qxg,sѝz^.Z| -a=ӖE_~MnO\\ʆ.KwR*n>K!WCm9ϒp -%$gN7' . "\0" . 'l \\1C@K&}l`$餼0lZ[s\'7p-Olvđ*-Q XiܧL&y%Ըt+W$shoE:wh[۶VfYfi+rܷןn<ݪIFП^ -˖ -zlzV mmgTV[;V36YɈ null, + 'modifiers' => array(), + 'callee' => $callee, + 'caller' => $caller, + 'trace' => $miniTrace, + ); + + if ($call) { + $ret['params'] = $call['parameters']; + $ret['modifiers'] = $call['modifiers']; + } + + return $ret; + } + + /** + * Dumps a backtrace. + * + * Functionally equivalent to Kint::dump(1) or Kint::dump(debug_backtrace(true)) + * + * @return int|string + */ + public static function trace() + { + if (!self::$enabled_mode) { + return 0; + } + + Utils::normalizeAliases(self::$aliases); + + $args = \func_get_args(); + + $call_info = self::getCallInfo(self::$aliases, \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), \count($args)); + + $statics = self::getStatics(); + + if (\in_array('~', $call_info['modifiers'], true)) { + $statics['enabled_mode'] = self::MODE_TEXT; + } + + $kintstance = self::createFromStatics($statics); + if (!$kintstance) { + // Should never happen + return 0; // @codeCoverageIgnore + } + + if (\in_array('-', $call_info['modifiers'], true)) { + while (\ob_get_level()) { + \ob_end_clean(); + } + } + + $kintstance->setStatesFromStatics($statics); + $kintstance->setStatesFromCallInfo($call_info); + + $trimmed_trace = array(); + $trace = \debug_backtrace(true); + + foreach ($trace as $frame) { + if (Utils::traceFrameIsListed($frame, self::$aliases)) { + $trimmed_trace = array(); + } + + $trimmed_trace[] = $frame; + } + + $output = $kintstance->dumpAll( + array($trimmed_trace), + array(BasicObject::blank('Kint\\Kint::trace()', 'debug_backtrace(true)')) + ); + + if (self::$return || \in_array('@', $call_info['modifiers'], true)) { + return $output; + } + + echo $output; + + if (\in_array('-', $call_info['modifiers'], true)) { + \flush(); // @codeCoverageIgnore + } + + return 0; + } + + /** + * Dumps some data. + * + * Functionally equivalent to Kint::dump(1) or Kint::dump(debug_backtrace(true)) + * + * @return int|string + */ + public static function dump() + { + if (!self::$enabled_mode) { + return 0; + } + + Utils::normalizeAliases(self::$aliases); + + $args = \func_get_args(); + + $call_info = self::getCallInfo(self::$aliases, \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), \count($args)); + + $statics = self::getStatics(); + + if (\in_array('~', $call_info['modifiers'], true)) { + $statics['enabled_mode'] = self::MODE_TEXT; + } + + $kintstance = self::createFromStatics($statics); + if (!$kintstance) { + // Should never happen + return 0; // @codeCoverageIgnore + } + + if (\in_array('-', $call_info['modifiers'], true)) { + while (\ob_get_level()) { + \ob_end_clean(); + } + } + + $kintstance->setStatesFromStatics($statics); + $kintstance->setStatesFromCallInfo($call_info); + + // If the call is Kint::dump(1) then dump a backtrace instead + if ($args === array(1) && (!isset($call_info['params'][0]['name']) || '1' === $call_info['params'][0]['name'])) { + $args = \debug_backtrace(true); + $trace = array(); + + foreach ($args as $index => $frame) { + if (Utils::traceFrameIsListed($frame, self::$aliases)) { + $trace = array(); + } + + $trace[] = $frame; + } + + if (isset($call_info['callee']['function'])) { + $tracename = $call_info['callee']['function'].'(1)'; + if (isset($call_info['callee']['class'], $call_info['callee']['type'])) { + $tracename = $call_info['callee']['class'].$call_info['callee']['type'].$tracename; + } + } else { + $tracename = 'Kint\\Kint::dump(1)'; + } + + $tracebase = BasicObject::blank($tracename, 'debug_backtrace(true)'); + + $output = $kintstance->dumpAll(array($trace), array($tracebase)); + } else { + $bases = self::getBasesFromParamInfo( + isset($call_info['params']) ? $call_info['params'] : array(), + \count($args) + ); + $output = $kintstance->dumpAll($args, $bases); + } + + if (self::$return || \in_array('@', $call_info['modifiers'], true)) { + return $output; + } + + echo $output; + + if (\in_array('-', $call_info['modifiers'], true)) { + \flush(); // @codeCoverageIgnore + } + + return 0; + } + + /** + * generic path display callback, can be configured in app_root_dirs; purpose is + * to show relevant path info and hide as much of the path as possible. + * + * @param string $file + * + * @return string + */ + public static function shortenPath($file) + { + $file = \array_values(\array_filter(\explode('/', \str_replace('\\', '/', $file)), 'strlen')); + + $longest_match = 0; + $match = '/'; + + foreach (self::$app_root_dirs as $path => $alias) { + if (empty($path)) { + continue; + } + + $path = \array_values(\array_filter(\explode('/', \str_replace('\\', '/', $path)), 'strlen')); + + if (\array_slice($file, 0, \count($path)) === $path && \count($path) > $longest_match) { + $longest_match = \count($path); + $match = $alias; + } + } + + if ($longest_match) { + $file = \array_merge(array($match), \array_slice($file, $longest_match)); + + return \implode('/', $file); + } + + // fallback to find common path with Kint dir + $kint = \array_values(\array_filter(\explode('/', \str_replace('\\', '/', KINT_DIR)), 'strlen')); + + foreach ($file as $i => $part) { + if (!isset($kint[$i]) || $kint[$i] !== $part) { + return ($i ? '.../' : '/').\implode('/', \array_slice($file, $i)); + } + } + + return '/'.\implode('/', $file); + } + + public static function getIdeLink($file, $line) + { + return \str_replace(array('%f', '%l'), array($file, $line), self::$file_link_format); + } + + /** + * Returns specific function call info from a stack trace frame, or null if no match could be found. + * + * @param array $frame The stack trace frame in question + * @param int $argc The amount of arguments received + * + * @return null|array{parameters:array, modifiers:array} params and modifiers, or null if a specific call could not be determined + */ + protected static function getSingleCall(array $frame, $argc) + { + if (!isset($frame['file'], $frame['line'], $frame['function']) || !\is_readable($frame['file'])) { + return null; + } + + if (empty($frame['class'])) { + $callfunc = $frame['function']; + } else { + $callfunc = array($frame['class'], $frame['function']); + } + + $calls = CallFinder::getFunctionCalls( + \file_get_contents($frame['file']), + $frame['line'], + $callfunc + ); + + $return = null; + + foreach ($calls as $call) { + $is_unpack = false; + + // Handle argument unpacking as a last resort + if (KINT_PHP56) { + foreach ($call['parameters'] as $i => &$param) { + if (0 === \strpos($param['name'], '...')) { + if ($i < $argc && $i === \count($call['parameters']) - 1) { + for ($j = 1; $j + $i < $argc; ++$j) { + $call['parameters'][] = array( + 'name' => 'array_values('.\substr($param['name'], 3).')['.$j.']', + 'path' => 'array_values('.\substr($param['path'], 3).')['.$j.']', + 'expression' => false, + ); + } + + $param['name'] = 'reset('.\substr($param['name'], 3).')'; + $param['path'] = 'reset('.\substr($param['path'], 3).')'; + $param['expression'] = false; + } else { + $call['parameters'] = \array_slice($call['parameters'], 0, $i); + } + + $is_unpack = true; + break; + } + + if ($i >= $argc) { + continue 2; + } + } + } + + if ($is_unpack || \count($call['parameters']) === $argc) { + if (null === $return) { + $return = $call; + } else { + // If we have multiple calls on the same line with the same amount of arguments, + // we can't be sure which it is so just return null and let them figure it out + return null; + } + } + } + + return $return; + } +} diff --git a/system/ThirdParty/Kint/resources/compiled/aante-light.css b/system/ThirdParty/Kint/resources/compiled/aante-light.css new file mode 100644 index 000000000000..2de17accf9a9 --- /dev/null +++ b/system/ThirdParty/Kint/resources/compiled/aante-light.css @@ -0,0 +1 @@ +.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:rgba(255,255,255,0.9)}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:none}.kint-rich.kint-folder.kint-show{display:block}.kint-rich.kint-folder dd.kint-folder{max-height:calc(100vh - 100px);padding-right:8px;overflow-y:scroll}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#aaa;color:#1d1e1e}.kint-rich .kint-focused{box-shadow:0 0 3px 2px red}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#1d1e1e;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:8px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#f8f8f8;border:1px solid #d7d7d7;color:#1d1e1e;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:4px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#aaa}.kint-rich>dl dl{padding:0 0 0 12px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMCAxNTAiPjxwYXRoIGQ9Ik02IDdoMThsLTkgMTV6bTAgMzBoMThsLTkgMTV6bTAgNDVoMThsLTktMTV6bTAgMzBoMThsLTktMTV6bTAgMTJsMTggMThtLTE4IDBsMTgtMTgiIGZpbGw9IiM1NTUiLz48cGF0aCBkPSJNNiAxMjZsMTggMThtLTE4IDBsMTgtMTgiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlPSIjNTU1Ii8+PC9zdmc+") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #d7d7d7}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#06f;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:red}.kint-rich dfn{font-style:normal;font-family:monospace;color:#1d1e1e}.kint-rich pre{color:#1d1e1e;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #d7d7d7;background:#f8f8f8;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(29,30,30,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#f8f8f8;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#1d1e1e;background:#f8f8f8}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #d7d7d7;border-top-width:0;border-bottom-width:0;padding:4px;float:right !important;margin:-4px 0;color:#1d1e1e;background:#f8f8f8;height:24px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#f8f8f8;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#f8f8f8}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#f8f8f8;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#1d1e1e}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#1d1e1e;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#1d1e1e;border-bottom:1px dotted #1d1e1e}.kint-rich ul{list-style:none;padding-left:12px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #d7d7d7}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 12px;padding-left:0;background:#f8f8f8;border:1px solid #d7d7d7;border-top:0}.kint-rich ul.kint-tabs>li{background:#f8f8f8;border:1px solid #d7d7d7;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#aaa;color:red}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#f8f8f8;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:20px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul:not(.kint-tabs)>li:not(:first-child){display:none}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#aaa;color:red}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #d7d7d7;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#aaa}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #d7d7d7;padding:2px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#f8f8f8;color:#1d1e1e}.kint-rich table td{background:#f8f8f8;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #aaa inset}.kint-rich table tr:hover var{color:red}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:4px;padding-bottom:4px;border-bottom:1px solid #f8f8f8}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #aaa;padding-right:8px;margin-right:8px}.kint-rich pre.kint-source>div.kint-highlight{background:#f8f8f8}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #aaa,0 1px #aaa,1px 0 #aaa,0 -1px #aaa;color:#f8f8f8;font-weight:bold}.kint-rich .kint-focused{box-shadow:0 0 3px 2px red}.kint-rich dt{font-weight:normal}.kint-rich dt.kint-parent{margin-top:4px}.kint-rich dl dl{margin-top:4px;padding-left:25px;border-left:none}.kint-rich>dl>dt{background:#f8f8f8}.kint-rich ul{margin:0;padding-left:0}.kint-rich ul:not(.kint-tabs)>li{border-left:0}.kint-rich ul.kint-tabs{background:#f8f8f8;border:1px solid #d7d7d7;border-width:0 1px 1px 1px;padding:4px 0 0 12px;margin-left:-1px;margin-top:-1px}.kint-rich ul.kint-tabs li,.kint-rich ul.kint-tabs li+li{margin:0 0 0 4px}.kint-rich ul.kint-tabs li{border-bottom-width:0;height:25px}.kint-rich ul.kint-tabs li:first-child{margin-left:0}.kint-rich ul.kint-tabs li.kint-active-tab{border-top:1px solid #d7d7d7;background:#fff;font-weight:bold;padding-top:0;border-bottom:1px solid #fff !important;margin-bottom:-1px}.kint-rich ul.kint-tabs li.kint-active-tab:hover{border-bottom:1px solid #fff}.kint-rich ul>li>pre{border:1px solid #d7d7d7}.kint-rich dt:hover+dd>ul{border-color:#aaa}.kint-rich pre{background:#fff;margin-top:4px;margin-left:25px}.kint-rich .kint-source{margin-left:-1px}.kint-rich .kint-source .kint-highlight{background:#cfc}.kint-rich .kint-parent.kint-show>.kint-search{border-bottom-width:1px}.kint-rich table td{background:#fff}.kint-rich table td>dl{padding:0;margin:0}.kint-rich table td>dl>dt.kint-parent{margin:0}.kint-rich table td:first-child,.kint-rich table td,.kint-rich table th{padding:2px 4px}.kint-rich table dd,.kint-rich table dt{background:#fff}.kint-rich table tr:hover>td{box-shadow:none;background:#cfc} diff --git a/system/ThirdParty/Kint/resources/compiled/microtime.js b/system/ThirdParty/Kint/resources/compiled/microtime.js new file mode 100644 index 000000000000..20e3445b2b05 --- /dev/null +++ b/system/ThirdParty/Kint/resources/compiled/microtime.js @@ -0,0 +1 @@ +void 0===window.kintMicrotimeInitialized&&(window.kintMicrotimeInitialized=1,window.addEventListener("load",function(){"use strict";var c={},i=Array.prototype.slice.call(document.querySelectorAll("[data-kint-microtime-group]"),0);i.forEach(function(i){if(i.querySelector(".kint-microtime-lap")){var t=i.getAttribute("data-kint-microtime-group"),e=parseFloat(i.querySelector(".kint-microtime-lap").innerHTML),r=parseFloat(i.querySelector(".kint-microtime-avg").innerHTML);void 0===c[t]&&(c[t]={}),(void 0===c[t].min||c[t].min>e)&&(c[t].min=e),(void 0===c[t].max||c[t].maxdl dl{padding:0 0 0 12px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMCAxNTAiPjxnIHN0cm9rZS13aWR0aD0iMiIgZmlsbD0iI0ZGRiI+PHBhdGggZD0iTTEgMWgyOHYyOEgxem01IDE0aDE4bS05IDlWNk0xIDYxaDI4djI4SDF6bTUgMTRoMTgiIHN0cm9rZT0iIzM3OSIvPjxwYXRoIGQ9Ik0xIDMxaDI4djI4SDF6bTUgMTRoMThtLTkgOVYzNk0xIDkxaDI4djI4SDF6bTUgMTRoMTgiIHN0cm9rZT0iIzVBMyIvPjxwYXRoIGQ9Ik0xIDEyMWgyOHYyOEgxem01IDVsMTggMThtLTE4IDBsMTgtMTgiIHN0cm9rZT0iI0NDQyIvPjwvZz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #b6cedb}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#0092db;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#5cb730}.kint-rich dfn{font-style:normal;font-family:monospace;color:#1d1e1e}.kint-rich pre{color:#1d1e1e;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #b6cedb;background:#e0eaef;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(29,30,30,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#e0eaef;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#1d1e1e;background:#e0eaef}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #b6cedb;border-top-width:0;border-bottom-width:0;padding:4px;float:right !important;margin:-4px 0;color:#1d1e1e;background:#c1d4df;height:24px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#d0d0d0;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#e8e8e8}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#c1d4df;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#1d1e1e}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#1d1e1e;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#1d1e1e;border-bottom:1px dotted #1d1e1e}.kint-rich ul{list-style:none;padding-left:12px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #b6cedb}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 12px;padding-left:0;background:#e0eaef;border:1px solid #b6cedb;border-top:0}.kint-rich ul.kint-tabs>li{background:#c1d4df;border:1px solid #b6cedb;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#0092db;color:#5cb730}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#e0eaef;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:20px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul:not(.kint-tabs)>li:not(:first-child){display:none}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#0092db;color:#5cb730}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #b6cedb;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#0092db}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #b6cedb;padding:2px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#c1d4df;color:#1d1e1e}.kint-rich table td{background:#e0eaef;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #0092db inset}.kint-rich table tr:hover var{color:#5cb730}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:4px;padding-bottom:4px;border-bottom:1px solid #c1d4df}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #0092db;padding-right:8px;margin-right:8px}.kint-rich pre.kint-source>div.kint-highlight{background:#c1d4df}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #0092db,0 1px #0092db,1px 0 #0092db,0 -1px #0092db;color:#e0eaef;font-weight:bold}.kint-rich>dl>dt{background:linear-gradient(to bottom, #e3ecf0 0, #c0d4df 100%)}.kint-rich ul.kint-tabs{background:linear-gradient(to bottom, #9dbed0 0px, #b2ccda 100%)}.kint-rich>dl:not(.kint-trace)>dd>ul.kint-tabs li{background:#e0eaef}.kint-rich>dl:not(.kint-trace)>dd>ul.kint-tabs li.kint-active-tab{background:#c1d4df}.kint-rich>dl.kint-trace>dt{background:linear-gradient(to bottom, #c0d4df 0px, #e3ecf0 100%)}.kint-rich .kint-source .kint-highlight{background:#f0eb96} diff --git a/system/ThirdParty/Kint/resources/compiled/plain.css b/system/ThirdParty/Kint/resources/compiled/plain.css new file mode 100644 index 000000000000..ba1eba0ae27f --- /dev/null +++ b/system/ThirdParty/Kint/resources/compiled/plain.css @@ -0,0 +1 @@ +.kint-plain{background:rgba(255,255,255,0.9);white-space:pre;display:block;font-family:monospace;color:#222}.kint-plain i{color:#d00;font-style:normal}.kint-plain u{color:#030;text-decoration:none;font-weight:bold}.kint-plain .kint-microtime-lap{font-weight:bold;text-shadow:1px 0 #fff, 0 1px #fff, -1px 0 #fff, 0 -1px #fff} diff --git a/system/ThirdParty/Kint/resources/compiled/plain.js b/system/ThirdParty/Kint/resources/compiled/plain.js new file mode 100644 index 000000000000..9791fc9f5cbe --- /dev/null +++ b/system/ThirdParty/Kint/resources/compiled/plain.js @@ -0,0 +1 @@ +void 0===window.kintPlain&&(window.kintPlain=function(){"use strict";var i={initLoad:function(){i.style=window.kintShared.dedupe("style.kint-plain-style",i.style),i.script=window.kintShared.dedupe("script.kint-plain-script",i.script)},style:null,script:null};return i}()),window.kintShared.runOnce(window.kintPlain.initLoad); diff --git a/system/ThirdParty/Kint/resources/compiled/rich.js b/system/ThirdParty/Kint/resources/compiled/rich.js new file mode 100644 index 000000000000..18fb072ead95 --- /dev/null +++ b/system/ThirdParty/Kint/resources/compiled/rich.js @@ -0,0 +1 @@ +void 0===window.kintRich&&(window.kintRich=function(){"use strict";var n={selectText:function(e){var t=window.getSelection(),a=document.createRange();a.selectNodeContents(e),t.removeAllRanges(),t.addRange(a)},each:function(e,t){Array.prototype.slice.call(document.querySelectorAll(e),0).forEach(t)},hasClass:function(e,t){return!!e.classList&&(void 0===t&&(t="kint-show"),e.classList.contains(t))},addClass:function(e,t){void 0===t&&(t="kint-show"),e.classList.add(t)},removeClass:function(e,t){return void 0===t&&(t="kint-show"),e.classList.remove(t),e},toggle:function(e,t){var a=n.getChildren(e);a&&(void 0===t&&(t=n.hasClass(e)),t?n.removeClass(e):n.addClass(e),1===a.childNodes.length&&(a=a.childNodes[0].childNodes[0])&&n.hasClass(a,"kint-parent")&&n.toggle(a,t))},toggleChildren:function(e,t){var a=n.getChildren(e);if(a){var r=a.getElementsByClassName("kint-parent"),o=r.length;for(void 0===t&&(t=!n.hasClass(e));o--;)n.toggle(r[o],t)}},toggleAll:function(e){for(var t=document.getElementsByClassName("kint-parent"),a=t.length,r=!n.hasClass(e.parentNode);a--;)n.toggle(t[a],r)},switchTab:function(e){var t,a=e.previousSibling,r=0;for(n.removeClass(e.parentNode.getElementsByClassName("kint-active-tab")[0],"kint-active-tab"),n.addClass(e,"kint-active-tab");a;)1===a.nodeType&&r++,a=a.previousSibling;t=e.parentNode.nextSibling.childNodes;for(var o=0;o"},openInNewWindow:function(e){var t=window.open();t&&(t.document.open(),t.document.write(n.mktag("html")+n.mktag("head")+n.mktag("title")+"Kint ("+(new Date).toISOString()+")"+n.mktag("/title")+n.mktag('meta charset="utf-8"')+document.getElementsByClassName("kint-rich-script")[0].outerHTML+document.getElementsByClassName("kint-rich-style")[0].outerHTML+n.mktag("/head")+n.mktag("body")+'
'+e.parentNode.outerHTML+"
"+n.mktag("/body")),t.document.close())},sortTable:function(e,a){var t=e.tBodies[0];[].slice.call(e.tBodies[0].rows).sort(function(e,t){if(e=e.cells[a].textContent.trim().toLocaleLowerCase(),t=t.cells[a].textContent.trim().toLocaleLowerCase(),isNaN(e)||isNaN(t)){if(isNaN(e)&&!isNaN(t))return 1;if(isNaN(t)&&!isNaN(e))return-1}else e=parseFloat(e),t=parseFloat(t);return eli:not(.kint-active-tab)",function(e){0===e.offsetWidth&&0===e.offsetHeight||n.keyboardNav.targets.push(e)})},sync:function(e){var t=document.querySelector(".kint-focused");if(t&&n.removeClass(t,"kint-focused"),n.keyboardNav.active){var a=n.keyboardNav.targets[n.keyboardNav.target];n.addClass(a,"kint-focused"),e||n.keyboardNav.scroll(a)}},scroll:function(e){var t=function(e){return e.offsetTop+(e.offsetParent?t(e.offsetParent):0)},a=t(e);if(n.folder){var r=n.folder.querySelector("dd.kint-folder");r.scrollTo(0,a-r.clientHeight/2)}else window.scrollTo(0,a-window.innerHeight/2)},moveCursor:function(e){for(n.keyboardNav.target+=e;n.keyboardNav.target<0;)n.keyboardNav.target+=n.keyboardNav.targets.length;for(;n.keyboardNav.target>=n.keyboardNav.targets.length;)n.keyboardNav.target-=n.keyboardNav.targets.length;n.keyboardNav.sync()},setCursor:function(e){n.keyboardNav.fetchTargets();for(var t=0;tdl dl{padding:0 0 0 15px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMzAgMTUwIj48ZGVmcz48cGF0aCBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNNCAzYTI0IDMyIDAgMCAxIDAgMjQgNDAgMjAtMTAgMCAxIDIzLTEyQTQwIDIwIDEwIDAgMSA0IDN6IiBpZD0iYSIvPjwvZGVmcz48ZyBmaWxsPSIjOTNhMWExIiBzdHJva2U9IiM5M2ExYTEiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxnIGZpbGw9IiM1ODZlNzUiIHN0cm9rZT0iIzU4NmU3NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAzMCkiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxwYXRoIGQ9Ik02IDEyNmwxOCAxOG0tMTggMGwxOC0xOCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2U9IiM1ODZlNzUiLz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #586e75}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#268bd2;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#2aa198}.kint-rich dfn{font-style:normal;font-family:monospace;color:#93a1a1}.kint-rich pre{color:#839496;margin:0 0 0 15px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #586e75;background:#002b36;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(131,148,150,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#002b36;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#839496;background:#002b36}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #586e75;border-top-width:0;border-bottom-width:0;padding:5px;float:right !important;margin:-5px 0;color:#93a1a1;background:#073642;height:26px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#252525;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#1b1b1b}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#073642;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#839496}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#839496;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#93a1a1;border-bottom:1px dotted #93a1a1}.kint-rich ul{list-style:none;padding-left:15px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #586e75}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 15px;padding-left:0;background:#002b36;border:1px solid #586e75;border-top:0}.kint-rich ul.kint-tabs>li{background:#073642;border:1px solid #586e75;cursor:pointer;display:inline-block;height:30px;margin:3px;padding:0 15px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#268bd2;color:#2aa198}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#002b36;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:25px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul:not(.kint-tabs)>li:not(:first-child){display:none}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#268bd2;color:#2aa198}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #586e75;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#268bd2}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2.5px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #586e75;padding:2.5px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#073642;color:#93a1a1}.kint-rich table td{background:#002b36;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}.kint-rich table tr:hover var{color:#2aa198}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:5px;padding-bottom:5px;border-bottom:1px solid #073642}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #268bd2;padding-right:10px;margin-right:10px}.kint-rich pre.kint-source>div.kint-highlight{background:#073642}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #268bd2,0 1px #268bd2,1px 0 #268bd2,0 -1px #268bd2;color:#002b36;font-weight:bold}body{background:#073642;color:#fff}.kint-rich{box-shadow:0 0 5px 3px #073642}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}.kint-rich>dl>dt,.kint-rich ul.kint-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}.kint-rich ul.kint-tabs li.kint-active-tab{padding-top:7px;height:34px}.kint-rich footer li{color:#ddd} diff --git a/system/ThirdParty/Kint/resources/compiled/solarized.css b/system/ThirdParty/Kint/resources/compiled/solarized.css new file mode 100644 index 000000000000..db5da0d2d3b7 --- /dev/null +++ b/system/ThirdParty/Kint/resources/compiled/solarized.css @@ -0,0 +1 @@ +.kint-rich{font-size:13px;overflow-x:auto;white-space:nowrap;background:rgba(255,255,255,0.9)}.kint-rich.kint-folder{position:fixed;bottom:0;left:0;right:0;z-index:999999;width:100%;margin:0;display:none}.kint-rich.kint-folder.kint-show{display:block}.kint-rich.kint-folder dd.kint-folder{max-height:calc(100vh - 100px);padding-right:10px;overflow-y:scroll}.kint-rich::selection,.kint-rich::-moz-selection,.kint-rich::-webkit-selection{background:#268bd2;color:#657b83}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #2aa198}.kint-rich,.kint-rich::before,.kint-rich::after,.kint-rich *,.kint-rich *::before,.kint-rich *::after{box-sizing:border-box;border-radius:0;color:#657b83;float:none !important;font-family:Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;line-height:15px;margin:0;padding:0;text-align:left}.kint-rich{margin:10px 0}.kint-rich dt,.kint-rich dl{width:auto}.kint-rich dt,.kint-rich div.access-path{background:#fdf6e3;border:1px solid #93a1a1;color:#657b83;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:5px}.kint-rich dt:hover,.kint-rich div.access-path:hover{border-color:#268bd2}.kint-rich>dl dl{padding:0 0 0 15px}.kint-rich dt.kint-parent>nav,.kint-rich>footer>nav{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMzAgMTUwIj48ZGVmcz48cGF0aCBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNNCAzYTI0IDMyIDAgMCAxIDAgMjQgNDAgMjAtMTAgMCAxIDIzLTEyQTQwIDIwIDEwIDAgMSA0IDN6IiBpZD0iYSIvPjwvZGVmcz48ZyBmaWxsPSIjOTNhMWExIiBzdHJva2U9IiM5M2ExYTEiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxnIGZpbGw9IiM1ODZlNzUiIHN0cm9rZT0iIzU4NmU3NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAzMCkiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48dXNlIHhsaW5rOmhyZWY9IiNhIiB0cmFuc2Zvcm09InJvdGF0ZSg5MCAtMTUgNDUpIi8+PC9nPjxwYXRoIGQ9Ik02IDEyNmwxOCAxOG0tMTggMGwxOC0xOCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2U9IiM1ODZlNzUiLz48L3N2Zz4=") no-repeat scroll 0 0/15px 75px transparent;cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}.kint-rich dt.kint-parent:hover>nav,.kint-rich>footer>nav:hover{background-position:0 25%}.kint-rich dt.kint-parent.kint-show>nav,.kint-rich>footer.kint-show>nav{background-position:0 50%}.kint-rich dt.kint-parent.kint-show:hover>nav,.kint-rich>footer.kint-show>nav:hover{background-position:0 75%}.kint-rich dt.kint-parent.kint-locked>nav{background-position:0 100%}.kint-rich dt.kint-parent+dd{display:none;border-left:1px dashed #93a1a1}.kint-rich dt.kint-parent.kint-show+dd{display:block}.kint-rich var,.kint-rich var a{color:#268bd2;font-style:normal}.kint-rich dt:hover var,.kint-rich dt:hover var a{color:#2aa198}.kint-rich dfn{font-style:normal;font-family:monospace;color:#586e75}.kint-rich pre{color:#657b83;margin:0 0 0 15px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #93a1a1;background:#fdf6e3;display:block;word-break:normal}.kint-rich .kint-popup-trigger,.kint-rich .kint-access-path-trigger,.kint-rich .kint-search-trigger{background:rgba(101,123,131,0.8);border-radius:3px;height:16px;font-size:16px;margin-left:5px;font-weight:bold;width:16px;text-align:center;float:right !important;cursor:pointer;color:#fdf6e3;position:relative;overflow:hidden;line-height:17.6px}.kint-rich .kint-popup-trigger:hover,.kint-rich .kint-access-path-trigger:hover,.kint-rich .kint-search-trigger:hover{color:#657b83;background:#fdf6e3}.kint-rich dt.kint-parent>.kint-popup-trigger{line-height:19.2px}.kint-rich .kint-search-trigger{font-size:20px}.kint-rich input.kint-search{display:none;border:1px solid #93a1a1;border-top-width:0;border-bottom-width:0;padding:5px;float:right !important;margin:-5px 0;color:#586e75;background:#eee8d5;height:26px;width:160px;position:relative;z-index:100}.kint-rich input.kint-search.kint-show{display:block}.kint-rich .kint-search-root ul.kint-tabs>li:not(.kint-search-match){background:#e2e2e2;opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match){opacity:0.5}.kint-rich .kint-search-root dl:not(.kint-search-match)>dt{background:#f0f0f0}.kint-rich .kint-search-root dl:not(.kint-search-match) dl,.kint-rich .kint-search-root dl:not(.kint-search-match) ul.kint-tabs>li:not(.kint-search-match){opacity:1}.kint-rich div.access-path{background:#eee8d5;display:none;margin-top:5px;padding:4px;white-space:pre}.kint-rich div.access-path.kint-show{display:block}.kint-rich footer{padding:0 3px 3px;font-size:9px;background:transparent}.kint-rich footer>.kint-popup-trigger{background:transparent;color:#657b83}.kint-rich footer nav{height:10px;width:10px;background-size:10px 50px}.kint-rich footer>ol{display:none;margin-left:32px}.kint-rich footer.kint-show>ol{display:block}.kint-rich a{color:#657b83;text-shadow:none;text-decoration:underline}.kint-rich a:hover{color:#586e75;border-bottom:1px dotted #586e75}.kint-rich ul{list-style:none;padding-left:15px}.kint-rich ul:not(.kint-tabs) li{border-left:1px dashed #93a1a1}.kint-rich ul:not(.kint-tabs) li>dl{border-left:none}.kint-rich ul.kint-tabs{margin:0 0 0 15px;padding-left:0;background:#fdf6e3;border:1px solid #93a1a1;border-top:0}.kint-rich ul.kint-tabs>li{background:#eee8d5;border:1px solid #93a1a1;cursor:pointer;display:inline-block;height:30px;margin:3px;padding:0 15px;vertical-align:top}.kint-rich ul.kint-tabs>li:hover,.kint-rich ul.kint-tabs>li.kint-active-tab:hover{border-color:#268bd2;color:#2aa198}.kint-rich ul.kint-tabs>li.kint-active-tab{background:#fdf6e3;border-top:0;margin-top:-1px;height:27px;line-height:24px}.kint-rich ul.kint-tabs>li:not(.kint-active-tab){line-height:25px}.kint-rich ul.kint-tabs li+li{margin-left:0}.kint-rich ul:not(.kint-tabs)>li:not(:first-child){display:none}.kint-rich dt:hover+dd>ul>li.kint-active-tab{border-color:#268bd2;color:#2aa198}.kint-rich dt>.kint-color-preview{width:16px;height:16px;display:inline-block;vertical-align:middle;margin-left:10px;border:1px solid #93a1a1;background-color:#ccc;background-image:url('data:image/svg+xml;utf8,');background-size:100%}.kint-rich dt>.kint-color-preview:hover{border-color:#268bd2}.kint-rich dt>.kint-color-preview>div{width:100%;height:100%}.kint-rich table{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-rich table *{font-size:12px}.kint-rich table dt{background:none;padding:2.5px}.kint-rich table dt .kint-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-rich table td,.kint-rich table th{border:1px solid #93a1a1;padding:2.5px;vertical-align:center}.kint-rich table th{cursor:alias}.kint-rich table td:first-child,.kint-rich table th{font-weight:bold;background:#eee8d5;color:#586e75}.kint-rich table td{background:#fdf6e3;white-space:pre}.kint-rich table td>dl{padding:0}.kint-rich table pre{border-top:0;border-right:0}.kint-rich table thead th:first-child{background:none;border:0}.kint-rich table tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}.kint-rich table tr:hover var{color:#2aa198}.kint-rich table ul.kint-tabs li.kint-active-tab{height:20px;line-height:17px}.kint-rich pre.kint-source{margin-left:-1px}.kint-rich pre.kint-source[data-kint-filename]:before{display:block;content:attr(data-kint-filename);margin-bottom:5px;padding-bottom:5px;border-bottom:1px solid #eee8d5}.kint-rich pre.kint-source>div:before{display:inline-block;content:counter(kint-l);counter-increment:kint-l;border-right:1px solid #268bd2;padding-right:10px;margin-right:10px}.kint-rich pre.kint-source>div.kint-highlight{background:#eee8d5}.kint-rich .kint-microtime-lap{text-shadow:-1px 0 #268bd2,0 1px #268bd2,1px 0 #268bd2,0 -1px #268bd2;color:#fdf6e3;font-weight:bold}.kint-rich .kint-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}.kint-rich>dl>dt,.kint-rich ul.kint-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}.kint-rich ul.kint-tabs li.kint-active-tab{padding-top:7px;height:34px}