mirror of
https://github.com/freescout-helpdesk/freescout.git
synced 2024-11-23 19:02:46 +01:00
PHP 8.2 compatibility
This commit is contained in:
parent
e107c41ce9
commit
23c8107463
@ -68,7 +68,7 @@ Mobile apps support the same functionality and modules as the web version of you
|
||||
FreeScout is a pure PHP/MySQL application, so it can be easily deployed even on a shared hosting.
|
||||
|
||||
* Nginx / Apache / IIS
|
||||
* PHP 7.1 - 8.1
|
||||
* PHP 7.1 - 8.2
|
||||
* MySQL 5.0+ / MariaDB 5.0+ / PostgreSQL
|
||||
|
||||
## Installation
|
||||
@ -103,7 +103,7 @@ Images & one-click installs:
|
||||
|
||||
Don't miss news, updates and new modules!
|
||||
|
||||
[Email Newsletter](https://freescout.net/subscribe/) | [Facebook](https://www.facebook.com/profile.php?id=100088012965853) | [Twitter](https://freescout.net/twitter/) | [YouTube](https://freescout.net/youtube/) | [RSS](https://freescout.net/feed/)
|
||||
[Email Newsletter](https://freescout.net/subscribe/) | [Facebook](https://freescout.net/facebook/) | [Twitter](https://freescout.net/twitter/) | [YouTube](https://freescout.net/youtube/) | [RSS](https://freescout.net/feed/)
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@ -1195,45 +1195,46 @@ class Helper
|
||||
}
|
||||
|
||||
/**
|
||||
* It looks like this is not used anywhere.
|
||||
* Json encode to avoid "Unable to JSON encode payload. Error code: 5"
|
||||
*/
|
||||
public static function jsonEncodeSafe($value, $options = 0, $depth = 512, $utfErrorFlag = false)
|
||||
{
|
||||
$encoded = json_encode($value, $options, $depth);
|
||||
switch (json_last_error()) {
|
||||
case JSON_ERROR_NONE:
|
||||
return $encoded;
|
||||
// case JSON_ERROR_DEPTH:
|
||||
// return 'Maximum stack depth exceeded'; // or trigger_error() or throw new Exception()
|
||||
// case JSON_ERROR_STATE_MISMATCH:
|
||||
// return 'Underflow or the modes mismatch'; // or trigger_error() or throw new Exception()
|
||||
// case JSON_ERROR_CTRL_CHAR:
|
||||
// return 'Unexpected control character found';
|
||||
// case JSON_ERROR_SYNTAX:
|
||||
// return 'Syntax error, malformed JSON'; // or trigger_error() or throw new Exception()
|
||||
case JSON_ERROR_UTF8:
|
||||
$clean = self::utf8ize($value);
|
||||
if ($utfErrorFlag) {
|
||||
//return 'UTF8 encoding error'; // or trigger_error() or throw new Exception()
|
||||
}
|
||||
return self::jsonEncodeSafe($clean, $options, $depth, true);
|
||||
// default:
|
||||
// return 'Unknown error'; // or trigger_error() or throw new Exception()
|
||||
// public static function jsonEncodeSafe($value, $options = 0, $depth = 512, $utfErrorFlag = false)
|
||||
// {
|
||||
// $encoded = json_encode($value, $options, $depth);
|
||||
// switch (json_last_error()) {
|
||||
// case JSON_ERROR_NONE:
|
||||
// return $encoded;
|
||||
// // case JSON_ERROR_DEPTH:
|
||||
// // return 'Maximum stack depth exceeded'; // or trigger_error() or throw new Exception()
|
||||
// // case JSON_ERROR_STATE_MISMATCH:
|
||||
// // return 'Underflow or the modes mismatch'; // or trigger_error() or throw new Exception()
|
||||
// // case JSON_ERROR_CTRL_CHAR:
|
||||
// // return 'Unexpected control character found';
|
||||
// // case JSON_ERROR_SYNTAX:
|
||||
// // return 'Syntax error, malformed JSON'; // or trigger_error() or throw new Exception()
|
||||
// case JSON_ERROR_UTF8:
|
||||
// $clean = self::utf8ize($value);
|
||||
// if ($utfErrorFlag) {
|
||||
// //return 'UTF8 encoding error'; // or trigger_error() or throw new Exception()
|
||||
// }
|
||||
// return self::jsonEncodeSafe($clean, $options, $depth, true);
|
||||
// // default:
|
||||
// // return 'Unknown error'; // or trigger_error() or throw new Exception()
|
||||
|
||||
}
|
||||
}
|
||||
// }
|
||||
// }
|
||||
|
||||
public static function utf8ize($mixed)
|
||||
{
|
||||
if (is_array($mixed)) {
|
||||
foreach ($mixed as $key => $value) {
|
||||
$mixed[$key] = self::utf8ize($value);
|
||||
}
|
||||
} else if (is_string ($mixed)) {
|
||||
return utf8_encode($mixed);
|
||||
}
|
||||
return $mixed;
|
||||
}
|
||||
// public static function utf8ize($mixed)
|
||||
// {
|
||||
// if (is_array($mixed)) {
|
||||
// foreach ($mixed as $key => $value) {
|
||||
// $mixed[$key] = self::utf8ize($value);
|
||||
// }
|
||||
// } else if (is_string ($mixed)) {
|
||||
// return utf8_encode($mixed);
|
||||
// }
|
||||
// return $mixed;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Check if host is available on the port specified.
|
||||
|
@ -125,11 +125,13 @@
|
||||
"Symfony\\Component\\Finder\\": "overrides/symfony/finder/",
|
||||
"Symfony\\Component\\Console\\Helper\\": "overrides/symfony/console/Helper/",
|
||||
"DebugBar\\": "overrides/maximebf/debugbar/src/DebugBar/",
|
||||
"DebugBar\\DataFormatter\\": "overrides/maximebf/debugbar/src/DataFormatter/DataFormatter/",
|
||||
"Illuminate\\Cache\\Console\\": "overrides/laravel/framework/src/Illuminate/Cache/Console/",
|
||||
"Dotenv\\": "overrides/vlucas/phpdotenv/src/",
|
||||
"Illuminate\\View\\": "overrides/laravel/framework/src/Illuminate/View/",
|
||||
"Symfony\\Component\\Routing\\": "overrides/symfony/routing/",
|
||||
"Symfony\\Component\\VarDumper\\Cloner\\": "overrides/symfony/var-dumper/Cloner/",
|
||||
"Symfony\\Component\\VarDumper\\Dumper\\": "overrides/symfony/var-dumper/Dumper/",
|
||||
"Devfactory\\Minify\\Providers\\": "overrides/devfactory/minify/src/Providers/",
|
||||
"Barryvdh\\Debugbar\\": "overrides/barryvdh/laravel-debugbar/src/",
|
||||
"Barryvdh\\Debugbar\\DataFormatter\\": "overrides/barryvdh/laravel-debugbar/src/DataFormatter/",
|
||||
@ -138,6 +140,7 @@
|
||||
"Spatie\\String\\": "overrides/spatie/string/src/",
|
||||
"GuzzleHttp\\": "overrides/guzzlehttp/guzzle/src/",
|
||||
"GuzzleHttp\\Cookie\\": "overrides/guzzlehttp/guzzle/src/Cookie/",
|
||||
"GuzzleHttp\\Psr7\\": "overrides/guzzlehttp/psr7/src/",
|
||||
"Ramsey\\Uuid\\": "overrides/ramsey/uuid/src/",
|
||||
"Rap2hpoutre\\LaravelLogViewer\\": "overrides/rap2hpoutre/laravel-log-viewer/src/Rap2hpoutre/LaravelLogViewer/",
|
||||
"Symfony\\Component\\Console\\Descriptor\\": "overrides/symfony/console/Descriptor",
|
||||
@ -224,6 +227,7 @@
|
||||
"vendor/symfony/finder/Iterator/DateRangeFilterIterator.php",
|
||||
"vendor/symfony/console/Helper/HelperSet.php",
|
||||
"vendor/maximebf/debugbar/src/DebugBar/DebugBar.php",
|
||||
"vendor/maximebf/debugbar/src/DebugBar/DataFormatter/DataFormatter.php",
|
||||
"vendor/laravel/framework/src/Illuminate/Cache/Console/ClearCommand.php",
|
||||
"vendor/vlucas/phpdotenv/src/Loader.php",
|
||||
"vendor/laravel/framework/src/Illuminate/View/View.php",
|
||||
@ -231,6 +235,7 @@
|
||||
"vendor/symfony/routing/CompiledRoute.php",
|
||||
"vendor/symfony/var-dumper/Cloner/Data.php",
|
||||
"vendor/symfony/var-dumper/Cloner/Stub.php",
|
||||
"vendor/symfony/var-dumper/Dumper/HtmlDumper.php",
|
||||
"vendor/devfactory/minify/src/Providers/BaseProvider.php",
|
||||
"vendor/barryvdh/laravel-debugbar/src/DataFormatter/QueryFormatter.php",
|
||||
"vendor/symfony/process/Process.php",
|
||||
@ -239,13 +244,16 @@
|
||||
"vendor/spatie/string/src/Str.php",
|
||||
"vendor/guzzlehttp/guzzle/src/Client.php",
|
||||
"vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php",
|
||||
"vendor/guzzlehttp/guzzle/src/psr7/src/LazyOpenStream.php",
|
||||
"vendor/ramsey/uuid/src/Uuid.php",
|
||||
"vendor/laravel/framework/src/Illuminate/Routing/Router.php",
|
||||
"vendor/rap2hpoutre/laravel-log-viewer/src/Rap2hpoutre/LaravelLogViewer/LaravelLogViewer.php",
|
||||
"vendor/symfony/console/Descriptor/TextDescriptor.php",
|
||||
"vendor/symfony/console/Helper/Helper.php",
|
||||
"vendor/symfony/finder/Iterator/SortableIterator.php",
|
||||
"vendor/symfony/css-selector/XPath/Extension/NodeExtension.php"
|
||||
"vendor/symfony/css-selector/XPath/Extension/NodeExtension.php",
|
||||
"vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/NameSync.php",
|
||||
"vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
|
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Post-transform that performs validation to the name attribute; if
|
||||
* it is present with an equivalent id attribute, it is passed through;
|
||||
* otherwise validation is performed.
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_NameSync extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
public $idDef;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->idDef = new HTMLPurifier_AttrDef_HTML_ID();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (!isset($attr['name'])) {
|
||||
return $attr;
|
||||
}
|
||||
$name = $attr['name'];
|
||||
if (isset($attr['id']) && $attr['id'] === $name) {
|
||||
return $attr;
|
||||
}
|
||||
$result = $this->idDef->validate($name, $config, $context);
|
||||
if ($result === false) {
|
||||
unset($attr['name']);
|
||||
} else {
|
||||
$attr['name'] = $result;
|
||||
}
|
||||
return $attr;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
383
overrides/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php
Normal file
383
overrides/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php
Normal file
@ -0,0 +1,383 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Forgivingly lexes HTML (SGML-style) markup into tokens.
|
||||
*
|
||||
* A lexer parses a string of SGML-style markup and converts them into
|
||||
* corresponding tokens. It doesn't check for well-formedness, although its
|
||||
* internal mechanism may make this automatic (such as the case of
|
||||
* HTMLPurifier_Lexer_DOMLex). There are several implementations to choose
|
||||
* from.
|
||||
*
|
||||
* A lexer is HTML-oriented: it might work with XML, but it's not
|
||||
* recommended, as we adhere to a subset of the specification for optimization
|
||||
* reasons. This might change in the future. Also, most tokenizers are not
|
||||
* expected to handle DTDs or PIs.
|
||||
*
|
||||
* This class should not be directly instantiated, but you may use create() to
|
||||
* retrieve a default copy of the lexer. Being a supertype, this class
|
||||
* does not actually define any implementation, but offers commonly used
|
||||
* convenience functions for subclasses.
|
||||
*
|
||||
* @note The unit tests will instantiate this class for testing purposes, as
|
||||
* many of the utility functions require a class to be instantiated.
|
||||
* This means that, even though this class is not runnable, it will
|
||||
* not be declared abstract.
|
||||
*
|
||||
* @par
|
||||
*
|
||||
* @note
|
||||
* We use tokens rather than create a DOM representation because DOM would:
|
||||
*
|
||||
* @par
|
||||
* -# Require more processing and memory to create,
|
||||
* -# Is not streamable, and
|
||||
* -# Has the entire document structure (html and body not needed).
|
||||
*
|
||||
* @par
|
||||
* However, DOM is helpful in that it makes it easy to move around nodes
|
||||
* without a lot of lookaheads to see when a tag is closed. This is a
|
||||
* limitation of the token system and some workarounds would be nice.
|
||||
*/
|
||||
class HTMLPurifier_Lexer
|
||||
{
|
||||
public $_entity_parser;
|
||||
|
||||
/**
|
||||
* Whether or not this lexer implements line-number/column-number tracking.
|
||||
* If it does, set to true.
|
||||
*/
|
||||
public $tracksLineNumbers = false;
|
||||
|
||||
// -- STATIC ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Retrieves or sets the default Lexer as a Prototype Factory.
|
||||
*
|
||||
* By default HTMLPurifier_Lexer_DOMLex will be returned. There are
|
||||
* a few exceptions involving special features that only DirectLex
|
||||
* implements.
|
||||
*
|
||||
* @note The behavior of this class has changed, rather than accepting
|
||||
* a prototype object, it now accepts a configuration object.
|
||||
* To specify your own prototype, set %Core.LexerImpl to it.
|
||||
* This change in behavior de-singletonizes the lexer object.
|
||||
*
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @return HTMLPurifier_Lexer
|
||||
* @throws HTMLPurifier_Exception
|
||||
*/
|
||||
public static function create($config)
|
||||
{
|
||||
if (!($config instanceof HTMLPurifier_Config)) {
|
||||
$lexer = $config;
|
||||
trigger_error(
|
||||
"Passing a prototype to
|
||||
HTMLPurifier_Lexer::create() is deprecated, please instead
|
||||
use %Core.LexerImpl",
|
||||
E_USER_WARNING
|
||||
);
|
||||
} else {
|
||||
$lexer = $config->get('Core.LexerImpl');
|
||||
}
|
||||
|
||||
$needs_tracking =
|
||||
$config->get('Core.MaintainLineNumbers') ||
|
||||
$config->get('Core.CollectErrors');
|
||||
|
||||
$inst = null;
|
||||
if (is_object($lexer)) {
|
||||
$inst = $lexer;
|
||||
} else {
|
||||
if (is_null($lexer)) {
|
||||
do {
|
||||
// auto-detection algorithm
|
||||
if ($needs_tracking) {
|
||||
$lexer = 'DirectLex';
|
||||
break;
|
||||
}
|
||||
|
||||
if (class_exists('DOMDocument', false) &&
|
||||
method_exists('DOMDocument', 'loadHTML') &&
|
||||
!extension_loaded('domxml')
|
||||
) {
|
||||
// check for DOM support, because while it's part of the
|
||||
// core, it can be disabled compile time. Also, the PECL
|
||||
// domxml extension overrides the default DOM, and is evil
|
||||
// and nasty and we shan't bother to support it
|
||||
$lexer = 'DOMLex';
|
||||
} else {
|
||||
$lexer = 'DirectLex';
|
||||
}
|
||||
} while (0);
|
||||
} // do..while so we can break
|
||||
|
||||
// instantiate recognized string names
|
||||
switch ($lexer) {
|
||||
case 'DOMLex':
|
||||
$inst = new HTMLPurifier_Lexer_DOMLex();
|
||||
break;
|
||||
case 'DirectLex':
|
||||
$inst = new HTMLPurifier_Lexer_DirectLex();
|
||||
break;
|
||||
case 'PH5P':
|
||||
$inst = new HTMLPurifier_Lexer_PH5P();
|
||||
break;
|
||||
default:
|
||||
throw new HTMLPurifier_Exception(
|
||||
"Cannot instantiate unrecognized Lexer type " .
|
||||
htmlspecialchars($lexer)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$inst) {
|
||||
throw new HTMLPurifier_Exception('No lexer was instantiated');
|
||||
}
|
||||
|
||||
// once PHP DOM implements native line numbers, or we
|
||||
// hack out something using XSLT, remove this stipulation
|
||||
if ($needs_tracking && !$inst->tracksLineNumbers) {
|
||||
throw new HTMLPurifier_Exception(
|
||||
'Cannot use lexer that does not support line numbers with ' .
|
||||
'Core.MaintainLineNumbers or Core.CollectErrors (use DirectLex instead)'
|
||||
);
|
||||
}
|
||||
|
||||
return $inst;
|
||||
|
||||
}
|
||||
|
||||
// -- CONVENIENCE MEMBERS ---------------------------------------------
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->_entity_parser = new HTMLPurifier_EntityParser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Most common entity to raw value conversion table for special entities.
|
||||
* @type array
|
||||
*/
|
||||
protected $_special_entity2str =
|
||||
array(
|
||||
'"' => '"',
|
||||
'&' => '&',
|
||||
'<' => '<',
|
||||
'>' => '>',
|
||||
''' => "'",
|
||||
''' => "'",
|
||||
''' => "'"
|
||||
);
|
||||
|
||||
public function parseText($string, $config) {
|
||||
return $this->parseData($string, false, $config);
|
||||
}
|
||||
|
||||
public function parseAttr($string, $config) {
|
||||
return $this->parseData($string, true, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses special entities into the proper characters.
|
||||
*
|
||||
* This string will translate escaped versions of the special characters
|
||||
* into the correct ones.
|
||||
*
|
||||
* @param string $string String character data to be parsed.
|
||||
* @return string Parsed character data.
|
||||
*/
|
||||
public function parseData($string, $is_attr, $config)
|
||||
{
|
||||
// following functions require at least one character
|
||||
if ($string === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
// subtracts amps that cannot possibly be escaped
|
||||
$num_amp = substr_count($string, '&') - substr_count($string, '& ') -
|
||||
($string[strlen($string) - 1] === '&' ? 1 : 0);
|
||||
|
||||
if (!$num_amp) {
|
||||
return $string;
|
||||
} // abort if no entities
|
||||
$num_esc_amp = substr_count($string, '&');
|
||||
$string = strtr($string, $this->_special_entity2str);
|
||||
|
||||
// code duplication for sake of optimization, see above
|
||||
$num_amp_2 = substr_count($string, '&') - substr_count($string, '& ') -
|
||||
($string[strlen($string) - 1] === '&' ? 1 : 0);
|
||||
|
||||
if ($num_amp_2 <= $num_esc_amp) {
|
||||
return $string;
|
||||
}
|
||||
|
||||
// hmm... now we have some uncommon entities. Use the callback.
|
||||
if ($config->get('Core.LegacyEntityDecoder')) {
|
||||
$string = $this->_entity_parser->substituteSpecialEntities($string);
|
||||
} else {
|
||||
if ($is_attr) {
|
||||
$string = $this->_entity_parser->substituteAttrEntities($string);
|
||||
} else {
|
||||
$string = $this->_entity_parser->substituteTextEntities($string);
|
||||
}
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lexes an HTML string into tokens.
|
||||
* @param $string String HTML.
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return HTMLPurifier_Token[] array representation of HTML.
|
||||
*/
|
||||
public function tokenizeHTML($string, $config, $context)
|
||||
{
|
||||
trigger_error('Call to abstract class', E_USER_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates CDATA sections into regular sections (through escaping).
|
||||
* @param string $string HTML string to process.
|
||||
* @return string HTML with CDATA sections escaped.
|
||||
*/
|
||||
protected static function escapeCDATA($string)
|
||||
{
|
||||
return preg_replace_callback(
|
||||
'/<!\[CDATA\[(.+?)\]\]>/s',
|
||||
array('HTMLPurifier_Lexer', 'CDATACallback'),
|
||||
$string
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Special CDATA case that is especially convoluted for <script>
|
||||
* @param string $string HTML string to process.
|
||||
* @return string HTML with CDATA sections escaped.
|
||||
*/
|
||||
protected static function escapeCommentedCDATA($string)
|
||||
{
|
||||
return preg_replace_callback(
|
||||
'#<!--//--><!\[CDATA\[//><!--(.+?)//--><!\]\]>#s',
|
||||
array('HTMLPurifier_Lexer', 'CDATACallback'),
|
||||
$string
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Special Internet Explorer conditional comments should be removed.
|
||||
* @param string $string HTML string to process.
|
||||
* @return string HTML with conditional comments removed.
|
||||
*/
|
||||
protected static function removeIEConditional($string)
|
||||
{
|
||||
return preg_replace(
|
||||
'#<!--\[if [^>]+\]>.*?<!\[endif\]-->#si', // probably should generalize for all strings
|
||||
'',
|
||||
$string
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function for escapeCDATA() that does the work.
|
||||
*
|
||||
* @warning Though this is public in order to let the callback happen,
|
||||
* calling it directly is not recommended.
|
||||
* @param array $matches PCRE matches array, with index 0 the entire match
|
||||
* and 1 the inside of the CDATA section.
|
||||
* @return string Escaped internals of the CDATA section.
|
||||
*/
|
||||
protected static function CDATACallback($matches)
|
||||
{
|
||||
// not exactly sure why the character set is needed, but whatever
|
||||
return htmlspecialchars($matches[1], ENT_COMPAT, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a piece of HTML and normalizes it by converting entities, fixing
|
||||
* encoding, extracting bits, and other good stuff.
|
||||
* @param string $html HTML.
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return string
|
||||
* @todo Consider making protected
|
||||
*/
|
||||
public function normalize($html, $config, $context)
|
||||
{
|
||||
// normalize newlines to \n
|
||||
if ($config->get('Core.NormalizeNewlines')) {
|
||||
$html = str_replace("\r\n", "\n", $html);
|
||||
$html = str_replace("\r", "\n", $html);
|
||||
}
|
||||
|
||||
if ($config->get('HTML.Trusted')) {
|
||||
// escape convoluted CDATA
|
||||
$html = $this->escapeCommentedCDATA($html);
|
||||
}
|
||||
|
||||
// escape CDATA
|
||||
$html = $this->escapeCDATA($html);
|
||||
|
||||
$html = $this->removeIEConditional($html);
|
||||
|
||||
// extract body from document if applicable
|
||||
if ($config->get('Core.ConvertDocumentToFragment')) {
|
||||
$e = false;
|
||||
if ($config->get('Core.CollectErrors')) {
|
||||
$e =& $context->get('ErrorCollector');
|
||||
}
|
||||
$new_html = $this->extractBody($html);
|
||||
if ($e && $new_html != $html) {
|
||||
$e->send(E_WARNING, 'Lexer: Extracted body');
|
||||
}
|
||||
$html = $new_html;
|
||||
}
|
||||
|
||||
// expand entities that aren't the big five
|
||||
if ($config->get('Core.LegacyEntityDecoder')) {
|
||||
$html = $this->_entity_parser->substituteNonSpecialEntities($html);
|
||||
}
|
||||
|
||||
// clean into wellformed UTF-8 string for an SGML context: this has
|
||||
// to be done after entity expansion because the entities sometimes
|
||||
// represent non-SGML characters (horror, horror!)
|
||||
$html = HTMLPurifier_Encoder::cleanUTF8($html);
|
||||
|
||||
// if processing instructions are to removed, remove them now
|
||||
if ($config->get('Core.RemoveProcessingInstructions')) {
|
||||
$html = preg_replace('#<\?.+?\?>#s', '', $html);
|
||||
}
|
||||
|
||||
$hidden_elements = $config->get('Core.HiddenElements');
|
||||
if ($config->get('Core.AggressivelyRemoveScript') &&
|
||||
!($config->get('HTML.Trusted') || !$config->get('Core.RemoveScriptContents')
|
||||
|| empty($hidden_elements["script"]))) {
|
||||
$html = preg_replace('#<script[^>]*>.*?</script>#i', '', $html);
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a string of HTML (fragment or document) and returns the content
|
||||
* @todo Consider making protected
|
||||
*/
|
||||
public function extractBody($html)
|
||||
{
|
||||
$matches = array();
|
||||
$result = preg_match('|(.*?)<body[^>]*>(.*)</body>|is', $html, $matches);
|
||||
if ($result) {
|
||||
// Make sure it's not in a comment
|
||||
$comment_start = strrpos($matches[1], '<!--');
|
||||
$comment_end = strrpos($matches[1], '-->');
|
||||
if ($comment_start === false ||
|
||||
($comment_end !== false && $comment_end > $comment_start)) {
|
||||
return $matches[2];
|
||||
}
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
40
overrides/guzzlehttp/psr7/src/LazyOpenStream.php
Normal file
40
overrides/guzzlehttp/psr7/src/LazyOpenStream.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
namespace GuzzleHttp\Psr7;
|
||||
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
/**
|
||||
* Lazily reads or writes to a file that is opened only after an IO operation
|
||||
* take place on the stream.
|
||||
*/
|
||||
#[\AllowDynamicProperties]
|
||||
class LazyOpenStream implements StreamInterface
|
||||
{
|
||||
use StreamDecoratorTrait;
|
||||
|
||||
/** @var string File to open */
|
||||
private $filename;
|
||||
|
||||
/** @var string $mode */
|
||||
private $mode;
|
||||
|
||||
/**
|
||||
* @param string $filename File to lazily open
|
||||
* @param string $mode fopen mode to use when opening the stream
|
||||
*/
|
||||
public function __construct($filename, $mode)
|
||||
{
|
||||
$this->filename = $filename;
|
||||
$this->mode = $mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the underlying stream lazily when required.
|
||||
*
|
||||
* @return StreamInterface
|
||||
*/
|
||||
protected function createStream()
|
||||
{
|
||||
return stream_for(try_fopen($this->filename, $this->mode));
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of the DebugBar package.
|
||||
*
|
||||
* (c) 2013 Maxime Bouroumeau-Fuseau
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace DebugBar\DataFormatter;
|
||||
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
use Symfony\Component\VarDumper\Dumper\CliDumper;
|
||||
|
||||
class DataFormatter implements DataFormatterInterface
|
||||
{
|
||||
public $cloner;
|
||||
public $dumper;
|
||||
|
||||
/**
|
||||
* DataFormatter constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->cloner = new VarCloner();
|
||||
$this->dumper = new CliDumper();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return string
|
||||
*/
|
||||
public function formatVar($data)
|
||||
{
|
||||
$output = '';
|
||||
|
||||
$this->dumper->dump(
|
||||
$this->cloner->cloneVar($data),
|
||||
function ($line, $depth) use (&$output) {
|
||||
// A negative depth means "end of dump"
|
||||
if ($depth >= 0) {
|
||||
// Adds a two spaces indentation to the line
|
||||
$output .= str_repeat(' ', $depth).$line."\n";
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return trim($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $seconds
|
||||
* @return string
|
||||
*/
|
||||
public function formatDuration($seconds)
|
||||
{
|
||||
if ($seconds < 0.001) {
|
||||
return round($seconds * 1000000) . 'μs';
|
||||
} elseif ($seconds < 1) {
|
||||
return round($seconds * 1000, 2) . 'ms';
|
||||
}
|
||||
return round($seconds, 2) . 's';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $size
|
||||
* @param int $precision
|
||||
* @return string
|
||||
*/
|
||||
public function formatBytes($size, $precision = 2)
|
||||
{
|
||||
if ($size === 0 || $size === null) {
|
||||
return "0B";
|
||||
}
|
||||
|
||||
$sign = $size < 0 ? '-' : '';
|
||||
$size = abs($size);
|
||||
|
||||
$base = log($size) / log(1024);
|
||||
$suffixes = array('B', 'KB', 'MB', 'GB', 'TB');
|
||||
return $sign . round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
|
||||
}
|
||||
}
|
@ -919,8 +919,11 @@ class Carbon extends DateTime implements JsonSerializable
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function setLastErrors(array $lastErrors)
|
||||
private static function setLastErrors($lastErrors)
|
||||
{
|
||||
if (!is_array($lastErrors)) {
|
||||
return;
|
||||
}
|
||||
static::$lastErrors = $lastErrors;
|
||||
}
|
||||
|
||||
|
904
overrides/symfony/var-dumper/Dumper/HtmlDumper.php
Normal file
904
overrides/symfony/var-dumper/Dumper/HtmlDumper.php
Normal file
@ -0,0 +1,904 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\VarDumper\Dumper;
|
||||
|
||||
use Symfony\Component\VarDumper\Cloner\Cursor;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
|
||||
/**
|
||||
* HtmlDumper dumps variables as HTML.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class HtmlDumper extends CliDumper
|
||||
{
|
||||
public static $defaultOutput = 'php://output';
|
||||
|
||||
protected $dumpHeader;
|
||||
protected $dumpPrefix = '<pre class=sf-dump id=%s data-indent-pad="%s">';
|
||||
protected $dumpSuffix = '</pre><script>Sfdump(%s)</script>';
|
||||
protected $dumpId = 'sf-dump';
|
||||
protected $colors = true;
|
||||
protected $headerIsDumped = false;
|
||||
protected $lastDepth = -1;
|
||||
protected $styles = [
|
||||
'default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all',
|
||||
'num' => 'font-weight:bold; color:#1299DA',
|
||||
'const' => 'font-weight:bold',
|
||||
'str' => 'font-weight:bold; color:#56DB3A',
|
||||
'note' => 'color:#1299DA',
|
||||
'ref' => 'color:#A0A0A0',
|
||||
'public' => 'color:#FFFFFF',
|
||||
'protected' => 'color:#FFFFFF',
|
||||
'private' => 'color:#FFFFFF',
|
||||
'meta' => 'color:#B729D9',
|
||||
'key' => 'color:#56DB3A',
|
||||
'index' => 'color:#1299DA',
|
||||
'ellipsis' => 'color:#FF8400',
|
||||
];
|
||||
|
||||
private $displayOptions = [
|
||||
'maxDepth' => 1,
|
||||
'maxStringLength' => 160,
|
||||
'fileLinkFormat' => null,
|
||||
];
|
||||
private $extraDisplayOptions = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct($output = null, $charset = null, $flags = 0)
|
||||
{
|
||||
AbstractDumper::__construct($output, $charset, $flags);
|
||||
$this->dumpId = 'sf-dump-'.mt_rand();
|
||||
$this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setStyles(array $styles)
|
||||
{
|
||||
$this->headerIsDumped = false;
|
||||
$this->styles = $styles + $this->styles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures display options.
|
||||
*
|
||||
* @param array $displayOptions A map of display options to customize the behavior
|
||||
*/
|
||||
public function setDisplayOptions(array $displayOptions)
|
||||
{
|
||||
$this->headerIsDumped = false;
|
||||
$this->displayOptions = $displayOptions + $this->displayOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an HTML header that will be dumped once in the output stream.
|
||||
*
|
||||
* @param string $header An HTML string
|
||||
*/
|
||||
public function setDumpHeader($header)
|
||||
{
|
||||
$this->dumpHeader = $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an HTML prefix and suffix that will encapse every single dump.
|
||||
*
|
||||
* @param string $prefix The prepended HTML string
|
||||
* @param string $suffix The appended HTML string
|
||||
*/
|
||||
public function setDumpBoundaries($prefix, $suffix)
|
||||
{
|
||||
$this->dumpPrefix = $prefix;
|
||||
$this->dumpSuffix = $suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function dump(Data $data, $output = null, array $extraDisplayOptions = [])
|
||||
{
|
||||
$this->extraDisplayOptions = $extraDisplayOptions;
|
||||
$result = parent::dump($data, $output);
|
||||
$this->dumpId = 'sf-dump-'.mt_rand();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the HTML header.
|
||||
*/
|
||||
protected function getDumpHeader()
|
||||
{
|
||||
$this->headerIsDumped = null !== $this->outputStream ? $this->outputStream : $this->lineDumper;
|
||||
|
||||
if (null !== $this->dumpHeader) {
|
||||
return $this->dumpHeader;
|
||||
}
|
||||
|
||||
$line = str_replace('{$options}', json_encode($this->displayOptions, \JSON_FORCE_OBJECT), <<<'EOHTML'
|
||||
<script>
|
||||
Sfdump = window.Sfdump || (function (doc) {
|
||||
|
||||
var refStyle = doc.createElement('style'),
|
||||
rxEsc = /([.*+?^${}()|\[\]\/\\])/g,
|
||||
idRx = /\bsf-dump-\d+-ref[012]\w+\b/,
|
||||
keyHint = 0 <= navigator.platform.toUpperCase().indexOf('MAC') ? 'Cmd' : 'Ctrl',
|
||||
addEventListener = function (e, n, cb) {
|
||||
e.addEventListener(n, cb, false);
|
||||
};
|
||||
|
||||
(doc.documentElement.firstElementChild || doc.documentElement.children[0]).appendChild(refStyle);
|
||||
|
||||
if (!doc.addEventListener) {
|
||||
addEventListener = function (element, eventName, callback) {
|
||||
element.attachEvent('on' + eventName, function (e) {
|
||||
e.preventDefault = function () {e.returnValue = false;};
|
||||
e.target = e.srcElement;
|
||||
callback(e);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function toggle(a, recursive) {
|
||||
var s = a.nextSibling || {}, oldClass = s.className, arrow, newClass;
|
||||
|
||||
if (/\bsf-dump-compact\b/.test(oldClass)) {
|
||||
arrow = '▼';
|
||||
newClass = 'sf-dump-expanded';
|
||||
} else if (/\bsf-dump-expanded\b/.test(oldClass)) {
|
||||
arrow = '▶';
|
||||
newClass = 'sf-dump-compact';
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (doc.createEvent && s.dispatchEvent) {
|
||||
var event = doc.createEvent('Event');
|
||||
event.initEvent('sf-dump-expanded' === newClass ? 'sfbeforedumpexpand' : 'sfbeforedumpcollapse', true, false);
|
||||
|
||||
s.dispatchEvent(event);
|
||||
}
|
||||
|
||||
a.lastChild.innerHTML = arrow;
|
||||
s.className = s.className.replace(/\bsf-dump-(compact|expanded)\b/, newClass);
|
||||
|
||||
if (recursive) {
|
||||
try {
|
||||
a = s.querySelectorAll('.'+oldClass);
|
||||
for (s = 0; s < a.length; ++s) {
|
||||
if (-1 == a[s].className.indexOf(newClass)) {
|
||||
a[s].className = newClass;
|
||||
a[s].previousSibling.lastChild.innerHTML = arrow;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
function collapse(a, recursive) {
|
||||
var s = a.nextSibling || {}, oldClass = s.className;
|
||||
|
||||
if (/\bsf-dump-expanded\b/.test(oldClass)) {
|
||||
toggle(a, recursive);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
function expand(a, recursive) {
|
||||
var s = a.nextSibling || {}, oldClass = s.className;
|
||||
|
||||
if (/\bsf-dump-compact\b/.test(oldClass)) {
|
||||
toggle(a, recursive);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
function collapseAll(root) {
|
||||
var a = root.querySelector('a.sf-dump-toggle');
|
||||
if (a) {
|
||||
collapse(a, true);
|
||||
expand(a);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function reveal(node) {
|
||||
var previous, parents = [];
|
||||
|
||||
while ((node = node.parentNode || {}) && (previous = node.previousSibling) && 'A' === previous.tagName) {
|
||||
parents.push(previous);
|
||||
}
|
||||
|
||||
if (0 !== parents.length) {
|
||||
parents.forEach(function (parent) {
|
||||
expand(parent);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function highlight(root, activeNode, nodes) {
|
||||
resetHighlightedNodes(root);
|
||||
|
||||
Array.from(nodes||[]).forEach(function (node) {
|
||||
if (!/\bsf-dump-highlight\b/.test(node.className)) {
|
||||
node.className = node.className + ' sf-dump-highlight';
|
||||
}
|
||||
});
|
||||
|
||||
if (!/\bsf-dump-highlight-active\b/.test(activeNode.className)) {
|
||||
activeNode.className = activeNode.className + ' sf-dump-highlight-active';
|
||||
}
|
||||
}
|
||||
|
||||
function resetHighlightedNodes(root) {
|
||||
Array.from(root.querySelectorAll('.sf-dump-str, .sf-dump-key, .sf-dump-public, .sf-dump-protected, .sf-dump-private')).forEach(function (strNode) {
|
||||
strNode.className = strNode.className.replace(/\bsf-dump-highlight\b/, '');
|
||||
strNode.className = strNode.className.replace(/\bsf-dump-highlight-active\b/, '');
|
||||
});
|
||||
}
|
||||
|
||||
return function (root, x) {
|
||||
root = doc.getElementById(root);
|
||||
|
||||
var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || ' ').replace(rxEsc, '\\$1')+')+', 'm'),
|
||||
options = {$options},
|
||||
elt = root.getElementsByTagName('A'),
|
||||
len = elt.length,
|
||||
i = 0, s, h,
|
||||
t = [];
|
||||
|
||||
while (i < len) t.push(elt[i++]);
|
||||
|
||||
for (i in x) {
|
||||
options[i] = x[i];
|
||||
}
|
||||
|
||||
function a(e, f) {
|
||||
addEventListener(root, e, function (e) {
|
||||
if ('A' == e.target.tagName) {
|
||||
f(e.target, e);
|
||||
} else if ('A' == e.target.parentNode.tagName) {
|
||||
f(e.target.parentNode, e);
|
||||
} else if (e.target.nextElementSibling && 'A' == e.target.nextElementSibling.tagName) {
|
||||
f(e.target.nextElementSibling, e, true);
|
||||
}
|
||||
});
|
||||
};
|
||||
function isCtrlKey(e) {
|
||||
return e.ctrlKey || e.metaKey;
|
||||
}
|
||||
function xpathString(str) {
|
||||
var parts = str.match(/[^'"]+|['"]/g).map(function (part) {
|
||||
if ("'" == part) {
|
||||
return '"\'"';
|
||||
}
|
||||
if ('"' == part) {
|
||||
return "'\"'";
|
||||
}
|
||||
|
||||
return "'" + part + "'";
|
||||
});
|
||||
|
||||
return "concat(" + parts.join(",") + ", '')";
|
||||
}
|
||||
function xpathHasClass(className) {
|
||||
return "contains(concat(' ', normalize-space(@class), ' '), ' " + className +" ')";
|
||||
}
|
||||
addEventListener(root, 'mouseover', function (e) {
|
||||
if ('' != refStyle.innerHTML) {
|
||||
refStyle.innerHTML = '';
|
||||
}
|
||||
});
|
||||
a('mouseover', function (a, e, c) {
|
||||
if (c) {
|
||||
e.target.style.cursor = "pointer";
|
||||
} else if (a = idRx.exec(a.className)) {
|
||||
try {
|
||||
refStyle.innerHTML = 'pre.sf-dump .'+a[0]+'{background-color: #B729D9; color: #FFF !important; border-radius: 2px}';
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
});
|
||||
a('click', function (a, e, c) {
|
||||
if (/\bsf-dump-toggle\b/.test(a.className)) {
|
||||
e.preventDefault();
|
||||
if (!toggle(a, isCtrlKey(e))) {
|
||||
var r = doc.getElementById(a.getAttribute('href').substr(1)),
|
||||
s = r.previousSibling,
|
||||
f = r.parentNode,
|
||||
t = a.parentNode;
|
||||
t.replaceChild(r, a);
|
||||
f.replaceChild(a, s);
|
||||
t.insertBefore(s, r);
|
||||
f = f.firstChild.nodeValue.match(indentRx);
|
||||
t = t.firstChild.nodeValue.match(indentRx);
|
||||
if (f && t && f[0] !== t[0]) {
|
||||
r.innerHTML = r.innerHTML.replace(new RegExp('^'+f[0].replace(rxEsc, '\\$1'), 'mg'), t[0]);
|
||||
}
|
||||
if (/\bsf-dump-compact\b/.test(r.className)) {
|
||||
toggle(s, isCtrlKey(e));
|
||||
}
|
||||
}
|
||||
|
||||
if (c) {
|
||||
} else if (doc.getSelection) {
|
||||
try {
|
||||
doc.getSelection().removeAllRanges();
|
||||
} catch (e) {
|
||||
doc.getSelection().empty();
|
||||
}
|
||||
} else {
|
||||
doc.selection.empty();
|
||||
}
|
||||
} else if (/\bsf-dump-str-toggle\b/.test(a.className)) {
|
||||
e.preventDefault();
|
||||
e = a.parentNode.parentNode;
|
||||
e.className = e.className.replace(/\bsf-dump-str-(expand|collapse)\b/, a.parentNode.className);
|
||||
}
|
||||
});
|
||||
|
||||
elt = root.getElementsByTagName('SAMP');
|
||||
len = elt.length;
|
||||
i = 0;
|
||||
|
||||
while (i < len) t.push(elt[i++]);
|
||||
len = t.length;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
elt = t[i];
|
||||
if ('SAMP' == elt.tagName) {
|
||||
a = elt.previousSibling || {};
|
||||
if ('A' != a.tagName) {
|
||||
a = doc.createElement('A');
|
||||
a.className = 'sf-dump-ref';
|
||||
elt.parentNode.insertBefore(a, elt);
|
||||
} else {
|
||||
a.innerHTML += ' ';
|
||||
}
|
||||
a.title = (a.title ? a.title+'\n[' : '[')+keyHint+'+click] Expand all children';
|
||||
a.innerHTML += '<span>▼</span>';
|
||||
a.className += ' sf-dump-toggle';
|
||||
|
||||
x = 1;
|
||||
if ('sf-dump' != elt.parentNode.className) {
|
||||
x += elt.parentNode.getAttribute('data-depth')/1;
|
||||
}
|
||||
elt.setAttribute('data-depth', x);
|
||||
var className = elt.className;
|
||||
elt.className = 'sf-dump-expanded';
|
||||
if (className ? 'sf-dump-expanded' !== className : (x > options.maxDepth)) {
|
||||
toggle(a);
|
||||
}
|
||||
} else if (/\bsf-dump-ref\b/.test(elt.className) && (a = elt.getAttribute('href'))) {
|
||||
a = a.substr(1);
|
||||
elt.className += ' '+a;
|
||||
|
||||
if (/[\[{]$/.test(elt.previousSibling.nodeValue)) {
|
||||
a = a != elt.nextSibling.id && doc.getElementById(a);
|
||||
try {
|
||||
s = a.nextSibling;
|
||||
elt.appendChild(a);
|
||||
s.parentNode.insertBefore(a, s);
|
||||
if (/^[@#]/.test(elt.innerHTML)) {
|
||||
elt.innerHTML += ' <span>▶</span>';
|
||||
} else {
|
||||
elt.innerHTML = '<span>▶</span>';
|
||||
elt.className = 'sf-dump-ref';
|
||||
}
|
||||
elt.className += ' sf-dump-toggle';
|
||||
} catch (e) {
|
||||
if ('&' == elt.innerHTML.charAt(0)) {
|
||||
elt.innerHTML = '…';
|
||||
elt.className = 'sf-dump-ref';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (doc.evaluate && Array.from && root.children.length > 1) {
|
||||
root.setAttribute('tabindex', 0);
|
||||
|
||||
SearchState = function () {
|
||||
this.nodes = [];
|
||||
this.idx = 0;
|
||||
};
|
||||
SearchState.prototype = {
|
||||
next: function () {
|
||||
if (this.isEmpty()) {
|
||||
return this.current();
|
||||
}
|
||||
this.idx = this.idx < (this.nodes.length - 1) ? this.idx + 1 : 0;
|
||||
|
||||
return this.current();
|
||||
},
|
||||
previous: function () {
|
||||
if (this.isEmpty()) {
|
||||
return this.current();
|
||||
}
|
||||
this.idx = this.idx > 0 ? this.idx - 1 : (this.nodes.length - 1);
|
||||
|
||||
return this.current();
|
||||
},
|
||||
isEmpty: function () {
|
||||
return 0 === this.count();
|
||||
},
|
||||
current: function () {
|
||||
if (this.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return this.nodes[this.idx];
|
||||
},
|
||||
reset: function () {
|
||||
this.nodes = [];
|
||||
this.idx = 0;
|
||||
},
|
||||
count: function () {
|
||||
return this.nodes.length;
|
||||
},
|
||||
};
|
||||
|
||||
function showCurrent(state)
|
||||
{
|
||||
var currentNode = state.current();
|
||||
if (currentNode) {
|
||||
reveal(currentNode);
|
||||
highlight(root, currentNode, state.nodes);
|
||||
}
|
||||
counter.textContent = (state.isEmpty() ? 0 : state.idx + 1) + ' of ' + state.count();
|
||||
}
|
||||
|
||||
var search = doc.createElement('div');
|
||||
search.className = 'sf-dump-search-wrapper sf-dump-search-hidden';
|
||||
search.innerHTML = '
|
||||
<input type="text" class="sf-dump-search-input">
|
||||
<span class="sf-dump-search-count">0 of 0<\/span>
|
||||
<button type="button" class="sf-dump-search-input-previous" tabindex="-1">
|
||||
<svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1683 1331l-166 165q-19 19-45 19t-45-19L896 965l-531 531q-19 19-45 19t-45-19l-166-165q-19-19-19-45.5t19-45.5l742-741q19-19 45-19t45 19l742 741q19 19 19 45.5t-19 45.5z"\/><\/svg>
|
||||
<\/button>
|
||||
<button type="button" class="sf-dump-search-input-next" tabindex="-1">
|
||||
<svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1683 808l-742 741q-19 19-45 19t-45-19L109 808q-19-19-19-45.5t19-45.5l166-165q19-19 45-19t45 19l531 531 531-531q19-19 45-19t45 19l166 165q19 19 19 45.5t-19 45.5z"\/><\/svg>
|
||||
<\/button>
|
||||
';
|
||||
root.insertBefore(search, root.firstChild);
|
||||
|
||||
var state = new SearchState();
|
||||
var searchInput = search.querySelector('.sf-dump-search-input');
|
||||
var counter = search.querySelector('.sf-dump-search-count');
|
||||
var searchInputTimer = 0;
|
||||
var previousSearchQuery = '';
|
||||
|
||||
addEventListener(searchInput, 'keyup', function (e) {
|
||||
var searchQuery = e.target.value;
|
||||
/* Don't perform anything if the pressed key didn't change the query */
|
||||
if (searchQuery === previousSearchQuery) {
|
||||
return;
|
||||
}
|
||||
previousSearchQuery = searchQuery;
|
||||
clearTimeout(searchInputTimer);
|
||||
searchInputTimer = setTimeout(function () {
|
||||
state.reset();
|
||||
collapseAll(root);
|
||||
resetHighlightedNodes(root);
|
||||
if ('' === searchQuery) {
|
||||
counter.textContent = '0 of 0';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var classMatches = [
|
||||
"sf-dump-str",
|
||||
"sf-dump-key",
|
||||
"sf-dump-public",
|
||||
"sf-dump-protected",
|
||||
"sf-dump-private",
|
||||
].map(xpathHasClass).join(' or ');
|
||||
|
||||
var xpathResult = doc.evaluate('.//span[' + classMatches + '][contains(translate(child::text(), ' + xpathString(searchQuery.toUpperCase()) + ', ' + xpathString(searchQuery.toLowerCase()) + '), ' + xpathString(searchQuery.toLowerCase()) + ')]', root, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
|
||||
|
||||
while (node = xpathResult.iterateNext()) state.nodes.push(node);
|
||||
|
||||
showCurrent(state);
|
||||
}, 400);
|
||||
});
|
||||
|
||||
Array.from(search.querySelectorAll('.sf-dump-search-input-next, .sf-dump-search-input-previous')).forEach(function (btn) {
|
||||
addEventListener(btn, 'click', function (e) {
|
||||
e.preventDefault();
|
||||
-1 !== e.target.className.indexOf('next') ? state.next() : state.previous();
|
||||
searchInput.focus();
|
||||
collapseAll(root);
|
||||
showCurrent(state);
|
||||
})
|
||||
});
|
||||
|
||||
addEventListener(root, 'keydown', function (e) {
|
||||
var isSearchActive = !/\bsf-dump-search-hidden\b/.test(search.className);
|
||||
if ((114 === e.keyCode && !isSearchActive) || (isCtrlKey(e) && 70 === e.keyCode)) {
|
||||
/* F3 or CMD/CTRL + F */
|
||||
e.preventDefault();
|
||||
search.className = search.className.replace(/\bsf-dump-search-hidden\b/, '');
|
||||
searchInput.focus();
|
||||
} else if (isSearchActive) {
|
||||
if (27 === e.keyCode) {
|
||||
/* ESC key */
|
||||
search.className += ' sf-dump-search-hidden';
|
||||
e.preventDefault();
|
||||
resetHighlightedNodes(root);
|
||||
searchInput.value = '';
|
||||
} else if (
|
||||
(isCtrlKey(e) && 71 === e.keyCode) /* CMD/CTRL + G */
|
||||
|| 13 === e.keyCode /* Enter */
|
||||
|| 114 === e.keyCode /* F3 */
|
||||
) {
|
||||
e.preventDefault();
|
||||
e.shiftKey ? state.previous() : state.next();
|
||||
collapseAll(root);
|
||||
showCurrent(state);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (0 >= options.maxStringLength) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
elt = root.querySelectorAll('.sf-dump-str');
|
||||
len = elt.length;
|
||||
i = 0;
|
||||
t = [];
|
||||
|
||||
while (i < len) t.push(elt[i++]);
|
||||
len = t.length;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
elt = t[i];
|
||||
s = elt.innerText || elt.textContent;
|
||||
x = s.length - options.maxStringLength;
|
||||
if (0 < x) {
|
||||
h = elt.innerHTML;
|
||||
elt[elt.innerText ? 'innerText' : 'textContent'] = s.substring(0, options.maxStringLength);
|
||||
elt.className += ' sf-dump-str-collapse';
|
||||
elt.innerHTML = '<span class=sf-dump-str-collapse>'+h+'<a class="sf-dump-ref sf-dump-str-toggle" title="Collapse"> ◀</a></span>'+
|
||||
'<span class=sf-dump-str-expand>'+elt.innerHTML+'<a class="sf-dump-ref sf-dump-str-toggle" title="'+x+' remaining characters"> ▶</a></span>';
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
};
|
||||
|
||||
})(document);
|
||||
</script><style>
|
||||
pre.sf-dump {
|
||||
display: block;
|
||||
white-space: pre;
|
||||
padding: 5px;
|
||||
}
|
||||
pre.sf-dump:after {
|
||||
content: "";
|
||||
visibility: hidden;
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
}
|
||||
pre.sf-dump span {
|
||||
display: inline;
|
||||
}
|
||||
pre.sf-dump .sf-dump-compact {
|
||||
display: none;
|
||||
}
|
||||
pre.sf-dump abbr {
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
cursor: help;
|
||||
}
|
||||
pre.sf-dump a {
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
border: 0;
|
||||
outline: none;
|
||||
color: inherit;
|
||||
}
|
||||
pre.sf-dump .sf-dump-ellipsis {
|
||||
display: inline-block;
|
||||
overflow: visible;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 5em;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
vertical-align: top;
|
||||
}
|
||||
pre.sf-dump .sf-dump-ellipsis+.sf-dump-ellipsis {
|
||||
max-width: none;
|
||||
}
|
||||
pre.sf-dump code {
|
||||
display:inline;
|
||||
padding:0;
|
||||
background:none;
|
||||
}
|
||||
.sf-dump-str-collapse .sf-dump-str-collapse {
|
||||
display: none;
|
||||
}
|
||||
.sf-dump-str-expand .sf-dump-str-expand {
|
||||
display: none;
|
||||
}
|
||||
.sf-dump-public.sf-dump-highlight,
|
||||
.sf-dump-protected.sf-dump-highlight,
|
||||
.sf-dump-private.sf-dump-highlight,
|
||||
.sf-dump-str.sf-dump-highlight,
|
||||
.sf-dump-key.sf-dump-highlight {
|
||||
background: rgba(111, 172, 204, 0.3);
|
||||
border: 1px solid #7DA0B1;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.sf-dump-public.sf-dump-highlight-active,
|
||||
.sf-dump-protected.sf-dump-highlight-active,
|
||||
.sf-dump-private.sf-dump-highlight-active,
|
||||
.sf-dump-str.sf-dump-highlight-active,
|
||||
.sf-dump-key.sf-dump-highlight-active {
|
||||
background: rgba(253, 175, 0, 0.4);
|
||||
border: 1px solid #ffa500;
|
||||
border-radius: 3px;
|
||||
}
|
||||
pre.sf-dump .sf-dump-search-hidden {
|
||||
display: none;
|
||||
}
|
||||
pre.sf-dump .sf-dump-search-wrapper {
|
||||
float: right;
|
||||
font-size: 0;
|
||||
white-space: nowrap;
|
||||
max-width: 100%;
|
||||
text-align: right;
|
||||
}
|
||||
pre.sf-dump .sf-dump-search-wrapper > * {
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
height: 21px;
|
||||
font-weight: normal;
|
||||
border-radius: 0;
|
||||
background: #FFF;
|
||||
color: #757575;
|
||||
border: 1px solid #BBB;
|
||||
}
|
||||
pre.sf-dump .sf-dump-search-wrapper > input.sf-dump-search-input {
|
||||
padding: 3px;
|
||||
height: 21px;
|
||||
font-size: 12px;
|
||||
border-right: none;
|
||||
width: 140px;
|
||||
border-top-left-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
color: #000;
|
||||
}
|
||||
pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next,
|
||||
pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous {
|
||||
background: #F2F2F2;
|
||||
outline: none;
|
||||
border-left: none;
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
}
|
||||
pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next {
|
||||
border-top-right-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next > svg,
|
||||
pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous > svg {
|
||||
pointer-events: none;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-count {
|
||||
display: inline-block;
|
||||
padding: 0 5px;
|
||||
margin: 0;
|
||||
border-left: none;
|
||||
line-height: 21px;
|
||||
font-size: 12px;
|
||||
}
|
||||
EOHTML
|
||||
);
|
||||
|
||||
foreach ($this->styles as $class => $style) {
|
||||
$line .= 'pre.sf-dump'.('default' === $class ? ', pre.sf-dump' : '').' .sf-dump-'.$class.'{'.$style.'}';
|
||||
}
|
||||
|
||||
return $this->dumpHeader = preg_replace('/\s+/', ' ', $line).'</style>'.$this->dumpHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function enterHash(Cursor $cursor, $type, $class, $hasChild)
|
||||
{
|
||||
parent::enterHash($cursor, $type, $class, false);
|
||||
|
||||
if ($cursor->skipChildren) {
|
||||
$cursor->skipChildren = false;
|
||||
$eol = ' class=sf-dump-compact>';
|
||||
} elseif ($this->expandNextHash) {
|
||||
$this->expandNextHash = false;
|
||||
$eol = ' class=sf-dump-expanded>';
|
||||
} else {
|
||||
$eol = '>';
|
||||
}
|
||||
|
||||
if ($hasChild) {
|
||||
$this->line .= '<samp';
|
||||
if ($cursor->refIndex) {
|
||||
$r = Cursor::HASH_OBJECT !== $type ? 1 - (Cursor::HASH_RESOURCE !== $type) : 2;
|
||||
$r .= $r && 0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->refIndex;
|
||||
|
||||
$this->line .= sprintf(' id=%s-ref%s', $this->dumpId, $r);
|
||||
}
|
||||
$this->line .= $eol;
|
||||
$this->dumpLine($cursor->depth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function leaveHash(Cursor $cursor, $type, $class, $hasChild, $cut)
|
||||
{
|
||||
$this->dumpEllipsis($cursor, $hasChild, $cut);
|
||||
if ($hasChild) {
|
||||
$this->line .= '</samp>';
|
||||
}
|
||||
parent::leaveHash($cursor, $type, $class, $hasChild, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function style($style, $value, $attr = [])
|
||||
{
|
||||
if ('' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$v = esc($value);
|
||||
|
||||
if ('ref' === $style) {
|
||||
if (empty($attr['count'])) {
|
||||
return sprintf('<a class=sf-dump-ref>%s</a>', $v);
|
||||
}
|
||||
$r = ('#' !== $v[0] ? 1 - ('@' !== $v[0]) : 2).substr($value, 1);
|
||||
|
||||
return sprintf('<a class=sf-dump-ref href=#%s-ref%s title="%d occurrences">%s</a>', $this->dumpId, $r, 1 + $attr['count'], $v);
|
||||
}
|
||||
|
||||
if ('const' === $style && isset($attr['value'])) {
|
||||
$style .= sprintf(' title="%s"', esc(is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value'])));
|
||||
} elseif ('public' === $style) {
|
||||
$style .= sprintf(' title="%s"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property');
|
||||
} elseif ('str' === $style && 1 < $attr['length']) {
|
||||
$style .= sprintf(' title="%d%s characters"', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : '');
|
||||
} elseif ('note' === $style && false !== $c = strrpos($v, '\\')) {
|
||||
return sprintf('<abbr title="%s" class=sf-dump-%s>%s</abbr>', $v, $style, substr($v, $c + 1));
|
||||
} elseif ('protected' === $style) {
|
||||
$style .= ' title="Protected property"';
|
||||
} elseif ('meta' === $style && isset($attr['title'])) {
|
||||
$style .= sprintf(' title="%s"', esc($this->utf8Encode($attr['title'])));
|
||||
} elseif ('private' === $style) {
|
||||
$style .= sprintf(' title="Private property defined in class: `%s`"', esc($this->utf8Encode($attr['class'])));
|
||||
}
|
||||
$map = static::$controlCharsMap;
|
||||
|
||||
if (isset($attr['ellipsis'])) {
|
||||
$class = 'sf-dump-ellipsis';
|
||||
if (isset($attr['ellipsis-type'])) {
|
||||
$class = sprintf('"%s sf-dump-ellipsis-%s"', $class, $attr['ellipsis-type']);
|
||||
}
|
||||
$label = esc(substr($value, -$attr['ellipsis']));
|
||||
$style = str_replace(' title="', " title=\"$v\n", $style);
|
||||
$v = sprintf('<span class=%s>%s</span>', $class, substr($v, 0, -\strlen($label)));
|
||||
|
||||
if (!empty($attr['ellipsis-tail'])) {
|
||||
$tail = \strlen(esc(substr($value, -$attr['ellipsis'], $attr['ellipsis-tail'])));
|
||||
$v .= sprintf('<span class=sf-dump-ellipsis>%s</span>%s', substr($label, 0, $tail), substr($label, $tail));
|
||||
} else {
|
||||
$v .= $label;
|
||||
}
|
||||
}
|
||||
|
||||
$v = "<span class=sf-dump-{$style}>".preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) {
|
||||
$s = '<span class=sf-dump-default>';
|
||||
$c = $c[$i = 0];
|
||||
do {
|
||||
$s .= isset($map[$c[$i]]) ? $map[$c[$i]] : sprintf('\x%02X', \ord($c[$i]));
|
||||
} while (isset($c[++$i]));
|
||||
|
||||
return $s.'</span>';
|
||||
}, $v).'</span>';
|
||||
|
||||
if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], isset($attr['line']) ? $attr['line'] : 0)) {
|
||||
$attr['href'] = $href;
|
||||
}
|
||||
if (isset($attr['href'])) {
|
||||
$target = isset($attr['file']) ? '' : ' target="_blank"';
|
||||
$v = sprintf('<a href="%s"%s rel="noopener noreferrer">%s</a>', esc($this->utf8Encode($attr['href'])), $target, $v);
|
||||
}
|
||||
if (isset($attr['lang'])) {
|
||||
$v = sprintf('<code class="%s">%s</code>', esc($attr['lang']), $v);
|
||||
}
|
||||
|
||||
return $v;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function dumpLine($depth, $endOfValue = false)
|
||||
{
|
||||
if (-1 === $this->lastDepth) {
|
||||
$this->line = sprintf($this->dumpPrefix, $this->dumpId, $this->indentPad).$this->line;
|
||||
}
|
||||
if ($this->headerIsDumped !== (null !== $this->outputStream ? $this->outputStream : $this->lineDumper)) {
|
||||
$this->line = $this->getDumpHeader().$this->line;
|
||||
}
|
||||
|
||||
if (-1 === $depth) {
|
||||
$args = ['"'.$this->dumpId.'"'];
|
||||
if ($this->extraDisplayOptions) {
|
||||
$args[] = json_encode($this->extraDisplayOptions, \JSON_FORCE_OBJECT);
|
||||
}
|
||||
// Replace is for BC
|
||||
$this->line .= sprintf(str_replace('"%s"', '%s', $this->dumpSuffix), implode(', ', $args));
|
||||
}
|
||||
$this->lastDepth = $depth;
|
||||
|
||||
$this->line = htmlentities($this->line);
|
||||
|
||||
if (-1 === $depth) {
|
||||
AbstractDumper::dumpLine(0);
|
||||
}
|
||||
AbstractDumper::dumpLine($depth);
|
||||
}
|
||||
|
||||
private function getSourceLink($file, $line)
|
||||
{
|
||||
$options = $this->extraDisplayOptions + $this->displayOptions;
|
||||
|
||||
if ($fmt = $options['fileLinkFormat']) {
|
||||
return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function esc($str)
|
||||
{
|
||||
return htmlspecialchars($str, \ENT_QUOTES, 'UTF-8');
|
||||
}
|
Loading…
Reference in New Issue
Block a user