summaryrefslogtreecommitdiff
path: root/vendor/symfony/debug
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/symfony/debug')
-rw-r--r--vendor/symfony/debug/.gitignore3
-rw-r--r--vendor/symfony/debug/BufferingLogger.php37
-rw-r--r--vendor/symfony/debug/CHANGELOG.md64
-rw-r--r--vendor/symfony/debug/Debug.php63
-rw-r--r--vendor/symfony/debug/DebugClassLoader.php384
-rw-r--r--vendor/symfony/debug/ErrorHandler.php746
-rw-r--r--vendor/symfony/debug/Exception/ClassNotFoundException.php33
-rw-r--r--vendor/symfony/debug/Exception/ContextErrorException.php40
-rw-r--r--vendor/symfony/debug/Exception/FatalErrorException.php82
-rw-r--r--vendor/symfony/debug/Exception/FatalThrowableError.php44
-rw-r--r--vendor/symfony/debug/Exception/FlattenException.php263
-rw-r--r--vendor/symfony/debug/Exception/OutOfMemoryException.php21
-rw-r--r--vendor/symfony/debug/Exception/SilencedErrorContext.php67
-rw-r--r--vendor/symfony/debug/Exception/UndefinedFunctionException.php33
-rw-r--r--vendor/symfony/debug/Exception/UndefinedMethodException.php33
-rw-r--r--vendor/symfony/debug/ExceptionHandler.php410
-rw-r--r--vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php206
-rw-r--r--vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php32
-rw-r--r--vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php84
-rw-r--r--vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php66
-rw-r--r--vendor/symfony/debug/LICENSE19
-rw-r--r--vendor/symfony/debug/README.md13
-rw-r--r--vendor/symfony/debug/Resources/ext/README.md134
-rw-r--r--vendor/symfony/debug/Resources/ext/config.m463
-rw-r--r--vendor/symfony/debug/Resources/ext/config.w3213
-rw-r--r--vendor/symfony/debug/Resources/ext/php_symfony_debug.h60
-rw-r--r--vendor/symfony/debug/Resources/ext/symfony_debug.c283
-rw-r--r--vendor/symfony/debug/Resources/ext/tests/001.phpt153
-rw-r--r--vendor/symfony/debug/Resources/ext/tests/002.phpt63
-rw-r--r--vendor/symfony/debug/Resources/ext/tests/002_1.phpt46
-rw-r--r--vendor/symfony/debug/Resources/ext/tests/003.phpt85
-rw-r--r--vendor/symfony/debug/Tests/DebugClassLoaderTest.php425
-rw-r--r--vendor/symfony/debug/Tests/ErrorHandlerTest.php536
-rw-r--r--vendor/symfony/debug/Tests/Exception/FlattenExceptionTest.php301
-rw-r--r--vendor/symfony/debug/Tests/ExceptionHandlerTest.php133
-rw-r--r--vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php176
-rw-r--r--vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php81
-rw-r--r--vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php76
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php13
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/ClassAlias.php3
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/DeprecatedClass.php12
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/DeprecatedInterface.php12
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/ExtendedFinalMethod.php17
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/FinalClass.php10
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/FinalMethod.php17
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/InternalClass.php15
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/InternalInterface.php10
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/InternalTrait.php10
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/InternalTrait2.php23
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/NonDeprecatedInterface.php7
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/PEARClass.php5
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/Throwing.php3
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/ToStringThrower.php24
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/casemismatch.php7
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/notPsr0Bis.php7
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/psr4/Psr4CaseMismatch.php7
-rw-r--r--vendor/symfony/debug/Tests/Fixtures/reallyNotPsr0.php7
-rw-r--r--vendor/symfony/debug/Tests/Fixtures2/RequiredTwice.php7
-rw-r--r--vendor/symfony/debug/Tests/HeaderMock.php38
-rw-r--r--vendor/symfony/debug/Tests/MockExceptionHandler.php24
-rw-r--r--vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt36
-rw-r--r--vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt40
-rw-r--r--vendor/symfony/debug/composer.json40
-rw-r--r--vendor/symfony/debug/phpunit.xml.dist33
64 files changed, 5798 insertions, 0 deletions
diff --git a/vendor/symfony/debug/.gitignore b/vendor/symfony/debug/.gitignore
new file mode 100644
index 00000000..c49a5d8d
--- /dev/null
+++ b/vendor/symfony/debug/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
diff --git a/vendor/symfony/debug/BufferingLogger.php b/vendor/symfony/debug/BufferingLogger.php
new file mode 100644
index 00000000..a2ed75b9
--- /dev/null
+++ b/vendor/symfony/debug/BufferingLogger.php
@@ -0,0 +1,37 @@
+<?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\Debug;
+
+use Psr\Log\AbstractLogger;
+
+/**
+ * A buffering logger that stacks logs for later.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class BufferingLogger extends AbstractLogger
+{
+ private $logs = array();
+
+ public function log($level, $message, array $context = array())
+ {
+ $this->logs[] = array($level, $message, $context);
+ }
+
+ public function cleanLogs()
+ {
+ $logs = $this->logs;
+ $this->logs = array();
+
+ return $logs;
+ }
+}
diff --git a/vendor/symfony/debug/CHANGELOG.md b/vendor/symfony/debug/CHANGELOG.md
new file mode 100644
index 00000000..31c67eb6
--- /dev/null
+++ b/vendor/symfony/debug/CHANGELOG.md
@@ -0,0 +1,64 @@
+CHANGELOG
+=========
+
+3.4.0
+-----
+
+* deprecated `ErrorHandler::stackErrors()` and `ErrorHandler::unstackErrors()`
+
+3.3.0
+-----
+
+* deprecated the `ContextErrorException` class: use \ErrorException directly now
+
+3.2.0
+-----
+
+* `FlattenException::getTrace()` now returns additional type descriptions
+ `integer` and `float`.
+
+
+3.0.0
+-----
+
+* removed classes, methods and interfaces deprecated in 2.x
+
+2.8.0
+-----
+
+* added BufferingLogger for errors that happen before a proper logger is configured
+* allow throwing from `__toString()` with `return trigger_error($e, E_USER_ERROR);`
+* deprecate ExceptionHandler::createResponse
+
+2.7.0
+-----
+
+* added deprecations checking for parent interfaces/classes to DebugClassLoader
+* added ZTS support to symfony_debug extension
+* added symfony_debug_backtrace() to symfony_debug extension
+ to track the backtrace of fatal errors
+
+2.6.0
+-----
+
+* generalized ErrorHandler and ExceptionHandler,
+ with some new methods and others deprecated
+* enhanced error messages for uncaught exceptions
+
+2.5.0
+-----
+
+* added ExceptionHandler::setHandler()
+* added UndefinedMethodFatalErrorHandler
+* deprecated DummyException
+
+2.4.0
+-----
+
+ * added a DebugClassLoader able to wrap any autoloader providing a findFile method
+ * improved error messages for not found classes and functions
+
+2.3.0
+-----
+
+ * added the component
diff --git a/vendor/symfony/debug/Debug.php b/vendor/symfony/debug/Debug.php
new file mode 100644
index 00000000..e3665ae5
--- /dev/null
+++ b/vendor/symfony/debug/Debug.php
@@ -0,0 +1,63 @@
+<?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\Debug;
+
+/**
+ * Registers all the debug tools.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class Debug
+{
+ private static $enabled = false;
+
+ /**
+ * Enables the debug tools.
+ *
+ * This method registers an error handler and an exception handler.
+ *
+ * If the Symfony ClassLoader component is available, a special
+ * class loader is also registered.
+ *
+ * @param int $errorReportingLevel The level of error reporting you want
+ * @param bool $displayErrors Whether to display errors (for development) or just log them (for production)
+ */
+ public static function enable($errorReportingLevel = E_ALL, $displayErrors = true)
+ {
+ if (static::$enabled) {
+ return;
+ }
+
+ static::$enabled = true;
+
+ if (null !== $errorReportingLevel) {
+ error_reporting($errorReportingLevel);
+ } else {
+ error_reporting(E_ALL);
+ }
+
+ if ('cli' !== PHP_SAPI) {
+ ini_set('display_errors', 0);
+ ExceptionHandler::register();
+ } elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) {
+ // CLI - display errors only if they're not already logged to STDERR
+ ini_set('display_errors', 1);
+ }
+ if ($displayErrors) {
+ ErrorHandler::register(new ErrorHandler(new BufferingLogger()));
+ } else {
+ ErrorHandler::register()->throwAt(0, true);
+ }
+
+ DebugClassLoader::enable();
+ }
+}
diff --git a/vendor/symfony/debug/DebugClassLoader.php b/vendor/symfony/debug/DebugClassLoader.php
new file mode 100644
index 00000000..9ff826ed
--- /dev/null
+++ b/vendor/symfony/debug/DebugClassLoader.php
@@ -0,0 +1,384 @@
+<?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\Debug;
+
+/**
+ * Autoloader checking if the class is really defined in the file found.
+ *
+ * The ClassLoader will wrap all registered autoloaders
+ * and will throw an exception if a file is found but does
+ * not declare the class.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Christophe Coevoet <stof@notk.org>
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class DebugClassLoader
+{
+ private $classLoader;
+ private $isFinder;
+ private $loaded = array();
+ private static $caseCheck;
+ private static $final = array();
+ private static $finalMethods = array();
+ private static $deprecated = array();
+ private static $internal = array();
+ private static $internalMethods = array();
+ private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
+ private static $darwinCache = array('/' => array('/', array()));
+
+ public function __construct(callable $classLoader)
+ {
+ $this->classLoader = $classLoader;
+ $this->isFinder = is_array($classLoader) && method_exists($classLoader[0], 'findFile');
+
+ if (!isset(self::$caseCheck)) {
+ $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), DIRECTORY_SEPARATOR);
+ $i = strrpos($file, DIRECTORY_SEPARATOR);
+ $dir = substr($file, 0, 1 + $i);
+ $file = substr($file, 1 + $i);
+ $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
+ $test = realpath($dir.$test);
+
+ if (false === $test || false === $i) {
+ // filesystem is case sensitive
+ self::$caseCheck = 0;
+ } elseif (substr($test, -strlen($file)) === $file) {
+ // filesystem is case insensitive and realpath() normalizes the case of characters
+ self::$caseCheck = 1;
+ } elseif (false !== stripos(PHP_OS, 'darwin')) {
+ // on MacOSX, HFS+ is case insensitive but realpath() doesn't normalize the case of characters
+ self::$caseCheck = 2;
+ } else {
+ // filesystem case checks failed, fallback to disabling them
+ self::$caseCheck = 0;
+ }
+ }
+ }
+
+ /**
+ * Gets the wrapped class loader.
+ *
+ * @return callable The wrapped class loader
+ */
+ public function getClassLoader()
+ {
+ return $this->classLoader;
+ }
+
+ /**
+ * Wraps all autoloaders.
+ */
+ public static function enable()
+ {
+ // Ensures we don't hit https://bugs.php.net/42098
+ class_exists('Symfony\Component\Debug\ErrorHandler');
+ class_exists('Psr\Log\LogLevel');
+
+ if (!is_array($functions = spl_autoload_functions())) {
+ return;
+ }
+
+ foreach ($functions as $function) {
+ spl_autoload_unregister($function);
+ }
+
+ foreach ($functions as $function) {
+ if (!is_array($function) || !$function[0] instanceof self) {
+ $function = array(new static($function), 'loadClass');
+ }
+
+ spl_autoload_register($function);
+ }
+ }
+
+ /**
+ * Disables the wrapping.
+ */
+ public static function disable()
+ {
+ if (!is_array($functions = spl_autoload_functions())) {
+ return;
+ }
+
+ foreach ($functions as $function) {
+ spl_autoload_unregister($function);
+ }
+
+ foreach ($functions as $function) {
+ if (is_array($function) && $function[0] instanceof self) {
+ $function = $function[0]->getClassLoader();
+ }
+
+ spl_autoload_register($function);
+ }
+ }
+
+ /**
+ * Loads the given class or interface.
+ *
+ * @param string $class The name of the class
+ *
+ * @return bool|null True, if loaded
+ *
+ * @throws \RuntimeException
+ */
+ public function loadClass($class)
+ {
+ $e = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
+
+ try {
+ if ($this->isFinder && !isset($this->loaded[$class])) {
+ $this->loaded[$class] = true;
+ if ($file = $this->classLoader[0]->findFile($class)) {
+ require $file;
+ }
+ } else {
+ call_user_func($this->classLoader, $class);
+ $file = false;
+ }
+ } finally {
+ error_reporting($e);
+ }
+
+ $exists = class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false);
+
+ if ($class && '\\' === $class[0]) {
+ $class = substr($class, 1);
+ }
+
+ if ($exists) {
+ $refl = new \ReflectionClass($class);
+ $name = $refl->getName();
+
+ if ($name !== $class && 0 === strcasecmp($name, $class)) {
+ throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name));
+ }
+
+ // Don't trigger deprecations for classes in the same vendor
+ if (2 > $len = 1 + (strpos($name, '\\') ?: strpos($name, '_'))) {
+ $len = 0;
+ $ns = '';
+ } else {
+ $ns = substr($name, 0, $len);
+ }
+
+ // Detect annotations on the class
+ if (false !== $doc = $refl->getDocComment()) {
+ foreach (array('final', 'deprecated', 'internal') as $annotation) {
+ if (false !== strpos($doc, '@'.$annotation) && preg_match('#\n \* @'.$annotation.'(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) {
+ self::${$annotation}[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
+ }
+ }
+ }
+
+ $parentAndTraits = class_uses($name, false);
+ if ($parent = get_parent_class($class)) {
+ $parentAndTraits[] = $parent;
+
+ if (isset(self::$final[$parent])) {
+ @trigger_error(sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $name), E_USER_DEPRECATED);
+ }
+ }
+
+ // Detect if the parent is annotated
+ foreach ($parentAndTraits + $this->getOwnInterfaces($name, $parent) as $use) {
+ if (isset(self::$deprecated[$use]) && strncmp($ns, $use, $len)) {
+ $type = class_exists($name, false) ? 'class' : (interface_exists($name, false) ? 'interface' : 'trait');
+ $verb = class_exists($use, false) || interface_exists($name, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses');
+
+ @trigger_error(sprintf('The "%s" %s %s "%s" that is deprecated%s.', $name, $type, $verb, $use, self::$deprecated[$use]), E_USER_DEPRECATED);
+ }
+ if (isset(self::$internal[$use]) && strncmp($ns, $use, $len)) {
+ @trigger_error(sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $name), E_USER_DEPRECATED);
+ }
+ }
+
+ // Inherit @final and @internal annotations for methods
+ self::$finalMethods[$name] = array();
+ self::$internalMethods[$name] = array();
+ foreach ($parentAndTraits as $use) {
+ foreach (array('finalMethods', 'internalMethods') as $property) {
+ if (isset(self::${$property}[$use])) {
+ self::${$property}[$name] = array_merge(self::${$property}[$name], self::${$property}[$use]);
+ }
+ }
+ }
+
+ $isClass = class_exists($name, false);
+ foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) {
+ if ($method->class !== $name) {
+ continue;
+ }
+
+ // Method from a trait
+ if ($method->getFilename() !== $refl->getFileName()) {
+ continue;
+ }
+
+ if ($isClass && $parent && isset(self::$finalMethods[$parent][$method->name])) {
+ list($declaringClass, $message) = self::$finalMethods[$parent][$method->name];
+ @trigger_error(sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED);
+ }
+
+ foreach ($parentAndTraits as $use) {
+ if (isset(self::$internalMethods[$use][$method->name])) {
+ list($declaringClass, $message) = self::$internalMethods[$use][$method->name];
+ if (strncmp($ns, $declaringClass, $len)) {
+ @trigger_error(sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED);
+ }
+ }
+ }
+
+ // Detect method annotations
+ if (false === $doc = $method->getDocComment()) {
+ continue;
+ }
+
+ foreach (array('final', 'internal') as $annotation) {
+ if (false !== strpos($doc, '@'.$annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) {
+ $message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
+ self::${$annotation.'Methods'}[$name][$method->name] = array($name, $message);
+ }
+ }
+ }
+
+ if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
+ @trigger_error(sprintf('The "%s" class uses the reserved name "%s", it will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
+ }
+ }
+
+ if ($file) {
+ if (!$exists) {
+ if (false !== strpos($class, '/')) {
+ throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class));
+ }
+
+ throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file));
+ }
+ if (self::$caseCheck) {
+ $real = explode('\\', $class.strrchr($file, '.'));
+ $tail = explode(DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, $file));
+
+ $i = count($tail) - 1;
+ $j = count($real) - 1;
+
+ while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
+ --$i;
+ --$j;
+ }
+
+ array_splice($tail, 0, $i + 1);
+ }
+ if (self::$caseCheck && $tail) {
+ $tail = DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $tail);
+ $tailLen = strlen($tail);
+ $real = $refl->getFileName();
+
+ if (2 === self::$caseCheck) {
+ // realpath() on MacOSX doesn't normalize the case of characters
+
+ $i = 1 + strrpos($real, '/');
+ $file = substr($real, $i);
+ $real = substr($real, 0, $i);
+
+ if (isset(self::$darwinCache[$real])) {
+ $kDir = $real;
+ } else {
+ $kDir = strtolower($real);
+
+ if (isset(self::$darwinCache[$kDir])) {
+ $real = self::$darwinCache[$kDir][0];
+ } else {
+ $dir = getcwd();
+ chdir($real);
+ $real = getcwd().'/';
+ chdir($dir);
+
+ $dir = $real;
+ $k = $kDir;
+ $i = strlen($dir) - 1;
+ while (!isset(self::$darwinCache[$k])) {
+ self::$darwinCache[$k] = array($dir, array());
+ self::$darwinCache[$dir] = &self::$darwinCache[$k];
+
+ while ('/' !== $dir[--$i]) {
+ }
+ $k = substr($k, 0, ++$i);
+ $dir = substr($dir, 0, $i--);
+ }
+ }
+ }
+
+ $dirFiles = self::$darwinCache[$kDir][1];
+
+ if (isset($dirFiles[$file])) {
+ $kFile = $file;
+ } else {
+ $kFile = strtolower($file);
+
+ if (!isset($dirFiles[$kFile])) {
+ foreach (scandir($real, 2) as $f) {
+ if ('.' !== $f[0]) {
+ $dirFiles[$f] = $f;
+ if ($f === $file) {
+ $kFile = $k = $file;
+ } elseif ($f !== $k = strtolower($f)) {
+ $dirFiles[$k] = $f;
+ }
+ }
+ }
+ self::$darwinCache[$kDir][1] = $dirFiles;
+ }
+ }
+
+ $real .= $dirFiles[$kFile];
+ }
+
+ if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
+ && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
+ ) {
+ throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)));
+ }
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * `class_implements` includes interfaces from the parents so we have to manually exclude them.
+ *
+ * @param string $class
+ * @param string|false $parent
+ *
+ * @return string[]
+ */
+ private function getOwnInterfaces($class, $parent)
+ {
+ $ownInterfaces = class_implements($class, false);
+
+ if ($parent) {
+ foreach (class_implements($parent, false) as $interface) {
+ unset($ownInterfaces[$interface]);
+ }
+ }
+
+ foreach ($ownInterfaces as $interface) {
+ foreach (class_implements($interface) as $interface) {
+ unset($ownInterfaces[$interface]);
+ }
+ }
+
+ return $ownInterfaces;
+ }
+}
diff --git a/vendor/symfony/debug/ErrorHandler.php b/vendor/symfony/debug/ErrorHandler.php
new file mode 100644
index 00000000..aebb740a
--- /dev/null
+++ b/vendor/symfony/debug/ErrorHandler.php
@@ -0,0 +1,746 @@
+<?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\Debug;
+
+use Psr\Log\LogLevel;
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Debug\Exception\ContextErrorException;
+use Symfony\Component\Debug\Exception\FatalErrorException;
+use Symfony\Component\Debug\Exception\FatalThrowableError;
+use Symfony\Component\Debug\Exception\OutOfMemoryException;
+use Symfony\Component\Debug\Exception\SilencedErrorContext;
+use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
+use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
+use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
+use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
+
+/**
+ * A generic ErrorHandler for the PHP engine.
+ *
+ * Provides five bit fields that control how errors are handled:
+ * - thrownErrors: errors thrown as \ErrorException
+ * - loggedErrors: logged errors, when not @-silenced
+ * - scopedErrors: errors thrown or logged with their local context
+ * - tracedErrors: errors logged with their stack trace
+ * - screamedErrors: never @-silenced errors
+ *
+ * Each error level can be logged by a dedicated PSR-3 logger object.
+ * Screaming only applies to logging.
+ * Throwing takes precedence over logging.
+ * Uncaught exceptions are logged as E_ERROR.
+ * E_DEPRECATED and E_USER_DEPRECATED levels never throw.
+ * E_RECOVERABLE_ERROR and E_USER_ERROR levels always throw.
+ * Non catchable errors that can be detected at shutdown time are logged when the scream bit field allows so.
+ * As errors have a performance cost, repeated errors are all logged, so that the developer
+ * can see them and weight them as more important to fix than others of the same level.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ * @author Grégoire Pineau <lyrixx@lyrixx.info>
+ */
+class ErrorHandler
+{
+ private $levels = array(
+ E_DEPRECATED => 'Deprecated',
+ E_USER_DEPRECATED => 'User Deprecated',
+ E_NOTICE => 'Notice',
+ E_USER_NOTICE => 'User Notice',
+ E_STRICT => 'Runtime Notice',
+ E_WARNING => 'Warning',
+ E_USER_WARNING => 'User Warning',
+ E_COMPILE_WARNING => 'Compile Warning',
+ E_CORE_WARNING => 'Core Warning',
+ E_USER_ERROR => 'User Error',
+ E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
+ E_COMPILE_ERROR => 'Compile Error',
+ E_PARSE => 'Parse Error',
+ E_ERROR => 'Error',
+ E_CORE_ERROR => 'Core Error',
+ );
+
+ private $loggers = array(
+ E_DEPRECATED => array(null, LogLevel::INFO),
+ E_USER_DEPRECATED => array(null, LogLevel::INFO),
+ E_NOTICE => array(null, LogLevel::WARNING),
+ E_USER_NOTICE => array(null, LogLevel::WARNING),
+ E_STRICT => array(null, LogLevel::WARNING),
+ E_WARNING => array(null, LogLevel::WARNING),
+ E_USER_WARNING => array(null, LogLevel::WARNING),
+ E_COMPILE_WARNING => array(null, LogLevel::WARNING),
+ E_CORE_WARNING => array(null, LogLevel::WARNING),
+ E_USER_ERROR => array(null, LogLevel::CRITICAL),
+ E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL),
+ E_COMPILE_ERROR => array(null, LogLevel::CRITICAL),
+ E_PARSE => array(null, LogLevel::CRITICAL),
+ E_ERROR => array(null, LogLevel::CRITICAL),
+ E_CORE_ERROR => array(null, LogLevel::CRITICAL),
+ );
+
+ private $thrownErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED
+ private $scopedErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED
+ private $tracedErrors = 0x77FB; // E_ALL - E_STRICT - E_PARSE
+ private $screamedErrors = 0x55; // E_ERROR + E_CORE_ERROR + E_COMPILE_ERROR + E_PARSE
+ private $loggedErrors = 0;
+ private $traceReflector;
+
+ private $isRecursive = 0;
+ private $isRoot = false;
+ private $exceptionHandler;
+ private $bootstrappingLogger;
+
+ private static $reservedMemory;
+ private static $stackedErrors = array();
+ private static $stackedErrorLevels = array();
+ private static $toStringException = null;
+ private static $silencedErrorCache = array();
+ private static $silencedErrorCount = 0;
+ private static $exitCode = 0;
+
+ /**
+ * Registers the error handler.
+ *
+ * @param self|null $handler The handler to register
+ * @param bool $replace Whether to replace or not any existing handler
+ *
+ * @return self The registered error handler
+ */
+ public static function register(self $handler = null, $replace = true)
+ {
+ if (null === self::$reservedMemory) {
+ self::$reservedMemory = str_repeat('x', 10240);
+ register_shutdown_function(__CLASS__.'::handleFatalError');
+ }
+
+ if ($handlerIsNew = null === $handler) {
+ $handler = new static();
+ }
+
+ if (null === $prev = set_error_handler(array($handler, 'handleError'))) {
+ restore_error_handler();
+ // Specifying the error types earlier would expose us to https://bugs.php.net/63206
+ set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
+ $handler->isRoot = true;
+ }
+
+ if ($handlerIsNew && is_array($prev) && $prev[0] instanceof self) {
+ $handler = $prev[0];
+ $replace = false;
+ }
+ if ($replace || !$prev) {
+ $handler->setExceptionHandler(set_exception_handler(array($handler, 'handleException')));
+ } else {
+ restore_error_handler();
+ }
+
+ $handler->throwAt(E_ALL & $handler->thrownErrors, true);
+
+ return $handler;
+ }
+
+ public function __construct(BufferingLogger $bootstrappingLogger = null)
+ {
+ if ($bootstrappingLogger) {
+ $this->bootstrappingLogger = $bootstrappingLogger;
+ $this->setDefaultLogger($bootstrappingLogger);
+ }
+ $this->traceReflector = new \ReflectionProperty('Exception', 'trace');
+ $this->traceReflector->setAccessible(true);
+ }
+
+ /**
+ * Sets a logger to non assigned errors levels.
+ *
+ * @param LoggerInterface $logger A PSR-3 logger to put as default for the given levels
+ * @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants
+ * @param bool $replace Whether to replace or not any existing logger
+ */
+ public function setDefaultLogger(LoggerInterface $logger, $levels = E_ALL, $replace = false)
+ {
+ $loggers = array();
+
+ if (is_array($levels)) {
+ foreach ($levels as $type => $logLevel) {
+ if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) {
+ $loggers[$type] = array($logger, $logLevel);
+ }
+ }
+ } else {
+ if (null === $levels) {
+ $levels = E_ALL;
+ }
+ foreach ($this->loggers as $type => $log) {
+ if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) {
+ $log[0] = $logger;
+ $loggers[$type] = $log;
+ }
+ }
+ }
+
+ $this->setLoggers($loggers);
+ }
+
+ /**
+ * Sets a logger for each error level.
+ *
+ * @param array $loggers Error levels to [LoggerInterface|null, LogLevel::*] map
+ *
+ * @return array The previous map
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setLoggers(array $loggers)
+ {
+ $prevLogged = $this->loggedErrors;
+ $prev = $this->loggers;
+ $flush = array();
+
+ foreach ($loggers as $type => $log) {
+ if (!isset($prev[$type])) {
+ throw new \InvalidArgumentException('Unknown error type: '.$type);
+ }
+ if (!is_array($log)) {
+ $log = array($log);
+ } elseif (!array_key_exists(0, $log)) {
+ throw new \InvalidArgumentException('No logger provided');
+ }
+ if (null === $log[0]) {
+ $this->loggedErrors &= ~$type;
+ } elseif ($log[0] instanceof LoggerInterface) {
+ $this->loggedErrors |= $type;
+ } else {
+ throw new \InvalidArgumentException('Invalid logger provided');
+ }
+ $this->loggers[$type] = $log + $prev[$type];
+
+ if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) {
+ $flush[$type] = $type;
+ }
+ }
+ $this->reRegister($prevLogged | $this->thrownErrors);
+
+ if ($flush) {
+ foreach ($this->bootstrappingLogger->cleanLogs() as $log) {
+ $type = $log[2]['exception'] instanceof \ErrorException ? $log[2]['exception']->getSeverity() : E_ERROR;
+ if (!isset($flush[$type])) {
+ $this->bootstrappingLogger->log($log[0], $log[1], $log[2]);
+ } elseif ($this->loggers[$type][0]) {
+ $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]);
+ }
+ }
+ }
+
+ return $prev;
+ }
+
+ /**
+ * Sets a user exception handler.
+ *
+ * @param callable $handler A handler that will be called on Exception
+ *
+ * @return callable|null The previous exception handler
+ */
+ public function setExceptionHandler(callable $handler = null)
+ {
+ $prev = $this->exceptionHandler;
+ $this->exceptionHandler = $handler;
+
+ return $prev;
+ }
+
+ /**
+ * Sets the PHP error levels that throw an exception when a PHP error occurs.
+ *
+ * @param int $levels A bit field of E_* constants for thrown errors
+ * @param bool $replace Replace or amend the previous value
+ *
+ * @return int The previous value
+ */
+ public function throwAt($levels, $replace = false)
+ {
+ $prev = $this->thrownErrors;
+ $this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
+ if (!$replace) {
+ $this->thrownErrors |= $prev;
+ }
+ $this->reRegister($prev | $this->loggedErrors);
+
+ return $prev;
+ }
+
+ /**
+ * Sets the PHP error levels for which local variables are preserved.
+ *
+ * @param int $levels A bit field of E_* constants for scoped errors
+ * @param bool $replace Replace or amend the previous value
+ *
+ * @return int The previous value
+ */
+ public function scopeAt($levels, $replace = false)
+ {
+ $prev = $this->scopedErrors;
+ $this->scopedErrors = (int) $levels;
+ if (!$replace) {
+ $this->scopedErrors |= $prev;
+ }
+
+ return $prev;
+ }
+
+ /**
+ * Sets the PHP error levels for which the stack trace is preserved.
+ *
+ * @param int $levels A bit field of E_* constants for traced errors
+ * @param bool $replace Replace or amend the previous value
+ *
+ * @return int The previous value
+ */
+ public function traceAt($levels, $replace = false)
+ {
+ $prev = $this->tracedErrors;
+ $this->tracedErrors = (int) $levels;
+ if (!$replace) {
+ $this->tracedErrors |= $prev;
+ }
+
+ return $prev;
+ }
+
+ /**
+ * Sets the error levels where the @-operator is ignored.
+ *
+ * @param int $levels A bit field of E_* constants for screamed errors
+ * @param bool $replace Replace or amend the previous value
+ *
+ * @return int The previous value
+ */
+ public function screamAt($levels, $replace = false)
+ {
+ $prev = $this->screamedErrors;
+ $this->screamedErrors = (int) $levels;
+ if (!$replace) {
+ $this->screamedErrors |= $prev;
+ }
+
+ return $prev;
+ }
+
+ /**
+ * Re-registers as a PHP error handler if levels changed.
+ */
+ private function reRegister($prev)
+ {
+ if ($prev !== $this->thrownErrors | $this->loggedErrors) {
+ $handler = set_error_handler('var_dump');
+ $handler = is_array($handler) ? $handler[0] : null;
+ restore_error_handler();
+ if ($handler === $this) {
+ restore_error_handler();
+ if ($this->isRoot) {
+ set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
+ } else {
+ set_error_handler(array($this, 'handleError'));
+ }
+ }
+ }
+ }
+
+ /**
+ * Handles errors by filtering then logging them according to the configured bit fields.
+ *
+ * @param int $type One of the E_* constants
+ * @param string $message
+ * @param string $file
+ * @param int $line
+ *
+ * @return bool Returns false when no handling happens so that the PHP engine can handle the error itself
+ *
+ * @throws \ErrorException When $this->thrownErrors requests so
+ *
+ * @internal
+ */
+ public function handleError($type, $message, $file, $line)
+ {
+ // Level is the current error reporting level to manage silent error.
+ // Strong errors are not authorized to be silenced.
+ $level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED;
+ $log = $this->loggedErrors & $type;
+ $throw = $this->thrownErrors & $type & $level;
+ $type &= $level | $this->screamedErrors;
+
+ if (!$type || (!$log && !$throw)) {
+ return $type && $log;
+ }
+ $scope = $this->scopedErrors & $type;
+
+ if (4 < $numArgs = func_num_args()) {
+ $context = $scope ? (func_get_arg(4) ?: array()) : array();
+ $backtrace = 5 < $numArgs ? func_get_arg(5) : null; // defined on HHVM
+ } else {
+ $context = array();
+ $backtrace = null;
+ }
+
+ if (isset($context['GLOBALS']) && $scope) {
+ $e = $context; // Whatever the signature of the method,
+ unset($e['GLOBALS'], $context); // $context is always a reference in 5.3
+ $context = $e;
+ }
+
+ if (null !== $backtrace && $type & E_ERROR) {
+ // E_ERROR fatal errors are triggered on HHVM when
+ // hhvm.error_handling.call_user_handler_on_fatals=1
+ // which is the way to get their backtrace.
+ $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
+
+ return true;
+ }
+
+ $logMessage = $this->levels[$type].': '.$message;
+
+ if (null !== self::$toStringException) {
+ $errorAsException = self::$toStringException;
+ self::$toStringException = null;
+ } elseif (!$throw && !($type & $level)) {
+ if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) {
+ $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), $type, $file, $line, false) : array();
+ $errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace);
+ } elseif (isset(self::$silencedErrorCache[$id][$message])) {
+ $lightTrace = null;
+ $errorAsException = self::$silencedErrorCache[$id][$message];
+ ++$errorAsException->count;
+ } else {
+ $lightTrace = array();
+ $errorAsException = null;
+ }
+
+ if (100 < ++self::$silencedErrorCount) {
+ self::$silencedErrorCache = $lightTrace = array();
+ self::$silencedErrorCount = 1;
+ }
+ if ($errorAsException) {
+ self::$silencedErrorCache[$id][$message] = $errorAsException;
+ }
+ if (null === $lightTrace) {
+ return;
+ }
+ } else {
+ if ($scope) {
+ $errorAsException = new ContextErrorException($logMessage, 0, $type, $file, $line, $context);
+ } else {
+ $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line);
+ }
+
+ // Clean the trace by removing function arguments and the first frames added by the error handler itself.
+ if ($throw || $this->tracedErrors & $type) {
+ $backtrace = $backtrace ?: $errorAsException->getTrace();
+ $lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw);
+ $this->traceReflector->setValue($errorAsException, $lightTrace);
+ } else {
+ $this->traceReflector->setValue($errorAsException, array());
+ }
+ }
+
+ if ($throw) {
+ if (E_USER_ERROR & $type) {
+ for ($i = 1; isset($backtrace[$i]); ++$i) {
+ if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function'])
+ && '__toString' === $backtrace[$i]['function']
+ && '->' === $backtrace[$i]['type']
+ && !isset($backtrace[$i - 1]['class'])
+ && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function'])
+ ) {
+ // Here, we know trigger_error() has been called from __toString().
+ // HHVM is fine with throwing from __toString() but PHP triggers a fatal error instead.
+ // A small convention allows working around the limitation:
+ // given a caught $e exception in __toString(), quitting the method with
+ // `return trigger_error($e, E_USER_ERROR);` allows this error handler
+ // to make $e get through the __toString() barrier.
+
+ foreach ($context as $e) {
+ if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) {
+ if (1 === $i) {
+ // On HHVM
+ $errorAsException = $e;
+ break;
+ }
+ self::$toStringException = $e;
+
+ return true;
+ }
+ }
+
+ if (1 < $i) {
+ // On PHP (not on HHVM), display the original error message instead of the default one.
+ $this->handleException($errorAsException);
+
+ // Stop the process by giving back the error to the native handler.
+ return false;
+ }
+ }
+ }
+ }
+
+ throw $errorAsException;
+ }
+
+ if ($this->isRecursive) {
+ $log = 0;
+ } elseif (self::$stackedErrorLevels) {
+ self::$stackedErrors[] = array(
+ $this->loggers[$type][0],
+ ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG,
+ $logMessage,
+ $errorAsException ? array('exception' => $errorAsException) : array(),
+ );
+ } else {
+ try {
+ $this->isRecursive = true;
+ $level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG;
+ $this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? array('exception' => $errorAsException) : array());
+ } finally {
+ $this->isRecursive = false;
+ }
+ }
+
+ return $type && $log;
+ }
+
+ /**
+ * Handles an exception by logging then forwarding it to another handler.
+ *
+ * @param \Exception|\Throwable $exception An exception to handle
+ * @param array $error An array as returned by error_get_last()
+ *
+ * @internal
+ */
+ public function handleException($exception, array $error = null)
+ {
+ if (null === $error) {
+ self::$exitCode = 255;
+ }
+ if (!$exception instanceof \Exception) {
+ $exception = new FatalThrowableError($exception);
+ }
+ $type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
+ $handlerException = null;
+
+ if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
+ if ($exception instanceof FatalErrorException) {
+ if ($exception instanceof FatalThrowableError) {
+ $error = array(
+ 'type' => $type,
+ 'message' => $message = $exception->getMessage(),
+ 'file' => $exception->getFile(),
+ 'line' => $exception->getLine(),
+ );
+ } else {
+ $message = 'Fatal '.$exception->getMessage();
+ }
+ } elseif ($exception instanceof \ErrorException) {
+ $message = 'Uncaught '.$exception->getMessage();
+ } else {
+ $message = 'Uncaught Exception: '.$exception->getMessage();
+ }
+ }
+ if ($this->loggedErrors & $type) {
+ try {
+ $this->loggers[$type][0]->log($this->loggers[$type][1], $message, array('exception' => $exception));
+ } catch (\Exception $handlerException) {
+ } catch (\Throwable $handlerException) {
+ }
+ }
+ if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) {
+ foreach ($this->getFatalErrorHandlers() as $handler) {
+ if ($e = $handler->handleError($error, $exception)) {
+ $exception = $e;
+ break;
+ }
+ }
+ }
+ try {
+ if (null !== $this->exceptionHandler) {
+ return \call_user_func($this->exceptionHandler, $exception);
+ }
+ $handlerException = $handlerException ?: $exception;
+ } catch (\Exception $handlerException) {
+ } catch (\Throwable $handlerException) {
+ }
+ $this->exceptionHandler = null;
+ if ($exception === $handlerException) {
+ self::$reservedMemory = null; // Disable the fatal error handler
+ throw $exception; // Give back $exception to the native handler
+ }
+ $this->handleException($handlerException);
+ }
+
+ /**
+ * Shutdown registered function for handling PHP fatal errors.
+ *
+ * @param array $error An array as returned by error_get_last()
+ *
+ * @internal
+ */
+ public static function handleFatalError(array $error = null)
+ {
+ if (null === self::$reservedMemory) {
+ return;
+ }
+
+ $handler = self::$reservedMemory = null;
+ $handlers = array();
+
+ while (!is_array($handler) || !$handler[0] instanceof self) {
+ $handler = set_exception_handler('var_dump');
+ restore_exception_handler();
+
+ if (!$handler) {
+ break;
+ }
+ restore_exception_handler();
+ array_unshift($handlers, $handler);
+ }
+ foreach ($handlers as $h) {
+ set_exception_handler($h);
+ }
+ if (!$handler) {
+ return;
+ }
+ if ($handler !== $h) {
+ $handler[0]->setExceptionHandler($h);
+ }
+ $handler = $handler[0];
+ $handlers = array();
+
+ if ($exit = null === $error) {
+ $error = error_get_last();
+ }
+
+ try {
+ while (self::$stackedErrorLevels) {
+ static::unstackErrors();
+ }
+ } catch (\Exception $exception) {
+ // Handled below
+ } catch (\Throwable $exception) {
+ // Handled below
+ }
+
+ if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
+ // Let's not throw anymore but keep logging
+ $handler->throwAt(0, true);
+ $trace = isset($error['backtrace']) ? $error['backtrace'] : null;
+
+ if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
+ $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace);
+ } else {
+ $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
+ }
+ }
+
+ try {
+ if (isset($exception)) {
+ self::$exitCode = 255;
+ $handler->handleException($exception, $error);
+ }
+ } catch (FatalErrorException $e) {
+ // Ignore this re-throw
+ }
+
+ if ($exit && self::$exitCode) {
+ $exitCode = self::$exitCode;
+ register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); });
+ }
+ }
+
+ /**
+ * Configures the error handler for delayed handling.
+ * Ensures also that non-catchable fatal errors are never silenced.
+ *
+ * As shown by http://bugs.php.net/42098 and http://bugs.php.net/60724
+ * PHP has a compile stage where it behaves unusually. To workaround it,
+ * we plug an error handler that only stacks errors for later.
+ *
+ * The most important feature of this is to prevent
+ * autoloading until unstackErrors() is called.
+ *
+ * @deprecated since version 3.4, to be removed in 4.0.
+ */
+ public static function stackErrors()
+ {
+ @trigger_error('Support for stacking errors is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED);
+
+ self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
+ }
+
+ /**
+ * Unstacks stacked errors and forwards to the logger.
+ *
+ * @deprecated since version 3.4, to be removed in 4.0.
+ */
+ public static function unstackErrors()
+ {
+ @trigger_error('Support for unstacking errors is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED);
+
+ $level = array_pop(self::$stackedErrorLevels);
+
+ if (null !== $level) {
+ $errorReportingLevel = error_reporting($level);
+ if ($errorReportingLevel !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) {
+ // If the user changed the error level, do not overwrite it
+ error_reporting($errorReportingLevel);
+ }
+ }
+
+ if (empty(self::$stackedErrorLevels)) {
+ $errors = self::$stackedErrors;
+ self::$stackedErrors = array();
+
+ foreach ($errors as $error) {
+ $error[0]->log($error[1], $error[2], $error[3]);
+ }
+ }
+ }
+
+ /**
+ * Gets the fatal error handlers.
+ *
+ * Override this method if you want to define more fatal error handlers.
+ *
+ * @return FatalErrorHandlerInterface[] An array of FatalErrorHandlerInterface
+ */
+ protected function getFatalErrorHandlers()
+ {
+ return array(
+ new UndefinedFunctionFatalErrorHandler(),
+ new UndefinedMethodFatalErrorHandler(),
+ new ClassNotFoundFatalErrorHandler(),
+ );
+ }
+
+ private function cleanTrace($backtrace, $type, $file, $line, $throw)
+ {
+ $lightTrace = $backtrace;
+
+ for ($i = 0; isset($backtrace[$i]); ++$i) {
+ if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) {
+ $lightTrace = array_slice($lightTrace, 1 + $i);
+ break;
+ }
+ }
+ if (!($throw || $this->scopedErrors & $type)) {
+ for ($i = 0; isset($lightTrace[$i]); ++$i) {
+ unset($lightTrace[$i]['args'], $lightTrace[$i]['object']);
+ }
+ }
+
+ return $lightTrace;
+ }
+}
diff --git a/vendor/symfony/debug/Exception/ClassNotFoundException.php b/vendor/symfony/debug/Exception/ClassNotFoundException.php
new file mode 100644
index 00000000..b91bf466
--- /dev/null
+++ b/vendor/symfony/debug/Exception/ClassNotFoundException.php
@@ -0,0 +1,33 @@
+<?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\Debug\Exception;
+
+/**
+ * Class (or Trait or Interface) Not Found Exception.
+ *
+ * @author Konstanton Myakshin <koc-dp@yandex.ru>
+ */
+class ClassNotFoundException extends FatalErrorException
+{
+ public function __construct($message, \ErrorException $previous)
+ {
+ parent::__construct(
+ $message,
+ $previous->getCode(),
+ $previous->getSeverity(),
+ $previous->getFile(),
+ $previous->getLine(),
+ $previous->getPrevious()
+ );
+ $this->setTrace($previous->getTrace());
+ }
+}
diff --git a/vendor/symfony/debug/Exception/ContextErrorException.php b/vendor/symfony/debug/Exception/ContextErrorException.php
new file mode 100644
index 00000000..6561d4df
--- /dev/null
+++ b/vendor/symfony/debug/Exception/ContextErrorException.php
@@ -0,0 +1,40 @@
+<?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\Debug\Exception;
+
+/**
+ * Error Exception with Variable Context.
+ *
+ * @author Christian Sciberras <uuf6429@gmail.com>
+ *
+ * @deprecated since version 3.3. Instead, \ErrorException will be used directly in 4.0.
+ */
+class ContextErrorException extends \ErrorException
+{
+ private $context = array();
+
+ public function __construct($message, $code, $severity, $filename, $lineno, $context = array())
+ {
+ parent::__construct($message, $code, $severity, $filename, $lineno);
+ $this->context = $context;
+ }
+
+ /**
+ * @return array Array of variables that existed when the exception occurred
+ */
+ public function getContext()
+ {
+ @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
+
+ return $this->context;
+ }
+}
diff --git a/vendor/symfony/debug/Exception/FatalErrorException.php b/vendor/symfony/debug/Exception/FatalErrorException.php
new file mode 100644
index 00000000..f24a54e7
--- /dev/null
+++ b/vendor/symfony/debug/Exception/FatalErrorException.php
@@ -0,0 +1,82 @@
+<?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\Debug\Exception;
+
+/**
+ * Fatal Error Exception.
+ *
+ * @author Konstanton Myakshin <koc-dp@yandex.ru>
+ */
+class FatalErrorException extends \ErrorException
+{
+ public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null)
+ {
+ parent::__construct($message, $code, $severity, $filename, $lineno);
+
+ if (null !== $trace) {
+ if (!$traceArgs) {
+ foreach ($trace as &$frame) {
+ unset($frame['args'], $frame['this'], $frame);
+ }
+ }
+
+ $this->setTrace($trace);
+ } elseif (null !== $traceOffset) {
+ if (function_exists('xdebug_get_function_stack')) {
+ $trace = xdebug_get_function_stack();
+ if (0 < $traceOffset) {
+ array_splice($trace, -$traceOffset);
+ }
+
+ foreach ($trace as &$frame) {
+ if (!isset($frame['type'])) {
+ // XDebug pre 2.1.1 doesn't currently set the call type key http://bugs.xdebug.org/view.php?id=695
+ if (isset($frame['class'])) {
+ $frame['type'] = '::';
+ }
+ } elseif ('dynamic' === $frame['type']) {
+ $frame['type'] = '->';
+ } elseif ('static' === $frame['type']) {
+ $frame['type'] = '::';
+ }
+
+ // XDebug also has a different name for the parameters array
+ if (!$traceArgs) {
+ unset($frame['params'], $frame['args']);
+ } elseif (isset($frame['params']) && !isset($frame['args'])) {
+ $frame['args'] = $frame['params'];
+ unset($frame['params']);
+ }
+ }
+
+ unset($frame);
+ $trace = array_reverse($trace);
+ } elseif (function_exists('symfony_debug_backtrace')) {
+ $trace = symfony_debug_backtrace();
+ if (0 < $traceOffset) {
+ array_splice($trace, 0, $traceOffset);
+ }
+ } else {
+ $trace = array();
+ }
+
+ $this->setTrace($trace);
+ }
+ }
+
+ protected function setTrace($trace)
+ {
+ $traceReflector = new \ReflectionProperty('Exception', 'trace');
+ $traceReflector->setAccessible(true);
+ $traceReflector->setValue($this, $trace);
+ }
+}
diff --git a/vendor/symfony/debug/Exception/FatalThrowableError.php b/vendor/symfony/debug/Exception/FatalThrowableError.php
new file mode 100644
index 00000000..34f43b17
--- /dev/null
+++ b/vendor/symfony/debug/Exception/FatalThrowableError.php
@@ -0,0 +1,44 @@
+<?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\Debug\Exception;
+
+/**
+ * Fatal Throwable Error.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class FatalThrowableError extends FatalErrorException
+{
+ public function __construct(\Throwable $e)
+ {
+ if ($e instanceof \ParseError) {
+ $message = 'Parse error: '.$e->getMessage();
+ $severity = E_PARSE;
+ } elseif ($e instanceof \TypeError) {
+ $message = 'Type error: '.$e->getMessage();
+ $severity = E_RECOVERABLE_ERROR;
+ } else {
+ $message = $e->getMessage();
+ $severity = E_ERROR;
+ }
+
+ \ErrorException::__construct(
+ $message,
+ $e->getCode(),
+ $severity,
+ $e->getFile(),
+ $e->getLine()
+ );
+
+ $this->setTrace($e->getTrace());
+ }
+}
diff --git a/vendor/symfony/debug/Exception/FlattenException.php b/vendor/symfony/debug/Exception/FlattenException.php
new file mode 100644
index 00000000..24679dca
--- /dev/null
+++ b/vendor/symfony/debug/Exception/FlattenException.php
@@ -0,0 +1,263 @@
+<?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\Debug\Exception;
+
+use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface;
+use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
+
+/**
+ * FlattenException wraps a PHP Exception to be able to serialize it.
+ *
+ * Basically, this class removes all objects from the trace.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class FlattenException
+{
+ private $message;
+ private $code;
+ private $previous;
+ private $trace;
+ private $class;
+ private $statusCode;
+ private $headers;
+ private $file;
+ private $line;
+
+ public static function create(\Exception $exception, $statusCode = null, array $headers = array())
+ {
+ $e = new static();
+ $e->setMessage($exception->getMessage());
+ $e->setCode($exception->getCode());
+
+ if ($exception instanceof HttpExceptionInterface) {
+ $statusCode = $exception->getStatusCode();
+ $headers = array_merge($headers, $exception->getHeaders());
+ } elseif ($exception instanceof RequestExceptionInterface) {
+ $statusCode = 400;
+ }
+
+ if (null === $statusCode) {
+ $statusCode = 500;
+ }
+
+ $e->setStatusCode($statusCode);
+ $e->setHeaders($headers);
+ $e->setTraceFromException($exception);
+ $e->setClass(get_class($exception));
+ $e->setFile($exception->getFile());
+ $e->setLine($exception->getLine());
+
+ $previous = $exception->getPrevious();
+
+ if ($previous instanceof \Exception) {
+ $e->setPrevious(static::create($previous));
+ } elseif ($previous instanceof \Throwable) {
+ $e->setPrevious(static::create(new FatalThrowableError($previous)));
+ }
+
+ return $e;
+ }
+
+ public function toArray()
+ {
+ $exceptions = array();
+ foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
+ $exceptions[] = array(
+ 'message' => $exception->getMessage(),
+ 'class' => $exception->getClass(),
+ 'trace' => $exception->getTrace(),
+ );
+ }
+
+ return $exceptions;
+ }
+
+ public function getStatusCode()
+ {
+ return $this->statusCode;
+ }
+
+ public function setStatusCode($code)
+ {
+ $this->statusCode = $code;
+ }
+
+ public function getHeaders()
+ {
+ return $this->headers;
+ }
+
+ public function setHeaders(array $headers)
+ {
+ $this->headers = $headers;
+ }
+
+ public function getClass()
+ {
+ return $this->class;
+ }
+
+ public function setClass($class)
+ {
+ $this->class = $class;
+ }
+
+ public function getFile()
+ {
+ return $this->file;
+ }
+
+ public function setFile($file)
+ {
+ $this->file = $file;
+ }
+
+ public function getLine()
+ {
+ return $this->line;
+ }
+
+ public function setLine($line)
+ {
+ $this->line = $line;
+ }
+
+ public function getMessage()
+ {
+ return $this->message;
+ }
+
+ public function setMessage($message)
+ {
+ $this->message = $message;
+ }
+
+ public function getCode()
+ {
+ return $this->code;
+ }
+
+ public function setCode($code)
+ {
+ $this->code = $code;
+ }
+
+ public function getPrevious()
+ {
+ return $this->previous;
+ }
+
+ public function setPrevious(FlattenException $previous)
+ {
+ $this->previous = $previous;
+ }
+
+ public function getAllPrevious()
+ {
+ $exceptions = array();
+ $e = $this;
+ while ($e = $e->getPrevious()) {
+ $exceptions[] = $e;
+ }
+
+ return $exceptions;
+ }
+
+ public function getTrace()
+ {
+ return $this->trace;
+ }
+
+ public function setTraceFromException(\Exception $exception)
+ {
+ $this->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine());
+ }
+
+ public function setTrace($trace, $file, $line)
+ {
+ $this->trace = array();
+ $this->trace[] = array(
+ 'namespace' => '',
+ 'short_class' => '',
+ 'class' => '',
+ 'type' => '',
+ 'function' => '',
+ 'file' => $file,
+ 'line' => $line,
+ 'args' => array(),
+ );
+ foreach ($trace as $entry) {
+ $class = '';
+ $namespace = '';
+ if (isset($entry['class'])) {
+ $parts = explode('\\', $entry['class']);
+ $class = array_pop($parts);
+ $namespace = implode('\\', $parts);
+ }
+
+ $this->trace[] = array(
+ 'namespace' => $namespace,
+ 'short_class' => $class,
+ 'class' => isset($entry['class']) ? $entry['class'] : '',
+ 'type' => isset($entry['type']) ? $entry['type'] : '',
+ 'function' => isset($entry['function']) ? $entry['function'] : null,
+ 'file' => isset($entry['file']) ? $entry['file'] : null,
+ 'line' => isset($entry['line']) ? $entry['line'] : null,
+ 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(),
+ );
+ }
+ }
+
+ private function flattenArgs($args, $level = 0, &$count = 0)
+ {
+ $result = array();
+ foreach ($args as $key => $value) {
+ if (++$count > 1e4) {
+ return array('array', '*SKIPPED over 10000 entries*');
+ }
+ if ($value instanceof \__PHP_Incomplete_Class) {
+ // is_object() returns false on PHP<=7.1
+ $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
+ } elseif (is_object($value)) {
+ $result[$key] = array('object', get_class($value));
+ } elseif (is_array($value)) {
+ if ($level > 10) {
+ $result[$key] = array('array', '*DEEP NESTED ARRAY*');
+ } else {
+ $result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count));
+ }
+ } elseif (null === $value) {
+ $result[$key] = array('null', null);
+ } elseif (is_bool($value)) {
+ $result[$key] = array('boolean', $value);
+ } elseif (is_int($value)) {
+ $result[$key] = array('integer', $value);
+ } elseif (is_float($value)) {
+ $result[$key] = array('float', $value);
+ } elseif (is_resource($value)) {
+ $result[$key] = array('resource', get_resource_type($value));
+ } else {
+ $result[$key] = array('string', (string) $value);
+ }
+ }
+
+ return $result;
+ }
+
+ private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
+ {
+ $array = new \ArrayObject($value);
+
+ return $array['__PHP_Incomplete_Class_Name'];
+ }
+}
diff --git a/vendor/symfony/debug/Exception/OutOfMemoryException.php b/vendor/symfony/debug/Exception/OutOfMemoryException.php
new file mode 100644
index 00000000..fec19798
--- /dev/null
+++ b/vendor/symfony/debug/Exception/OutOfMemoryException.php
@@ -0,0 +1,21 @@
+<?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\Debug\Exception;
+
+/**
+ * Out of memory exception.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class OutOfMemoryException extends FatalErrorException
+{
+}
diff --git a/vendor/symfony/debug/Exception/SilencedErrorContext.php b/vendor/symfony/debug/Exception/SilencedErrorContext.php
new file mode 100644
index 00000000..4be83491
--- /dev/null
+++ b/vendor/symfony/debug/Exception/SilencedErrorContext.php
@@ -0,0 +1,67 @@
+<?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\Debug\Exception;
+
+/**
+ * Data Object that represents a Silenced Error.
+ *
+ * @author Grégoire Pineau <lyrixx@lyrixx.info>
+ */
+class SilencedErrorContext implements \JsonSerializable
+{
+ public $count = 1;
+
+ private $severity;
+ private $file;
+ private $line;
+ private $trace;
+
+ public function __construct($severity, $file, $line, array $trace = array(), $count = 1)
+ {
+ $this->severity = $severity;
+ $this->file = $file;
+ $this->line = $line;
+ $this->trace = $trace;
+ $this->count = $count;
+ }
+
+ public function getSeverity()
+ {
+ return $this->severity;
+ }
+
+ public function getFile()
+ {
+ return $this->file;
+ }
+
+ public function getLine()
+ {
+ return $this->line;
+ }
+
+ public function getTrace()
+ {
+ return $this->trace;
+ }
+
+ public function JsonSerialize()
+ {
+ return array(
+ 'severity' => $this->severity,
+ 'file' => $this->file,
+ 'line' => $this->line,
+ 'trace' => $this->trace,
+ 'count' => $this->count,
+ );
+ }
+}
diff --git a/vendor/symfony/debug/Exception/UndefinedFunctionException.php b/vendor/symfony/debug/Exception/UndefinedFunctionException.php
new file mode 100644
index 00000000..a66ae2a3
--- /dev/null
+++ b/vendor/symfony/debug/Exception/UndefinedFunctionException.php
@@ -0,0 +1,33 @@
+<?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\Debug\Exception;
+
+/**
+ * Undefined Function Exception.
+ *
+ * @author Konstanton Myakshin <koc-dp@yandex.ru>
+ */
+class UndefinedFunctionException extends FatalErrorException
+{
+ public function __construct($message, \ErrorException $previous)
+ {
+ parent::__construct(
+ $message,
+ $previous->getCode(),
+ $previous->getSeverity(),
+ $previous->getFile(),
+ $previous->getLine(),
+ $previous->getPrevious()
+ );
+ $this->setTrace($previous->getTrace());
+ }
+}
diff --git a/vendor/symfony/debug/Exception/UndefinedMethodException.php b/vendor/symfony/debug/Exception/UndefinedMethodException.php
new file mode 100644
index 00000000..350dc318
--- /dev/null
+++ b/vendor/symfony/debug/Exception/UndefinedMethodException.php
@@ -0,0 +1,33 @@
+<?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\Debug\Exception;
+
+/**
+ * Undefined Method Exception.
+ *
+ * @author Grégoire Pineau <lyrixx@lyrixx.info>
+ */
+class UndefinedMethodException extends FatalErrorException
+{
+ public function __construct($message, \ErrorException $previous)
+ {
+ parent::__construct(
+ $message,
+ $previous->getCode(),
+ $previous->getSeverity(),
+ $previous->getFile(),
+ $previous->getLine(),
+ $previous->getPrevious()
+ );
+ $this->setTrace($previous->getTrace());
+ }
+}
diff --git a/vendor/symfony/debug/ExceptionHandler.php b/vendor/symfony/debug/ExceptionHandler.php
new file mode 100644
index 00000000..97470cb6
--- /dev/null
+++ b/vendor/symfony/debug/ExceptionHandler.php
@@ -0,0 +1,410 @@
+<?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\Debug;
+
+use Symfony\Component\Debug\Exception\FlattenException;
+use Symfony\Component\Debug\Exception\OutOfMemoryException;
+use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
+
+/**
+ * ExceptionHandler converts an exception to a Response object.
+ *
+ * It is mostly useful in debug mode to replace the default PHP/XDebug
+ * output with something prettier and more useful.
+ *
+ * As this class is mainly used during Kernel boot, where nothing is yet
+ * available, the Response content is always HTML.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ExceptionHandler
+{
+ private $debug;
+ private $charset;
+ private $handler;
+ private $caughtBuffer;
+ private $caughtLength;
+ private $fileLinkFormat;
+
+ public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
+ {
+ $this->debug = $debug;
+ $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8';
+ $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
+ }
+
+ /**
+ * Registers the exception handler.
+ *
+ * @param bool $debug Enable/disable debug mode, where the stack trace is displayed
+ * @param string|null $charset The charset used by exception messages
+ * @param string|null $fileLinkFormat The IDE link template
+ *
+ * @return static
+ */
+ public static function register($debug = true, $charset = null, $fileLinkFormat = null)
+ {
+ $handler = new static($debug, $charset, $fileLinkFormat);
+
+ $prev = set_exception_handler(array($handler, 'handle'));
+ if (is_array($prev) && $prev[0] instanceof ErrorHandler) {
+ restore_exception_handler();
+ $prev[0]->setExceptionHandler(array($handler, 'handle'));
+ }
+
+ return $handler;
+ }
+
+ /**
+ * Sets a user exception handler.
+ *
+ * @param callable $handler An handler that will be called on Exception
+ *
+ * @return callable|null The previous exception handler if any
+ */
+ public function setHandler(callable $handler = null)
+ {
+ $old = $this->handler;
+ $this->handler = $handler;
+
+ return $old;
+ }
+
+ /**
+ * Sets the format for links to source files.
+ *
+ * @param string|FileLinkFormatter $fileLinkFormat The format for links to source files
+ *
+ * @return string The previous file link format
+ */
+ public function setFileLinkFormat($fileLinkFormat)
+ {
+ $old = $this->fileLinkFormat;
+ $this->fileLinkFormat = $fileLinkFormat;
+
+ return $old;
+ }
+
+ /**
+ * Sends a response for the given Exception.
+ *
+ * To be as fail-safe as possible, the exception is first handled
+ * by our simple exception handler, then by the user exception handler.
+ * The latter takes precedence and any output from the former is cancelled,
+ * if and only if nothing bad happens in this handling path.
+ */
+ public function handle(\Exception $exception)
+ {
+ if (null === $this->handler || $exception instanceof OutOfMemoryException) {
+ $this->sendPhpResponse($exception);
+
+ return;
+ }
+
+ $caughtLength = $this->caughtLength = 0;
+
+ ob_start(function ($buffer) {
+ $this->caughtBuffer = $buffer;
+
+ return '';
+ });
+
+ $this->sendPhpResponse($exception);
+ while (null === $this->caughtBuffer && ob_end_flush()) {
+ // Empty loop, everything is in the condition
+ }
+ if (isset($this->caughtBuffer[0])) {
+ ob_start(function ($buffer) {
+ if ($this->caughtLength) {
+ // use substr_replace() instead of substr() for mbstring overloading resistance
+ $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtLength);
+ if (isset($cleanBuffer[0])) {
+ $buffer = $cleanBuffer;
+ }
+ }
+
+ return $buffer;
+ });
+
+ echo $this->caughtBuffer;
+ $caughtLength = ob_get_length();
+ }
+ $this->caughtBuffer = null;
+
+ try {
+ call_user_func($this->handler, $exception);
+ $this->caughtLength = $caughtLength;
+ } catch (\Exception $e) {
+ if (!$caughtLength) {
+ // All handlers failed. Let PHP handle that now.
+ throw $exception;
+ }
+ }
+ }
+
+ /**
+ * Sends the error associated with the given Exception as a plain PHP response.
+ *
+ * This method uses plain PHP functions like header() and echo to output
+ * the response.
+ *
+ * @param \Exception|FlattenException $exception An \Exception or FlattenException instance
+ */
+ public function sendPhpResponse($exception)
+ {
+ if (!$exception instanceof FlattenException) {
+ $exception = FlattenException::create($exception);
+ }
+
+ if (!headers_sent()) {
+ header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
+ foreach ($exception->getHeaders() as $name => $value) {
+ header($name.': '.$value, false);
+ }
+ header('Content-Type: text/html; charset='.$this->charset);
+ }
+
+ echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
+ }
+
+ /**
+ * Gets the full HTML content associated with the given exception.
+ *
+ * @param \Exception|FlattenException $exception An \Exception or FlattenException instance
+ *
+ * @return string The HTML content as a string
+ */
+ public function getHtml($exception)
+ {
+ if (!$exception instanceof FlattenException) {
+ $exception = FlattenException::create($exception);
+ }
+
+ return $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
+ }
+
+ /**
+ * Gets the HTML content associated with the given exception.
+ *
+ * @return string The content as a string
+ */
+ public function getContent(FlattenException $exception)
+ {
+ switch ($exception->getStatusCode()) {
+ case 404:
+ $title = 'Sorry, the page you are looking for could not be found.';
+ break;
+ default:
+ $title = 'Whoops, looks like something went wrong.';
+ }
+
+ $content = '';
+ if ($this->debug) {
+ try {
+ $count = count($exception->getAllPrevious());
+ $total = $count + 1;
+ foreach ($exception->toArray() as $position => $e) {
+ $ind = $count - $position + 1;
+ $class = $this->formatClass($e['class']);
+ $message = nl2br($this->escapeHtml($e['message']));
+ $content .= sprintf(<<<'EOF'
+ <div class="trace trace-as-html">
+ <table class="trace-details">
+ <thead class="trace-head"><tr><th>
+ <h3 class="trace-class">
+ <span class="text-muted">(%d/%d)</span>
+ <span class="exception_title">%s</span>
+ </h3>
+ <p class="break-long-words trace-message">%s</p>
+ </th></tr></thead>
+ <tbody>
+EOF
+ , $ind, $total, $class, $message);
+ foreach ($e['trace'] as $trace) {
+ $content .= '<tr><td>';
+ if ($trace['function']) {
+ $content .= sprintf('at <span class="trace-class">%s</span><span class="trace-type">%s</span><span class="trace-method">%s</span>(<span class="trace-arguments">%s</span>)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
+ }
+ if (isset($trace['file']) && isset($trace['line'])) {
+ $content .= $this->formatPath($trace['file'], $trace['line']);
+ }
+ $content .= "</td></tr>\n";
+ }
+
+ $content .= "</tbody>\n</table>\n</div>\n";
+ }
+ } catch (\Exception $e) {
+ // something nasty happened and we cannot throw an exception anymore
+ if ($this->debug) {
+ $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $this->escapeHtml($e->getMessage()));
+ } else {
+ $title = 'Whoops, looks like something went wrong.';
+ }
+ }
+ }
+
+ $symfonyGhostImageContents = $this->getSymfonyGhostAsSvg();
+
+ return <<<EOF
+ <div class="exception-summary">
+ <div class="container">
+ <div class="exception-message-wrapper">
+ <h1 class="break-long-words exception-message">$title</h1>
+ <div class="exception-illustration hidden-xs-down">$symfonyGhostImageContents</div>
+ </div>
+ </div>
+ </div>
+
+ <div class="container">
+ $content
+ </div>
+EOF;
+ }
+
+ /**
+ * Gets the stylesheet associated with the given exception.
+ *
+ * @return string The stylesheet as a string
+ */
+ public function getStylesheet(FlattenException $exception)
+ {
+ return <<<'EOF'
+ body { background-color: #F9F9F9; color: #222; font: 14px/1.4 Helvetica, Arial, sans-serif; margin: 0; padding-bottom: 45px; }
+
+ a { cursor: pointer; text-decoration: none; }
+ a:hover { text-decoration: underline; }
+ abbr[title] { border-bottom: none; cursor: help; text-decoration: none; }
+
+ code, pre { font: 13px/1.5 Consolas, Monaco, Menlo, "Ubuntu Mono", "Liberation Mono", monospace; }
+
+ table, tr, th, td { background: #FFF; border-collapse: collapse; vertical-align: top; }
+ table { background: #FFF; border: 1px solid #E0E0E0; box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; width: 100%; }
+ table th, table td { border: solid #E0E0E0; border-width: 1px 0; padding: 8px 10px; }
+ table th { background-color: #E0E0E0; font-weight: bold; text-align: left; }
+
+ .hidden-xs-down { display: none; }
+ .block { display: block; }
+ .break-long-words { -ms-word-break: break-all; word-break: break-all; word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; }
+ .text-muted { color: #999; }
+
+ .container { max-width: 1024px; margin: 0 auto; padding: 0 15px; }
+ .container::after { content: ""; display: table; clear: both; }
+
+ .exception-summary { background: #B0413E; border-bottom: 2px solid rgba(0, 0, 0, 0.1); border-top: 1px solid rgba(0, 0, 0, .3); flex: 0 0 auto; margin-bottom: 30px; }
+
+ .exception-message-wrapper { display: flex; align-items: center; min-height: 70px; }
+ .exception-message { flex-grow: 1; padding: 30px 0; }
+ .exception-message, .exception-message a { color: #FFF; font-size: 21px; font-weight: 400; margin: 0; }
+ .exception-message.long { font-size: 18px; }
+ .exception-message a { border-bottom: 1px solid rgba(255, 255, 255, 0.5); font-size: inherit; text-decoration: none; }
+ .exception-message a:hover { border-bottom-color: #ffffff; }
+
+ .exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; }
+
+ .trace + .trace { margin-top: 30px; }
+ .trace-head .trace-class { color: #222; font-size: 18px; font-weight: bold; line-height: 1.3; margin: 0; position: relative; }
+
+ .trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; }
+
+ .trace-file-path, .trace-file-path a { color: #222; margin-top: 3px; font-size: 13px; }
+ .trace-class { color: #B0413E; }
+ .trace-type { padding: 0 2px; }
+ .trace-method { color: #B0413E; font-weight: bold; }
+ .trace-arguments { color: #777; font-weight: normal; padding-left: 2px; }
+
+ @media (min-width: 575px) {
+ .hidden-xs-down { display: initial; }
+ }
+EOF;
+ }
+
+ private function decorate($content, $css)
+ {
+ return <<<EOF
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="{$this->charset}" />
+ <meta name="robots" content="noindex,nofollow" />
+ <style>$css</style>
+ </head>
+ <body>
+ $content
+ </body>
+</html>
+EOF;
+ }
+
+ private function formatClass($class)
+ {
+ $parts = explode('\\', $class);
+
+ return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts));
+ }
+
+ private function formatPath($path, $line)
+ {
+ $file = $this->escapeHtml(preg_match('#[^/\\\\]*+$#', $path, $file) ? $file[0] : $path);
+ $fmt = $this->fileLinkFormat;
+
+ if ($fmt && $link = is_string($fmt) ? strtr($fmt, array('%f' => $path, '%l' => $line)) : $fmt->format($path, $line)) {
+ return sprintf('<span class="block trace-file-path">in <a href="%s" title="Go to source">%s (line %d)</a></span>', $this->escapeHtml($link), $file, $line);
+ }
+
+ return sprintf('<span class="block trace-file-path">in <a title="%s line %3$d"><strong>%s</strong> (line %d)</a></span>', $this->escapeHtml($path), $file, $line);
+ }
+
+ /**
+ * Formats an array as a string.
+ *
+ * @param array $args The argument array
+ *
+ * @return string
+ */
+ private function formatArgs(array $args)
+ {
+ $result = array();
+ foreach ($args as $key => $item) {
+ if ('object' === $item[0]) {
+ $formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1]));
+ } elseif ('array' === $item[0]) {
+ $formattedValue = sprintf('<em>array</em>(%s)', is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
+ } elseif ('null' === $item[0]) {
+ $formattedValue = '<em>null</em>';
+ } elseif ('boolean' === $item[0]) {
+ $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
+ } elseif ('resource' === $item[0]) {
+ $formattedValue = '<em>resource</em>';
+ } else {
+ $formattedValue = str_replace("\n", '', $this->escapeHtml(var_export($item[1], true)));
+ }
+
+ $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue);
+ }
+
+ return implode(', ', $result);
+ }
+
+ /**
+ * HTML-encodes a string.
+ */
+ private function escapeHtml($str)
+ {
+ return htmlspecialchars($str, ENT_COMPAT | ENT_SUBSTITUTE, $this->charset);
+ }
+
+ private function getSymfonyGhostAsSvg()
+ {
+ return '<svg viewBox="0 0 136 81" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M92.358 20.403a23.168 23.168 0 0 1 9.003 1.881 23.67 23.67 0 0 1 5.197 3.079 24.257 24.257 0 0 1 3.457 3.296 24.771 24.771 0 0 1 5.042 9.396c.486 1.72.78 3.492.895 5.28l.008.142.028.158.015.246v13.875c.116.034.232.065.348.098.193.054.383.116.577.168.487.125.989.191 1.49.215.338.016.689.023 1.021-.059.021-.005.032-.029.048-.044l.095-.1c.243-.265.461-.552.663-.851.277-.408.523-.837.746-1.279l.042-.087c-.066-.012-.131-.026-.197-.04l-.099-.023a5.536 5.536 0 0 1-.694-.242 5.649 5.649 0 0 1-2.374-1.845 5.694 5.694 0 0 1-.824-1.594 6.514 6.514 0 0 1-.267-2.781c.045-.394.126-.779.233-1.159.079-.278.162-.562.307-.812.094-.163.129-.196.247-.341l.79-.882c.143-.143.174-.186.34-.303.249-.174.536-.289.834-.333.074-.011.15-.014.224-.02l1.188-.037c.173.004.217-.002.388.028s.211.05.375.105l.018.007c.059.026.119.05.176.079.151.076.179.104.313.2l.006-.021c.073-.187.084-.238.187-.41.077-.129.167-.249.27-.357.051-.054.108-.103.162-.154l1.124-.95c.14-.107.172-.14.327-.224.155-.085.199-.094.363-.154l.019-.006c.169-.043.211-.06.385-.077.174-.016.218-.007.392.003l1.446.158c.193.033.244.033.43.098.278.097.534.259.744.47.053.053.1.112.149.167l.923 1.158.149.213.028.054.017-.014.184-.125c.196-.104.196-.104.402-.184l1.386-.451c.064-.018.126-.038.19-.052.129-.028.259-.042.39-.043.16-.002.321.017.478.047.364.069.711.21 1.032.396.162.094.316.199.469.308.088.063.176.132.27.188l.021.011c.19.123.245.146.409.305.185.178.336.393.443.63.035.079.061.162.091.243l.439 1.428c.045.175.062.219.081.4.02.193.006.381-.015.573a7.79 7.79 0 0 1-.101.645c-.09.455-.212.901-.365 1.339-.128.366-.273.73-.445 1.077-.658 1.335-1.652 2.512-2.917 3.265a6.399 6.399 0 0 1-1.019.489 6.097 6.097 0 0 1-.631.203c-.226.058-.455.1-.686.134l-.096.012-.061.007c-.01.176-.022.352-.036.528-.034.39-.082.778-.153 1.163a14.258 14.258 0 0 1-.574 2.114c-.229.654-.484 1.306-.806 1.918a9.16 9.16 0 0 1-.386.656c-.219.348-.451.686-.697 1.013-.448.594-.946 1.148-1.521 1.614-.255.207-.52.397-.808.553-.9.489-1.919.648-2.921.735-.493.038-.986.059-1.478.099-.162.015-.324.033-.486.049-.145.011-.289.022-.434.03a15.768 15.768 0 0 1-2.778-.118c0 1.416.007 2.832-.001 4.248a9.737 9.737 0 0 1-.684 3.479 9.615 9.615 0 0 1-1.72 2.804 9.326 9.326 0 0 1-3.04 2.279 9.046 9.046 0 0 1-5.33.715 9.064 9.064 0 0 1-2.988-1.079 9.363 9.363 0 0 1-2.761-2.429 10.078 10.078 0 0 1-1.05 1.16 9.281 9.281 0 0 1-1.871 1.358 9.033 9.033 0 0 1-2.495.926 9.04 9.04 0 0 1-6.462-1.072 9.395 9.395 0 0 1-2.602-2.292l-.062-.08a10.896 10.896 0 0 1-.53.635 9.266 9.266 0 0 1-2.671 2.032 9.028 9.028 0 0 1-6.044.751 9.048 9.048 0 0 1-2.436-.934 9.343 9.343 0 0 1-2.286-1.803 9.572 9.572 0 0 1-1.783-2.757 9.705 9.705 0 0 1-.773-3.693V67.244c-.157.024-.314.047-.472.067-.487.06-.977.103-1.469.109-.313.004-.627-.009-.94-.028-.426-.025-.85-.065-1.273-.125-1.833-.264-3.65-.92-5.109-2.117a8.172 8.172 0 0 1-1.064-1.049 10.155 10.155 0 0 1-.878-1.236 15.277 15.277 0 0 1-.7-1.274 20.835 20.835 0 0 1-1.889-6.194l-.018-.142-.008-.061a6.47 6.47 0 0 1-.99-.297 6.135 6.135 0 0 1-.61-.285 6.587 6.587 0 0 1-.889-.562c-1.228-.924-2.124-2.259-2.668-3.711a9.947 9.947 0 0 1-.307-.99 10.288 10.288 0 0 1-.318-1.923c-.009-.147-.011-.293-.015-.44v-.037c.008-.175.004-.22.037-.393.033-.173.053-.213.11-.378l.561-1.417c.031-.068.06-.139.095-.206a2.028 2.028 0 0 1 .771-.803c.093-.054.194-.095.289-.145l.311-.179c.352-.194.714-.358 1.107-.44.213-.044.426-.061.643-.061l.034.001c.177.014.223.01.396.052.174.041.214.065.379.132l1.347.635c.073.04.15.076.221.121.142.091.272.2.388.325.154.166.176.222.297.414l.022.047.722-.762.168-.158c.165-.122.202-.161.385-.253.206-.102.429-.168.656-.193.076-.008.152-.008.228-.011l1.46.013c.177.011.223.007.397.046.175.038.215.061.381.126l.018.008c.154.08.196.094.338.196.142.102.169.137.294.259l.853.912.152-.067.191-.063.019-.005.196-.042c.177-.019.222-.031.401-.022.066.003.133.013.199.02l1.185.182c.073.016.147.027.219.047.288.08.558.227.784.428.151.135.177.181.303.339l.714 1.004c.097.152.127.187.201.352.077.172.123.352.164.536.029.134.056.269.08.404.063.361.102.725.112 1.091.021.78-.08 1.566-.321 2.307a5.906 5.906 0 0 1-.532 1.183 5.463 5.463 0 0 1-3.257 2.489l-.03.008c.195.584.433 1.155.712 1.701.215.422.453.833.735 1.211.026.035.026.034.053.068l.058.072c.056.024.113.042.171.06.319.09.653.121.982.14.488.027.978.013 1.461-.06.167-.028.333-.062.499-.089.134-.022.267-.042.401-.066l.28-.056c.154-.023.308-.049.462-.076l.115-.021V43.881c.011-.203.006-.203.042-.404a26.66 26.66 0 0 1 .226-2.241 24.737 24.737 0 0 1 5.72-12.577 24.204 24.204 0 0 1 3.457-3.296 23.653 23.653 0 0 1 4.937-2.966 23.215 23.215 0 0 1 5.604-1.681 23.703 23.703 0 0 1 3.958-.313zm-.287 2.042a21.169 21.169 0 0 0-8.012 1.622 21.636 21.636 0 0 0-4.799 2.766 22.233 22.233 0 0 0-3.205 2.985 22.705 22.705 0 0 0-4.897 9.196 23.383 23.383 0 0 0-.737 4.867h-.025v15.744c-.258.053-.258.052-.517.101-.28.051-.56.1-.841.144-.211.04-.421.079-.632.115l-.232.037-.411.078c-.116.02-.233.035-.348.057-.305.056-.609.11-.917.14a9.929 9.929 0 0 1-1.883-.017c-.514-.056-1.044-.155-1.51-.397a1.762 1.762 0 0 1-.33-.218 1.925 1.925 0 0 1-.234-.252 5.248 5.248 0 0 1-.174-.22 8.97 8.97 0 0 1-.582-.883 13.806 13.806 0 0 1-.941-1.971 14.348 14.348 0 0 1-.608-1.954 14.04 14.04 0 0 1-.169-.86l-.015-.11-.015-.109c.161-.007.16-.007.321-.016a12.793 12.793 0 0 0 1.413-.182 4.43 4.43 0 0 0 .28-.074 3.56 3.56 0 0 0 1.199-.616c.309-.244.576-.543.786-.88.163-.261.292-.544.387-.838.123-.378.192-.774.214-1.172a5.102 5.102 0 0 0-.024-.865 7.192 7.192 0 0 0-.145-.799l-.714-1.005-1.184-.182-.019.005-.946.758-.12 1.229a4.953 4.953 0 0 1 .111.455c.032.181.052.36.043.544a1.04 1.04 0 0 1-.056.303c-.11.301-.419.451-.696.548-.402.142-.813.25-1.229.339l.07-.648c.022-.191.047-.381.08-.57.036-.207.079-.413.152-.61.077-.211.182-.412.296-.605.044-.074.092-.146.135-.222.029-.048.031-.047.055-.098.016-.033.031-.064.045-.098l-.026-1.551-1.042-1.116-.018-.008-1.459-.014-1.022 1.079c-.049.128-.08.258-.111.393a5.274 5.274 0 0 0-.1.651 5.55 5.55 0 0 0-.031.466c-.009.687.104 1.37.294 2.028.11.382.262.753.402 1.123-.115-.029-.228-.06-.342-.092a9.526 9.526 0 0 1-1.176-.446c-.108-.05-.111-.048-.191-.097a1.921 1.921 0 0 1-.327-.249c-.416-.4-.589-.986-.671-1.55a5.643 5.643 0 0 1-.057-.549c-.007-.143-.006-.286-.007-.429-.001-.186.005-.372.011-.558l.001-.039-.567-1.446-1.347-.634c-.316-.008-.599.144-.867.299-.109.063-.218.126-.33.185a2.058 2.058 0 0 1-.125.061l-.042.019-.561 1.416c0 .209.014.416.036.624.04.377.106.75.196 1.118.076.309.164.616.275.913.415 1.109 1.093 2.146 2.043 2.838.234.171.485.317.746.442.183.088.371.161.565.22.263.079.532.13.803.17.296.045.594.075.892.095l.108.007c.004.151.01.302.017.453.011.177.023.353.038.529a18.13 18.13 0 0 0 .762 3.752c.239.76.522 1.505.857 2.225.23.494.483.977.767 1.44.288.469.608.915.989 1.308 1.001 1.028 2.324 1.648 3.687 1.976.643.155 1.298.243 1.955.287.311.021.622.036.933.033.418-.006.835-.041 1.25-.094.238-.03.477-.064.713-.11.117-.023.232-.053.348-.081.196-.048.392-.097.586-.151.147-.041.291-.094.436-.144.204-.069.408-.139.608-.217l.006-.003c0 2.207-.013 4.414.001 6.62a7.942 7.942 0 0 0 .13 1.32 7.545 7.545 0 0 0 2.383 4.243 7.23 7.23 0 0 0 2.258 1.372 7.094 7.094 0 0 0 7.012-1.164 7.504 7.504 0 0 0 2.035-2.613 7.727 7.727 0 0 0 .676-2.401l.009-.088.038-.765a8.16 8.16 0 0 0 .113 1.324c.121.694.338 1.37.643 2.001a7.49 7.49 0 0 0 1.692 2.275 7.266 7.266 0 0 0 2.24 1.399 7.11 7.11 0 0 0 4.615.19 7.212 7.212 0 0 0 2.351-1.218 7.501 7.501 0 0 0 2.128-2.64 7.763 7.763 0 0 0 .702-2.39l.01-.088.009-.088.038-.765a9.339 9.339 0 0 0 .021.575 7.626 7.626 0 0 0 .621 2.504 7.507 7.507 0 0 0 2.35 2.972 7.1 7.1 0 0 0 7.026.881 7.275 7.275 0 0 0 2.268-1.515 7.525 7.525 0 0 0 1.612-2.338 7.58 7.58 0 0 0 .572-2.033c.048-.347.069-.696.071-1.046v-6.721c.136.051.271.101.408.148a12.153 12.153 0 0 0 1.976.443c.264.035.529.055.794.071.33.02.66.031.991.027.245-.002.49-.012.735-.031.245-.018.49-.048.735-.068.407-.03.814-.051 1.221-.079a9.493 9.493 0 0 0 1.384-.188c.315-.073.626-.174.912-.329a3.53 3.53 0 0 0 .586-.418c.46-.386.85-.85 1.205-1.337a12.178 12.178 0 0 0 .801-1.246c.122-.232.229-.471.33-.712a15.873 15.873 0 0 0 .681-1.988c.136-.525.23-1.058.282-1.598.035-.41.052-.822.088-1.232.03-.317.078-.632.121-.947l.018-.145.016-.145c.144.009.287.016.431.021.459.009.924.007 1.378-.07a4.456 4.456 0 0 0 1.353-.482c.989-.55 1.752-1.466 2.258-2.488.116-.235.214-.48.304-.727a7.58 7.58 0 0 0 .377-1.43c.016-.109.027-.218.039-.328l.001-.009-.438-1.428a5.206 5.206 0 0 1-.16-.096c-.158-.105-.311-.219-.467-.326a3.829 3.829 0 0 0-.159-.1 1.356 1.356 0 0 0-.509-.18l-.01-.001-1.386.452-.681 1.323c-.016.212-.023.424-.043.636a5.66 5.66 0 0 1-.139.873c-.118.494-.316.999-.702 1.338a1.865 1.865 0 0 1-.496.301l-.272.087a9.57 9.57 0 0 1-.83.205 8.797 8.797 0 0 1-.582.091l.229-.462c.079-.163.158-.325.229-.492.051-.118.096-.239.139-.36.036-.103.076-.209.103-.315.019-.075.031-.153.041-.229.017-.132.031-.263.043-.395.035-.368.06-.737.094-1.104.02-.187.048-.372.067-.559.015-.167.015-.336.012-.505a4.76 4.76 0 0 0-.074-.826c-.012-.065-.03-.13-.045-.194l-.003-.009-.923-1.157-1.446-.159-.019.006-1.124.95-.154 1.489c.011.034.024.066.037.099.044.115.107.221.161.331.046.096.088.193.13.29l.031.076c.013.033.017.07.023.105.012.096.022.191.031.287.031.364.047.73.081 1.093.013.102.028.202.04.303.014.145.027.29.033.435.014.28.016.561.023.841a9.588 9.588 0 0 1-.862-.323c-.063-.027-.128-.062-.193-.084a1.325 1.325 0 0 0-.067-.013c-.081-.01-.162-.017-.243-.025-.245-.02-.49-.037-.734-.061-.066-.007-.132-.014-.198-.028l-.017-.005c-.03-.013-.029-.014-.067-.038a1.614 1.614 0 0 1-.161-.108.863.863 0 0 1-.22-.242c-.089-.155-.102-.34-.09-.517.02-.299.117-.591.228-.866l.004-.009-.018-1.197-.874-.84-.018-.007-1.188.036-.79.882c-.037.112-.074.224-.106.338a4.756 4.756 0 0 0-.171 1.906c.039.329.115.654.233.963a3.542 3.542 0 0 0 1.263 1.636c.313.222.659.393 1.019.517.237.082.487.111.734.145.479.06.959.106 1.438.166.121.017.241.037.362.058l.158.026a12.12 12.12 0 0 1-.923 2.565 13.221 13.221 0 0 1-.829 1.474 9.474 9.474 0 0 1-.984 1.286c-.08.087-.163.17-.248.252a1.655 1.655 0 0 1-.329.262 2.376 2.376 0 0 1-.722.247c-.457.089-.927.093-1.39.071-.391-.018-.781-.06-1.168-.123a7.817 7.817 0 0 1-.609-.124c-.226-.056-.448-.124-.671-.191-.065-.019-.131-.035-.197-.054a14.75 14.75 0 0 1-.543-.165 23.384 23.384 0 0 1-.453-.128c-.196-.059-.195-.059-.39-.12l-.276-.077V43.881h-.025a34.633 34.633 0 0 0-.031-.557 23.606 23.606 0 0 0-.4-2.994 22.743 22.743 0 0 0-1.492-4.708 22.567 22.567 0 0 0-4.593-6.748 21.865 21.865 0 0 0-6.882-4.706 21.175 21.175 0 0 0-8.115-1.722l-.411-.001zm9.15 33.69c.109.015.214.038.315.085a1.012 1.012 0 0 1 .574.771c.021.132.013.268.009.4a8.38 8.38 0 0 1-.026.476 8.767 8.767 0 0 1-1.564 4.282c-.306.437-.65.846-1.024 1.222a10.09 10.09 0 0 1-4.612 2.627c-1.32.343-2.704.427-4.055.254a10.422 10.422 0 0 1-2.67-.709 9.917 9.917 0 0 1-3.57-2.503 9.312 9.312 0 0 1-.775-.984 8.933 8.933 0 0 1-.731-1.288 8.648 8.648 0 0 1-.795-3.377c-.003-.104-.008-.211 0-.316a1.042 1.042 0 0 1 .254-.609.98.98 0 0 1 1.337-.125 1.023 1.023 0 0 1 .385.719c.007.151.006.303.014.454a6.547 6.547 0 0 0 .524 2.217c.257.595.599 1.15 1.006 1.648.325.398.691.759 1.087 1.081.312.253.642.482.987.684 2.592 1.522 5.945 1.538 8.553.047a7.982 7.982 0 0 0 1.069-.731 7.619 7.619 0 0 0 1.142-1.15 6.949 6.949 0 0 0 1.018-1.741 6.538 6.538 0 0 0 .467-2.425l.004-.084a1.012 1.012 0 0 1 .672-.876c.08-.028.158-.04.241-.05.082-.003.082-.003.164.001zm-70.51-12.426c-15.5.93-28.544-5.922-30.126-16.443C-1.156 15.689 11.64 4.024 29.14 1.235c17.501-2.79 33.123 4.345 34.864 15.922 1.575 10.475-8.749 21.021-23.691 25.001l.001.099a31.185 31.185 0 0 0 .042.833c.007.094.019.188.021.282.006.178.013.356.024.534.011.16.024.32.039.48.017.154.038.306.058.459.036.273.077.544.144.811a4.723 4.723 0 0 0 .449 1.128c.192.332.434.628.702.898l.047.05c.151.139.302.275.461.403.24.192.492.367.748.537.474.314.962.6 1.457.877l.041.023.588.735-.729.586c-.376.112-.755.216-1.135.309a11.193 11.193 0 0 1-2.562.355 8.575 8.575 0 0 1-2.995-.486 8.461 8.461 0 0 1-.96-.413 11.194 11.194 0 0 1-1.836-1.152 13.345 13.345 0 0 1-1.07-.934c-.23-.221-.454-.448-.672-.681-.121-.129-.246-.258-.36-.395a23.448 23.448 0 0 1-1.328-1.773c-.051-.076-.049-.077-.095-.155l-.277-.477-.072-.13c-.081-.177-.159-.357-.238-.535l-.003-.01-.092-.707zm52.409-7.804c3.557 0 6.444 3.201 6.444 7.145 0 3.944-2.887 7.146-6.444 7.146s-6.444-3.202-6.444-7.146 2.887-7.145 6.444-7.145zm18.062 0c3.557 0 6.444 3.201 6.444 7.145 0 3.944-2.887 7.146-6.444 7.146s-6.444-3.202-6.444-7.146 2.887-7.145 6.444-7.145zM83.12 42.029c1.915 0 3.47 1.601 3.47 3.573s-1.555 3.573-3.47 3.573c-1.915 0-3.47-1.601-3.47-3.573s1.555-3.573 3.47-3.573zm17.846 0c1.915 0 3.47 1.601 3.47 3.573s-1.555 3.573-3.47 3.573c-1.915 0-3.47-1.601-3.47-3.573s1.555-3.573 3.47-3.573zM17.019 28c-.368 1.65-1.848 5.008-5.178 5.799-2.572.611-4.153-.815-4.544-2.559-.424-1.891.722-3.532 2.121-4.575a3.473 3.473 0 0 1-1.446-2.099c-.421-1.875.867-3.637 3.184-4.187 1.917-.455 3.185.248 3.462 1.482.265 1.184-.534 2.275-1.828 2.582-.878.209-1.574-.042-1.718-.683a1.4 1.4 0 0 1 .044-.704s.287.227.894.083c.751-.179 1.086-.709.972-1.219-.14-.625-.892-.827-1.739-.626-1.054.25-2.06 1.096-1.713 2.642.232 1.036.871 1.56 1.483 1.813.245-.11.481-.183.688-.233.943-.224 1.48-.005 1.587.472.092.411-.144.935-1.166 1.178a3.255 3.255 0 0 1-1.548.004c-.837.771-1.58 1.883-1.27 3.264.276 1.234 1.267 2.125 2.944 1.726 2.598-.617 3.861-3.638 4.277-4.883-.353-.574-.615-1.153-.732-1.676-.107-.477.145-1.005.863-1.175.48-.114.702.127.846.769a2.77 2.77 0 0 1-.03.995c.209.331.443.622.735.951.616-1.983 1.369-3.877 1.737-3.964.591-.141 1.492.65 1.492.65-.815.644-1.689 2.376-2.333 4.158.804.658 1.627 1.103 2.139.982.43-.102.735-.577.95-1.151-.323-2.226.975-4.331 2.31-4.648.703-.167 1.257.204 1.39.796.114.51-.044 1.379-.854 1.745-.236-1.053-.672-1.348-.944-1.283-.495.117-.844 1.413-.538 2.778.232 1.037.712 1.529 1.351 1.377.756-.179 1.333-1.176 1.699-2.128-.265-2.095.877-4.166 2.221-4.486.671-.159 1.214.162 1.391.952.332 1.48-.986 2.885-2.173 3.444.265.734.673 1.053 1.281.909.96-.229 1.578-1.465 1.923-2.506-.125-1.267-.26-2.385-.406-3.035l-.055-.247s1.568-.286 1.778.652l.019.082c.238-.663.67-1.216 1.309-1.368.83-.197 1.526.504 1.755 1.524.497 2.22-.556 4.428-1.834 4.732-.368.087-.642.066-.883-.033.121 1.288.292 2.651.542 3.77.126.559.272 1.061.448 1.47-.464.11-1.797.392-1.978-.414-.16-.716-.342-3.206-.554-5.612-.504 1.107-1.311 2.192-2.441 2.46-1.008.24-1.685-.303-2.055-1.182-.491 1.082-1.281 2.148-2.381 2.409-.817.194-1.554-.117-1.988-1.013-.36.843-.875 1.555-1.54 1.713-.639.152-1.53-.295-2.4-1.024-.239.888-.384 1.668-.39 2.241 0 0-.701.028-.804-.433-.096-.427.065-1.436.341-2.61a10.315 10.315 0 0 1-.713-.848zm38.163-17.803c.068.157.185.527.266.889.424 1.892.37 4.451.739 6.42-.065.61-.387 3.077-1.352 3.307-.192.045-.333-.06-.422-.454-.14-.626-.091-1.607-.293-2.512-.258-1.152-.782-1.686-1.517-1.511-.767.182-1.287 1.016-1.643 2.054-.022-.099-.053-.386-.093-.567-.211-.938-1.779-.652-1.779-.652a6.2 6.2 0 0 1 .457 1.364c.07.31.119.618.155.921-.246.495-.637.996-1.225 1.135-.064.015-.128.031-.195.029a6.977 6.977 0 0 0-.126-.784c-.258-1.152-.871-2.011-1.526-1.855a.712.712 0 0 0-.423.291c-1.337.317-2.358 2.107-2.118 3.919-.214.889-.551 1.757-1.059 1.877-.415.099-.724-.452-1.03-1.817-.059-.263-.09-.706-.122-1.149.142-.64.177-1.237.081-1.665-.107-.477-.417-.733-.816-.638-.715.17-.909 1.75-.52 3.801-.238.92-.639 1.915-1.278 2.067-.464.11-.835-.27-1.012-1.059-.158-.708-.196-1.929-.236-3.08 1.201-.424 1.911-1.009 1.775-1.617-.114-.51-.739-.743-.739-.743s-.124.722-1.064 1.258c-.029-.582-.064-1.111-.137-1.44-.137-.609-.458-.914-1.688-.622.158.327.274.698.359 1.076.103.46.162.949.189 1.445-.611.128-.947.052-.947.052s-.1.457-.041.72c.078.345.432.348 1.026.224.02 1.364-.067 2.701.143 3.639.306 1.365 1.231 1.89 2.046 1.697.907-.216 1.539-1.275 1.914-2.36.407 1.245 1.031 1.955 1.951 1.736.731-.174 1.261-1.142 1.587-2.195.431.765 1.15 1.129 1.983.931 1.214-.289 1.742-1.54 1.835-2.775 0 0 .147-.018.243-.04.526-.125.949-.488 1.26-.915.04.788.053 1.518.194 2.146.111.493.339.612.595.552.495-.118 1.081-.881 1.081-.881a3.93 3.93 0 0 1-.383-1.035c-.284-1.267.317-3.541.988-3.7.208-.049.377.257.492.767.057.255.092.504.115.751l.098 1.469c.024.246.059.496.116.751.158.707.63 1.236 1.381 1.058 1.317-.313 2.07-2.634 2.178-3.956.228.157.536.175.909.086-.505-2.253.089-6.136-.298-7.864-.1-.444-1.001-.58-1.607-.583l-.467.037zM33.729 22.293c.415-.099.711.246.885 1.02.287 1.283-.222 2.616-.797 2.753-.191.045-.695-.025-.961-1.21-.025-.115-.051-.23-.061-.349.05-1.277.439-2.097.934-2.214zm-5.187.955c.271-.065.511.104.588.449.137.609-.338 1.345-1.275 1.966-.255-1.36.159-2.29.687-2.415zm18.032-.403c-.607.144-1.062-.458-1.239-1.248-.217-.97.001-2.097.644-2.457.001.155.038.32.075.484.147.658.554 1.497 1.268 1.83-.017.749-.253 1.273-.748 1.391zm9.877-1.654c.103.461.496.714 1.039.585.799-.19.973-.993.847-1.553-.125-.559-.461-.93-.988-.805-.543.13-1.108.836-.898 1.773zm-14.21-5.442c-.104-.461-.497-.714-1.056-.581-.783.186-.972.993-.847 1.552.126.56.461.93.908.824.56-.133 1.172-1.006.995-1.795z" fill="#fff" fill-opacity=".6"></path></svg>';
+ }
+}
diff --git a/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php b/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php
new file mode 100644
index 00000000..32ba9a09
--- /dev/null
+++ b/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php
@@ -0,0 +1,206 @@
+<?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\Debug\FatalErrorHandler;
+
+use Symfony\Component\Debug\Exception\ClassNotFoundException;
+use Symfony\Component\Debug\Exception\FatalErrorException;
+use Symfony\Component\Debug\DebugClassLoader;
+use Composer\Autoload\ClassLoader as ComposerClassLoader;
+use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader;
+
+/**
+ * ErrorHandler for classes that do not exist.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function handleError(array $error, FatalErrorException $exception)
+ {
+ $messageLen = strlen($error['message']);
+ $notFoundSuffix = '\' not found';
+ $notFoundSuffixLen = strlen($notFoundSuffix);
+ if ($notFoundSuffixLen > $messageLen) {
+ return;
+ }
+
+ if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
+ return;
+ }
+
+ foreach (array('class', 'interface', 'trait') as $typeName) {
+ $prefix = ucfirst($typeName).' \'';
+ $prefixLen = strlen($prefix);
+ if (0 !== strpos($error['message'], $prefix)) {
+ continue;
+ }
+
+ $fullyQualifiedClassName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
+ if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) {
+ $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1);
+ $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex);
+ $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix);
+ $tail = ' for another namespace?';
+ } else {
+ $className = $fullyQualifiedClassName;
+ $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className);
+ $tail = '?';
+ }
+
+ if ($candidates = $this->getClassCandidates($className)) {
+ $tail = array_pop($candidates).'"?';
+ if ($candidates) {
+ $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail;
+ } else {
+ $tail = ' for "'.$tail;
+ }
+ }
+ $message .= "\nDid you forget a \"use\" statement".$tail;
+
+ return new ClassNotFoundException($message, $exception);
+ }
+ }
+
+ /**
+ * Tries to guess the full namespace for a given class name.
+ *
+ * By default, it looks for PSR-0 and PSR-4 classes registered via a Symfony or a Composer
+ * autoloader (that should cover all common cases).
+ *
+ * @param string $class A class name (without its namespace)
+ *
+ * @return array An array of possible fully qualified class names
+ */
+ private function getClassCandidates($class)
+ {
+ if (!is_array($functions = spl_autoload_functions())) {
+ return array();
+ }
+
+ // find Symfony and Composer autoloaders
+ $classes = array();
+
+ foreach ($functions as $function) {
+ if (!is_array($function)) {
+ continue;
+ }
+ // get class loaders wrapped by DebugClassLoader
+ if ($function[0] instanceof DebugClassLoader) {
+ $function = $function[0]->getClassLoader();
+
+ if (!is_array($function)) {
+ continue;
+ }
+ }
+
+ if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader) {
+ foreach ($function[0]->getPrefixes() as $prefix => $paths) {
+ foreach ($paths as $path) {
+ $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
+ }
+ }
+ }
+ if ($function[0] instanceof ComposerClassLoader) {
+ foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) {
+ foreach ($paths as $path) {
+ $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
+ }
+ }
+ }
+ }
+
+ return array_unique($classes);
+ }
+
+ /**
+ * @param string $path
+ * @param string $class
+ * @param string $prefix
+ *
+ * @return array
+ */
+ private function findClassInPath($path, $class, $prefix)
+ {
+ if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
+ return array();
+ }
+
+ $classes = array();
+ $filename = $class.'.php';
+ foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
+ if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) {
+ $classes[] = $class;
+ }
+ }
+
+ return $classes;
+ }
+
+ /**
+ * @param string $path
+ * @param string $file
+ * @param string $prefix
+ *
+ * @return string|null
+ */
+ private function convertFileToClass($path, $file, $prefix)
+ {
+ $candidates = array(
+ // namespaced class
+ $namespacedClass = str_replace(array($path.DIRECTORY_SEPARATOR, '.php', '/'), array('', '', '\\'), $file),
+ // namespaced class (with target dir)
+ $prefix.$namespacedClass,
+ // namespaced class (with target dir and separator)
+ $prefix.'\\'.$namespacedClass,
+ // PEAR class
+ str_replace('\\', '_', $namespacedClass),
+ // PEAR class (with target dir)
+ str_replace('\\', '_', $prefix.$namespacedClass),
+ // PEAR class (with target dir and separator)
+ str_replace('\\', '_', $prefix.'\\'.$namespacedClass),
+ );
+
+ if ($prefix) {
+ $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); });
+ }
+
+ // We cannot use the autoloader here as most of them use require; but if the class
+ // is not found, the new autoloader call will require the file again leading to a
+ // "cannot redeclare class" error.
+ foreach ($candidates as $candidate) {
+ if ($this->classExists($candidate)) {
+ return $candidate;
+ }
+ }
+
+ require_once $file;
+
+ foreach ($candidates as $candidate) {
+ if ($this->classExists($candidate)) {
+ return $candidate;
+ }
+ }
+ }
+
+ /**
+ * @param string $class
+ *
+ * @return bool
+ */
+ private function classExists($class)
+ {
+ return class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false);
+ }
+}
diff --git a/vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php b/vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php
new file mode 100644
index 00000000..6b87eb30
--- /dev/null
+++ b/vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php
@@ -0,0 +1,32 @@
+<?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\Debug\FatalErrorHandler;
+
+use Symfony\Component\Debug\Exception\FatalErrorException;
+
+/**
+ * Attempts to convert fatal errors to exceptions.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface FatalErrorHandlerInterface
+{
+ /**
+ * Attempts to convert an error into an exception.
+ *
+ * @param array $error An array as returned by error_get_last()
+ * @param FatalErrorException $exception A FatalErrorException instance
+ *
+ * @return FatalErrorException|null A FatalErrorException instance if the class is able to convert the error, null otherwise
+ */
+ public function handleError(array $error, FatalErrorException $exception);
+}
diff --git a/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php b/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php
new file mode 100644
index 00000000..c6f391a7
--- /dev/null
+++ b/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php
@@ -0,0 +1,84 @@
+<?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\Debug\FatalErrorHandler;
+
+use Symfony\Component\Debug\Exception\UndefinedFunctionException;
+use Symfony\Component\Debug\Exception\FatalErrorException;
+
+/**
+ * ErrorHandler for undefined functions.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function handleError(array $error, FatalErrorException $exception)
+ {
+ $messageLen = strlen($error['message']);
+ $notFoundSuffix = '()';
+ $notFoundSuffixLen = strlen($notFoundSuffix);
+ if ($notFoundSuffixLen > $messageLen) {
+ return;
+ }
+
+ if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
+ return;
+ }
+
+ $prefix = 'Call to undefined function ';
+ $prefixLen = strlen($prefix);
+ if (0 !== strpos($error['message'], $prefix)) {
+ return;
+ }
+
+ $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
+ if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) {
+ $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1);
+ $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex);
+ $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix);
+ } else {
+ $functionName = $fullyQualifiedFunctionName;
+ $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName);
+ }
+
+ $candidates = array();
+ foreach (get_defined_functions() as $type => $definedFunctionNames) {
+ foreach ($definedFunctionNames as $definedFunctionName) {
+ if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) {
+ $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1);
+ } else {
+ $definedFunctionNameBasename = $definedFunctionName;
+ }
+
+ if ($definedFunctionNameBasename === $functionName) {
+ $candidates[] = '\\'.$definedFunctionName;
+ }
+ }
+ }
+
+ if ($candidates) {
+ sort($candidates);
+ $last = array_pop($candidates).'"?';
+ if ($candidates) {
+ $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
+ } else {
+ $candidates = '"'.$last;
+ }
+ $message .= "\nDid you mean to call ".$candidates;
+ }
+
+ return new UndefinedFunctionException($message, $exception);
+ }
+}
diff --git a/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php b/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php
new file mode 100644
index 00000000..6fa62b6f
--- /dev/null
+++ b/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php
@@ -0,0 +1,66 @@
+<?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\Debug\FatalErrorHandler;
+
+use Symfony\Component\Debug\Exception\FatalErrorException;
+use Symfony\Component\Debug\Exception\UndefinedMethodException;
+
+/**
+ * ErrorHandler for undefined methods.
+ *
+ * @author Grégoire Pineau <lyrixx@lyrixx.info>
+ */
+class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function handleError(array $error, FatalErrorException $exception)
+ {
+ preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches);
+ if (!$matches) {
+ return;
+ }
+
+ $className = $matches[1];
+ $methodName = $matches[2];
+
+ $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className);
+
+ if (!class_exists($className) || null === $methods = get_class_methods($className)) {
+ // failed to get the class or its methods on which an unknown method was called (for example on an anonymous class)
+ return new UndefinedMethodException($message, $exception);
+ }
+
+ $candidates = array();
+ foreach ($methods as $definedMethodName) {
+ $lev = levenshtein($methodName, $definedMethodName);
+ if ($lev <= strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) {
+ $candidates[] = $definedMethodName;
+ }
+ }
+
+ if ($candidates) {
+ sort($candidates);
+ $last = array_pop($candidates).'"?';
+ if ($candidates) {
+ $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
+ } else {
+ $candidates = '"'.$last;
+ }
+
+ $message .= "\nDid you mean to call ".$candidates;
+ }
+
+ return new UndefinedMethodException($message, $exception);
+ }
+}
diff --git a/vendor/symfony/debug/LICENSE b/vendor/symfony/debug/LICENSE
new file mode 100644
index 00000000..17d16a13
--- /dev/null
+++ b/vendor/symfony/debug/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-2017 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/symfony/debug/README.md b/vendor/symfony/debug/README.md
new file mode 100644
index 00000000..a1d16175
--- /dev/null
+++ b/vendor/symfony/debug/README.md
@@ -0,0 +1,13 @@
+Debug Component
+===============
+
+The Debug component provides tools to ease debugging PHP code.
+
+Resources
+---------
+
+ * [Documentation](https://symfony.com/doc/current/components/debug/index.html)
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/symfony/issues) and
+ [send Pull Requests](https://github.com/symfony/symfony/pulls)
+ in the [main Symfony repository](https://github.com/symfony/symfony)
diff --git a/vendor/symfony/debug/Resources/ext/README.md b/vendor/symfony/debug/Resources/ext/README.md
new file mode 100644
index 00000000..25dccf07
--- /dev/null
+++ b/vendor/symfony/debug/Resources/ext/README.md
@@ -0,0 +1,134 @@
+Symfony Debug Extension for PHP 5
+=================================
+
+This extension publishes several functions to help building powerful debugging tools.
+It is compatible with PHP 5.3, 5.4, 5.5 and 5.6; with ZTS and non-ZTS modes.
+It is not required thus not provided for PHP 7.
+
+symfony_zval_info()
+-------------------
+
+- exposes zval_hash/refcounts, allowing e.g. efficient exploration of arbitrary structures in PHP,
+- does work with references, preventing memory copying.
+
+Its behavior is about the same as:
+
+```php
+<?php
+
+function symfony_zval_info($key, $array, $options = 0)
+{
+
+ // $options is currently not used, but could be in future version.
+
+ if (!array_key_exists($key, $array)) {
+ return null;
+ }
+
+ $info = array(
+ 'type' => gettype($array[$key]),
+ 'zval_hash' => /* hashed memory address of $array[$key] */,
+ 'zval_refcount' => /* internal zval refcount of $array[$key] */,
+ 'zval_isref' => /* is_ref status of $array[$key] */,
+ );
+
+ switch ($info['type']) {
+ case 'object':
+ $info += array(
+ 'object_class' => get_class($array[$key]),
+ 'object_refcount' => /* internal object refcount of $array[$key] */,
+ 'object_hash' => spl_object_hash($array[$key]),
+ 'object_handle' => /* internal object handle $array[$key] */,
+ );
+ break;
+
+ case 'resource':
+ $info += array(
+ 'resource_handle' => (int) $array[$key],
+ 'resource_type' => get_resource_type($array[$key]),
+ 'resource_refcount' => /* internal resource refcount of $array[$key] */,
+ );
+ break;
+
+ case 'array':
+ $info += array(
+ 'array_count' => count($array[$key]),
+ );
+ break;
+
+ case 'string':
+ $info += array(
+ 'strlen' => strlen($array[$key]),
+ );
+ break;
+ }
+
+ return $info;
+}
+```
+
+symfony_debug_backtrace()
+-------------------------
+
+This function works like debug_backtrace(), except that it can fetch the full backtrace in case of fatal errors:
+
+```php
+function foo() { fatal(); }
+function bar() { foo(); }
+
+function sd() { var_dump(symfony_debug_backtrace()); }
+
+register_shutdown_function('sd');
+
+bar();
+
+/* Will output
+Fatal error: Call to undefined function fatal() in foo.php on line 42
+array(3) {
+ [0]=>
+ array(2) {
+ ["function"]=>
+ string(2) "sd"
+ ["args"]=>
+ array(0) {
+ }
+ }
+ [1]=>
+ array(4) {
+ ["file"]=>
+ string(7) "foo.php"
+ ["line"]=>
+ int(1)
+ ["function"]=>
+ string(3) "foo"
+ ["args"]=>
+ array(0) {
+ }
+ }
+ [2]=>
+ array(4) {
+ ["file"]=>
+ string(102) "foo.php"
+ ["line"]=>
+ int(2)
+ ["function"]=>
+ string(3) "bar"
+ ["args"]=>
+ array(0) {
+ }
+ }
+}
+*/
+```
+
+Usage
+-----
+
+To enable the extension from source, run:
+
+```
+ phpize
+ ./configure
+ make
+ sudo make install
+```
diff --git a/vendor/symfony/debug/Resources/ext/config.m4 b/vendor/symfony/debug/Resources/ext/config.m4
new file mode 100644
index 00000000..3c560471
--- /dev/null
+++ b/vendor/symfony/debug/Resources/ext/config.m4
@@ -0,0 +1,63 @@
+dnl $Id$
+dnl config.m4 for extension symfony_debug
+
+dnl Comments in this file start with the string 'dnl'.
+dnl Remove where necessary. This file will not work
+dnl without editing.
+
+dnl If your extension references something external, use with:
+
+dnl PHP_ARG_WITH(symfony_debug, for symfony_debug support,
+dnl Make sure that the comment is aligned:
+dnl [ --with-symfony_debug Include symfony_debug support])
+
+dnl Otherwise use enable:
+
+PHP_ARG_ENABLE(symfony_debug, whether to enable symfony_debug support,
+dnl Make sure that the comment is aligned:
+[ --enable-symfony_debug Enable symfony_debug support])
+
+if test "$PHP_SYMFONY_DEBUG" != "no"; then
+ dnl Write more examples of tests here...
+
+ dnl # --with-symfony_debug -> check with-path
+ dnl SEARCH_PATH="/usr/local /usr" # you might want to change this
+ dnl SEARCH_FOR="/include/symfony_debug.h" # you most likely want to change this
+ dnl if test -r $PHP_SYMFONY_DEBUG/$SEARCH_FOR; then # path given as parameter
+ dnl SYMFONY_DEBUG_DIR=$PHP_SYMFONY_DEBUG
+ dnl else # search default path list
+ dnl AC_MSG_CHECKING([for symfony_debug files in default path])
+ dnl for i in $SEARCH_PATH ; do
+ dnl if test -r $i/$SEARCH_FOR; then
+ dnl SYMFONY_DEBUG_DIR=$i
+ dnl AC_MSG_RESULT(found in $i)
+ dnl fi
+ dnl done
+ dnl fi
+ dnl
+ dnl if test -z "$SYMFONY_DEBUG_DIR"; then
+ dnl AC_MSG_RESULT([not found])
+ dnl AC_MSG_ERROR([Please reinstall the symfony_debug distribution])
+ dnl fi
+
+ dnl # --with-symfony_debug -> add include path
+ dnl PHP_ADD_INCLUDE($SYMFONY_DEBUG_DIR/include)
+
+ dnl # --with-symfony_debug -> check for lib and symbol presence
+ dnl LIBNAME=symfony_debug # you may want to change this
+ dnl LIBSYMBOL=symfony_debug # you most likely want to change this
+
+ dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
+ dnl [
+ dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SYMFONY_DEBUG_DIR/lib, SYMFONY_DEBUG_SHARED_LIBADD)
+ dnl AC_DEFINE(HAVE_SYMFONY_DEBUGLIB,1,[ ])
+ dnl ],[
+ dnl AC_MSG_ERROR([wrong symfony_debug lib version or lib not found])
+ dnl ],[
+ dnl -L$SYMFONY_DEBUG_DIR/lib -lm
+ dnl ])
+ dnl
+ dnl PHP_SUBST(SYMFONY_DEBUG_SHARED_LIBADD)
+
+ PHP_NEW_EXTENSION(symfony_debug, symfony_debug.c, $ext_shared)
+fi
diff --git a/vendor/symfony/debug/Resources/ext/config.w32 b/vendor/symfony/debug/Resources/ext/config.w32
new file mode 100644
index 00000000..487e6913
--- /dev/null
+++ b/vendor/symfony/debug/Resources/ext/config.w32
@@ -0,0 +1,13 @@
+// $Id$
+// vim:ft=javascript
+
+// If your extension references something external, use ARG_WITH
+// ARG_WITH("symfony_debug", "for symfony_debug support", "no");
+
+// Otherwise, use ARG_ENABLE
+// ARG_ENABLE("symfony_debug", "enable symfony_debug support", "no");
+
+if (PHP_SYMFONY_DEBUG != "no") {
+ EXTENSION("symfony_debug", "symfony_debug.c");
+}
+
diff --git a/vendor/symfony/debug/Resources/ext/php_symfony_debug.h b/vendor/symfony/debug/Resources/ext/php_symfony_debug.h
new file mode 100644
index 00000000..26d0e8c0
--- /dev/null
+++ b/vendor/symfony/debug/Resources/ext/php_symfony_debug.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#ifndef PHP_SYMFONY_DEBUG_H
+#define PHP_SYMFONY_DEBUG_H
+
+extern zend_module_entry symfony_debug_module_entry;
+#define phpext_symfony_debug_ptr &symfony_debug_module_entry
+
+#define PHP_SYMFONY_DEBUG_VERSION "2.7"
+
+#ifdef PHP_WIN32
+# define PHP_SYMFONY_DEBUG_API __declspec(dllexport)
+#elif defined(__GNUC__) && __GNUC__ >= 4
+# define PHP_SYMFONY_DEBUG_API __attribute__ ((visibility("default")))
+#else
+# define PHP_SYMFONY_DEBUG_API
+#endif
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+ZEND_BEGIN_MODULE_GLOBALS(symfony_debug)
+ intptr_t req_rand_init;
+ void (*old_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
+ zval *debug_bt;
+ZEND_END_MODULE_GLOBALS(symfony_debug)
+
+PHP_MINIT_FUNCTION(symfony_debug);
+PHP_MSHUTDOWN_FUNCTION(symfony_debug);
+PHP_RINIT_FUNCTION(symfony_debug);
+PHP_RSHUTDOWN_FUNCTION(symfony_debug);
+PHP_MINFO_FUNCTION(symfony_debug);
+PHP_GINIT_FUNCTION(symfony_debug);
+PHP_GSHUTDOWN_FUNCTION(symfony_debug);
+
+PHP_FUNCTION(symfony_zval_info);
+PHP_FUNCTION(symfony_debug_backtrace);
+
+static char *_symfony_debug_memory_address_hash(void * TSRMLS_DC);
+static const char *_symfony_debug_zval_type(zval *);
+static const char* _symfony_debug_get_resource_type(long TSRMLS_DC);
+static int _symfony_debug_get_resource_refcount(long TSRMLS_DC);
+
+void symfony_debug_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
+
+#ifdef ZTS
+#define SYMFONY_DEBUG_G(v) TSRMG(symfony_debug_globals_id, zend_symfony_debug_globals *, v)
+#else
+#define SYMFONY_DEBUG_G(v) (symfony_debug_globals.v)
+#endif
+
+#endif /* PHP_SYMFONY_DEBUG_H */
diff --git a/vendor/symfony/debug/Resources/ext/symfony_debug.c b/vendor/symfony/debug/Resources/ext/symfony_debug.c
new file mode 100644
index 00000000..0d7cb602
--- /dev/null
+++ b/vendor/symfony/debug/Resources/ext/symfony_debug.c
@@ -0,0 +1,283 @@
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "php_symfony_debug.h"
+#include "ext/standard/php_rand.h"
+#include "ext/standard/php_lcg.h"
+#include "ext/spl/php_spl.h"
+#include "Zend/zend_gc.h"
+#include "Zend/zend_builtin_functions.h"
+#include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */
+#include "ext/standard/php_array.h"
+#include "Zend/zend_interfaces.h"
+#include "SAPI.h"
+
+#define IS_PHP_53 ZEND_EXTENSION_API_NO == 220090626
+
+ZEND_DECLARE_MODULE_GLOBALS(symfony_debug)
+
+ZEND_BEGIN_ARG_INFO_EX(symfony_zval_arginfo, 0, 0, 2)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_ARRAY_INFO(0, array, 0)
+ ZEND_ARG_INFO(0, options)
+ZEND_END_ARG_INFO()
+
+const zend_function_entry symfony_debug_functions[] = {
+ PHP_FE(symfony_zval_info, symfony_zval_arginfo)
+ PHP_FE(symfony_debug_backtrace, NULL)
+ PHP_FE_END
+};
+
+PHP_FUNCTION(symfony_debug_backtrace)
+{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+#if IS_PHP_53
+ zend_fetch_debug_backtrace(return_value, 1, 0 TSRMLS_CC);
+#else
+ zend_fetch_debug_backtrace(return_value, 1, 0, 0 TSRMLS_CC);
+#endif
+
+ if (!SYMFONY_DEBUG_G(debug_bt)) {
+ return;
+ }
+
+ php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(SYMFONY_DEBUG_G(debug_bt)), 0 TSRMLS_CC);
+}
+
+PHP_FUNCTION(symfony_zval_info)
+{
+ zval *key = NULL, *arg = NULL;
+ zval **data = NULL;
+ HashTable *array = NULL;
+ long options = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zh|l", &key, &array, &options) == FAILURE) {
+ return;
+ }
+
+ switch (Z_TYPE_P(key)) {
+ case IS_STRING:
+ if (zend_symtable_find(array, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&data) == FAILURE) {
+ return;
+ }
+ break;
+ case IS_LONG:
+ if (zend_hash_index_find(array, Z_LVAL_P(key), (void **)&data)) {
+ return;
+ }
+ break;
+ }
+
+ arg = *data;
+
+ array_init(return_value);
+
+ add_assoc_string(return_value, "type", (char *)_symfony_debug_zval_type(arg), 1);
+ add_assoc_stringl(return_value, "zval_hash", _symfony_debug_memory_address_hash((void *)arg TSRMLS_CC), 16, 0);
+ add_assoc_long(return_value, "zval_refcount", Z_REFCOUNT_P(arg));
+ add_assoc_bool(return_value, "zval_isref", (zend_bool)Z_ISREF_P(arg));
+
+ if (Z_TYPE_P(arg) == IS_OBJECT) {
+ char hash[33] = {0};
+
+ php_spl_object_hash(arg, (char *)hash TSRMLS_CC);
+ add_assoc_stringl(return_value, "object_class", (char *)Z_OBJCE_P(arg)->name, Z_OBJCE_P(arg)->name_length, 1);
+ add_assoc_long(return_value, "object_refcount", EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(arg)].bucket.obj.refcount);
+ add_assoc_string(return_value, "object_hash", hash, 1);
+ add_assoc_long(return_value, "object_handle", Z_OBJ_HANDLE_P(arg));
+ } else if (Z_TYPE_P(arg) == IS_ARRAY) {
+ add_assoc_long(return_value, "array_count", zend_hash_num_elements(Z_ARRVAL_P(arg)));
+ } else if(Z_TYPE_P(arg) == IS_RESOURCE) {
+ add_assoc_long(return_value, "resource_handle", Z_LVAL_P(arg));
+ add_assoc_string(return_value, "resource_type", (char *)_symfony_debug_get_resource_type(Z_LVAL_P(arg) TSRMLS_CC), 1);
+ add_assoc_long(return_value, "resource_refcount", _symfony_debug_get_resource_refcount(Z_LVAL_P(arg) TSRMLS_CC));
+ } else if (Z_TYPE_P(arg) == IS_STRING) {
+ add_assoc_long(return_value, "strlen", Z_STRLEN_P(arg));
+ }
+}
+
+void symfony_debug_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args)
+{
+ TSRMLS_FETCH();
+ zval *retval;
+
+ switch (type) {
+ case E_ERROR:
+ case E_PARSE:
+ case E_CORE_ERROR:
+ case E_CORE_WARNING:
+ case E_COMPILE_ERROR:
+ case E_COMPILE_WARNING:
+ ALLOC_INIT_ZVAL(retval);
+#if IS_PHP_53
+ zend_fetch_debug_backtrace(retval, 1, 0 TSRMLS_CC);
+#else
+ zend_fetch_debug_backtrace(retval, 1, 0, 0 TSRMLS_CC);
+#endif
+ SYMFONY_DEBUG_G(debug_bt) = retval;
+ }
+
+ SYMFONY_DEBUG_G(old_error_cb)(type, error_filename, error_lineno, format, args);
+}
+
+static const char* _symfony_debug_get_resource_type(long rsid TSRMLS_DC)
+{
+ const char *res_type;
+ res_type = zend_rsrc_list_get_rsrc_type(rsid TSRMLS_CC);
+
+ if (!res_type) {
+ return "Unknown";
+ }
+
+ return res_type;
+}
+
+static int _symfony_debug_get_resource_refcount(long rsid TSRMLS_DC)
+{
+ zend_rsrc_list_entry *le;
+
+ if (zend_hash_index_find(&EG(regular_list), rsid, (void **) &le)==SUCCESS) {
+ return le->refcount;
+ }
+
+ return 0;
+}
+
+static char *_symfony_debug_memory_address_hash(void *address TSRMLS_DC)
+{
+ char *result = NULL;
+ intptr_t address_rand;
+
+ if (!SYMFONY_DEBUG_G(req_rand_init)) {
+ if (!BG(mt_rand_is_seeded)) {
+ php_mt_srand(GENERATE_SEED() TSRMLS_CC);
+ }
+ SYMFONY_DEBUG_G(req_rand_init) = (intptr_t)php_mt_rand(TSRMLS_C);
+ }
+
+ address_rand = (intptr_t)address ^ SYMFONY_DEBUG_G(req_rand_init);
+
+ spprintf(&result, 17, "%016zx", address_rand);
+
+ return result;
+}
+
+static const char *_symfony_debug_zval_type(zval *zv)
+{
+ switch (Z_TYPE_P(zv)) {
+ case IS_NULL:
+ return "NULL";
+ break;
+
+ case IS_BOOL:
+ return "boolean";
+ break;
+
+ case IS_LONG:
+ return "integer";
+ break;
+
+ case IS_DOUBLE:
+ return "double";
+ break;
+
+ case IS_STRING:
+ return "string";
+ break;
+
+ case IS_ARRAY:
+ return "array";
+ break;
+
+ case IS_OBJECT:
+ return "object";
+
+ case IS_RESOURCE:
+ return "resource";
+
+ default:
+ return "unknown type";
+ }
+}
+
+zend_module_entry symfony_debug_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "symfony_debug",
+ symfony_debug_functions,
+ PHP_MINIT(symfony_debug),
+ PHP_MSHUTDOWN(symfony_debug),
+ PHP_RINIT(symfony_debug),
+ PHP_RSHUTDOWN(symfony_debug),
+ PHP_MINFO(symfony_debug),
+ PHP_SYMFONY_DEBUG_VERSION,
+ PHP_MODULE_GLOBALS(symfony_debug),
+ PHP_GINIT(symfony_debug),
+ PHP_GSHUTDOWN(symfony_debug),
+ NULL,
+ STANDARD_MODULE_PROPERTIES_EX
+};
+
+#ifdef COMPILE_DL_SYMFONY_DEBUG
+ZEND_GET_MODULE(symfony_debug)
+#endif
+
+PHP_GINIT_FUNCTION(symfony_debug)
+{
+ memset(symfony_debug_globals, 0 , sizeof(*symfony_debug_globals));
+}
+
+PHP_GSHUTDOWN_FUNCTION(symfony_debug)
+{
+
+}
+
+PHP_MINIT_FUNCTION(symfony_debug)
+{
+ SYMFONY_DEBUG_G(old_error_cb) = zend_error_cb;
+ zend_error_cb = symfony_debug_error_cb;
+
+ return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(symfony_debug)
+{
+ zend_error_cb = SYMFONY_DEBUG_G(old_error_cb);
+
+ return SUCCESS;
+}
+
+PHP_RINIT_FUNCTION(symfony_debug)
+{
+ return SUCCESS;
+}
+
+PHP_RSHUTDOWN_FUNCTION(symfony_debug)
+{
+ return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(symfony_debug)
+{
+ php_info_print_table_start();
+ php_info_print_table_header(2, "Symfony Debug support", "enabled");
+ php_info_print_table_header(2, "Symfony Debug version", PHP_SYMFONY_DEBUG_VERSION);
+ php_info_print_table_end();
+}
diff --git a/vendor/symfony/debug/Resources/ext/tests/001.phpt b/vendor/symfony/debug/Resources/ext/tests/001.phpt
new file mode 100644
index 00000000..15e183a7
--- /dev/null
+++ b/vendor/symfony/debug/Resources/ext/tests/001.phpt
@@ -0,0 +1,153 @@
+--TEST--
+Test symfony_zval_info API
+--SKIPIF--
+<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
+--FILE--
+<?php
+
+$int = 42;
+$float = 42.42;
+$str = 'foobar';
+$object = new StdClass();
+$array = array('foo', 'bar');
+$resource = tmpfile();
+$null = null;
+$bool = true;
+
+$anotherint = 42;
+$refcount2 = &$anotherint;
+
+$var = array(
+ 'int' => $int,
+ 'float' => $float,
+ 'str' => $str,
+ 'object' => $object,
+ 'array' => $array,
+ 'resource' => $resource,
+ 'null' => $null,
+ 'bool' => $bool,
+ 'refcount' => &$refcount2,
+);
+
+var_dump(symfony_zval_info('int', $var));
+var_dump(symfony_zval_info('float', $var));
+var_dump(symfony_zval_info('str', $var));
+var_dump(symfony_zval_info('object', $var));
+var_dump(symfony_zval_info('array', $var));
+var_dump(symfony_zval_info('resource', $var));
+var_dump(symfony_zval_info('null', $var));
+var_dump(symfony_zval_info('bool', $var));
+
+var_dump(symfony_zval_info('refcount', $var));
+var_dump(symfony_zval_info('not-exist', $var));
+?>
+--EXPECTF--
+array(4) {
+ ["type"]=>
+ string(7) "integer"
+ ["zval_hash"]=>
+ string(16) "%s"
+ ["zval_refcount"]=>
+ int(2)
+ ["zval_isref"]=>
+ bool(false)
+}
+array(4) {
+ ["type"]=>
+ string(6) "double"
+ ["zval_hash"]=>
+ string(16) "%s"
+ ["zval_refcount"]=>
+ int(2)
+ ["zval_isref"]=>
+ bool(false)
+}
+array(5) {
+ ["type"]=>
+ string(6) "string"
+ ["zval_hash"]=>
+ string(16) "%s"
+ ["zval_refcount"]=>
+ int(2)
+ ["zval_isref"]=>
+ bool(false)
+ ["strlen"]=>
+ int(6)
+}
+array(8) {
+ ["type"]=>
+ string(6) "object"
+ ["zval_hash"]=>
+ string(16) "%s"
+ ["zval_refcount"]=>
+ int(2)
+ ["zval_isref"]=>
+ bool(false)
+ ["object_class"]=>
+ string(8) "stdClass"
+ ["object_refcount"]=>
+ int(1)
+ ["object_hash"]=>
+ string(32) "%s"
+ ["object_handle"]=>
+ int(%d)
+}
+array(5) {
+ ["type"]=>
+ string(5) "array"
+ ["zval_hash"]=>
+ string(16) "%s"
+ ["zval_refcount"]=>
+ int(2)
+ ["zval_isref"]=>
+ bool(false)
+ ["array_count"]=>
+ int(2)
+}
+array(7) {
+ ["type"]=>
+ string(8) "resource"
+ ["zval_hash"]=>
+ string(16) "%s"
+ ["zval_refcount"]=>
+ int(2)
+ ["zval_isref"]=>
+ bool(false)
+ ["resource_handle"]=>
+ int(%d)
+ ["resource_type"]=>
+ string(6) "stream"
+ ["resource_refcount"]=>
+ int(1)
+}
+array(4) {
+ ["type"]=>
+ string(4) "NULL"
+ ["zval_hash"]=>
+ string(16) "%s"
+ ["zval_refcount"]=>
+ int(2)
+ ["zval_isref"]=>
+ bool(false)
+}
+array(4) {
+ ["type"]=>
+ string(7) "boolean"
+ ["zval_hash"]=>
+ string(16) "%s"
+ ["zval_refcount"]=>
+ int(2)
+ ["zval_isref"]=>
+ bool(false)
+}
+array(4) {
+ ["type"]=>
+ string(7) "integer"
+ ["zval_hash"]=>
+ string(16) "%s"
+ ["zval_refcount"]=>
+ int(3)
+ ["zval_isref"]=>
+ bool(true)
+}
+NULL
diff --git a/vendor/symfony/debug/Resources/ext/tests/002.phpt b/vendor/symfony/debug/Resources/ext/tests/002.phpt
new file mode 100644
index 00000000..2bc6d712
--- /dev/null
+++ b/vendor/symfony/debug/Resources/ext/tests/002.phpt
@@ -0,0 +1,63 @@
+--TEST--
+Test symfony_debug_backtrace in case of fatal error
+--SKIPIF--
+<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
+--FILE--
+<?php
+
+function bar()
+{
+ foo();
+}
+
+function foo()
+{
+ notexist();
+}
+
+function bt()
+{
+ print_r(symfony_debug_backtrace());
+}
+
+register_shutdown_function('bt');
+
+bar();
+
+?>
+--EXPECTF--
+Fatal error: Call to undefined function notexist() in %s on line %d
+Array
+(
+ [0] => Array
+ (
+ [function] => bt
+ [args] => Array
+ (
+ )
+
+ )
+
+ [1] => Array
+ (
+ [file] => %s
+ [line] => %d
+ [function] => foo
+ [args] => Array
+ (
+ )
+
+ )
+
+ [2] => Array
+ (
+ [file] => %s
+ [line] => %d
+ [function] => bar
+ [args] => Array
+ (
+ )
+
+ )
+
+)
diff --git a/vendor/symfony/debug/Resources/ext/tests/002_1.phpt b/vendor/symfony/debug/Resources/ext/tests/002_1.phpt
new file mode 100644
index 00000000..4e9e34f1
--- /dev/null
+++ b/vendor/symfony/debug/Resources/ext/tests/002_1.phpt
@@ -0,0 +1,46 @@
+--TEST--
+Test symfony_debug_backtrace in case of non fatal error
+--SKIPIF--
+<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
+--FILE--
+<?php
+
+function bar()
+{
+ bt();
+}
+
+function bt()
+{
+ print_r(symfony_debug_backtrace());
+}
+
+bar();
+
+?>
+--EXPECTF--
+Array
+(
+ [0] => Array
+ (
+ [file] => %s
+ [line] => %d
+ [function] => bt
+ [args] => Array
+ (
+ )
+
+ )
+
+ [1] => Array
+ (
+ [file] => %s
+ [line] => %d
+ [function] => bar
+ [args] => Array
+ (
+ )
+
+ )
+
+)
diff --git a/vendor/symfony/debug/Resources/ext/tests/003.phpt b/vendor/symfony/debug/Resources/ext/tests/003.phpt
new file mode 100644
index 00000000..2a494e27
--- /dev/null
+++ b/vendor/symfony/debug/Resources/ext/tests/003.phpt
@@ -0,0 +1,85 @@
+--TEST--
+Test ErrorHandler in case of fatal error
+--SKIPIF--
+<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
+--FILE--
+<?php
+
+namespace Psr\Log;
+
+class LogLevel
+{
+ const EMERGENCY = 'emergency';
+ const ALERT = 'alert';
+ const CRITICAL = 'critical';
+ const ERROR = 'error';
+ const WARNING = 'warning';
+ const NOTICE = 'notice';
+ const INFO = 'info';
+ const DEBUG = 'debug';
+}
+
+namespace Symfony\Component\Debug;
+
+$dir = __DIR__.'/../../../';
+require $dir.'ErrorHandler.php';
+require $dir.'Exception/FatalErrorException.php';
+require $dir.'Exception/UndefinedFunctionException.php';
+require $dir.'FatalErrorHandler/FatalErrorHandlerInterface.php';
+require $dir.'FatalErrorHandler/ClassNotFoundFatalErrorHandler.php';
+require $dir.'FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php';
+require $dir.'FatalErrorHandler/UndefinedMethodFatalErrorHandler.php';
+
+function bar()
+{
+ foo();
+}
+
+function foo()
+{
+ notexist();
+}
+
+$handler = ErrorHandler::register();
+$handler->setExceptionHandler('print_r');
+
+if (function_exists('xdebug_disable')) {
+ xdebug_disable();
+}
+
+bar();
+?>
+--EXPECTF--
+Fatal error: Call to undefined function Symfony\Component\Debug\notexist() in %s on line %d
+Symfony\Component\Debug\Exception\UndefinedFunctionException Object
+(
+ [message:protected] => Attempted to call function "notexist" from namespace "Symfony\Component\Debug".
+ [string:Exception:private] =>
+ [code:protected] => 0
+ [file:protected] => %s
+ [line:protected] => %d
+ [trace:Exception:private] => Array
+ (
+ [0] => Array
+ (
+%A [function] => Symfony\Component\Debug\foo
+%A [args] => Array
+ (
+ )
+
+ )
+
+ [1] => Array
+ (
+%A [function] => Symfony\Component\Debug\bar
+%A [args] => Array
+ (
+ )
+
+ )
+%A
+ )
+
+ [previous:Exception:private] =>
+ [severity:protected] => 1
+)
diff --git a/vendor/symfony/debug/Tests/DebugClassLoaderTest.php b/vendor/symfony/debug/Tests/DebugClassLoaderTest.php
new file mode 100644
index 00000000..0219f533
--- /dev/null
+++ b/vendor/symfony/debug/Tests/DebugClassLoaderTest.php
@@ -0,0 +1,425 @@
+<?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\Debug\Tests;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Debug\DebugClassLoader;
+use Symfony\Component\Debug\ErrorHandler;
+
+class DebugClassLoaderTest extends TestCase
+{
+ /**
+ * @var int Error reporting level before running tests
+ */
+ private $errorReporting;
+
+ private $loader;
+
+ protected function setUp()
+ {
+ $this->errorReporting = error_reporting(E_ALL);
+ $this->loader = new ClassLoader();
+ spl_autoload_register(array($this->loader, 'loadClass'), true, true);
+ DebugClassLoader::enable();
+ }
+
+ protected function tearDown()
+ {
+ DebugClassLoader::disable();
+ spl_autoload_unregister(array($this->loader, 'loadClass'));
+ error_reporting($this->errorReporting);
+ }
+
+ public function testIdempotence()
+ {
+ DebugClassLoader::enable();
+
+ $functions = spl_autoload_functions();
+ foreach ($functions as $function) {
+ if (is_array($function) && $function[0] instanceof DebugClassLoader) {
+ $reflClass = new \ReflectionClass($function[0]);
+ $reflProp = $reflClass->getProperty('classLoader');
+ $reflProp->setAccessible(true);
+
+ $this->assertNotInstanceOf('Symfony\Component\Debug\DebugClassLoader', $reflProp->getValue($function[0]));
+
+ return;
+ }
+ }
+
+ $this->fail('DebugClassLoader did not register');
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage boo
+ */
+ public function testThrowingClass()
+ {
+ try {
+ class_exists(__NAMESPACE__.'\Fixtures\Throwing');
+ $this->fail('Exception expected');
+ } catch (\Exception $e) {
+ $this->assertSame('boo', $e->getMessage());
+ }
+
+ // the second call also should throw
+ class_exists(__NAMESPACE__.'\Fixtures\Throwing');
+ }
+
+ public function testUnsilencing()
+ {
+ if (\PHP_VERSION_ID >= 70000) {
+ $this->markTestSkipped('PHP7 throws exceptions, unsilencing is not required anymore.');
+ }
+ if (defined('HHVM_VERSION')) {
+ $this->markTestSkipped('HHVM is not handled in this test case.');
+ }
+
+ ob_start();
+
+ $this->iniSet('log_errors', 0);
+ $this->iniSet('display_errors', 1);
+
+ // See below: this will fail with parse error
+ // but this should not be @-silenced.
+ @class_exists(__NAMESPACE__.'\TestingUnsilencing', true);
+
+ $output = ob_get_clean();
+
+ $this->assertStringMatchesFormat('%aParse error%a', $output);
+ }
+
+ public function testStacking()
+ {
+ // the ContextErrorException must not be loaded to test the workaround
+ // for https://bugs.php.net/65322.
+ if (class_exists('Symfony\Component\Debug\Exception\ContextErrorException', false)) {
+ $this->markTestSkipped('The ContextErrorException class is already loaded.');
+ }
+ if (defined('HHVM_VERSION')) {
+ $this->markTestSkipped('HHVM is not handled in this test case.');
+ }
+
+ ErrorHandler::register();
+
+ try {
+ // Trigger autoloading + E_STRICT at compile time
+ // which in turn triggers $errorHandler->handle()
+ // that again triggers autoloading for ContextErrorException.
+ // Error stacking works around the bug above and everything is fine.
+
+ eval('
+ namespace '.__NAMESPACE__.';
+ class ChildTestingStacking extends TestingStacking { function foo($bar) {} }
+ ');
+ $this->fail('ContextErrorException expected');
+ } catch (\ErrorException $exception) {
+ // if an exception is thrown, the test passed
+ $this->assertStringStartsWith(__FILE__, $exception->getFile());
+ if (\PHP_VERSION_ID < 70000) {
+ $this->assertRegExp('/^Runtime Notice: Declaration/', $exception->getMessage());
+ $this->assertEquals(E_STRICT, $exception->getSeverity());
+ } else {
+ $this->assertRegExp('/^Warning: Declaration/', $exception->getMessage());
+ $this->assertEquals(E_WARNING, $exception->getSeverity());
+ }
+ } finally {
+ restore_error_handler();
+ restore_exception_handler();
+ }
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Case mismatch between loaded and declared class names
+ */
+ public function testNameCaseMismatch()
+ {
+ class_exists(__NAMESPACE__.'\TestingCaseMismatch', true);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Case mismatch between class and real file names
+ */
+ public function testFileCaseMismatch()
+ {
+ if (!file_exists(__DIR__.'/Fixtures/CaseMismatch.php')) {
+ $this->markTestSkipped('Can only be run on case insensitive filesystems');
+ }
+
+ class_exists(__NAMESPACE__.'\Fixtures\CaseMismatch', true);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Case mismatch between loaded and declared class names
+ */
+ public function testPsr4CaseMismatch()
+ {
+ class_exists(__NAMESPACE__.'\Fixtures\Psr4CaseMismatch', true);
+ }
+
+ public function testNotPsr0()
+ {
+ $this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\NotPSR0', true));
+ }
+
+ public function testNotPsr0Bis()
+ {
+ $this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\NotPSR0bis', true));
+ }
+
+ public function testClassAlias()
+ {
+ $this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\ClassAlias', true));
+ }
+
+ /**
+ * @dataProvider provideDeprecatedSuper
+ */
+ public function testDeprecatedSuper($class, $super, $type)
+ {
+ set_error_handler(function () { return false; });
+ $e = error_reporting(0);
+ trigger_error('', E_USER_DEPRECATED);
+
+ class_exists('Test\\'.__NAMESPACE__.'\\'.$class, true);
+
+ error_reporting($e);
+ restore_error_handler();
+
+ $lastError = error_get_last();
+ unset($lastError['file'], $lastError['line']);
+
+ $xError = array(
+ 'type' => E_USER_DEPRECATED,
+ 'message' => 'The "Test\Symfony\Component\Debug\Tests\\'.$class.'" class '.$type.' "Symfony\Component\Debug\Tests\Fixtures\\'.$super.'" that is deprecated but this is a test deprecation notice.',
+ );
+
+ $this->assertSame($xError, $lastError);
+ }
+
+ public function provideDeprecatedSuper()
+ {
+ return array(
+ array('DeprecatedInterfaceClass', 'DeprecatedInterface', 'implements'),
+ array('DeprecatedParentClass', 'DeprecatedClass', 'extends'),
+ );
+ }
+
+ public function testInterfaceExtendsDeprecatedInterface()
+ {
+ set_error_handler(function () { return false; });
+ $e = error_reporting(0);
+ trigger_error('', E_USER_NOTICE);
+
+ class_exists('Test\\'.__NAMESPACE__.'\\NonDeprecatedInterfaceClass', true);
+
+ error_reporting($e);
+ restore_error_handler();
+
+ $lastError = error_get_last();
+ unset($lastError['file'], $lastError['line']);
+
+ $xError = array(
+ 'type' => E_USER_NOTICE,
+ 'message' => '',
+ );
+
+ $this->assertSame($xError, $lastError);
+ }
+
+ public function testDeprecatedSuperInSameNamespace()
+ {
+ set_error_handler(function () { return false; });
+ $e = error_reporting(0);
+ trigger_error('', E_USER_NOTICE);
+
+ class_exists('Symfony\Bridge\Debug\Tests\Fixtures\ExtendsDeprecatedParent', true);
+
+ error_reporting($e);
+ restore_error_handler();
+
+ $lastError = error_get_last();
+ unset($lastError['file'], $lastError['line']);
+
+ $xError = array(
+ 'type' => E_USER_NOTICE,
+ 'message' => '',
+ );
+
+ $this->assertSame($xError, $lastError);
+ }
+
+ public function testReservedForPhp7()
+ {
+ if (\PHP_VERSION_ID >= 70000) {
+ $this->markTestSkipped('PHP7 already prevents using reserved names.');
+ }
+
+ set_error_handler(function () { return false; });
+ $e = error_reporting(0);
+ trigger_error('', E_USER_NOTICE);
+
+ class_exists('Test\\'.__NAMESPACE__.'\\Float', true);
+
+ error_reporting($e);
+ restore_error_handler();
+
+ $lastError = error_get_last();
+ unset($lastError['file'], $lastError['line']);
+
+ $xError = array(
+ 'type' => E_USER_DEPRECATED,
+ 'message' => 'The "Test\Symfony\Component\Debug\Tests\Float" class uses the reserved name "Float", it will break on PHP 7 and higher',
+ );
+
+ $this->assertSame($xError, $lastError);
+ }
+
+ public function testExtendedFinalClass()
+ {
+ set_error_handler(function () { return false; });
+ $e = error_reporting(0);
+ trigger_error('', E_USER_NOTICE);
+
+ class_exists('Test\\'.__NAMESPACE__.'\\ExtendsFinalClass', true);
+
+ error_reporting($e);
+ restore_error_handler();
+
+ $lastError = error_get_last();
+ unset($lastError['file'], $lastError['line']);
+
+ $xError = array(
+ 'type' => E_USER_DEPRECATED,
+ 'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass" class is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass".',
+ );
+
+ $this->assertSame($xError, $lastError);
+ }
+
+ public function testExtendedFinalMethod()
+ {
+ set_error_handler(function () { return false; });
+ $e = error_reporting(0);
+ trigger_error('', E_USER_NOTICE);
+
+ class_exists(__NAMESPACE__.'\\Fixtures\\ExtendedFinalMethod', true);
+
+ error_reporting($e);
+ restore_error_handler();
+
+ $lastError = error_get_last();
+ unset($lastError['file'], $lastError['line']);
+
+ $xError = array(
+ 'type' => E_USER_DEPRECATED,
+ 'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".',
+ );
+
+ $this->assertSame($xError, $lastError);
+ }
+
+ public function testExtendedDeprecatedMethodDoesntTriggerAnyNotice()
+ {
+ set_error_handler(function () { return false; });
+ $e = error_reporting(0);
+ trigger_error('', E_USER_NOTICE);
+
+ class_exists('Test\\'.__NAMESPACE__.'\\ExtendsAnnotatedClass', true);
+
+ error_reporting($e);
+ restore_error_handler();
+
+ $lastError = error_get_last();
+ unset($lastError['file'], $lastError['line']);
+
+ $this->assertSame(array('type' => E_USER_NOTICE, 'message' => ''), $lastError);
+ }
+
+ public function testInternalsUse()
+ {
+ $deprecations = array();
+ set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
+ $e = error_reporting(E_USER_DEPRECATED);
+
+ class_exists('Test\\'.__NAMESPACE__.'\\ExtendsInternals', true);
+
+ error_reporting($e);
+ restore_error_handler();
+
+ $this->assertSame($deprecations, array(
+ 'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass" class is considered internal since version 3.4. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".',
+ 'The "Symfony\Component\Debug\Tests\Fixtures\InternalInterface" interface is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".',
+ 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait" trait is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".',
+ 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait2::internalMethod()" method is considered internal since version 3.4. It may change without further notice. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".',
+ ));
+ }
+}
+
+class ClassLoader
+{
+ public function loadClass($class)
+ {
+ }
+
+ public function getClassMap()
+ {
+ return array(__NAMESPACE__.'\Fixtures\NotPSR0bis' => __DIR__.'/Fixtures/notPsr0Bis.php');
+ }
+
+ public function findFile($class)
+ {
+ $fixtureDir = __DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR;
+
+ if (__NAMESPACE__.'\TestingUnsilencing' === $class) {
+ eval('-- parse error --');
+ } elseif (__NAMESPACE__.'\TestingStacking' === $class) {
+ eval('namespace '.__NAMESPACE__.'; class TestingStacking { function foo() {} }');
+ } elseif (__NAMESPACE__.'\TestingCaseMismatch' === $class) {
+ eval('namespace '.__NAMESPACE__.'; class TestingCaseMisMatch {}');
+ } elseif (__NAMESPACE__.'\Fixtures\Psr4CaseMismatch' === $class) {
+ return $fixtureDir.'psr4'.DIRECTORY_SEPARATOR.'Psr4CaseMismatch.php';
+ } elseif (__NAMESPACE__.'\Fixtures\NotPSR0' === $class) {
+ return $fixtureDir.'reallyNotPsr0.php';
+ } elseif (__NAMESPACE__.'\Fixtures\NotPSR0bis' === $class) {
+ return $fixtureDir.'notPsr0Bis.php';
+ } elseif ('Symfony\Bridge\Debug\Tests\Fixtures\ExtendsDeprecatedParent' === $class) {
+ eval('namespace Symfony\Bridge\Debug\Tests\Fixtures; class ExtendsDeprecatedParent extends \\'.__NAMESPACE__.'\Fixtures\DeprecatedClass {}');
+ } elseif ('Test\\'.__NAMESPACE__.'\DeprecatedParentClass' === $class) {
+ eval('namespace Test\\'.__NAMESPACE__.'; class DeprecatedParentClass extends \\'.__NAMESPACE__.'\Fixtures\DeprecatedClass {}');
+ } elseif ('Test\\'.__NAMESPACE__.'\DeprecatedInterfaceClass' === $class) {
+ eval('namespace Test\\'.__NAMESPACE__.'; class DeprecatedInterfaceClass implements \\'.__NAMESPACE__.'\Fixtures\DeprecatedInterface {}');
+ } elseif ('Test\\'.__NAMESPACE__.'\NonDeprecatedInterfaceClass' === $class) {
+ eval('namespace Test\\'.__NAMESPACE__.'; class NonDeprecatedInterfaceClass implements \\'.__NAMESPACE__.'\Fixtures\NonDeprecatedInterface {}');
+ } elseif ('Test\\'.__NAMESPACE__.'\Float' === $class) {
+ eval('namespace Test\\'.__NAMESPACE__.'; class Float {}');
+ } elseif ('Test\\'.__NAMESPACE__.'\ExtendsFinalClass' === $class) {
+ eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsFinalClass extends \\'.__NAMESPACE__.'\Fixtures\FinalClass {}');
+ } elseif ('Test\\'.__NAMESPACE__.'\ExtendsAnnotatedClass' === $class) {
+ eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsAnnotatedClass extends \\'.__NAMESPACE__.'\Fixtures\AnnotatedClass {
+ public function deprecatedMethod() { }
+ }');
+ } elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternals' === $class) {
+ eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternals extends ExtendsInternalsParent {
+ use \\'.__NAMESPACE__.'\Fixtures\InternalTrait;
+
+ public function internalMethod() { }
+ }');
+ } elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternalsParent' === $class) {
+ eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternalsParent extends \\'.__NAMESPACE__.'\Fixtures\InternalClass implements \\'.__NAMESPACE__.'\Fixtures\InternalInterface { }');
+ }
+ }
+}
diff --git a/vendor/symfony/debug/Tests/ErrorHandlerTest.php b/vendor/symfony/debug/Tests/ErrorHandlerTest.php
new file mode 100644
index 00000000..4cbe47f3
--- /dev/null
+++ b/vendor/symfony/debug/Tests/ErrorHandlerTest.php
@@ -0,0 +1,536 @@
+<?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\Debug\Tests;
+
+use PHPUnit\Framework\TestCase;
+use Psr\Log\LogLevel;
+use Symfony\Component\Debug\BufferingLogger;
+use Symfony\Component\Debug\ErrorHandler;
+use Symfony\Component\Debug\Exception\SilencedErrorContext;
+
+/**
+ * ErrorHandlerTest.
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ErrorHandlerTest extends TestCase
+{
+ public function testRegister()
+ {
+ $handler = ErrorHandler::register();
+
+ try {
+ $this->assertInstanceOf('Symfony\Component\Debug\ErrorHandler', $handler);
+ $this->assertSame($handler, ErrorHandler::register());
+
+ $newHandler = new ErrorHandler();
+
+ $this->assertSame($newHandler, ErrorHandler::register($newHandler, false));
+ $h = set_error_handler('var_dump');
+ restore_error_handler();
+ $this->assertSame(array($handler, 'handleError'), $h);
+
+ try {
+ $this->assertSame($newHandler, ErrorHandler::register($newHandler, true));
+ $h = set_error_handler('var_dump');
+ restore_error_handler();
+ $this->assertSame(array($newHandler, 'handleError'), $h);
+ } catch (\Exception $e) {
+ }
+
+ restore_error_handler();
+ restore_exception_handler();
+
+ if (isset($e)) {
+ throw $e;
+ }
+ } catch (\Exception $e) {
+ }
+
+ restore_error_handler();
+ restore_exception_handler();
+
+ if (isset($e)) {
+ throw $e;
+ }
+ }
+
+ public function testNotice()
+ {
+ ErrorHandler::register();
+
+ try {
+ self::triggerNotice($this);
+ $this->fail('ErrorException expected');
+ } catch (\ErrorException $exception) {
+ // if an exception is thrown, the test passed
+ $this->assertEquals(E_NOTICE, $exception->getSeverity());
+ $this->assertEquals(__FILE__, $exception->getFile());
+ $this->assertRegExp('/^Notice: Undefined variable: (foo|bar)/', $exception->getMessage());
+
+ $trace = $exception->getTrace();
+
+ $this->assertEquals(__FILE__, $trace[0]['file']);
+ $this->assertEquals(__CLASS__, $trace[0]['class']);
+ $this->assertEquals('triggerNotice', $trace[0]['function']);
+ $this->assertEquals('::', $trace[0]['type']);
+
+ $this->assertEquals(__FILE__, $trace[0]['file']);
+ $this->assertEquals(__CLASS__, $trace[1]['class']);
+ $this->assertEquals(__FUNCTION__, $trace[1]['function']);
+ $this->assertEquals('->', $trace[1]['type']);
+ } finally {
+ restore_error_handler();
+ restore_exception_handler();
+ }
+ }
+
+ // dummy function to test trace in error handler.
+ private static function triggerNotice($that)
+ {
+ $that->assertSame('', $foo.$foo.$bar);
+ }
+
+ public function testConstruct()
+ {
+ try {
+ $handler = ErrorHandler::register();
+ $handler->throwAt(3, true);
+ $this->assertEquals(3 | E_RECOVERABLE_ERROR | E_USER_ERROR, $handler->throwAt(0));
+ } finally {
+ restore_error_handler();
+ restore_exception_handler();
+ }
+ }
+
+ public function testDefaultLogger()
+ {
+ try {
+ $handler = ErrorHandler::register();
+
+ $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+
+ $handler->setDefaultLogger($logger, E_NOTICE);
+ $handler->setDefaultLogger($logger, array(E_USER_NOTICE => LogLevel::CRITICAL));
+
+ $loggers = array(
+ E_DEPRECATED => array(null, LogLevel::INFO),
+ E_USER_DEPRECATED => array(null, LogLevel::INFO),
+ E_NOTICE => array($logger, LogLevel::WARNING),
+ E_USER_NOTICE => array($logger, LogLevel::CRITICAL),
+ E_STRICT => array(null, LogLevel::WARNING),
+ E_WARNING => array(null, LogLevel::WARNING),
+ E_USER_WARNING => array(null, LogLevel::WARNING),
+ E_COMPILE_WARNING => array(null, LogLevel::WARNING),
+ E_CORE_WARNING => array(null, LogLevel::WARNING),
+ E_USER_ERROR => array(null, LogLevel::CRITICAL),
+ E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL),
+ E_COMPILE_ERROR => array(null, LogLevel::CRITICAL),
+ E_PARSE => array(null, LogLevel::CRITICAL),
+ E_ERROR => array(null, LogLevel::CRITICAL),
+ E_CORE_ERROR => array(null, LogLevel::CRITICAL),
+ );
+ $this->assertSame($loggers, $handler->setLoggers(array()));
+ } finally {
+ restore_error_handler();
+ restore_exception_handler();
+ }
+ }
+
+ public function testHandleError()
+ {
+ try {
+ $handler = ErrorHandler::register();
+ $handler->throwAt(0, true);
+ $this->assertFalse($handler->handleError(0, 'foo', 'foo.php', 12, array()));
+
+ restore_error_handler();
+ restore_exception_handler();
+
+ $handler = ErrorHandler::register();
+ $handler->throwAt(3, true);
+ $this->assertFalse($handler->handleError(4, 'foo', 'foo.php', 12, array()));
+
+ restore_error_handler();
+ restore_exception_handler();
+
+ $handler = ErrorHandler::register();
+ $handler->throwAt(3, true);
+ try {
+ $handler->handleError(4, 'foo', 'foo.php', 12, array());
+ } catch (\ErrorException $e) {
+ $this->assertSame('Parse Error: foo', $e->getMessage());
+ $this->assertSame(4, $e->getSeverity());
+ $this->assertSame('foo.php', $e->getFile());
+ $this->assertSame(12, $e->getLine());
+ }
+
+ restore_error_handler();
+ restore_exception_handler();
+
+ $handler = ErrorHandler::register();
+ $handler->throwAt(E_USER_DEPRECATED, true);
+ $this->assertFalse($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array()));
+
+ restore_error_handler();
+ restore_exception_handler();
+
+ $handler = ErrorHandler::register();
+ $handler->throwAt(E_DEPRECATED, true);
+ $this->assertFalse($handler->handleError(E_DEPRECATED, 'foo', 'foo.php', 12, array()));
+
+ restore_error_handler();
+ restore_exception_handler();
+
+ $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+
+ $warnArgCheck = function ($logLevel, $message, $context) {
+ $this->assertEquals('info', $logLevel);
+ $this->assertEquals('User Deprecated: foo', $message);
+ $this->assertArrayHasKey('exception', $context);
+ $exception = $context['exception'];
+ $this->assertInstanceOf(\ErrorException::class, $exception);
+ $this->assertSame('User Deprecated: foo', $exception->getMessage());
+ $this->assertSame(E_USER_DEPRECATED, $exception->getSeverity());
+ };
+
+ $logger
+ ->expects($this->once())
+ ->method('log')
+ ->will($this->returnCallback($warnArgCheck))
+ ;
+
+ $handler = ErrorHandler::register();
+ $handler->setDefaultLogger($logger, E_USER_DEPRECATED);
+ $this->assertTrue($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array()));
+
+ restore_error_handler();
+ restore_exception_handler();
+
+ $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+
+ $line = null;
+ $logArgCheck = function ($level, $message, $context) use (&$line) {
+ $this->assertEquals('Notice: Undefined variable: undefVar', $message);
+ $this->assertArrayHasKey('exception', $context);
+ $exception = $context['exception'];
+ $this->assertInstanceOf(SilencedErrorContext::class, $exception);
+ $this->assertSame(E_NOTICE, $exception->getSeverity());
+ $this->assertSame(__FILE__, $exception->getFile());
+ $this->assertSame($line, $exception->getLine());
+ $this->assertNotEmpty($exception->getTrace());
+ $this->assertSame(1, $exception->count);
+ };
+
+ $logger
+ ->expects($this->once())
+ ->method('log')
+ ->will($this->returnCallback($logArgCheck))
+ ;
+
+ $handler = ErrorHandler::register();
+ $handler->setDefaultLogger($logger, E_NOTICE);
+ $handler->screamAt(E_NOTICE);
+ unset($undefVar);
+ $line = __LINE__ + 1;
+ @$undefVar++;
+
+ restore_error_handler();
+ restore_exception_handler();
+ } catch (\Exception $e) {
+ restore_error_handler();
+ restore_exception_handler();
+
+ throw $e;
+ }
+ }
+
+ public function testHandleUserError()
+ {
+ try {
+ $handler = ErrorHandler::register();
+ $handler->throwAt(0, true);
+
+ $e = null;
+ $x = new \Exception('Foo');
+
+ try {
+ $f = new Fixtures\ToStringThrower($x);
+ $f .= ''; // Trigger $f->__toString()
+ } catch (\Exception $e) {
+ }
+
+ $this->assertSame($x, $e);
+ } finally {
+ restore_error_handler();
+ restore_exception_handler();
+ }
+ }
+
+ public function testHandleDeprecation()
+ {
+ $logArgCheck = function ($level, $message, $context) {
+ $this->assertEquals(LogLevel::INFO, $level);
+ $this->assertArrayHasKey('exception', $context);
+ $exception = $context['exception'];
+ $this->assertInstanceOf(\ErrorException::class, $exception);
+ $this->assertSame('User Deprecated: Foo deprecation', $exception->getMessage());
+ };
+
+ $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+ $logger
+ ->expects($this->once())
+ ->method('log')
+ ->will($this->returnCallback($logArgCheck))
+ ;
+
+ $handler = new ErrorHandler();
+ $handler->setDefaultLogger($logger);
+ @$handler->handleError(E_USER_DEPRECATED, 'Foo deprecation', __FILE__, __LINE__, array());
+ }
+
+ public function testHandleException()
+ {
+ try {
+ $handler = ErrorHandler::register();
+
+ $exception = new \Exception('foo');
+
+ $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+
+ $logArgCheck = function ($level, $message, $context) {
+ $this->assertSame('Uncaught Exception: foo', $message);
+ $this->assertArrayHasKey('exception', $context);
+ $this->assertInstanceOf(\Exception::class, $context['exception']);
+ };
+
+ $logger
+ ->expects($this->exactly(2))
+ ->method('log')
+ ->will($this->returnCallback($logArgCheck))
+ ;
+
+ $handler->setDefaultLogger($logger, E_ERROR);
+
+ try {
+ $handler->handleException($exception);
+ $this->fail('Exception expected');
+ } catch (\Exception $e) {
+ $this->assertSame($exception, $e);
+ }
+
+ $handler->setExceptionHandler(function ($e) use ($exception) {
+ $this->assertSame($exception, $e);
+ });
+
+ $handler->handleException($exception);
+ } finally {
+ restore_error_handler();
+ restore_exception_handler();
+ }
+ }
+
+ /**
+ * @group legacy
+ */
+ public function testErrorStacking()
+ {
+ try {
+ $handler = ErrorHandler::register();
+ $handler->screamAt(E_USER_WARNING);
+
+ $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+
+ $logger
+ ->expects($this->exactly(2))
+ ->method('log')
+ ->withConsecutive(
+ array($this->equalTo(LogLevel::WARNING), $this->equalTo('Dummy log')),
+ array($this->equalTo(LogLevel::DEBUG), $this->equalTo('User Warning: Silenced warning'))
+ )
+ ;
+
+ $handler->setDefaultLogger($logger, array(E_USER_WARNING => LogLevel::WARNING));
+
+ ErrorHandler::stackErrors();
+ @trigger_error('Silenced warning', E_USER_WARNING);
+ $logger->log(LogLevel::WARNING, 'Dummy log');
+ ErrorHandler::unstackErrors();
+ } finally {
+ restore_error_handler();
+ restore_exception_handler();
+ }
+ }
+
+ public function testBootstrappingLogger()
+ {
+ $bootLogger = new BufferingLogger();
+ $handler = new ErrorHandler($bootLogger);
+
+ $loggers = array(
+ E_DEPRECATED => array($bootLogger, LogLevel::INFO),
+ E_USER_DEPRECATED => array($bootLogger, LogLevel::INFO),
+ E_NOTICE => array($bootLogger, LogLevel::WARNING),
+ E_USER_NOTICE => array($bootLogger, LogLevel::WARNING),
+ E_STRICT => array($bootLogger, LogLevel::WARNING),
+ E_WARNING => array($bootLogger, LogLevel::WARNING),
+ E_USER_WARNING => array($bootLogger, LogLevel::WARNING),
+ E_COMPILE_WARNING => array($bootLogger, LogLevel::WARNING),
+ E_CORE_WARNING => array($bootLogger, LogLevel::WARNING),
+ E_USER_ERROR => array($bootLogger, LogLevel::CRITICAL),
+ E_RECOVERABLE_ERROR => array($bootLogger, LogLevel::CRITICAL),
+ E_COMPILE_ERROR => array($bootLogger, LogLevel::CRITICAL),
+ E_PARSE => array($bootLogger, LogLevel::CRITICAL),
+ E_ERROR => array($bootLogger, LogLevel::CRITICAL),
+ E_CORE_ERROR => array($bootLogger, LogLevel::CRITICAL),
+ );
+
+ $this->assertSame($loggers, $handler->setLoggers(array()));
+
+ $handler->handleError(E_DEPRECATED, 'Foo message', __FILE__, 123, array());
+
+ $logs = $bootLogger->cleanLogs();
+
+ $this->assertCount(1, $logs);
+ $log = $logs[0];
+ $this->assertSame('info', $log[0]);
+ $this->assertSame('Deprecated: Foo message', $log[1]);
+ $this->assertArrayHasKey('exception', $log[2]);
+ $exception = $log[2]['exception'];
+ $this->assertInstanceOf(\ErrorException::class, $exception);
+ $this->assertSame('Deprecated: Foo message', $exception->getMessage());
+ $this->assertSame(__FILE__, $exception->getFile());
+ $this->assertSame(123, $exception->getLine());
+ $this->assertSame(E_DEPRECATED, $exception->getSeverity());
+
+ $bootLogger->log(LogLevel::WARNING, 'Foo message', array('exception' => $exception));
+
+ $mockLogger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+ $mockLogger->expects($this->once())
+ ->method('log')
+ ->with(LogLevel::WARNING, 'Foo message', array('exception' => $exception));
+
+ $handler->setLoggers(array(E_DEPRECATED => array($mockLogger, LogLevel::WARNING)));
+ }
+
+ public function testSettingLoggerWhenExceptionIsBuffered()
+ {
+ $bootLogger = new BufferingLogger();
+ $handler = new ErrorHandler($bootLogger);
+
+ $exception = new \Exception('Foo message');
+
+ $mockLogger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+ $mockLogger->expects($this->once())
+ ->method('log')
+ ->with(LogLevel::CRITICAL, 'Uncaught Exception: Foo message', array('exception' => $exception));
+
+ $handler->setExceptionHandler(function () use ($handler, $mockLogger) {
+ $handler->setDefaultLogger($mockLogger);
+ });
+
+ $handler->handleException($exception);
+ }
+
+ public function testHandleFatalError()
+ {
+ try {
+ $handler = ErrorHandler::register();
+
+ $error = array(
+ 'type' => E_PARSE,
+ 'message' => 'foo',
+ 'file' => 'bar',
+ 'line' => 123,
+ );
+
+ $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+
+ $logArgCheck = function ($level, $message, $context) {
+ $this->assertEquals('Fatal Parse Error: foo', $message);
+ $this->assertArrayHasKey('exception', $context);
+ $this->assertInstanceOf(\Exception::class, $context['exception']);
+ };
+
+ $logger
+ ->expects($this->once())
+ ->method('log')
+ ->will($this->returnCallback($logArgCheck))
+ ;
+
+ $handler->setDefaultLogger($logger, E_PARSE);
+
+ $handler->handleFatalError($error);
+
+ restore_error_handler();
+ restore_exception_handler();
+ } catch (\Exception $e) {
+ restore_error_handler();
+ restore_exception_handler();
+
+ throw $e;
+ }
+ }
+
+ /**
+ * @requires PHP 7
+ */
+ public function testHandleErrorException()
+ {
+ $exception = new \Error("Class 'Foo' not found");
+
+ $handler = new ErrorHandler();
+ $handler->setExceptionHandler(function () use (&$args) {
+ $args = func_get_args();
+ });
+
+ $handler->handleException($exception);
+
+ $this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $args[0]);
+ $this->assertStringStartsWith("Attempted to load class \"Foo\" from the global namespace.\nDid you forget a \"use\" statement", $args[0]->getMessage());
+ }
+
+ public function testHandleFatalErrorOnHHVM()
+ {
+ try {
+ $handler = ErrorHandler::register();
+
+ $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+ $logger
+ ->expects($this->once())
+ ->method('log')
+ ->with(
+ $this->equalTo(LogLevel::CRITICAL),
+ $this->equalTo('Fatal Error: foo')
+ )
+ ;
+
+ $handler->setDefaultLogger($logger, E_ERROR);
+
+ $error = array(
+ 'type' => E_ERROR + 0x1000000, // This error level is used by HHVM for fatal errors
+ 'message' => 'foo',
+ 'file' => 'bar',
+ 'line' => 123,
+ 'context' => array(123),
+ 'backtrace' => array(456),
+ );
+
+ call_user_func_array(array($handler, 'handleError'), $error);
+ $handler->handleFatalError($error);
+ } finally {
+ restore_error_handler();
+ restore_exception_handler();
+ }
+ }
+}
diff --git a/vendor/symfony/debug/Tests/Exception/FlattenExceptionTest.php b/vendor/symfony/debug/Tests/Exception/FlattenExceptionTest.php
new file mode 100644
index 00000000..e7762bde
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Exception/FlattenExceptionTest.php
@@ -0,0 +1,301 @@
+<?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\Debug\Tests\Exception;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Debug\Exception\FlattenException;
+use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
+use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
+use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
+use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
+use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
+use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
+use Symfony\Component\HttpKernel\Exception\GoneHttpException;
+use Symfony\Component\HttpKernel\Exception\LengthRequiredHttpException;
+use Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException;
+use Symfony\Component\HttpKernel\Exception\PreconditionRequiredHttpException;
+use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
+use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
+use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
+
+class FlattenExceptionTest extends TestCase
+{
+ public function testStatusCode()
+ {
+ $flattened = FlattenException::create(new \RuntimeException(), 403);
+ $this->assertEquals('403', $flattened->getStatusCode());
+
+ $flattened = FlattenException::create(new \RuntimeException());
+ $this->assertEquals('500', $flattened->getStatusCode());
+
+ $flattened = FlattenException::create(new NotFoundHttpException());
+ $this->assertEquals('404', $flattened->getStatusCode());
+
+ $flattened = FlattenException::create(new UnauthorizedHttpException('Basic realm="My Realm"'));
+ $this->assertEquals('401', $flattened->getStatusCode());
+
+ $flattened = FlattenException::create(new BadRequestHttpException());
+ $this->assertEquals('400', $flattened->getStatusCode());
+
+ $flattened = FlattenException::create(new NotAcceptableHttpException());
+ $this->assertEquals('406', $flattened->getStatusCode());
+
+ $flattened = FlattenException::create(new ConflictHttpException());
+ $this->assertEquals('409', $flattened->getStatusCode());
+
+ $flattened = FlattenException::create(new MethodNotAllowedHttpException(array('POST')));
+ $this->assertEquals('405', $flattened->getStatusCode());
+
+ $flattened = FlattenException::create(new AccessDeniedHttpException());
+ $this->assertEquals('403', $flattened->getStatusCode());
+
+ $flattened = FlattenException::create(new GoneHttpException());
+ $this->assertEquals('410', $flattened->getStatusCode());
+
+ $flattened = FlattenException::create(new LengthRequiredHttpException());
+ $this->assertEquals('411', $flattened->getStatusCode());
+
+ $flattened = FlattenException::create(new PreconditionFailedHttpException());
+ $this->assertEquals('412', $flattened->getStatusCode());
+
+ $flattened = FlattenException::create(new PreconditionRequiredHttpException());
+ $this->assertEquals('428', $flattened->getStatusCode());
+
+ $flattened = FlattenException::create(new ServiceUnavailableHttpException());
+ $this->assertEquals('503', $flattened->getStatusCode());
+
+ $flattened = FlattenException::create(new TooManyRequestsHttpException());
+ $this->assertEquals('429', $flattened->getStatusCode());
+
+ $flattened = FlattenException::create(new UnsupportedMediaTypeHttpException());
+ $this->assertEquals('415', $flattened->getStatusCode());
+
+ if (class_exists(SuspiciousOperationException::class)) {
+ $flattened = FlattenException::create(new SuspiciousOperationException());
+ $this->assertEquals('400', $flattened->getStatusCode());
+ }
+ }
+
+ public function testHeadersForHttpException()
+ {
+ $flattened = FlattenException::create(new MethodNotAllowedHttpException(array('POST')));
+ $this->assertEquals(array('Allow' => 'POST'), $flattened->getHeaders());
+
+ $flattened = FlattenException::create(new UnauthorizedHttpException('Basic realm="My Realm"'));
+ $this->assertEquals(array('WWW-Authenticate' => 'Basic realm="My Realm"'), $flattened->getHeaders());
+
+ $flattened = FlattenException::create(new ServiceUnavailableHttpException('Fri, 31 Dec 1999 23:59:59 GMT'));
+ $this->assertEquals(array('Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'), $flattened->getHeaders());
+
+ $flattened = FlattenException::create(new ServiceUnavailableHttpException(120));
+ $this->assertEquals(array('Retry-After' => 120), $flattened->getHeaders());
+
+ $flattened = FlattenException::create(new TooManyRequestsHttpException('Fri, 31 Dec 1999 23:59:59 GMT'));
+ $this->assertEquals(array('Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'), $flattened->getHeaders());
+
+ $flattened = FlattenException::create(new TooManyRequestsHttpException(120));
+ $this->assertEquals(array('Retry-After' => 120), $flattened->getHeaders());
+ }
+
+ /**
+ * @dataProvider flattenDataProvider
+ */
+ public function testFlattenHttpException(\Exception $exception, $statusCode)
+ {
+ $flattened = FlattenException::create($exception);
+ $flattened2 = FlattenException::create($exception);
+
+ $flattened->setPrevious($flattened2);
+
+ $this->assertEquals($exception->getMessage(), $flattened->getMessage(), 'The message is copied from the original exception.');
+ $this->assertEquals($exception->getCode(), $flattened->getCode(), 'The code is copied from the original exception.');
+ $this->assertInstanceOf($flattened->getClass(), $exception, 'The class is set to the class of the original exception');
+ }
+
+ /**
+ * @dataProvider flattenDataProvider
+ */
+ public function testPrevious(\Exception $exception, $statusCode)
+ {
+ $flattened = FlattenException::create($exception);
+ $flattened2 = FlattenException::create($exception);
+
+ $flattened->setPrevious($flattened2);
+
+ $this->assertSame($flattened2, $flattened->getPrevious());
+
+ $this->assertSame(array($flattened2), $flattened->getAllPrevious());
+ }
+
+ /**
+ * @requires PHP 7.0
+ */
+ public function testPreviousError()
+ {
+ $exception = new \Exception('test', 123, new \ParseError('Oh noes!', 42));
+
+ $flattened = FlattenException::create($exception)->getPrevious();
+
+ $this->assertEquals($flattened->getMessage(), 'Parse error: Oh noes!', 'The message is copied from the original exception.');
+ $this->assertEquals($flattened->getCode(), 42, 'The code is copied from the original exception.');
+ $this->assertEquals($flattened->getClass(), 'Symfony\Component\Debug\Exception\FatalThrowableError', 'The class is set to the class of the original exception');
+ }
+
+ /**
+ * @dataProvider flattenDataProvider
+ */
+ public function testLine(\Exception $exception)
+ {
+ $flattened = FlattenException::create($exception);
+ $this->assertSame($exception->getLine(), $flattened->getLine());
+ }
+
+ /**
+ * @dataProvider flattenDataProvider
+ */
+ public function testFile(\Exception $exception)
+ {
+ $flattened = FlattenException::create($exception);
+ $this->assertSame($exception->getFile(), $flattened->getFile());
+ }
+
+ /**
+ * @dataProvider flattenDataProvider
+ */
+ public function testToArray(\Exception $exception, $statusCode)
+ {
+ $flattened = FlattenException::create($exception);
+ $flattened->setTrace(array(), 'foo.php', 123);
+
+ $this->assertEquals(array(
+ array(
+ 'message' => 'test',
+ 'class' => 'Exception',
+ 'trace' => array(array(
+ 'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => '', 'file' => 'foo.php', 'line' => 123,
+ 'args' => array(),
+ )),
+ ),
+ ), $flattened->toArray());
+ }
+
+ public function flattenDataProvider()
+ {
+ return array(
+ array(new \Exception('test', 123), 500),
+ );
+ }
+
+ public function testArguments()
+ {
+ $dh = opendir(__DIR__);
+ $fh = tmpfile();
+
+ $incomplete = unserialize('O:14:"BogusTestClass":0:{}');
+
+ $exception = $this->createException(array(
+ (object) array('foo' => 1),
+ new NotFoundHttpException(),
+ $incomplete,
+ $dh,
+ $fh,
+ function () {},
+ array(1, 2),
+ array('foo' => 123),
+ null,
+ true,
+ false,
+ 0,
+ 0.0,
+ '0',
+ '',
+ INF,
+ NAN,
+ ));
+
+ $flattened = FlattenException::create($exception);
+ $trace = $flattened->getTrace();
+ $args = $trace[1]['args'];
+ $array = $args[0][1];
+
+ closedir($dh);
+ fclose($fh);
+
+ $i = 0;
+ $this->assertSame(array('object', 'stdClass'), $array[$i++]);
+ $this->assertSame(array('object', 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException'), $array[$i++]);
+ $this->assertSame(array('incomplete-object', 'BogusTestClass'), $array[$i++]);
+ $this->assertSame(array('resource', defined('HHVM_VERSION') ? 'Directory' : 'stream'), $array[$i++]);
+ $this->assertSame(array('resource', 'stream'), $array[$i++]);
+
+ $args = $array[$i++];
+ $this->assertSame($args[0], 'object');
+ $this->assertTrue('Closure' === $args[1] || is_subclass_of($args[1], '\Closure'), 'Expect object class name to be Closure or a subclass of Closure.');
+
+ $this->assertSame(array('array', array(array('integer', 1), array('integer', 2))), $array[$i++]);
+ $this->assertSame(array('array', array('foo' => array('integer', 123))), $array[$i++]);
+ $this->assertSame(array('null', null), $array[$i++]);
+ $this->assertSame(array('boolean', true), $array[$i++]);
+ $this->assertSame(array('boolean', false), $array[$i++]);
+ $this->assertSame(array('integer', 0), $array[$i++]);
+ $this->assertSame(array('float', 0.0), $array[$i++]);
+ $this->assertSame(array('string', '0'), $array[$i++]);
+ $this->assertSame(array('string', ''), $array[$i++]);
+ $this->assertSame(array('float', INF), $array[$i++]);
+
+ // assertEquals() does not like NAN values.
+ $this->assertEquals($array[$i][0], 'float');
+ $this->assertTrue(is_nan($array[$i++][1]));
+ }
+
+ public function testRecursionInArguments()
+ {
+ $a = array('foo', array(2, &$a));
+ $exception = $this->createException($a);
+
+ $flattened = FlattenException::create($exception);
+ $trace = $flattened->getTrace();
+ $this->assertContains('*DEEP NESTED ARRAY*', serialize($trace));
+ }
+
+ public function testTooBigArray()
+ {
+ $a = array();
+ for ($i = 0; $i < 20; ++$i) {
+ for ($j = 0; $j < 50; ++$j) {
+ for ($k = 0; $k < 10; ++$k) {
+ $a[$i][$j][$k] = 'value';
+ }
+ }
+ }
+ $a[20] = 'value';
+ $a[21] = 'value1';
+ $exception = $this->createException($a);
+
+ $flattened = FlattenException::create($exception);
+ $trace = $flattened->getTrace();
+
+ $this->assertSame($trace[1]['args'][0], array('array', array('array', '*SKIPPED over 10000 entries*')));
+
+ $serializeTrace = serialize($trace);
+
+ $this->assertContains('*SKIPPED over 10000 entries*', $serializeTrace);
+ $this->assertNotContains('*value1*', $serializeTrace);
+ }
+
+ private function createException($foo)
+ {
+ return new \Exception();
+ }
+}
diff --git a/vendor/symfony/debug/Tests/ExceptionHandlerTest.php b/vendor/symfony/debug/Tests/ExceptionHandlerTest.php
new file mode 100644
index 00000000..0285eff1
--- /dev/null
+++ b/vendor/symfony/debug/Tests/ExceptionHandlerTest.php
@@ -0,0 +1,133 @@
+<?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\Debug\Tests;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Debug\ExceptionHandler;
+use Symfony\Component\Debug\Exception\OutOfMemoryException;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
+
+require_once __DIR__.'/HeaderMock.php';
+
+class ExceptionHandlerTest extends TestCase
+{
+ protected function setUp()
+ {
+ testHeader();
+ }
+
+ protected function tearDown()
+ {
+ testHeader();
+ }
+
+ public function testDebug()
+ {
+ $handler = new ExceptionHandler(false);
+
+ ob_start();
+ $handler->sendPhpResponse(new \RuntimeException('Foo'));
+ $response = ob_get_clean();
+
+ $this->assertContains('Whoops, looks like something went wrong.', $response);
+ $this->assertNotContains('<div class="trace trace-as-html">', $response);
+
+ $handler = new ExceptionHandler(true);
+
+ ob_start();
+ $handler->sendPhpResponse(new \RuntimeException('Foo'));
+ $response = ob_get_clean();
+
+ $this->assertContains('Whoops, looks like something went wrong.', $response);
+ $this->assertContains('<div class="trace trace-as-html">', $response);
+ }
+
+ public function testStatusCode()
+ {
+ $handler = new ExceptionHandler(false, 'iso8859-1');
+
+ ob_start();
+ $handler->sendPhpResponse(new NotFoundHttpException('Foo'));
+ $response = ob_get_clean();
+
+ $this->assertContains('Sorry, the page you are looking for could not be found.', $response);
+
+ $expectedHeaders = array(
+ array('HTTP/1.0 404', true, null),
+ array('Content-Type: text/html; charset=iso8859-1', true, null),
+ );
+
+ $this->assertSame($expectedHeaders, testHeader());
+ }
+
+ public function testHeaders()
+ {
+ $handler = new ExceptionHandler(false, 'iso8859-1');
+
+ ob_start();
+ $handler->sendPhpResponse(new MethodNotAllowedHttpException(array('POST')));
+ $response = ob_get_clean();
+
+ $expectedHeaders = array(
+ array('HTTP/1.0 405', true, null),
+ array('Allow: POST', false, null),
+ array('Content-Type: text/html; charset=iso8859-1', true, null),
+ );
+
+ $this->assertSame($expectedHeaders, testHeader());
+ }
+
+ public function testNestedExceptions()
+ {
+ $handler = new ExceptionHandler(true);
+ ob_start();
+ $handler->sendPhpResponse(new \RuntimeException('Foo', 0, new \RuntimeException('Bar')));
+ $response = ob_get_clean();
+
+ $this->assertStringMatchesFormat('%A<p class="break-long-words trace-message">Foo</p>%A<p class="break-long-words trace-message">Bar</p>%A', $response);
+ }
+
+ public function testHandle()
+ {
+ $exception = new \Exception('foo');
+
+ $handler = $this->getMockBuilder('Symfony\Component\Debug\ExceptionHandler')->setMethods(array('sendPhpResponse'))->getMock();
+ $handler
+ ->expects($this->exactly(2))
+ ->method('sendPhpResponse');
+
+ $handler->handle($exception);
+
+ $handler->setHandler(function ($e) use ($exception) {
+ $this->assertSame($exception, $e);
+ });
+
+ $handler->handle($exception);
+ }
+
+ public function testHandleOutOfMemoryException()
+ {
+ $exception = new OutOfMemoryException('foo', 0, E_ERROR, __FILE__, __LINE__);
+
+ $handler = $this->getMockBuilder('Symfony\Component\Debug\ExceptionHandler')->setMethods(array('sendPhpResponse'))->getMock();
+ $handler
+ ->expects($this->once())
+ ->method('sendPhpResponse');
+
+ $handler->setHandler(function ($e) {
+ $this->fail('OutOfMemoryException should bypass the handler');
+ });
+
+ $handler->handle($exception);
+ }
+}
diff --git a/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php b/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php
new file mode 100644
index 00000000..65c80fc1
--- /dev/null
+++ b/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php
@@ -0,0 +1,176 @@
+<?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\Debug\Tests\FatalErrorHandler;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Debug\Exception\FatalErrorException;
+use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
+use Symfony\Component\Debug\DebugClassLoader;
+use Composer\Autoload\ClassLoader as ComposerClassLoader;
+
+class ClassNotFoundFatalErrorHandlerTest extends TestCase
+{
+ public static function setUpBeforeClass()
+ {
+ foreach (spl_autoload_functions() as $function) {
+ if (!is_array($function)) {
+ continue;
+ }
+
+ // get class loaders wrapped by DebugClassLoader
+ if ($function[0] instanceof DebugClassLoader) {
+ $function = $function[0]->getClassLoader();
+ }
+
+ if ($function[0] instanceof ComposerClassLoader) {
+ $function[0]->add('Symfony_Component_Debug_Tests_Fixtures', dirname(dirname(dirname(dirname(dirname(__DIR__))))));
+ break;
+ }
+ }
+ }
+
+ /**
+ * @dataProvider provideClassNotFoundData
+ */
+ public function testHandleClassNotFound($error, $translatedMessage, $autoloader = null)
+ {
+ if ($autoloader) {
+ // Unregister all autoloaders to ensure the custom provided
+ // autoloader is the only one to be used during the test run.
+ $autoloaders = spl_autoload_functions();
+ array_map('spl_autoload_unregister', $autoloaders);
+ spl_autoload_register($autoloader);
+ }
+
+ $handler = new ClassNotFoundFatalErrorHandler();
+
+ $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line']));
+
+ if ($autoloader) {
+ spl_autoload_unregister($autoloader);
+ array_map('spl_autoload_register', $autoloaders);
+ }
+
+ $this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $exception);
+ $this->assertSame($translatedMessage, $exception->getMessage());
+ $this->assertSame($error['type'], $exception->getSeverity());
+ $this->assertSame($error['file'], $exception->getFile());
+ $this->assertSame($error['line'], $exception->getLine());
+ }
+
+ public function provideClassNotFoundData()
+ {
+ $autoloader = new ComposerClassLoader();
+ $autoloader->add('Symfony\Component\Debug\Exception\\', realpath(__DIR__.'/../../Exception'));
+
+ $debugClassLoader = new DebugClassLoader(array($autoloader, 'loadClass'));
+
+ return array(
+ array(
+ array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Class \'WhizBangFactory\' not found',
+ ),
+ "Attempted to load class \"WhizBangFactory\" from the global namespace.\nDid you forget a \"use\" statement?",
+ ),
+ array(
+ array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Class \'Foo\\Bar\\WhizBangFactory\' not found',
+ ),
+ "Attempted to load class \"WhizBangFactory\" from namespace \"Foo\\Bar\".\nDid you forget a \"use\" statement for another namespace?",
+ ),
+ array(
+ array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Class \'UndefinedFunctionException\' not found',
+ ),
+ "Attempted to load class \"UndefinedFunctionException\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?",
+ ),
+ array(
+ array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Class \'PEARClass\' not found',
+ ),
+ "Attempted to load class \"PEARClass\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony_Component_Debug_Tests_Fixtures_PEARClass\"?",
+ ),
+ array(
+ array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
+ ),
+ "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?",
+ ),
+ array(
+ array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
+ ),
+ "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?",
+ array($autoloader, 'loadClass'),
+ ),
+ array(
+ array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
+ ),
+ "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?",
+ array($debugClassLoader, 'loadClass'),
+ ),
+ array(
+ array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
+ ),
+ "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\Bar\".\nDid you forget a \"use\" statement for another namespace?",
+ function ($className) { /* do nothing here */ },
+ ),
+ );
+ }
+
+ public function testCannotRedeclareClass()
+ {
+ if (!file_exists(__DIR__.'/../FIXTURES2/REQUIREDTWICE.PHP')) {
+ $this->markTestSkipped('Can only be run on case insensitive filesystems');
+ }
+
+ require_once __DIR__.'/../FIXTURES2/REQUIREDTWICE.PHP';
+
+ $error = array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Class \'Foo\\Bar\\RequiredTwice\' not found',
+ );
+
+ $handler = new ClassNotFoundFatalErrorHandler();
+ $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line']));
+
+ $this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $exception);
+ }
+}
diff --git a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php
new file mode 100644
index 00000000..1dc21200
--- /dev/null
+++ b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php
@@ -0,0 +1,81 @@
+<?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\Debug\Tests\FatalErrorHandler;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Debug\Exception\FatalErrorException;
+use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
+
+class UndefinedFunctionFatalErrorHandlerTest extends TestCase
+{
+ /**
+ * @dataProvider provideUndefinedFunctionData
+ */
+ public function testUndefinedFunction($error, $translatedMessage)
+ {
+ $handler = new UndefinedFunctionFatalErrorHandler();
+ $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line']));
+
+ $this->assertInstanceOf('Symfony\Component\Debug\Exception\UndefinedFunctionException', $exception);
+ // class names are case insensitive and PHP/HHVM do not return the same
+ $this->assertSame(strtolower($translatedMessage), strtolower($exception->getMessage()));
+ $this->assertSame($error['type'], $exception->getSeverity());
+ $this->assertSame($error['file'], $exception->getFile());
+ $this->assertSame($error['line'], $exception->getLine());
+ }
+
+ public function provideUndefinedFunctionData()
+ {
+ return array(
+ array(
+ array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Call to undefined function test_namespaced_function()',
+ ),
+ "Attempted to call function \"test_namespaced_function\" from the global namespace.\nDid you mean to call \"\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function\"?",
+ ),
+ array(
+ array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Call to undefined function Foo\\Bar\\Baz\\test_namespaced_function()',
+ ),
+ "Attempted to call function \"test_namespaced_function\" from namespace \"Foo\\Bar\\Baz\".\nDid you mean to call \"\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function\"?",
+ ),
+ array(
+ array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Call to undefined function foo()',
+ ),
+ 'Attempted to call function "foo" from the global namespace.',
+ ),
+ array(
+ array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Call to undefined function Foo\\Bar\\Baz\\foo()',
+ ),
+ 'Attempted to call function "foo" from namespace "Foo\Bar\Baz".',
+ ),
+ );
+ }
+}
+
+function test_namespaced_function()
+{
+}
diff --git a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php
new file mode 100644
index 00000000..739e5b2b
--- /dev/null
+++ b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php
@@ -0,0 +1,76 @@
+<?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\Debug\Tests\FatalErrorHandler;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Debug\Exception\FatalErrorException;
+use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
+
+class UndefinedMethodFatalErrorHandlerTest extends TestCase
+{
+ /**
+ * @dataProvider provideUndefinedMethodData
+ */
+ public function testUndefinedMethod($error, $translatedMessage)
+ {
+ $handler = new UndefinedMethodFatalErrorHandler();
+ $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line']));
+
+ $this->assertInstanceOf('Symfony\Component\Debug\Exception\UndefinedMethodException', $exception);
+ $this->assertSame($translatedMessage, $exception->getMessage());
+ $this->assertSame($error['type'], $exception->getSeverity());
+ $this->assertSame($error['file'], $exception->getFile());
+ $this->assertSame($error['line'], $exception->getLine());
+ }
+
+ public function provideUndefinedMethodData()
+ {
+ return array(
+ array(
+ array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Call to undefined method SplObjectStorage::what()',
+ ),
+ 'Attempted to call an undefined method named "what" of class "SplObjectStorage".',
+ ),
+ array(
+ array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Call to undefined method SplObjectStorage::walid()',
+ ),
+ "Attempted to call an undefined method named \"walid\" of class \"SplObjectStorage\".\nDid you mean to call \"valid\"?",
+ ),
+ array(
+ array(
+ 'type' => 1,
+ 'line' => 12,
+ 'file' => 'foo.php',
+ 'message' => 'Call to undefined method SplObjectStorage::offsetFet()',
+ ),
+ "Attempted to call an undefined method named \"offsetFet\" of class \"SplObjectStorage\".\nDid you mean to call e.g. \"offsetGet\", \"offsetSet\" or \"offsetUnset\"?",
+ ),
+ array(
+ array(
+ 'type' => 1,
+ 'message' => 'Call to undefined method class@anonymous::test()',
+ 'file' => '/home/possum/work/symfony/test.php',
+ 'line' => 11,
+ ),
+ 'Attempted to call an undefined method named "test" of class "class@anonymous".',
+ ),
+ );
+ }
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php b/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php
new file mode 100644
index 00000000..dff9517d
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+class AnnotatedClass
+{
+ /**
+ * @deprecated since version 3.4.
+ */
+ public function deprecatedMethod()
+ {
+ }
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/ClassAlias.php b/vendor/symfony/debug/Tests/Fixtures/ClassAlias.php
new file mode 100644
index 00000000..9d6dbaa7
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/ClassAlias.php
@@ -0,0 +1,3 @@
+<?php
+
+class_alias('Symfony\Component\Debug\Tests\Fixtures\NotPSR0bis', 'Symfony\Component\Debug\Tests\Fixtures\ClassAlias');
diff --git a/vendor/symfony/debug/Tests/Fixtures/DeprecatedClass.php b/vendor/symfony/debug/Tests/Fixtures/DeprecatedClass.php
new file mode 100644
index 00000000..51fde5af
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/DeprecatedClass.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+/**
+ * @deprecated but this is a test
+ * deprecation notice
+ * @foobar
+ */
+class DeprecatedClass
+{
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/DeprecatedInterface.php b/vendor/symfony/debug/Tests/Fixtures/DeprecatedInterface.php
new file mode 100644
index 00000000..6bab62f9
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/DeprecatedInterface.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+/**
+ * @deprecated but this is a test
+ * deprecation notice
+ * @foobar
+ */
+interface DeprecatedInterface
+{
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/ExtendedFinalMethod.php b/vendor/symfony/debug/Tests/Fixtures/ExtendedFinalMethod.php
new file mode 100644
index 00000000..2bd337e5
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/ExtendedFinalMethod.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+class ExtendedFinalMethod extends FinalMethod
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function finalMethod()
+ {
+ }
+
+ public function anotherMethod()
+ {
+ }
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/FinalClass.php b/vendor/symfony/debug/Tests/Fixtures/FinalClass.php
new file mode 100644
index 00000000..2cf26b19
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/FinalClass.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+/**
+ * @final since version 3.3.
+ */
+class FinalClass
+{
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/FinalMethod.php b/vendor/symfony/debug/Tests/Fixtures/FinalMethod.php
new file mode 100644
index 00000000..92ec4218
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/FinalMethod.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+class FinalMethod
+{
+ /**
+ * @final since version 3.3.
+ */
+ public function finalMethod()
+ {
+ }
+
+ public function anotherMethod()
+ {
+ }
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/InternalClass.php b/vendor/symfony/debug/Tests/Fixtures/InternalClass.php
new file mode 100644
index 00000000..119842c2
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/InternalClass.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+/**
+ * @internal since version 3.4.
+ */
+class InternalClass
+{
+ use InternalTrait2;
+
+ public function usedInInternalClass()
+ {
+ }
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/InternalInterface.php b/vendor/symfony/debug/Tests/Fixtures/InternalInterface.php
new file mode 100644
index 00000000..dd79f501
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/InternalInterface.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+/**
+ * @internal
+ */
+interface InternalInterface
+{
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/InternalTrait.php b/vendor/symfony/debug/Tests/Fixtures/InternalTrait.php
new file mode 100644
index 00000000..7bb4635c
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/InternalTrait.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+/**
+ * @internal
+ */
+trait InternalTrait
+{
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/InternalTrait2.php b/vendor/symfony/debug/Tests/Fixtures/InternalTrait2.php
new file mode 100644
index 00000000..05f18e83
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/InternalTrait2.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+/**
+ * @internal
+ */
+trait InternalTrait2
+{
+ /**
+ * @internal since version 3.4
+ */
+ public function internalMethod()
+ {
+ }
+
+ /**
+ * @internal but should not trigger a deprecation
+ */
+ public function usedInInternalClass()
+ {
+ }
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/NonDeprecatedInterface.php b/vendor/symfony/debug/Tests/Fixtures/NonDeprecatedInterface.php
new file mode 100644
index 00000000..a4179a57
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/NonDeprecatedInterface.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+interface NonDeprecatedInterface extends DeprecatedInterface
+{
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/PEARClass.php b/vendor/symfony/debug/Tests/Fixtures/PEARClass.php
new file mode 100644
index 00000000..39f22818
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/PEARClass.php
@@ -0,0 +1,5 @@
+<?php
+
+class Symfony_Component_Debug_Tests_Fixtures_PEARClass
+{
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/Throwing.php b/vendor/symfony/debug/Tests/Fixtures/Throwing.php
new file mode 100644
index 00000000..21e0aba1
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/Throwing.php
@@ -0,0 +1,3 @@
+<?php
+
+throw new \Exception('boo');
diff --git a/vendor/symfony/debug/Tests/Fixtures/ToStringThrower.php b/vendor/symfony/debug/Tests/Fixtures/ToStringThrower.php
new file mode 100644
index 00000000..40a5fb7f
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/ToStringThrower.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+class ToStringThrower
+{
+ private $exception;
+
+ public function __construct(\Exception $e)
+ {
+ $this->exception = $e;
+ }
+
+ public function __toString()
+ {
+ try {
+ throw $this->exception;
+ } catch (\Exception $e) {
+ // Using user_error() here is on purpose so we do not forget
+ // that this alias also should work alongside with trigger_error().
+ return user_error($e, E_USER_ERROR);
+ }
+ }
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/casemismatch.php b/vendor/symfony/debug/Tests/Fixtures/casemismatch.php
new file mode 100644
index 00000000..691d660f
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/casemismatch.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+class CaseMismatch
+{
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/notPsr0Bis.php b/vendor/symfony/debug/Tests/Fixtures/notPsr0Bis.php
new file mode 100644
index 00000000..4cf52671
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/notPsr0Bis.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+class NotPSR0bis
+{
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/psr4/Psr4CaseMismatch.php b/vendor/symfony/debug/Tests/Fixtures/psr4/Psr4CaseMismatch.php
new file mode 100644
index 00000000..ec48dd22
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/psr4/Psr4CaseMismatch.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+class PSR4CaseMismatch
+{
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures/reallyNotPsr0.php b/vendor/symfony/debug/Tests/Fixtures/reallyNotPsr0.php
new file mode 100644
index 00000000..8554725a
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures/reallyNotPsr0.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures;
+
+class NotPSR0
+{
+}
diff --git a/vendor/symfony/debug/Tests/Fixtures2/RequiredTwice.php b/vendor/symfony/debug/Tests/Fixtures2/RequiredTwice.php
new file mode 100644
index 00000000..604bc37f
--- /dev/null
+++ b/vendor/symfony/debug/Tests/Fixtures2/RequiredTwice.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace Symfony\Component\Debug\Tests\Fixtures2;
+
+class RequiredTwice
+{
+}
diff --git a/vendor/symfony/debug/Tests/HeaderMock.php b/vendor/symfony/debug/Tests/HeaderMock.php
new file mode 100644
index 00000000..65d0b588
--- /dev/null
+++ b/vendor/symfony/debug/Tests/HeaderMock.php
@@ -0,0 +1,38 @@
+<?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\Debug;
+
+function headers_sent()
+{
+ return false;
+}
+
+function header($str, $replace = true, $status = null)
+{
+ Tests\testHeader($str, $replace, $status);
+}
+
+namespace Symfony\Component\Debug\Tests;
+
+function testHeader()
+{
+ static $headers = array();
+
+ if (!$h = func_get_args()) {
+ $h = $headers;
+ $headers = array();
+
+ return $h;
+ }
+
+ $headers[] = func_get_args();
+}
diff --git a/vendor/symfony/debug/Tests/MockExceptionHandler.php b/vendor/symfony/debug/Tests/MockExceptionHandler.php
new file mode 100644
index 00000000..2d6ce564
--- /dev/null
+++ b/vendor/symfony/debug/Tests/MockExceptionHandler.php
@@ -0,0 +1,24 @@
+<?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\Debug\Tests;
+
+use Symfony\Component\Debug\ExceptionHandler;
+
+class MockExceptionHandler extends ExceptionHandler
+{
+ public $e;
+
+ public function handle(\Exception $e)
+ {
+ $this->e = $e;
+ }
+}
diff --git a/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt b/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt
new file mode 100644
index 00000000..877e208f
--- /dev/null
+++ b/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Test rethrowing in custom exception handler
+--FILE--
+<?php
+
+namespace Symfony\Component\Debug;
+
+$vendor = __DIR__;
+while (!file_exists($vendor.'/vendor')) {
+ $vendor = dirname($vendor);
+}
+require $vendor.'/vendor/autoload.php';
+
+if (true) {
+ class TestLogger extends \Psr\Log\AbstractLogger
+ {
+ public function log($level, $message, array $context = array())
+ {
+ echo $message, "\n";
+ }
+ }
+}
+
+set_exception_handler(function ($e) { echo 123; throw $e; });
+ErrorHandler::register()->setDefaultLogger(new TestLogger());
+ini_set('display_errors', 1);
+
+throw new \Exception('foo');
+
+?>
+--EXPECTF--
+Uncaught Exception: foo
+123
+Fatal error: Uncaught %s:25
+Stack trace:
+%a
diff --git a/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt b/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt
new file mode 100644
index 00000000..bd7b644d
--- /dev/null
+++ b/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt
@@ -0,0 +1,40 @@
+--TEST--
+Test catching fatal errors when handlers are nested
+--FILE--
+<?php
+
+namespace Symfony\Component\Debug;
+
+$vendor = __DIR__;
+while (!file_exists($vendor.'/vendor')) {
+ $vendor = dirname($vendor);
+}
+require $vendor.'/vendor/autoload.php';
+
+Debug::enable();
+ini_set('display_errors', 0);
+
+$eHandler = set_error_handler('var_dump');
+$xHandler = set_exception_handler('var_dump');
+
+var_dump(array(
+ $eHandler[0] === $xHandler[0] ? 'Error and exception handlers do match' : 'Error and exception handlers are different',
+));
+
+$eHandler[0]->setExceptionHandler('print_r');
+
+if (true) {
+ class Broken implements \Serializable {};
+}
+
+?>
+--EXPECTF--
+array(1) {
+ [0]=>
+ string(37) "Error and exception handlers do match"
+}
+object(Symfony\Component\Debug\Exception\FatalErrorException)#%d (%d) {
+ ["message":protected]=>
+ string(199) "Error: Class Symfony\Component\Debug\Broken contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Serializable::serialize, Serializable::unserialize)"
+%a
+}
diff --git a/vendor/symfony/debug/composer.json b/vendor/symfony/debug/composer.json
new file mode 100644
index 00000000..f98a5d07
--- /dev/null
+++ b/vendor/symfony/debug/composer.json
@@ -0,0 +1,40 @@
+{
+ "name": "symfony/debug",
+ "type": "library",
+ "description": "Symfony Debug Component",
+ "keywords": [],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": "^5.5.9|>=7.0.8",
+ "psr/log": "~1.0"
+ },
+ "conflict": {
+ "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
+ },
+ "require-dev": {
+ "symfony/http-kernel": "~2.8|~3.0|~4.0"
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Component\\Debug\\": "" },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4-dev"
+ }
+ }
+}
diff --git a/vendor/symfony/debug/phpunit.xml.dist b/vendor/symfony/debug/phpunit.xml.dist
new file mode 100644
index 00000000..12e58612
--- /dev/null
+++ b/vendor/symfony/debug/phpunit.xml.dist
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
+ backupGlobals="false"
+ colors="true"
+ bootstrap="vendor/autoload.php"
+ failOnRisky="true"
+ failOnWarning="true"
+>
+ <php>
+ <ini name="error_reporting" value="-1" />
+ </php>
+
+ <testsuites>
+ <testsuite name="Symfony Debug Component Test Suite">
+ <directory>./Tests/</directory>
+ </testsuite>
+ <testsuite name="Symfony Debug Extension Test Suite">
+ <directory suffix=".phpt">./Resources/ext/tests/</directory>
+ </testsuite>
+ </testsuites>
+
+ <filter>
+ <whitelist>
+ <directory>./</directory>
+ <exclude>
+ <directory>./Tests</directory>
+ <directory>./vendor</directory>
+ </exclude>
+ </whitelist>
+ </filter>
+</phpunit>