diff --git a/COPYRIGHT b/COPYRIGHT index d980219c420..d04c007ff65 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -31,7 +31,7 @@ NuSoap 0.9.5 LGPL 2.1+ Yes PEAR Mail_MIME 1.8.9 BSD Yes NuSoap dependency ParseDown 1.6 MIT License Yes Markdown parser PCLZip 2.8.4 LGPL-3+ Yes Library to zip/unzip files -PHPDebugBar 1.15.1 MIT License Yes Used only by the module "debugbar" for developers +PHPDebugBar 1.18.2 MIT License Yes Used only by the module "debugbar" for developers PHP-Imap 2.7.2 MIT License Yes Library to use IMAP with OAuth PHPSpreadSheet 1.8.2 LGPL-2.1+ Yes Read/Write XLS files, read ODS files php-iban 4.1.1 LGPL-3+ Yes Parse and validate IBAN (and IIBAN) bank account information in PHP diff --git a/htdocs/includes/maximebf/debugbar/composer.json b/htdocs/includes/maximebf/debugbar/composer.json index e68fc461f1c..50793eb6f6c 100644 --- a/htdocs/includes/maximebf/debugbar/composer.json +++ b/htdocs/includes/maximebf/debugbar/composer.json @@ -17,12 +17,13 @@ } ], "require": { - "php": ">=5.6", - "psr/log": "^1.0", - "symfony/var-dumper": "^2.6|^3|^4" + "php": "^7.1|^8", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^4|^5|^6" }, "require-dev": { - "phpunit/phpunit": "^5" + "phpunit/phpunit": ">=7.5.20 <10.0", + "twig/twig": "^1.38|^2.7|^3.0" }, "autoload": { "psr-4": { @@ -36,7 +37,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.18-dev" } } } diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/MonologCollector.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/MonologCollector.php index f24b296d574..49eb37c27f5 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/MonologCollector.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/MonologCollector.php @@ -57,9 +57,9 @@ class MonologCollector extends AbstractProcessingHandler implements DataCollecto } /** - * @param array $record + * @param array|\Monolog\LogRecord $record */ - protected function write(array $record) + protected function write($record): void { $this->records[] = array( 'message' => $record['formatted'], diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/NamespacedTwigProfileCollector.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/NamespacedTwigProfileCollector.php new file mode 100644 index 00000000000..02e7306e232 --- /dev/null +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/NamespacedTwigProfileCollector.php @@ -0,0 +1,204 @@ + + * $env = new \Twig\Environment($loader); // Or from a PSR11-container + * $profile = new \Twig\Profiler\Profile(); + * $env->addExtension(new \Twig\Extension\ProfilerExtension($profile)); + * $debugbar->addCollector(new ModernTwigProfileCollector($profile, $env)); + * // or: $debugbar->addCollector(new ModernTwigProfileCollector($profile, $loader)); + * + */ +class NamespacedTwigProfileCollector extends DataCollector implements Renderable, AssetProvider +{ + /** + * @var Profile + */ + private $profile; + + /** + * @var LoaderInterface|Environment|null + */ + private $loader; + + /** + * @var int + */ + private $templateCount; + + /** + * @var int + */ + private $blockCount; + + /** + * @var int + */ + private $macroCount; + /** + * @var array[] { + * @var string $name + * @var int $render_time + * @var string $render_time_str + * @var string $memory_str + * @var string $xdebug_link + * } + */ + private $templates; + + /** + * TwigProfileCollector constructor. + * + * @param Profile $profile + * @param LoaderInterface|Environment $loaderOrEnv + */ + public function __construct(Profile $profile, $loaderOrEnv = null) + { + $this->profile = $profile; + if ($loaderOrEnv instanceof Environment) { + $loaderOrEnv = $loaderOrEnv->getLoader(); + } + $this->loader = $loaderOrEnv; + } + + /** + * Returns a hash where keys are control names and their values + * an array of options as defined in {@see \DebugBar\JavascriptRenderer::addControl()} + * + * @return array + */ + public function getWidgets() + { + return [ + 'twig' => [ + 'icon' => 'leaf', + 'widget' => 'PhpDebugBar.Widgets.TemplatesWidget', + 'map' => 'twig', + 'default' => json_encode(['templates' => []]), + ], + 'twig:badge' => [ + 'map' => 'twig.badge', + 'default' => 0, + ], + ]; + } + + /** + * @return array + */ + public function getAssets() + { + return [ + 'css' => 'widgets/templates/widget.css', + 'js' => 'widgets/templates/widget.js', + ]; + } + + /** + * Called by the DebugBar when data needs to be collected + * + * @return array Collected data + */ + public function collect() + { + $this->templateCount = $this->blockCount = $this->macroCount = 0; + $this->templates = []; + $this->computeData($this->profile); + + return [ + 'nb_templates' => $this->templateCount, + 'nb_blocks' => $this->blockCount, + 'nb_macros' => $this->macroCount, + 'templates' => $this->templates, + 'accumulated_render_time' => $this->profile->getDuration(), + 'accumulated_render_time_str' => $this->getDataFormatter()->formatDuration($this->profile->getDuration()), + 'memory_usage_str' => $this->getDataFormatter()->formatBytes($this->profile->getMemoryUsage()), + 'callgraph' => $this->getHtmlCallGraph(), + 'badge' => implode( + '/', + [ + $this->templateCount, + $this->blockCount, + $this->macroCount, + ] + ), + ]; + } + + /** + * Returns the unique name of the collector + * + * @return string + */ + public function getName() + { + return 'twig'; + } + + public function getHtmlCallGraph() + { + $dumper = new HtmlDumper(); + return $dumper->dump($this->profile); + } + + /** + * Get an Xdebug Link to a file + * + * @return array { + * @var string url + * @var bool ajax + * } + */ + public function getXdebugLink($template, $line = 1) + { + if (is_null($this->loader)) { + return null; + } + $file = $this->loader->getSourceContext($template)->getPath(); + + return parent::getXdebugLink($file, $line); + } + + private function computeData(Profile $profile) + { + $this->templateCount += ($profile->isTemplate() ? 1 : 0); + $this->blockCount += ($profile->isBlock() ? 1 : 0); + $this->macroCount += ($profile->isMacro() ? 1 : 0); + if ($profile->isTemplate()) { + $this->templates[] = [ + 'name' => $profile->getName(), + 'render_time' => $profile->getDuration(), + 'render_time_str' => $this->getDataFormatter()->formatDuration($profile->getDuration()), + 'memory_str' => $this->getDataFormatter()->formatBytes($profile->getMemoryUsage()), + 'xdebug_link' => $this->getXdebugLink($profile->getTemplate()), + ]; + } + foreach ($profile as $p) { + $this->computeData($p); + } + } +} diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/SwiftMailer/SwiftLogCollector.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/SwiftMailer/SwiftLogCollector.php index fdef79a0bdc..e8c2fcd92f0 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/SwiftMailer/SwiftLogCollector.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/SwiftMailer/SwiftLogCollector.php @@ -34,7 +34,16 @@ class SwiftLogCollector extends MessagesCollector implements Swift_Plugins_Logge public function dump() { - return implode(PHP_EOL, $this->_log); + $dump = ''; + foreach ($this->messages as $message) { + if (!$message['is_string']) { + continue; + } + + $dump .= $message['message'] . PHP_EOL; + } + + return $dump; } public function getName() diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TimeableTwigExtensionProfiler.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TimeableTwigExtensionProfiler.php index 3611d2d8efa..30238cc20a4 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TimeableTwigExtensionProfiler.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TimeableTwigExtensionProfiler.php @@ -57,4 +57,4 @@ class TimeableTwigExtensionProfiler extends \Twig_Extension_Profiler $this->timeDataCollector->stopMeasure($profile->getName()); } } -} \ No newline at end of file +} diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TraceableTwigEnvironment.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TraceableTwigEnvironment.php index cdaae7a4525..9e98c191115 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TraceableTwigEnvironment.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TraceableTwigEnvironment.php @@ -24,6 +24,8 @@ use Twig_TokenStream; /** * Wrapped a Twig Environment to provide profiling features + * + * @deprecated */ class TraceableTwigEnvironment extends Twig_Environment { diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TraceableTwigTemplate.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TraceableTwigTemplate.php index 648f7baf4da..1d57d2a518a 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TraceableTwigTemplate.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TraceableTwigTemplate.php @@ -15,6 +15,8 @@ use Twig_TemplateInterface; /** * Wraps a Twig_Template to add profiling features + * + * @deprecated */ class TraceableTwigTemplate extends Twig_Template implements Twig_TemplateInterface { diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TwigCollector.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TwigCollector.php index c571d835bcc..bb48ab79a36 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TwigCollector.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/Twig/TwigCollector.php @@ -26,6 +26,8 @@ use DebugBar\DataCollector\Renderable; * $env = new TraceableTwigEnvironment(new Twig_Environment($loader)); * $debugbar->addCollector(new TwigCollector($env)); * + * + * @deprecated use DebugBar\Bridge\TwigProfileCollector instead */ class TwigCollector extends DataCollector implements Renderable, AssetProvider { diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/TwigProfileCollector.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/TwigProfileCollector.php index efd3a7d523e..ce68fcbb403 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/TwigProfileCollector.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/Bridge/TwigProfileCollector.php @@ -34,6 +34,8 @@ use DebugBar\DataCollector\Renderable; * $debugbar->addCollector(new TwigProfileCollector($profile, $env)); * // or: $debugbar->addCollector(new TwigProfileCollector($profile, $loader)); * + * + * @deprecated Use `\Debugbar\Bridge\NamespacedTwigProfileCollector` instead for Twig 2.x and 3.x */ class TwigProfileCollector extends DataCollector implements Renderable, AssetProvider { diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/AggregatedCollector.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/AggregatedCollector.php index c1fd96aef26..56c9dc7aa47 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/AggregatedCollector.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/AggregatedCollector.php @@ -48,7 +48,7 @@ class AggregatedCollector implements DataCollectorInterface, ArrayAccess /** * @param DataCollectorInterface $collector */ - public function addCollector(DataCollectorInterface $collector) + public function addCollector(DataCollectorInterface $collector) : void { $this->collectors[$collector->getName()] = $collector; } @@ -56,7 +56,7 @@ class AggregatedCollector implements DataCollectorInterface, ArrayAccess /** * @return array */ - public function getCollectors() + public function getCollectors() : array { return $this->collectors; } @@ -66,7 +66,7 @@ class AggregatedCollector implements DataCollectorInterface, ArrayAccess * * @param string $property */ - public function setMergeProperty($property) + public function setMergeProperty($property) : void { $this->mergeProperty = $property; } @@ -74,7 +74,7 @@ class AggregatedCollector implements DataCollectorInterface, ArrayAccess /** * @return string */ - public function getMergeProperty() + public function getMergeProperty() : string { return $this->mergeProperty; } @@ -87,7 +87,7 @@ class AggregatedCollector implements DataCollectorInterface, ArrayAccess * * @param bool|string $sort */ - public function setSort($sort) + public function setSort($sort) : void { $this->sort = $sort; } @@ -103,7 +103,7 @@ class AggregatedCollector implements DataCollectorInterface, ArrayAccess /** * @return array */ - public function collect() + public function collect() : array { $aggregate = array(); foreach ($this->collectors as $collector) { @@ -123,7 +123,7 @@ class AggregatedCollector implements DataCollectorInterface, ArrayAccess * @param array $data * @return array */ - protected function sort($data) + protected function sort($data) : array { if (is_string($this->sort)) { $p = $this->sort; @@ -142,7 +142,7 @@ class AggregatedCollector implements DataCollectorInterface, ArrayAccess /** * @return string */ - public function getName() + public function getName() : string { return $this->name; } @@ -155,7 +155,7 @@ class AggregatedCollector implements DataCollectorInterface, ArrayAccess * @param mixed $value * @throws DebugBarException */ - public function offsetSet($key, $value) + public function offsetSet($key, $value): void { throw new DebugBarException("AggregatedCollector[] is read-only"); } @@ -164,6 +164,7 @@ class AggregatedCollector implements DataCollectorInterface, ArrayAccess * @param mixed $key * @return mixed */ + #[\ReturnTypeWillChange] public function offsetGet($key) { return $this->collectors[$key]; @@ -173,7 +174,7 @@ class AggregatedCollector implements DataCollectorInterface, ArrayAccess * @param mixed $key * @return bool */ - public function offsetExists($key) + public function offsetExists($key): bool { return isset($this->collectors[$key]); } @@ -182,7 +183,7 @@ class AggregatedCollector implements DataCollectorInterface, ArrayAccess * @param mixed $key * @throws DebugBarException */ - public function offsetUnset($key) + public function offsetUnset($key): void { throw new DebugBarException("AggregatedCollector[] is read-only"); } diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/ExceptionsCollector.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/ExceptionsCollector.php index 285bc971102..3fcac398016 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/ExceptionsCollector.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/ExceptionsCollector.php @@ -21,6 +21,10 @@ class ExceptionsCollector extends DataCollector implements Renderable protected $exceptions = array(); protected $chainExceptions = false; + // The HTML var dumper requires debug bar users to support the new inline assets, which not all + // may support yet - so return false by default for now. + protected $useHtmlVarDumper = false; + /** * Adds an exception to be profiled in the debug bar * @@ -65,6 +69,30 @@ class ExceptionsCollector extends DataCollector implements Renderable return $this->exceptions; } + /** + * Sets a flag indicating whether the Symfony HtmlDumper will be used to dump variables for + * rich variable rendering. + * + * @param bool $value + * @return $this + */ + public function useHtmlVarDumper($value = true) + { + $this->useHtmlVarDumper = $value; + return $this; + } + + /** + * Indicates whether the Symfony HtmlDumper will be used to dump variables for rich variable + * rendering. + * + * @return mixed + */ + public function isHtmlVarDumperUsed() + { + return $this->useHtmlVarDumper; + } + public function collect() { return array( @@ -102,6 +130,11 @@ class ExceptionsCollector extends DataCollector implements Renderable $lines = array("Cannot open the file ($filePath) in which the exception occurred "); } + $traceHtml = null; + if ($this->isHtmlVarDumperUsed()) { + $traceHtml = $this->getVarDumper()->renderVar($e->getTrace()); + } + return array( 'type' => get_class($e), 'message' => $e->getMessage(), @@ -109,6 +142,7 @@ class ExceptionsCollector extends DataCollector implements Renderable 'file' => $filePath, 'line' => $e->getLine(), 'stack_trace' => $e->getTraceAsString(), + 'stack_trace_html' => $traceHtml, 'surrounding_lines' => $lines, 'xdebug_link' => $this->getXdebugLink($filePath, $e->getLine()) ); diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/MemoryCollector.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/MemoryCollector.php index 894f8870adc..1a34f3bddb0 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/MemoryCollector.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/MemoryCollector.php @@ -67,7 +67,7 @@ class MemoryCollector extends DataCollector implements Renderable $this->updatePeakUsage(); return array( 'peak_usage' => $this->peakUsage, - 'peak_usage_str' => $this->getDataFormatter()->formatBytes($this->peakUsage) + 'peak_usage_str' => $this->getDataFormatter()->formatBytes($this->peakUsage, 0) ); } diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/MessagesCollector.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/MessagesCollector.php index f26d3716ca2..8859e7d0175 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/MessagesCollector.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/MessagesCollector.php @@ -183,11 +183,37 @@ class MessagesCollector extends AbstractLogger implements DataCollectorInterface * @param $message * @param array $context */ - public function log($level, $message, array $context = array()) + public function log($level, $message, array $context = array()): void { + // For string messages, interpolate the context following PSR-3 + if (is_string($message)) { + $message = $this->interpolate($message, $context); + } $this->addMessage($message, $level); } + /** + * Interpolates context values into the message placeholders. + * + * @param $message + * @param array $context + * @return string + */ + function interpolate($message, array $context = array()) + { + // build a replacement array with braces around the context keys + $replace = array(); + foreach ($context as $key => $val) { + // check that the value can be cast to string + if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) { + $replace['{' . $key . '}'] = $val; + } + } + + // interpolate replacement values into the message and return + return strtr($message, $replace); + } + /** * Deletes all messages */ diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/PDOCollector.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/PDOCollector.php index e1eb35ad0bc..77e36307095 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/PDOCollector.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/PDOCollector.php @@ -21,10 +21,10 @@ class PDOCollector extends DataCollector implements Renderable, AssetProvider protected $sqlQuotationChar = '<>'; /** - * @param TraceablePDO $pdo + * @param \PDO $pdo * @param TimeDataCollector $timeCollector */ - public function __construct(TraceablePDO $pdo = null, TimeDataCollector $timeCollector = null) + public function __construct(\PDO $pdo = null, TimeDataCollector $timeCollector = null) { $this->timeCollector = $timeCollector; if ($pdo !== null) { @@ -65,11 +65,14 @@ class PDOCollector extends DataCollector implements Renderable, AssetProvider * @param TraceablePDO $pdo * @param string $name Optional connection name */ - public function addConnection(TraceablePDO $pdo, $name = null) + public function addConnection(\PDO $pdo, $name = null) { if ($name === null) { $name = spl_object_hash($pdo); } + if (!($pdo instanceof TraceablePDO)) { + $pdo = new TraceablePDO($pdo); + } $this->connections[$name] = $pdo; } diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/TraceablePDO.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/TraceablePDO.php index e448a794ad3..753964a343c 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/TraceablePDO.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/TraceablePDO.php @@ -23,13 +23,13 @@ class TraceablePDO extends PDO $this->pdo->setAttribute(PDO::ATTR_STATEMENT_CLASS, [TraceablePDOStatement::class, [$this]]); } - /** - * Initiates a transaction - * - * @link http://php.net/manual/en/pdo.begintransaction.php - * @return bool TRUE on success or FALSE on failure. - */ - public function beginTransaction() + /** + * Initiates a transaction + * + * @link http://php.net/manual/en/pdo.begintransaction.php + * @return bool TRUE on success or FALSE on failure. + */ + public function beginTransaction() : bool { return $this->pdo->beginTransaction(); } @@ -40,7 +40,7 @@ class TraceablePDO extends PDO * @link http://php.net/manual/en/pdo.commit.php * @return bool TRUE on success or FALSE on failure. */ - public function commit() + public function commit() : bool { return $this->pdo->commit(); } @@ -51,6 +51,7 @@ class TraceablePDO extends PDO * @link http://php.net/manual/en/pdo.errorinfo.php * @return array PDO::errorInfo returns an array of error information */ + #[\ReturnTypeWillChange] public function errorCode() { return $this->pdo->errorCode(); @@ -62,7 +63,7 @@ class TraceablePDO extends PDO * @link http://php.net/manual/en/pdo.errorinfo.php * @return array PDO::errorInfo returns an array of error information */ - public function errorInfo() + public function errorInfo() : array { return $this->pdo->errorInfo(); } @@ -77,6 +78,7 @@ class TraceablePDO extends PDO * return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE. * Please read the section on Booleans for more information */ + #[\ReturnTypeWillChange] public function exec($statement) { return $this->profileCall('exec', $statement, func_get_args()); @@ -90,6 +92,7 @@ class TraceablePDO extends PDO * @return mixed A successful call returns the value of the requested PDO attribute. * An unsuccessful call returns null. */ + #[\ReturnTypeWillChange] public function getAttribute($attribute) { return $this->pdo->getAttribute($attribute); @@ -101,7 +104,7 @@ class TraceablePDO extends PDO * @link http://php.net/manual/en/pdo.intransaction.php * @return bool TRUE if a transaction is currently active, and FALSE if not. */ - public function inTransaction() + public function inTransaction() : bool { return $this->pdo->inTransaction(); } @@ -114,36 +117,41 @@ class TraceablePDO extends PDO * @return string If a sequence name was not specified for the name parameter, PDO::lastInsertId * returns a string representing the row ID of the last row that was inserted into the database. */ + #[\ReturnTypeWillChange] public function lastInsertId($name = null) { return $this->pdo->lastInsertId($name); } - /** - * Prepares a statement for execution and returns a statement object - * - * @link http://php.net/manual/en/pdo.prepare.php - * @param string $statement This must be a valid SQL statement template for the target DB server. - * @param array $driver_options [optional] This array holds one or more key=>value pairs to - * set attribute values for the PDOStatement object that this method returns. - * @return TraceablePDOStatement|bool If the database server successfully prepares the statement, - * PDO::prepare returns a PDOStatement object. If the database server cannot successfully prepare - * the statement, PDO::prepare returns FALSE or emits PDOException (depending on error handling). - */ + /** + * Prepares a statement for execution and returns a statement object + * + * @link http://php.net/manual/en/pdo.prepare.php + * @param string $statement This must be a valid SQL statement template for the target DB server. + * @param array $driver_options [optional] This array holds one or more key=>value pairs to + * set attribute values for the PDOStatement object that this method returns. + * @return TraceablePDOStatement|bool If the database server successfully prepares the statement, + * PDO::prepare returns a PDOStatement object. If the database server cannot successfully prepare + * the statement, PDO::prepare returns FALSE or emits PDOException (depending on error handling). + */ + #[\ReturnTypeWillChange] public function prepare($statement, $driver_options = []) { return $this->pdo->prepare($statement, $driver_options); } - /** - * Executes an SQL statement, returning a result set as a PDOStatement object - * - * @link http://php.net/manual/en/pdo.query.php - * @param string $statement - * @return TraceablePDOStatement|bool PDO::query returns a PDOStatement object, or FALSE on - * failure. - */ - public function query($statement) + /** + * Executes an SQL statement, returning a result set as a PDOStatement object + * + * @link http://php.net/manual/en/pdo.query.php + * @param string $statement + * @param int $fetchMode + * @param mixed ...$fetchModeArgs + * @return TraceablePDOStatement|bool PDO::query returns a PDOStatement object, or FALSE on + * failure. + */ + #[\ReturnTypeWillChange] + public function query($statement, $fetchMode = null, ...$fetchModeArgs) { return $this->profileCall('query', $statement, func_get_args()); } @@ -158,6 +166,7 @@ class TraceablePDO extends PDO * @return string|bool A quoted string that is theoretically safe to pass into an SQL statement. * Returns FALSE if the driver does not support quoting in this way. */ + #[\ReturnTypeWillChange] public function quote($string, $parameter_type = PDO::PARAM_STR) { return $this->pdo->quote($string, $parameter_type); @@ -169,7 +178,7 @@ class TraceablePDO extends PDO * @link http://php.net/manual/en/pdo.rollback.php * @return bool TRUE on success or FALSE on failure. */ - public function rollBack() + public function rollBack() : bool { return $this->pdo->rollBack(); } @@ -182,7 +191,7 @@ class TraceablePDO extends PDO * @param mixed $value * @return bool TRUE on success or FALSE on failure. */ - public function setAttribute($attribute, $value) + public function setAttribute($attribute, $value) : bool { return $this->pdo->setAttribute($attribute, $value); } @@ -195,6 +204,7 @@ class TraceablePDO extends PDO * @param array $args * @return mixed The result of the call */ + #[\ReturnTypeWillChange] protected function profileCall($method, $sql, array $args) { $trace = new TracedStatement($sql); @@ -226,7 +236,7 @@ class TraceablePDO extends PDO * * @param TracedStatement $stmt */ - public function addExecutedStatement(TracedStatement $stmt) + public function addExecutedStatement(TracedStatement $stmt) : void { $this->executedStatements[] = $stmt; } @@ -234,9 +244,9 @@ class TraceablePDO extends PDO /** * Returns the accumulated execution time of statements * - * @return int + * @return float */ - public function getAccumulatedStatementsDuration() + public function getAccumulatedStatementsDuration() : float { return array_reduce($this->executedStatements, function ($v, $s) { return $v + $s->getDuration(); }); } @@ -246,7 +256,7 @@ class TraceablePDO extends PDO * * @return int */ - public function getMemoryUsage() + public function getMemoryUsage() : int { return array_reduce($this->executedStatements, function ($v, $s) { return $v + $s->getMemoryUsage(); }); } @@ -256,7 +266,7 @@ class TraceablePDO extends PDO * * @return int */ - public function getPeakMemoryUsage() + public function getPeakMemoryUsage() : int { return array_reduce($this->executedStatements, function ($v, $s) { $m = $s->getEndMemory(); return $m > $v ? $m : $v; }); } @@ -266,7 +276,7 @@ class TraceablePDO extends PDO * * @return TracedStatement[] */ - public function getExecutedStatements() + public function getExecutedStatements() : array { return $this->executedStatements; } @@ -276,7 +286,7 @@ class TraceablePDO extends PDO * * @return TracedStatement[] */ - public function getFailedExecutedStatements() + public function getFailedExecutedStatements() : array { return array_filter($this->executedStatements, function ($s) { return !$s->isSuccess(); }); } diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/TraceablePDOStatement.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/TraceablePDOStatement.php index d125b19a2eb..011bbfe4351 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/TraceablePDOStatement.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/TraceablePDOStatement.php @@ -39,6 +39,7 @@ class TraceablePDOStatement extends PDOStatement * @param mixed $driverdata [optional] Optional parameter(s) for the driver. * @return bool TRUE on success or FALSE on failure. */ + #[\ReturnTypeWillChange] public function bindColumn($column, &$param, $type = null, $maxlen = null, $driverdata = null) { $this->boundParameters[$column] = $param; @@ -61,7 +62,7 @@ class TraceablePDOStatement extends PDOStatement * @param mixed $driver_options [optional] * @return bool TRUE on success or FALSE on failure. */ - public function bindParam($parameter, &$variable, $data_type = PDO::PARAM_STR, $length = null, $driver_options = null) + public function bindParam($parameter, &$variable, $data_type = PDO::PARAM_STR, $length = null, $driver_options = null) : bool { $this->boundParameters[$parameter] = $variable; $args = array_merge([$parameter, &$variable], array_slice(func_get_args(), 2)); @@ -80,7 +81,7 @@ class TraceablePDOStatement extends PDOStatement * constants. * @return bool TRUE on success or FALSE on failure. */ - public function bindValue($parameter, $value, $data_type = PDO::PARAM_STR) + public function bindValue($parameter, $value, $data_type = PDO::PARAM_STR) : bool { $this->boundParameters[$parameter] = $value; return call_user_func_array(['parent', 'bindValue'], func_get_args()); @@ -96,7 +97,7 @@ class TraceablePDOStatement extends PDOStatement * @throws PDOException * @return bool TRUE on success or FALSE on failure. */ - public function execute($input_parameters = null) + public function execute($input_parameters = null) : bool { $preparedId = spl_object_hash($this); $boundParameters = $this->boundParameters; diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/TracedStatement.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/TracedStatement.php index c4eef46aaeb..9111489b0ea 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/TracedStatement.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PDO/TracedStatement.php @@ -27,12 +27,14 @@ class TracedStatement protected $exception; + protected $preparedId; + /** * @param string $sql * @param array $params - * @param string $preparedId + * @param null|string $preparedId */ - public function __construct($sql, array $params = [], $preparedId = null) + public function __construct(string $sql, array $params = [], ?string $preparedId = null) { $this->sql = $sql; $this->parameters = $this->checkParameters($params); @@ -43,7 +45,7 @@ class TracedStatement * @param null $startTime * @param null $startMemory */ - public function start($startTime = null, $startMemory = null) + public function start($startTime = null, $startMemory = null) : void { $this->startTime = $startTime ?: microtime(true); $this->startMemory = $startMemory ?: memory_get_usage(false); @@ -55,7 +57,7 @@ class TracedStatement * @param float $endTime * @param int $endMemory */ - public function end(\Exception $exception = null, $rowCount = 0, $endTime = null, $endMemory = null) + public function end(\Exception $exception = null, int $rowCount = 0, float $endTime = null, int $endMemory = null) : void { $this->endTime = $endTime ?: microtime(true); $this->duration = $this->endTime - $this->startTime; @@ -71,10 +73,10 @@ class TracedStatement * @param array $params * @return array */ - public function checkParameters($params) + public function checkParameters(array $params) : array { foreach ($params as &$param) { - if (!mb_check_encoding($param, 'UTF-8')) { + if (!mb_check_encoding($param ?? '', 'UTF-8')) { $param = '[BINARY DATA]'; } } @@ -86,7 +88,7 @@ class TracedStatement * * @return string */ - public function getSql() + public function getSql() : string { return $this->sql; } @@ -97,7 +99,7 @@ class TracedStatement * @param string $quotationChar * @return string */ - public function getSqlWithParams($quotationChar = '<>') + public function getSqlWithParams(string $quotationChar = '<>') : string { if (($l = strlen($quotationChar)) > 1) { $quoteLeft = substr($quotationChar, 0, $l / 2); @@ -123,7 +125,11 @@ class TracedStatement } $matchRule = "/({$marker}(?!\w))(?=(?:[^$quotationChar]|[$quotationChar][^$quotationChar]*[$quotationChar])*$)/"; - for ($i = 0; $i <= mb_substr_count($sql, $k); $i++) { + $count = mb_substr_count($sql, $k); + if ($count < 1) { + $count = mb_substr_count($sql, $matchRule); + } + for ($i = 0; $i <= $count; $i++) { $sql = preg_replace($matchRule, $v, $sql, 1); } } @@ -138,7 +144,7 @@ class TracedStatement * * @return int */ - public function getRowCount() + public function getRowCount() : int { return $this->rowCount; } @@ -148,11 +154,11 @@ class TracedStatement * * @return array */ - public function getParameters() + public function getParameters() : array { $params = []; foreach ($this->parameters as $name => $param) { - $params[$name] = htmlentities($param, ENT_QUOTES, 'UTF-8', false); + $params[$name] = htmlentities($param?:"", ENT_QUOTES, 'UTF-8', false); } return $params; } @@ -160,9 +166,9 @@ class TracedStatement /** * Returns the prepared statement id * - * @return string + * @return null|string */ - public function getPreparedId() + public function getPreparedId() : ?string { return $this->preparedId; } @@ -172,7 +178,7 @@ class TracedStatement * * @return boolean */ - public function isPrepared() + public function isPrepared() : bool { return $this->preparedId !== null; } @@ -180,7 +186,7 @@ class TracedStatement /** * @return float */ - public function getStartTime() + public function getStartTime() : float { return $this->startTime; } @@ -188,7 +194,7 @@ class TracedStatement /** * @return float */ - public function getEndTime() + public function getEndTime() : float { return $this->endTime; } @@ -198,7 +204,7 @@ class TracedStatement * * @return float */ - public function getDuration() + public function getDuration() : float { return $this->duration; } @@ -206,7 +212,7 @@ class TracedStatement /** * @return int */ - public function getStartMemory() + public function getStartMemory() : int { return $this->startMemory; } @@ -214,7 +220,7 @@ class TracedStatement /** * @return int */ - public function getEndMemory() + public function getEndMemory() : int { return $this->endMemory; } @@ -224,7 +230,7 @@ class TracedStatement * * @return int */ - public function getMemoryUsage() + public function getMemoryUsage() : int { return $this->memoryDelta; } @@ -234,7 +240,7 @@ class TracedStatement * * @return boolean */ - public function isSuccess() + public function isSuccess() : bool { return $this->exception === null; } @@ -244,8 +250,8 @@ class TracedStatement * * @return \Exception */ - public function getException() - { + public function getException() : \Exception + { return $this->exception; } @@ -264,7 +270,7 @@ class TracedStatement * * @return string */ - public function getErrorMessage() + public function getErrorMessage() : string { return $this->exception !== null ? $this->exception->getMessage() : ''; } diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PhpInfoCollector.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PhpInfoCollector.php index 57e9e45f47f..15a3f22dc38 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PhpInfoCollector.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/PhpInfoCollector.php @@ -29,7 +29,7 @@ class PhpInfoCollector extends DataCollector implements Renderable public function collect() { return array( - 'version' => PHP_VERSION, + 'version' => implode('.', [PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION]), 'interface' => PHP_SAPI ); } diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/TimeDataCollector.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/TimeDataCollector.php index 27a2e1a2df2..5794ccd7cb3 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/TimeDataCollector.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataCollector/TimeDataCollector.php @@ -134,6 +134,7 @@ class TimeDataCollector extends DataCollector implements Renderable * @param string $label * @param \Closure $closure * @param string|null $collector + * @return mixed */ public function measure($label, \Closure $closure, $collector = null) { @@ -142,6 +143,7 @@ class TimeDataCollector extends DataCollector implements Renderable $result = $closure(); $params = is_array($result) ? $result : array(); $this->stopMeasure($name, $params); + return $result; } /** diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/DataFormatter.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/DataFormatter.php index 7ffb19892c8..d933f3466ea 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/DataFormatter.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/DataFormatter.php @@ -15,6 +15,10 @@ use Symfony\Component\VarDumper\Dumper\CliDumper; class DataFormatter implements DataFormatterInterface { + public $cloner; + + public $dumper; + /** * DataFormatter constructor. */ @@ -54,8 +58,10 @@ class DataFormatter implements DataFormatterInterface { if ($seconds < 0.001) { return round($seconds * 1000000) . 'μs'; - } elseif ($seconds < 1) { + } elseif ($seconds < 0.1) { return round($seconds * 1000, 2) . 'ms'; + } elseif ($seconds < 1) { + return round($seconds * 1000) . 'ms'; } return round($seconds, 2) . 's'; } @@ -76,6 +82,6 @@ class DataFormatter implements DataFormatterInterface $base = log($size) / log(1024); $suffixes = array('B', 'KB', 'MB', 'GB', 'TB'); - return $sign . round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)]; + return $sign . round(pow(1024, $base - floor($base)), $precision) . $suffixes[(int) floor($base)]; } } diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/DataFormatterInterface.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/DataFormatterInterface.php index cb7b426e70b..e4b464b7ed8 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/DataFormatterInterface.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/DataFormatterInterface.php @@ -18,7 +18,7 @@ interface DataFormatterInterface /** * Transforms a PHP variable to a string representation * - * @param mixed $var + * @param mixed $data * @return string */ function formatVar($data); diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/DebugBarVarDumper.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/DebugBarVarDumper.php index 7b92ddf0a34..768879957fa 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/DebugBarVarDumper.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/DebugBarVarDumper.php @@ -4,7 +4,7 @@ namespace DebugBar\DataFormatter; use DebugBar\DataCollector\AssetProvider; use DebugBar\DataFormatter\VarDumper\DebugBarHtmlDumper; -use DebugBar\DataFormatter\VarDumper\SeekingData; +use Symfony\Component\VarDumper\Cloner\Data\SeekingData; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Cloner\VarCloner; @@ -254,8 +254,6 @@ class DebugBarVarDumper implements AssetProvider public function renderCapturedVar($capturedData, $seekPath = array()) { $data = unserialize($capturedData); - // The seek method was added in Symfony 3.2; emulate the behavior via SeekingData for older - // Symfony versions. if (!method_exists($data, 'seek')) { $data = new SeekingData($data->getRawData()); } @@ -285,7 +283,7 @@ class DebugBarVarDumper implements AssetProvider */ public function getAssets() { $dumper = $this->getDumper(); - $dumper->setDumpHeader(null); // this will cause the default dump header to regenerate + $dumper->resetDumpHeader(); // this will cause the default dump header to regenerate return array( 'inline_head' => array( 'html_var_dumper' => $dumper->getDumpHeaderByDebugBar(), diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/VarDumper/DebugBarHtmlDumper.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/VarDumper/DebugBarHtmlDumper.php index 0ff4919c18b..136d1ae8f0c 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/VarDumper/DebugBarHtmlDumper.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/VarDumper/DebugBarHtmlDumper.php @@ -10,6 +10,14 @@ use Symfony\Component\VarDumper\Dumper\HtmlDumper; */ class DebugBarHtmlDumper extends HtmlDumper { + /** + * Resets an HTML header. + */ + public function resetDumpHeader() + { + $this->dumpHeader = null; + } + public function getDumpHeaderByDebugBar() { // getDumpHeader is protected: return str_replace('pre.sf-dump', '.phpdebugbar pre.sf-dump', $this->getDumpHeader()); diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/VarDumper/SeekingData.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/VarDumper/SeekingData.php deleted file mode 100644 index be71ebfc9ce..00000000000 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DataFormatter/VarDumper/SeekingData.php +++ /dev/null @@ -1,103 +0,0 @@ -getRawData(); - $item = $thisData[$this->position][$this->key]; - - if (!$item instanceof Stub || !$item->position) { - return; - } - $keys = array($key); - - switch ($item->type) { - case Stub::TYPE_OBJECT: - $keys[] = "\0+\0".$key; - $keys[] = "\0*\0".$key; - $keys[] = "\0~\0".$key; - $keys[] = "\0$item->class\0$key"; - case Stub::TYPE_ARRAY: - case Stub::TYPE_RESOURCE: - break; - default: - return; - } - - $data = null; - $children = $thisData[$item->position]; - - foreach ($keys as $key) { - if (isset($children[$key]) || array_key_exists($key, $children)) { - $data = clone $this; - $data->key = $key; - $data->position = $item->position; - break; - } - } - - return $data; - } - - /** - * {@inheritdoc} - */ - public function dump(DumperInterface $dumper) - { - // Override the base class dump to use the position and key - $refs = array(0); - $class = new \ReflectionClass($this); - $dumpItem = $class->getMethod('dumpItem'); - $dumpItem->setAccessible(true); - $data = $this->getRawData(); - $args = array($dumper, new Cursor(), &$refs, $data[$this->position][$this->key]); - $dumpItem->invokeArgs($this, $args); - } -} diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/DebugBar.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/DebugBar.php index af900a801e8..b3999b476b5 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/DebugBar.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/DebugBar.php @@ -471,21 +471,25 @@ class DebugBar implements ArrayAccess // -------------------------------------------- // ArrayAccess implementation + #[\ReturnTypeWillChange] public function offsetSet($key, $value) { throw new DebugBarException("DebugBar[] is read-only"); } + #[\ReturnTypeWillChange] public function offsetGet($key) { return $this->getCollector($key); } + #[\ReturnTypeWillChange] public function offsetExists($key) { return $this->hasCollector($key); } + #[\ReturnTypeWillChange] public function offsetUnset($key) { throw new DebugBarException("DebugBar[] is read-only"); diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/JavascriptRenderer.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/JavascriptRenderer.php index 7f7ed84e0dd..b61d74fd43e 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/JavascriptRenderer.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/JavascriptRenderer.php @@ -82,6 +82,8 @@ class JavascriptRenderer protected $openHandlerUrl; + protected $cspNonce; + /** * @param \DebugBar\DebugBar $debugBar * @param string $baseUrl @@ -183,6 +185,9 @@ class JavascriptRenderer if (array_key_exists('open_handler_url', $options)) { $this->setOpenHandlerUrl($options['open_handler_url']); } + if (array_key_exists('csp_nonce', $options)) { + $this->setCspNonce($options['csp_nonce']); + } } /** @@ -606,6 +611,28 @@ class JavascriptRenderer return $this->openHandlerUrl; } + /** + * Sets the CSP Nonce (or remove it by setting to null) + * + * @param string|null $nonce + * @return $this + */ + public function setCspNonce($nonce = null) + { + $this->cspNonce = $nonce; + return $this; + } + + /** + * Get the CSP Nonce + * + * @return string|null + */ + public function getCspNonce() + { + return $this->cspNonce; + } + /** * Add assets stored in files to render in the head * @@ -692,8 +719,8 @@ class JavascriptRenderer } foreach ($additionalAssets as $assets) { - $basePath = isset($assets['base_path']) ? $assets['base_path'] : null; - $baseUrl = isset($assets['base_url']) ? $assets['base_url'] : null; + $basePath = isset($assets['base_path']) ? $assets['base_path'] : ''; + $baseUrl = isset($assets['base_url']) ? $assets['base_url'] : ''; $root = $this->getRelativeRoot($relativeTo, $this->makeUriRelativeTo($basePath, $this->basePath), $this->makeUriRelativeTo($baseUrl, $this->baseUrl)); @@ -719,7 +746,7 @@ class JavascriptRenderer $cssFiles = array_unique($cssFiles); $jsFiles = array_unique($jsFiles); - return $this->filterAssetArray(array($cssFiles, $jsFiles, $inlineCss, $inlineJs, $inlineHead), $type); + return $this->filterAssetArray(array($cssFiles, $jsFiles, $inlineCss, $inlineJs, $inlineHead), $type ?? ''); } /** @@ -762,7 +789,9 @@ class JavascriptRenderer return $uris; } - if ($uri && (substr($uri, 0, 1) === '/' || preg_match('/^([a-zA-Z]+:\/\/|[a-zA-Z]:\/|[a-zA-Z]:\\\)/', $uri))) { + $uri = $uri ?? ''; + + if (substr($uri, 0, 1) === '/' || preg_match('/^([a-zA-Z]+:\/\/|[a-zA-Z]:\/|[a-zA-Z]:\\\)/', $uri)) { return $uri; } return rtrim($root, '/') . "/$uri"; @@ -775,10 +804,10 @@ class JavascriptRenderer * @param string $type 'css', 'js', 'inline_css', 'inline_js', 'inline_head', or null for all * @return array */ - protected function filterAssetArray($array, $type = null) + protected function filterAssetArray($array, $type = '') { $types = array('css', 'js', 'inline_css', 'inline_js', 'inline_head'); - $typeIndex = is_null($type) ? false : array_search(strtolower($type), $types); + $typeIndex = array_search(strtolower($type ?? ''), $types); return $typeIndex !== false ? $array[$typeIndex] : $array; } @@ -905,6 +934,8 @@ class JavascriptRenderer list($cssFiles, $jsFiles, $inlineCss, $inlineJs, $inlineHead) = $this->getAssets(null, self::RELATIVE_URL); $html = ''; + $nonce = $this->getNonceAttribute(); + foreach ($cssFiles as $file) { $html .= sprintf('' . "\n", $file); } @@ -918,7 +949,7 @@ class JavascriptRenderer } foreach ($inlineJs as $content) { - $html .= sprintf('' . "\n", $content); + $html .= sprintf('' . "\n", $nonce, $content); } foreach ($inlineHead as $content) { @@ -926,7 +957,7 @@ class JavascriptRenderer } if ($this->enableJqueryNoConflict && !$this->useRequireJs) { - $html .= '' . "\n"; + $html .= '' . "\n"; } return $html; @@ -1013,10 +1044,12 @@ class JavascriptRenderer $suffix = !$initialize ? '(ajax)' : null; $js .= $this->getAddDatasetCode($this->debugBar->getCurrentRequestId(), $this->debugBar->getData(), $suffix); + $nonce = $this->getNonceAttribute(); + if ($this->useRequireJs){ - return "\n"; + return "\n"; } else { - return "\n"; + return "\n"; } } @@ -1149,4 +1182,17 @@ class JavascriptRenderer ); return $js; } + + /** + * If a nonce it set, create the correct attribute + * @return string + */ + protected function getNonceAttribute() + { + if ($nonce = $this->getCspNonce()) { + return ' nonce="' . $nonce .'"'; + } + + return ''; + } } diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/debugbar.css b/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/debugbar.css index 502d2482954..606e51dab0e 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/debugbar.css +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/debugbar.css @@ -116,11 +116,10 @@ div.phpdebugbar-closed, div.phpdebugbar-minimized{ } /* -------------------------------------- */ -div.phpdebugbar-header, a.phpdebugbar-restore-btn { +a.phpdebugbar-restore-btn { background: #efefef url(data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2020%2020%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Ccircle%20fill%3D%22%23000%22%20cx%3D%2210%22%20cy%3D%2210%22%20r%3D%229%22%2F%3E%3Cpath%20d%3D%22M6.039%208.342c.463%200%20.772.084.927.251.154.168.191.455.11.862-.084.424-.247.727-.487.908-.241.182-.608.272-1.1.272h-.743l.456-2.293h.837zm-2.975%204.615h1.22l.29-1.457H5.62c.461%200%20.84-.047%201.139-.142.298-.095.569-.254.812-.477.205-.184.37-.387.497-.608.127-.222.217-.466.27-.734.13-.65.032-1.155-.292-1.518-.324-.362-.84-.543-1.545-.543H4.153l-1.089%205.479zM9.235%206.02h1.21l-.289%201.458h1.079c.679%200%201.147.115%201.405.347.258.231.335.607.232%201.125l-.507%202.55h-1.23l.481-2.424c.055-.276.035-.464-.06-.565-.095-.1-.298-.15-.608-.15H9.98L9.356%2011.5h-1.21l1.089-5.48M15.566%208.342c.464%200%20.773.084.928.251.154.168.19.455.11.862-.084.424-.247.727-.488.908-.24.182-.607.272-1.1.272h-.742l.456-2.293h.836zm-2.974%204.615h1.22l.29-1.457h1.046c.461%200%20.84-.047%201.139-.142.298-.095.569-.254.812-.477.205-.184.37-.387.497-.608.127-.222.217-.466.27-.734.129-.65.032-1.155-.292-1.518-.324-.362-.84-.543-1.545-.543H13.68l-1.089%205.479z%22%20fill%3D%22%23FFF%22%2F%3E%3C%2Fsvg%3E) no-repeat 5px 4px / 20px 20px; } div.phpdebugbar-header { - padding-left: 29px; min-height: 26px; line-height: 16px; } diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/debugbar.js b/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/debugbar.js index 09c3caebdc6..66658d25938 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/debugbar.js +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/debugbar.js @@ -477,6 +477,10 @@ if (typeof(PhpDebugBar) == 'undefined') { this.$dragCapture = $('
').addClass(csscls('drag-capture')).appendTo(this.$el); this.$resizehdle = $('
').addClass(csscls('resize-handle')).appendTo(this.$el); this.$header = $('
').addClass(csscls('header')).appendTo(this.$el); + this.$headerBtn = $('').addClass(csscls('restore-btn')).appendTo(this.$header); + this.$headerBtn.click(function() { + self.close(); + }); this.$headerLeft = $('
').addClass(csscls('header-left')).appendTo(this.$header); this.$headerRight = $('
').addClass(csscls('header-right')).appendTo(this.$header); var $body = this.$body = $('
').addClass(csscls('body')).appendTo(this.$el); @@ -944,6 +948,7 @@ if (typeof(PhpDebugBar) == 'undefined') { var self = this; this.openHandler.load(id, function(data) { self.addDataSet(data, id, suffix, show); + self.resize(); callback && callback(data); }); }, @@ -1160,7 +1165,7 @@ if (typeof(PhpDebugBar) == 'undefined') { var self = this; var proxied = window.fetch; - if (proxied === undefined && proxied.polyfill !== undefined) { + if (proxied !== undefined && proxied.polyfill !== undefined) { return; } @@ -1169,8 +1174,6 @@ if (typeof(PhpDebugBar) == 'undefined') { promise.then(function (response) { self.handle(response); - }, function (e) { - self.handle(response); }); return promise; @@ -1204,7 +1207,9 @@ if (typeof(PhpDebugBar) == 'undefined') { var xhr = this; this.addEventListener("readystatechange", function() { var skipUrl = self.debugbar.openHandler ? self.debugbar.openHandler.get('url') : null; - if (xhr.readyState == 4 && url.indexOf(skipUrl) !== 0) { + var href = (typeof url === 'string') ? url : url.href; + + if (xhr.readyState == 4 && href.indexOf(skipUrl) !== 0) { self.handle(xhr); } }, false); diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/widgets.js b/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/widgets.js index b4a583dfc52..a0cd2888ba6 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/widgets.js +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/widgets.js @@ -216,11 +216,11 @@ if (typeof(PhpDebugBar) == 'undefined') { }); // ------------------------------------------------------------------ - + /** * An extension of KVListWidget where the data represents a list * of variables - * + * * Options: * - data */ @@ -353,7 +353,7 @@ if (typeof(PhpDebugBar) == 'undefined') { this.$list.$el.appendTo(this.$el); this.$toolbar = $('
').addClass(csscls('toolbar')).appendTo(this.$el); - $('') + $('') .on('change', function() { self.set('search', this.value); }) .appendTo(this.$toolbar); @@ -468,7 +468,7 @@ if (typeof(PhpDebugBar) == 'undefined') { m.appendTo(li); this.$el.append(li); - + if (measure.params && !$.isEmptyObject(measure.params)) { var table = $('
Params
').addClass(csscls('params')).appendTo(li); for (var key in measure.params) { @@ -518,7 +518,7 @@ if (typeof(PhpDebugBar) == 'undefined') { }); // ------------------------------------------------------------------ - + /** * Widget for the displaying exceptions * @@ -550,20 +550,26 @@ if (typeof(PhpDebugBar) == 'undefined') { } if (e.surrounding_lines) { var pre = createCodeBlock(e.surrounding_lines.join(""), 'php').addClass(csscls('file')).appendTo(li); - li.click(function() { - if (pre.is(':visible')) { - pre.hide(); - } else { - pre.show(); - } - }); + if (!e.stack_trace_html) { + // This click event makes the var-dumper hard to use. + li.click(function () { + if (pre.is(':visible')) { + pre.hide(); + } else { + pre.show(); + } + }); + } } - if (e.stack_trace) { - e.stack_trace.split("\n").forEach(function(trace) { - var $traceLine = $('
'); - $('').addClass(csscls('filename')).text(trace).appendTo($traceLine); - $traceLine.appendTo(li); - }); + if (e.stack_trace_html) { + var $trace = $('').addClass(csscls('filename')).html(e.stack_trace_html); + $trace.appendTo(li); + } else if (e.stack_trace) { + e.stack_trace.split("\n").forEach(function (trace) { + var $traceLine = $('
'); + $('').addClass(csscls('filename')).text(trace).appendTo($traceLine); + $traceLine.appendTo(li); + }); } }}); this.$list.$el.appendTo(this.$el); @@ -578,6 +584,6 @@ if (typeof(PhpDebugBar) == 'undefined') { } }); - + })(PhpDebugBar.$); diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/widgets/templates/widget.css b/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/widgets/templates/widget.css index 29f6ab979bc..1cd7df41c07 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/widgets/templates/widget.css +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/widgets/templates/widget.css @@ -11,6 +11,7 @@ div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status { div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-render-time, div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-memory, div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-param-count, +div.phpdebugbar-widgets-templates a.phpdebugbar-widgets-editor-link, div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-type { float: right; margin-left: 8px; @@ -19,6 +20,7 @@ div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-type { div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status span.phpdebugbar-widgets-render-time, div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status span.phpdebugbar-widgets-memory, div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status span.phpdebugbar-widgets-param-count, +div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status a.phpdebugbar-widgets-editor-link, div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status span.phpdebugbar-widgets-type { color: #555; } @@ -26,12 +28,17 @@ div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-render-time:before, div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-memory:before, div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-param-count:before, div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-type:before, +div.phpdebugbar-widgets-templates a.phpdebugbar-widgets-editor-link:before, div.phpdebugbar-widgets-templates a.phpdebugbar-widgets-editor-link:before { font-family: PhpDebugbarFontAwesome; margin-right: 4px; font-size: 12px; } +div.phpdebugbar-widgets-templates a.phpdebugbar-widgets-editor-link:hover +{ + color: #ffffff; +} div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-render-time:before { content: "\f017"; } diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/widgets/templates/widget.js b/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/widgets/templates/widget.js index 8763e7eda68..056e9c4196d 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/widgets/templates/widget.js +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/Resources/widgets/templates/widget.js @@ -39,6 +39,9 @@ if (typeof(tpl.type) != 'undefined' && tpl.type) { $('').addClass(csscls('type')).text(tpl.type).appendTo(li); } + if (typeof(tpl.editorLink) != 'undefined' && tpl.editorLink) { + $('').addClass(csscls('editor-link')).text('file').appendTo(li); + } if (tpl.params && !$.isEmptyObject(tpl.params)) { var table = $('
Params
').addClass(csscls('params')).appendTo(li); for (var key in tpl.params) { diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/Storage/FileStorage.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/Storage/FileStorage.php index 98923e272b3..41c2be55a3c 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/Storage/FileStorage.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/Storage/FileStorage.php @@ -62,7 +62,7 @@ class FileStorage implements StorageInterface //Sort the files, newest first usort($files, function ($a, $b) { - return $a['time'] < $b['time']; + return $a['time'] <=> $b['time']; }); //Load the metadata and filter the results. diff --git a/htdocs/includes/maximebf/debugbar/src/DebugBar/Storage/RedisStorage.php b/htdocs/includes/maximebf/debugbar/src/DebugBar/Storage/RedisStorage.php index f145369660b..fe79082dc14 100644 --- a/htdocs/includes/maximebf/debugbar/src/DebugBar/Storage/RedisStorage.php +++ b/htdocs/includes/maximebf/debugbar/src/DebugBar/Storage/RedisStorage.php @@ -15,13 +15,15 @@ namespace DebugBar\Storage; */ class RedisStorage implements StorageInterface { + /** @var \Predis\Client|\Redis */ protected $redis; + /** @var string */ protected $hash; /** - * @param \Predis\Client $redis Redis Client - * @param string $hash + * @param \Predis\Client|\Redis $redis Redis Client + * @param string $hash */ public function __construct($redis, $hash = 'phpdebugbar') { @@ -34,9 +36,9 @@ class RedisStorage implements StorageInterface */ public function save($id, $data) { - $this->redis->hset("$this->hash:meta", $id, serialize($data['__meta'])); + $this->redis->hSet("$this->hash:meta", $id, serialize($data['__meta'])); unset($data['__meta']); - $this->redis->hset("$this->hash:data", $id, serialize($data)); + $this->redis->hSet("$this->hash:data", $id, serialize($data)); } /** @@ -44,19 +46,25 @@ class RedisStorage implements StorageInterface */ public function get($id) { - return array_merge(unserialize($this->redis->hget("$this->hash:data", $id)), - array('__meta' => unserialize($this->redis->hget("$this->hash:meta", $id)))); + return array_merge(unserialize($this->redis->hGet("$this->hash:data", $id)), + array('__meta' => unserialize($this->redis->hGet("$this->hash:meta", $id)))); } /** * {@inheritdoc} */ - public function find(array $filters = array(), $max = 20, $offset = 0) + public function find(array $filters = [], $max = 20, $offset = 0) { - $results = array(); + $results = []; $cursor = "0"; + $isPhpRedis = get_class($this->redis) === 'Redis'; + do { - list($cursor, $data) = $this->redis->hscan("$this->hash:meta", $cursor); + if ($isPhpRedis) { + $data = $this->redis->hScan("$this->hash:meta", $cursor); + } else { + [$cursor, $data] = $this->redis->hScan("$this->hash:meta", $cursor); + } foreach ($data as $meta) { if ($meta = unserialize($meta)) { @@ -66,11 +74,11 @@ class RedisStorage implements StorageInterface } } } while($cursor); - - usort($results, function ($a, $b) { - return $a['utime'] < $b['utime']; + + usort($results, static function ($a, $b) { + return $b['utime'] <=> $a['utime']; }); - + return array_slice($results, $offset, $max); } @@ -92,6 +100,7 @@ class RedisStorage implements StorageInterface */ public function clear() { - $this->redis->del($this->hash); + $this->redis->del("$this->hash:data"); + $this->redis->del("$this->hash:meta"); } }