summaryrefslogtreecommitdiff
path: root/vendor/doctrine/common/lib
diff options
context:
space:
mode:
authorDevian <devianleong@gmail.com>2021-04-22 17:03:46 +0800
committerDevian <devianleong@gmail.com>2021-04-22 17:03:46 +0800
commit745cf2431a71d0e6c5f08f8605839279b2f7496e (patch)
tree11e4c7a19ac9f9efc1bb253b29b1fa488c34238e /vendor/doctrine/common/lib
Initiate commit
Diffstat (limited to 'vendor/doctrine/common/lib')
-rw-r--r--vendor/doctrine/common/lib/Doctrine/Common/ClassLoader.php289
-rw-r--r--vendor/doctrine/common/lib/Doctrine/Common/CommonException.php14
-rw-r--r--vendor/doctrine/common/lib/Doctrine/Common/Comparable.php26
-rw-r--r--vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php230
-rw-r--r--vendor/doctrine/common/lib/Doctrine/Common/Proxy/Autoloader.php100
-rw-r--r--vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/InvalidArgumentException.php113
-rw-r--r--vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/OutOfBoundsException.php28
-rw-r--r--vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/ProxyException.php12
-rw-r--r--vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/UnexpectedValueException.php74
-rw-r--r--vendor/doctrine/common/lib/Doctrine/Common/Proxy/Proxy.php65
-rw-r--r--vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyDefinition.php42
-rw-r--r--vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php1194
-rw-r--r--vendor/doctrine/common/lib/Doctrine/Common/Util/ClassUtils.php112
-rw-r--r--vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php185
14 files changed, 2484 insertions, 0 deletions
diff --git a/vendor/doctrine/common/lib/Doctrine/Common/ClassLoader.php b/vendor/doctrine/common/lib/Doctrine/Common/ClassLoader.php
new file mode 100644
index 0000000..2a53bad
--- /dev/null
+++ b/vendor/doctrine/common/lib/Doctrine/Common/ClassLoader.php
@@ -0,0 +1,289 @@
+<?php
+
+namespace Doctrine\Common;
+
+use function class_exists;
+use function interface_exists;
+use function is_array;
+use function is_file;
+use function reset;
+use function spl_autoload_functions;
+use function spl_autoload_register;
+use function spl_autoload_unregister;
+use function str_replace;
+use function stream_resolve_include_path;
+use function strpos;
+use function trait_exists;
+use function trigger_error;
+
+use const DIRECTORY_SEPARATOR;
+use const E_USER_DEPRECATED;
+
+@trigger_error(ClassLoader::class . ' is deprecated.', E_USER_DEPRECATED);
+
+/**
+ * A <tt>ClassLoader</tt> is an autoloader for class files that can be
+ * installed on the SPL autoload stack. It is a class loader that either loads only classes
+ * of a specific namespace or all namespaces and it is suitable for working together
+ * with other autoloaders in the SPL autoload stack.
+ *
+ * If no include path is configured through the constructor or {@link setIncludePath}, a ClassLoader
+ * relies on the PHP <code>include_path</code>.
+ *
+ * @deprecated The ClassLoader is deprecated and will be removed in version 4.0 of doctrine/common.
+ */
+class ClassLoader
+{
+ /**
+ * PHP file extension.
+ *
+ * @var string
+ */
+ protected $fileExtension = '.php';
+
+ /**
+ * Current namespace.
+ *
+ * @var string|null
+ */
+ protected $namespace;
+
+ /**
+ * Current include path.
+ *
+ * @var string|null
+ */
+ protected $includePath;
+
+ /**
+ * PHP namespace separator.
+ *
+ * @var string
+ */
+ protected $namespaceSeparator = '\\';
+
+ /**
+ * Creates a new <tt>ClassLoader</tt> that loads classes of the
+ * specified namespace from the specified include path.
+ *
+ * If no include path is given, the ClassLoader relies on the PHP include_path.
+ * If neither a namespace nor an include path is given, the ClassLoader will
+ * be responsible for loading all classes, thereby relying on the PHP include_path.
+ *
+ * @param string|null $ns The namespace of the classes to load.
+ * @param string|null $includePath The base include path to use.
+ */
+ public function __construct($ns = null, $includePath = null)
+ {
+ $this->namespace = $ns;
+ $this->includePath = $includePath;
+ }
+
+ /**
+ * Sets the namespace separator used by classes in the namespace of this ClassLoader.
+ *
+ * @param string $sep The separator to use.
+ *
+ * @return void
+ */
+ public function setNamespaceSeparator($sep)
+ {
+ $this->namespaceSeparator = $sep;
+ }
+
+ /**
+ * Gets the namespace separator used by classes in the namespace of this ClassLoader.
+ *
+ * @return string
+ */
+ public function getNamespaceSeparator()
+ {
+ return $this->namespaceSeparator;
+ }
+
+ /**
+ * Sets the base include path for all class files in the namespace of this ClassLoader.
+ *
+ * @param string|null $includePath
+ *
+ * @return void
+ */
+ public function setIncludePath($includePath)
+ {
+ $this->includePath = $includePath;
+ }
+
+ /**
+ * Gets the base include path for all class files in the namespace of this ClassLoader.
+ *
+ * @return string|null
+ */
+ public function getIncludePath()
+ {
+ return $this->includePath;
+ }
+
+ /**
+ * Sets the file extension of class files in the namespace of this ClassLoader.
+ *
+ * @param string $fileExtension
+ *
+ * @return void
+ */
+ public function setFileExtension($fileExtension)
+ {
+ $this->fileExtension = $fileExtension;
+ }
+
+ /**
+ * Gets the file extension of class files in the namespace of this ClassLoader.
+ *
+ * @return string
+ */
+ public function getFileExtension()
+ {
+ return $this->fileExtension;
+ }
+
+ /**
+ * Registers this ClassLoader on the SPL autoload stack.
+ *
+ * @return void
+ */
+ public function register()
+ {
+ spl_autoload_register([$this, 'loadClass']);
+ }
+
+ /**
+ * Removes this ClassLoader from the SPL autoload stack.
+ *
+ * @return void
+ */
+ public function unregister()
+ {
+ spl_autoload_unregister([$this, 'loadClass']);
+ }
+
+ /**
+ * Loads the given class or interface.
+ *
+ * @param string $className The name of the class to load.
+ *
+ * @return bool TRUE if the class has been successfully loaded, FALSE otherwise.
+ *
+ * @psalm-param class-string $className
+ */
+ public function loadClass($className)
+ {
+ if (self::typeExists($className)) {
+ return true;
+ }
+
+ if (! $this->canLoadClass($className)) {
+ return false;
+ }
+
+ require($this->includePath !== null ? $this->includePath . DIRECTORY_SEPARATOR : '')
+ . str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className)
+ . $this->fileExtension;
+
+ return self::typeExists($className);
+ }
+
+ /**
+ * Asks this ClassLoader whether it can potentially load the class (file) with
+ * the given name.
+ *
+ * @param string $className The fully-qualified name of the class.
+ *
+ * @return bool TRUE if this ClassLoader can load the class, FALSE otherwise.
+ *
+ * @psalm-param class-string $className
+ */
+ public function canLoadClass($className)
+ {
+ if ($this->namespace !== null && strpos($className, $this->namespace . $this->namespaceSeparator) !== 0) {
+ return false;
+ }
+
+ $file = str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className) . $this->fileExtension;
+
+ if ($this->includePath !== null) {
+ return is_file($this->includePath . DIRECTORY_SEPARATOR . $file);
+ }
+
+ return stream_resolve_include_path($file) !== false;
+ }
+
+ /**
+ * Checks whether a class with a given name exists. A class "exists" if it is either
+ * already defined in the current request or if there is an autoloader on the SPL
+ * autoload stack that is a) responsible for the class in question and b) is able to
+ * load a class file in which the class definition resides.
+ *
+ * If the class is not already defined, each autoloader in the SPL autoload stack
+ * is asked whether it is able to tell if the class exists. If the autoloader is
+ * a <tt>ClassLoader</tt>, {@link canLoadClass} is used, otherwise the autoload
+ * function of the autoloader is invoked and expected to return a value that
+ * evaluates to TRUE if the class (file) exists. As soon as one autoloader reports
+ * that the class exists, TRUE is returned.
+ *
+ * Note that, depending on what kinds of autoloaders are installed on the SPL
+ * autoload stack, the class (file) might already be loaded as a result of checking
+ * for its existence. This is not the case with a <tt>ClassLoader</tt>, who separates
+ * these responsibilities.
+ *
+ * @param string $className The fully-qualified name of the class.
+ *
+ * @return bool TRUE if the class exists as per the definition given above, FALSE otherwise.
+ *
+ * @psalm-param class-string $className
+ */
+ public static function classExists($className)
+ {
+ return self::typeExists($className, true);
+ }
+
+ /**
+ * Gets the <tt>ClassLoader</tt> from the SPL autoload stack that is responsible
+ * for (and is able to load) the class with the given name.
+ *
+ * @param string $className The name of the class.
+ *
+ * @return ClassLoader|null The <tt>ClassLoader</tt> for the class or NULL if no such <tt>ClassLoader</tt> exists.
+ *
+ * @psalm-param class-string $className
+ */
+ public static function getClassLoader($className)
+ {
+ foreach (spl_autoload_functions() as $loader) {
+ if (! is_array($loader)) {
+ continue;
+ }
+
+ $classLoader = reset($loader);
+
+ if ($classLoader instanceof ClassLoader && $classLoader->canLoadClass($className)) {
+ return $classLoader;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Checks whether a given type exists
+ *
+ * @param string $type
+ * @param bool $autoload
+ *
+ * @return bool
+ */
+ private static function typeExists($type, $autoload = false)
+ {
+ return class_exists($type, $autoload)
+ || interface_exists($type, $autoload)
+ || trait_exists($type, $autoload);
+ }
+}
diff --git a/vendor/doctrine/common/lib/Doctrine/Common/CommonException.php b/vendor/doctrine/common/lib/Doctrine/Common/CommonException.php
new file mode 100644
index 0000000..a2aba0e
--- /dev/null
+++ b/vendor/doctrine/common/lib/Doctrine/Common/CommonException.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Doctrine\Common;
+
+use Exception;
+
+/**
+ * Base exception class for package Doctrine\Common.
+ *
+ * @deprecated The doctrine/common package is deprecated, please use specific packages and their exceptions instead.
+ */
+class CommonException extends Exception
+{
+}
diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Comparable.php b/vendor/doctrine/common/lib/Doctrine/Common/Comparable.php
new file mode 100644
index 0000000..f9ac4be
--- /dev/null
+++ b/vendor/doctrine/common/lib/Doctrine/Common/Comparable.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Doctrine\Common;
+
+/**
+ * Comparable interface that allows to compare two value objects to each other for similarity.
+ *
+ * @link www.doctrine-project.org
+ */
+interface Comparable
+{
+ /**
+ * Compares the current object to the passed $other.
+ *
+ * Returns 0 if they are semantically equal, 1 if the other object
+ * is less than the current one, or -1 if its more than the current one.
+ *
+ * This method should not check for identity using ===, only for semantical equality for example
+ * when two different DateTime instances point to the exact same Date + TZ.
+ *
+ * @param mixed $other
+ *
+ * @return int
+ */
+ public function compareTo($other);
+}
diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php
new file mode 100644
index 0000000..a7af281
--- /dev/null
+++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php
@@ -0,0 +1,230 @@
+<?php
+
+namespace Doctrine\Common\Proxy;
+
+use Doctrine\Common\Proxy\Exception\InvalidArgumentException;
+use Doctrine\Common\Proxy\Exception\OutOfBoundsException;
+use Doctrine\Common\Util\ClassUtils;
+use Doctrine\Persistence\Mapping\ClassMetadata;
+use Doctrine\Persistence\Mapping\ClassMetadataFactory;
+
+use function class_exists;
+use function file_exists;
+use function in_array;
+use function interface_exists;
+
+/**
+ * Abstract factory for proxy objects.
+ */
+abstract class AbstractProxyFactory
+{
+ /**
+ * Never autogenerate a proxy and rely that it was generated by some
+ * process before deployment.
+ */
+ public const AUTOGENERATE_NEVER = 0;
+
+ /**
+ * Always generates a new proxy in every request.
+ *
+ * This is only sane during development.
+ */
+ public const AUTOGENERATE_ALWAYS = 1;
+
+ /**
+ * Autogenerate the proxy class when the proxy file does not exist.
+ *
+ * This strategy causes a file exists call whenever any proxy is used the
+ * first time in a request.
+ */
+ public const AUTOGENERATE_FILE_NOT_EXISTS = 2;
+
+ /**
+ * Generate the proxy classes using eval().
+ *
+ * This strategy is only sane for development, and even then it gives me
+ * the creeps a little.
+ */
+ public const AUTOGENERATE_EVAL = 3;
+
+ private const AUTOGENERATE_MODES = [
+ self::AUTOGENERATE_NEVER,
+ self::AUTOGENERATE_ALWAYS,
+ self::AUTOGENERATE_FILE_NOT_EXISTS,
+ self::AUTOGENERATE_EVAL,
+ ];
+
+ /** @var ClassMetadataFactory */
+ private $metadataFactory;
+
+ /** @var ProxyGenerator the proxy generator responsible for creating the proxy classes/files. */
+ private $proxyGenerator;
+
+ /** @var int Whether to automatically (re)generate proxy classes. */
+ private $autoGenerate;
+
+ /** @var ProxyDefinition[] */
+ private $definitions = [];
+
+ /**
+ * @param bool|int $autoGenerate
+ *
+ * @throws InvalidArgumentException When auto generate mode is not valid.
+ */
+ public function __construct(ProxyGenerator $proxyGenerator, ClassMetadataFactory $metadataFactory, $autoGenerate)
+ {
+ $this->proxyGenerator = $proxyGenerator;
+ $this->metadataFactory = $metadataFactory;
+ $this->autoGenerate = (int) $autoGenerate;
+
+ if (! in_array($this->autoGenerate, self::AUTOGENERATE_MODES, true)) {
+ throw InvalidArgumentException::invalidAutoGenerateMode($autoGenerate);
+ }
+ }
+
+ /**
+ * Gets a reference proxy instance for the entity of the given type and identified by
+ * the given identifier.
+ *
+ * @param string $className
+ * @param array<mixed> $identifier
+ *
+ * @return Proxy
+ *
+ * @throws OutOfBoundsException
+ */
+ public function getProxy($className, array $identifier)
+ {
+ $definition = $this->definitions[$className] ?? $this->getProxyDefinition($className);
+ $fqcn = $definition->proxyClassName;
+ $proxy = new $fqcn($definition->initializer, $definition->cloner);
+
+ foreach ($definition->identifierFields as $idField) {
+ if (! isset($identifier[$idField])) {
+ throw OutOfBoundsException::missingPrimaryKeyValue($className, $idField);
+ }
+
+ $definition->reflectionFields[$idField]->setValue($proxy, $identifier[$idField]);
+ }
+
+ return $proxy;
+ }
+
+ /**
+ * Generates proxy classes for all given classes.
+ *
+ * @param ClassMetadata[] $classes The classes (ClassMetadata instances)
+ * for which to generate proxies.
+ * @param string $proxyDir The target directory of the proxy classes. If not specified, the
+ * directory configured on the Configuration of the EntityManager used
+ * by this factory is used.
+ *
+ * @return int Number of generated proxies.
+ */
+ public function generateProxyClasses(array $classes, $proxyDir = null)
+ {
+ $generated = 0;
+
+ foreach ($classes as $class) {
+ if ($this->skipClass($class)) {
+ continue;
+ }
+
+ $proxyFileName = $this->proxyGenerator->getProxyFileName($class->getName(), $proxyDir);
+
+ $this->proxyGenerator->generateProxyClass($class, $proxyFileName);
+
+ $generated += 1;
+ }
+
+ return $generated;
+ }
+
+ /**
+ * Reset initialization/cloning logic for an un-initialized proxy
+ *
+ * @return Proxy
+ *
+ * @throws InvalidArgumentException
+ */
+ public function resetUninitializedProxy(Proxy $proxy)
+ {
+ if ($proxy->__isInitialized()) {
+ throw InvalidArgumentException::unitializedProxyExpected($proxy);
+ }
+
+ $className = ClassUtils::getClass($proxy);
+ $definition = $this->definitions[$className] ?? $this->getProxyDefinition($className);
+
+ $proxy->__setInitializer($definition->initializer);
+ $proxy->__setCloner($definition->cloner);
+
+ return $proxy;
+ }
+
+ /**
+ * Get a proxy definition for the given class name.
+ *
+ * @param string $className
+ *
+ * @return ProxyDefinition
+ *
+ * @psalm-param class-string $className
+ */
+ private function getProxyDefinition($className)
+ {
+ $classMetadata = $this->metadataFactory->getMetadataFor($className);
+ $className = $classMetadata->getName(); // aliases and case sensitivity
+
+ $this->definitions[$className] = $this->createProxyDefinition($className);
+ $proxyClassName = $this->definitions[$className]->proxyClassName;
+
+ if (! class_exists($proxyClassName, false)) {
+ $fileName = $this->proxyGenerator->getProxyFileName($className);
+
+ switch ($this->autoGenerate) {
+ case self::AUTOGENERATE_NEVER:
+ require $fileName;
+ break;
+
+ case self::AUTOGENERATE_FILE_NOT_EXISTS:
+ if (! file_exists($fileName)) {
+ $this->proxyGenerator->generateProxyClass($classMetadata, $fileName);
+ }
+
+ require $fileName;
+ break;
+
+ case self::AUTOGENERATE_ALWAYS:
+ $this->proxyGenerator->generateProxyClass($classMetadata, $fileName);
+ require $fileName;
+ break;
+
+ case self::AUTOGENERATE_EVAL:
+ $this->proxyGenerator->generateProxyClass($classMetadata, false);
+ break;
+ }
+ }
+
+ return $this->definitions[$className];
+ }
+
+ /**
+ * Determine if this class should be skipped during proxy generation.
+ *
+ * @return bool
+ */
+ abstract protected function skipClass(ClassMetadata $metadata);
+
+ /**
+ * @param string $className
+ *
+ * @return ProxyDefinition
+ *
+ * @psalm-param class-string $className
+ */
+ abstract protected function createProxyDefinition($className);
+}
+
+interface_exists(ClassMetadata::class);
+interface_exists(ClassMetadataFactory::class);
diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Autoloader.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Autoloader.php
new file mode 100644
index 0000000..58d221a
--- /dev/null
+++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Autoloader.php
@@ -0,0 +1,100 @@
+<?php
+
+namespace Doctrine\Common\Proxy;
+
+use Closure;
+use Doctrine\Common\Proxy\Exception\InvalidArgumentException;
+
+use function call_user_func;
+use function file_exists;
+use function is_callable;
+use function ltrim;
+use function spl_autoload_register;
+use function str_replace;
+use function strlen;
+use function strpos;
+use function substr;
+
+use const DIRECTORY_SEPARATOR;
+
+/**
+ * Special Autoloader for Proxy classes, which are not PSR-0 compliant.
+ *
+ * @internal
+ */
+class Autoloader
+{
+ /**
+ * Resolves proxy class name to a filename based on the following pattern.
+ *
+ * 1. Remove Proxy namespace from class name.
+ * 2. Remove namespace separators from remaining class name.
+ * 3. Return PHP filename from proxy-dir with the result from 2.
+ *
+ * @param string $proxyDir
+ * @param string $proxyNamespace
+ * @param string $className
+ *
+ * @return string
+ *
+ * @throws InvalidArgumentException
+ *
+ * @psalm-param class-string $className
+ */
+ public static function resolveFile($proxyDir, $proxyNamespace, $className)
+ {
+ if (strpos($className, $proxyNamespace) !== 0) {
+ throw InvalidArgumentException::notProxyClass($className, $proxyNamespace);
+ }
+
+ // remove proxy namespace from class name
+ $classNameRelativeToProxyNamespace = substr($className, strlen($proxyNamespace));
+
+ // remove namespace separators from remaining class name
+ $fileName = str_replace('\\', '', $classNameRelativeToProxyNamespace);
+
+ return $proxyDir . DIRECTORY_SEPARATOR . $fileName . '.php';
+ }
+
+ /**
+ * Registers and returns autoloader callback for the given proxy dir and namespace.
+ *
+ * @param string $proxyDir
+ * @param string $proxyNamespace
+ * @param callable|null $notFoundCallback Invoked when the proxy file is not found.
+ *
+ * @return Closure
+ *
+ * @throws InvalidArgumentException
+ */
+ public static function register($proxyDir, $proxyNamespace, $notFoundCallback = null)
+ {
+ $proxyNamespace = ltrim($proxyNamespace, '\\');
+
+ if ($notFoundCallback !== null && ! is_callable($notFoundCallback)) {
+ throw InvalidArgumentException::invalidClassNotFoundCallback($notFoundCallback);
+ }
+
+ $autoloader = static function ($className) use ($proxyDir, $proxyNamespace, $notFoundCallback) {
+ if ($proxyNamespace === '') {
+ return;
+ }
+
+ if (strpos($className, $proxyNamespace) !== 0) {
+ return;
+ }
+
+ $file = Autoloader::resolveFile($proxyDir, $proxyNamespace, $className);
+
+ if ($notFoundCallback && ! file_exists($file)) {
+ call_user_func($notFoundCallback, $proxyDir, $proxyNamespace, $className);
+ }
+
+ require $file;
+ };
+
+ spl_autoload_register($autoloader);
+
+ return $autoloader;
+ }
+}
diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/InvalidArgumentException.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000..db92809
--- /dev/null
+++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/InvalidArgumentException.php
@@ -0,0 +1,113 @@
+<?php
+
+namespace Doctrine\Common\Proxy\Exception;
+
+use Doctrine\Persistence\Proxy;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+use function get_class;
+use function gettype;
+use function interface_exists;
+use function is_object;
+use function sprintf;
+
+/**
+ * Proxy Invalid Argument Exception.
+ *
+ * @link www.doctrine-project.org
+ */
+class InvalidArgumentException extends BaseInvalidArgumentException implements ProxyException
+{
+ /**
+ * @return self
+ */
+ public static function proxyDirectoryRequired()
+ {
+ return new self('You must configure a proxy directory. See docs for details');
+ }
+
+ /**
+ * @param string $className
+ * @param string $proxyNamespace
+ *
+ * @return self
+ *
+ * @psalm-param class-string $className
+ */
+ public static function notProxyClass($className, $proxyNamespace)
+ {
+ return new self(sprintf('The class "%s" is not part of the proxy namespace "%s"', $className, $proxyNamespace));
+ }
+
+ /**
+ * @param string $name
+ *
+ * @return self
+ */
+ public static function invalidPlaceholder($name)
+ {
+ return new self(sprintf('Provided placeholder for "%s" must be either a string or a valid callable', $name));
+ }
+
+ /**
+ * @return self
+ */
+ public static function proxyNamespaceRequired()
+ {
+ return new self('You must configure a proxy namespace');
+ }
+
+ /**
+ * @return self
+ */
+ public static function unitializedProxyExpected(Proxy $proxy)
+ {
+ return new self(sprintf('Provided proxy of type "%s" must not be initialized.', get_class($proxy)));
+ }
+
+ /**
+ * @param mixed $callback
+ *
+ * @return self
+ */
+ public static function invalidClassNotFoundCallback($callback)
+ {
+ $type = is_object($callback) ? get_class($callback) : gettype($callback);
+
+ return new self(sprintf('Invalid \$notFoundCallback given: must be a callable, "%s" given', $type));
+ }
+
+ /**
+ * @param string $className
+ *
+ * @return self
+ *
+ * @psalm-param class-string $className
+ */
+ public static function classMustNotBeAbstract($className)
+ {
+ return new self(sprintf('Unable to create a proxy for an abstract class "%s".', $className));
+ }
+
+ /**
+ * @param string $className
+ *
+ * @return self
+ *
+ * @psalm-param class-string $className
+ */
+ public static function classMustNotBeFinal($className)
+ {
+ return new self(sprintf('Unable to create a proxy for a final class "%s".', $className));
+ }
+
+ /**
+ * @param mixed $value
+ */
+ public static function invalidAutoGenerateMode($value): self
+ {
+ return new self(sprintf('Invalid auto generate mode "%s" given.', $value));
+ }
+}
+
+interface_exists(Proxy::class);
diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/OutOfBoundsException.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/OutOfBoundsException.php
new file mode 100644
index 0000000..b9fde45
--- /dev/null
+++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/OutOfBoundsException.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Doctrine\Common\Proxy\Exception;
+
+use OutOfBoundsException as BaseOutOfBoundsException;
+
+use function sprintf;
+
+/**
+ * Proxy Invalid Argument Exception.
+ *
+ * @link www.doctrine-project.org
+ */
+class OutOfBoundsException extends BaseOutOfBoundsException implements ProxyException
+{
+ /**
+ * @param string $className
+ * @param string $idField
+ *
+ * @return self
+ *
+ * @psalm-param class-string $className
+ */
+ public static function missingPrimaryKeyValue($className, $idField)
+ {
+ return new self(sprintf('Missing value for primary key %s on %s', $idField, $className));
+ }
+}
diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/ProxyException.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/ProxyException.php
new file mode 100644
index 0000000..f827fbd
--- /dev/null
+++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/ProxyException.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace Doctrine\Common\Proxy\Exception;
+
+/**
+ * Base exception interface for proxy exceptions.
+ *
+ * @link www.doctrine-project.org
+ */
+interface ProxyException
+{
+}
diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/UnexpectedValueException.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/UnexpectedValueException.php
new file mode 100644
index 0000000..9f85a1a
--- /dev/null
+++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/UnexpectedValueException.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace Doctrine\Common\Proxy\Exception;
+
+use Throwable;
+use UnexpectedValueException as BaseUnexpectedValueException;
+
+use function sprintf;
+
+/**
+ * Proxy Unexpected Value Exception.
+ *
+ * @link www.doctrine-project.org
+ */
+class UnexpectedValueException extends BaseUnexpectedValueException implements ProxyException
+{
+ /**
+ * @param string $proxyDirectory
+ *
+ * @return self
+ */
+ public static function proxyDirectoryNotWritable($proxyDirectory)
+ {
+ return new self(sprintf('Your proxy directory "%s" must be writable', $proxyDirectory));
+ }
+
+ /**
+ * @param string $className
+ * @param string $methodName
+ * @param string $parameterName
+ *
+ * @return self
+ *
+ * @psalm-param class-string $className
+ */
+ public static function invalidParameterTypeHint(
+ $className,
+ $methodName,
+ $parameterName,
+ ?Throwable $previous = null
+ ) {
+ return new self(
+ sprintf(
+ 'The type hint of parameter "%s" in method "%s" in class "%s" is invalid.',
+ $parameterName,
+ $methodName,
+ $className
+ ),
+ 0,
+ $previous
+ );
+ }
+
+ /**
+ * @param string $className
+ * @param string $methodName
+ *
+ * @return self
+ *
+ * @psalm-param class-string $className
+ */
+ public static function invalidReturnTypeHint($className, $methodName, ?Throwable $previous = null)
+ {
+ return new self(
+ sprintf(
+ 'The return type of method "%s" in class "%s" is invalid.',
+ $methodName,
+ $className
+ ),
+ 0,
+ $previous
+ );
+ }
+}
diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Proxy.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Proxy.php
new file mode 100644
index 0000000..93f144a
--- /dev/null
+++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Proxy.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace Doctrine\Common\Proxy;
+
+use Closure;
+use Doctrine\Persistence\Proxy as BaseProxy;
+
+/**
+ * Interface for proxy classes.
+ */
+interface Proxy extends BaseProxy
+{
+ /**
+ * Marks the proxy as initialized or not.
+ *
+ * @param bool $initialized
+ *
+ * @return void
+ */
+ public function __setInitialized($initialized);
+
+ /**
+ * Sets the initializer callback to be used when initializing the proxy. That
+ * initializer should accept 3 parameters: $proxy, $method and $params. Those
+ * are respectively the proxy object that is being initialized, the method name
+ * that triggered initialization and the parameters passed to that method.
+ *
+ * @return void
+ */
+ public function __setInitializer(?Closure $initializer = null);
+
+ /**
+ * Retrieves the initializer callback used to initialize the proxy.
+ *
+ * @see __setInitializer
+ *
+ * @return Closure|null
+ */
+ public function __getInitializer();
+
+ /**
+ * Sets the callback to be used when cloning the proxy. That initializer should accept
+ * a single parameter, which is the cloned proxy instance itself.
+ *
+ * @return void
+ */
+ public function __setCloner(?Closure $cloner = null);
+
+ /**
+ * Retrieves the callback to be used when cloning the proxy.
+ *
+ * @see __setCloner
+ *
+ * @return Closure|null
+ */
+ public function __getCloner();
+
+ /**
+ * Retrieves the list of lazy loaded properties for a given proxy
+ *
+ * @return array<string, mixed> Keys are the property names, and values are the default values
+ * for those properties.
+ */
+ public function __getLazyProperties();
+}
diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyDefinition.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyDefinition.php
new file mode 100644
index 0000000..a7f3957
--- /dev/null
+++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyDefinition.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace Doctrine\Common\Proxy;
+
+use ReflectionProperty;
+
+/**
+ * Definition structure how to create a proxy.
+ */
+class ProxyDefinition
+{
+ /** @var string */
+ public $proxyClassName;
+
+ /** @var array<string> */
+ public $identifierFields;
+
+ /** @var ReflectionProperty[] */
+ public $reflectionFields;
+
+ /** @var callable */
+ public $initializer;
+
+ /** @var callable */
+ public $cloner;
+
+ /**
+ * @param string $proxyClassName
+ * @param array<string> $identifierFields
+ * @param array<string, ReflectionProperty> $reflectionFields
+ * @param callable $initializer
+ * @param callable $cloner
+ */
+ public function __construct($proxyClassName, array $identifierFields, array $reflectionFields, $initializer, $cloner)
+ {
+ $this->proxyClassName = $proxyClassName;
+ $this->identifierFields = $identifierFields;
+ $this->reflectionFields = $reflectionFields;
+ $this->initializer = $initializer;
+ $this->cloner = $cloner;
+ }
+}
diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php
new file mode 100644
index 0000000..5504078
--- /dev/null
+++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php
@@ -0,0 +1,1194 @@
+<?php
+
+namespace Doctrine\Common\Proxy;
+
+use Doctrine\Common\Proxy\Exception\InvalidArgumentException;
+use Doctrine\Common\Proxy\Exception\UnexpectedValueException;
+use Doctrine\Common\Util\ClassUtils;
+use Doctrine\Persistence\Mapping\ClassMetadata;
+use ReflectionMethod;
+use ReflectionNamedType;
+use ReflectionParameter;
+use ReflectionProperty;
+use ReflectionType;
+use ReflectionUnionType;
+
+use function array_combine;
+use function array_diff;
+use function array_key_exists;
+use function array_map;
+use function array_slice;
+use function assert;
+use function call_user_func;
+use function chmod;
+use function class_exists;
+use function dirname;
+use function explode;
+use function file;
+use function file_put_contents;
+use function implode;
+use function in_array;
+use function interface_exists;
+use function is_callable;
+use function is_dir;
+use function is_string;
+use function is_writable;
+use function lcfirst;
+use function ltrim;
+use function method_exists;
+use function mkdir;
+use function preg_match;
+use function preg_match_all;
+use function rename;
+use function rtrim;
+use function sprintf;
+use function str_replace;
+use function strrev;
+use function strtolower;
+use function strtr;
+use function substr;
+use function trim;
+use function uniqid;
+use function var_export;
+
+use const DIRECTORY_SEPARATOR;
+
+/**
+ * This factory is used to generate proxy classes.
+ * It builds proxies from given parameters, a template and class metadata.
+ */
+class ProxyGenerator
+{
+ /**
+ * Used to match very simple id methods that don't need
+ * to be decorated since the identifier is known.
+ */
+ public const PATTERN_MATCH_ID_METHOD = '((public\s+)?(function\s+%s\s*\(\)\s*)\s*(?::\s*\??\s*\\\\?[a-z_\x7f-\xff][\w\x7f-\xff]*(?:\\\\[a-z_\x7f-\xff][\w\x7f-\xff]*)*\s*)?{\s*return\s*\$this->%s;\s*})i';
+
+ /**
+ * The namespace that contains all proxy classes.
+ *
+ * @var string
+ */
+ private $proxyNamespace;
+
+ /**
+ * The directory that contains all proxy classes.
+ *
+ * @var string
+ */
+ private $proxyDirectory;
+
+ /**
+ * Map of callables used to fill in placeholders set in the template.
+ *
+ * @var string[]|callable[]
+ */
+ protected $placeholders = [
+ 'baseProxyInterface' => Proxy::class,
+ 'additionalProperties' => '',
+ ];
+
+ /**
+ * Template used as a blueprint to generate proxies.
+ *
+ * @var string
+ */
+ protected $proxyClassTemplate = '<?php
+
+namespace <namespace>;
+
+/**
+ * DO NOT EDIT THIS FILE - IT WAS CREATED BY DOCTRINE\'S PROXY GENERATOR
+ */
+class <proxyShortClassName> extends \<className> implements \<baseProxyInterface>
+{
+ /**
+ * @var \Closure the callback responsible for loading properties in the proxy object. This callback is called with
+ * three parameters, being respectively the proxy object to be initialized, the method that triggered the
+ * initialization process and an array of ordered parameters that were passed to that method.
+ *
+ * @see \Doctrine\Common\Proxy\Proxy::__setInitializer
+ */
+ public $__initializer__;
+
+ /**
+ * @var \Closure the callback responsible of loading properties that need to be copied in the cloned object
+ *
+ * @see \Doctrine\Common\Proxy\Proxy::__setCloner
+ */
+ public $__cloner__;
+
+ /**
+ * @var boolean flag indicating if this object was already initialized
+ *
+ * @see \Doctrine\Persistence\Proxy::__isInitialized
+ */
+ public $__isInitialized__ = false;
+
+ /**
+ * @var array<string, null> properties to be lazy loaded, indexed by property name
+ */
+ public static $lazyPropertiesNames = <lazyPropertiesNames>;
+
+ /**
+ * @var array<string, mixed> default values of properties to be lazy loaded, with keys being the property names
+ *
+ * @see \Doctrine\Common\Proxy\Proxy::__getLazyProperties
+ */
+ public static $lazyPropertiesDefaults = <lazyPropertiesDefaults>;
+
+<additionalProperties>
+
+<constructorImpl>
+
+<magicGet>
+
+<magicSet>
+
+<magicIsset>
+
+<sleepImpl>
+
+<wakeupImpl>
+
+<cloneImpl>
+
+ /**
+ * Forces initialization of the proxy
+ */
+ public function __load()
+ {
+ $this->__initializer__ && $this->__initializer__->__invoke($this, \'__load\', []);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @internal generated method: use only when explicitly handling proxy specific loading logic
+ */
+ public function __isInitialized()
+ {
+ return $this->__isInitialized__;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @internal generated method: use only when explicitly handling proxy specific loading logic
+ */
+ public function __setInitialized($initialized)
+ {
+ $this->__isInitialized__ = $initialized;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @internal generated method: use only when explicitly handling proxy specific loading logic
+ */
+ public function __setInitializer(\Closure $initializer = null)
+ {
+ $this->__initializer__ = $initializer;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @internal generated method: use only when explicitly handling proxy specific loading logic
+ */
+ public function __getInitializer()
+ {
+ return $this->__initializer__;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @internal generated method: use only when explicitly handling proxy specific loading logic
+ */
+ public function __setCloner(\Closure $cloner = null)
+ {
+ $this->__cloner__ = $cloner;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @internal generated method: use only when explicitly handling proxy specific cloning logic
+ */
+ public function __getCloner()
+ {
+ return $this->__cloner__;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @internal generated method: use only when explicitly handling proxy specific loading logic
+ * @deprecated no longer in use - generated code now relies on internal components rather than generated public API
+ * @static
+ */
+ public function __getLazyProperties()
+ {
+ return self::$lazyPropertiesDefaults;
+ }
+
+ <methods>
+}
+';
+
+ /**
+ * Initializes a new instance of the <tt>ProxyFactory</tt> class that is
+ * connected to the given <tt>EntityManager</tt>.
+ *
+ * @param string $proxyDirectory The directory to use for the proxy classes. It must exist.
+ * @param string $proxyNamespace The namespace to use for the proxy classes.
+ *
+ * @throws InvalidArgumentException
+ */
+ public function __construct($proxyDirectory, $proxyNamespace)
+ {
+ if (! $proxyDirectory) {
+ throw InvalidArgumentException::proxyDirectoryRequired();
+ }
+
+ if (! $proxyNamespace) {
+ throw InvalidArgumentException::proxyNamespaceRequired();
+ }
+
+ $this->proxyDirectory = $proxyDirectory;
+ $this->proxyNamespace = $proxyNamespace;
+ }
+
+ /**
+ * Sets a placeholder to be replaced in the template.
+ *
+ * @param string $name
+ * @param string|callable $placeholder
+ *
+ * @throws InvalidArgumentException
+ */
+ public function setPlaceholder($name, $placeholder)
+ {
+ if (! is_string($placeholder) && ! is_callable($placeholder)) {
+ throw InvalidArgumentException::invalidPlaceholder($name);
+ }
+
+ $this->placeholders[$name] = $placeholder;
+ }
+
+ /**
+ * Sets the base template used to create proxy classes.
+ *
+ * @param string $proxyClassTemplate
+ */
+ public function setProxyClassTemplate($proxyClassTemplate)
+ {
+ $this->proxyClassTemplate = (string) $proxyClassTemplate;
+ }
+
+ /**
+ * Generates a proxy class file.
+ *
+ * @param ClassMetadata $class Metadata for the original class.
+ * @param string|bool $fileName Filename (full path) for the generated class. If none is given, eval() is used.
+ *
+ * @throws InvalidArgumentException
+ * @throws UnexpectedValueException
+ */
+ public function generateProxyClass(ClassMetadata $class, $fileName = false)
+ {
+ $this->verifyClassCanBeProxied($class);
+
+ preg_match_all('(<([a-zA-Z]+)>)', $this->proxyClassTemplate, $placeholderMatches);
+
+ $placeholderMatches = array_combine($placeholderMatches[0], $placeholderMatches[1]);
+ $placeholders = [];
+
+ foreach ($placeholderMatches as $placeholder => $name) {
+ $placeholders[$placeholder] = $this->placeholders[$name] ?? [$this, 'generate' . $name];
+ }
+
+ foreach ($placeholders as & $placeholder) {
+ if (! is_callable($placeholder)) {
+ continue;
+ }
+
+ $placeholder = call_user_func($placeholder, $class);
+ }
+
+ $proxyCode = strtr($this->proxyClassTemplate, $placeholders);
+
+ if (! $fileName) {
+ $proxyClassName = $this->generateNamespace($class) . '\\' . $this->generateProxyShortClassName($class);
+
+ if (! class_exists($proxyClassName)) {
+ eval(substr($proxyCode, 5));
+ }
+
+ return;
+ }
+
+ $parentDirectory = dirname($fileName);
+
+ if (! is_dir($parentDirectory) && (@mkdir($parentDirectory, 0775, true) === false)) {
+ throw UnexpectedValueException::proxyDirectoryNotWritable($this->proxyDirectory);
+ }
+
+ if (! is_writable($parentDirectory)) {
+ throw UnexpectedValueException::proxyDirectoryNotWritable($this->proxyDirectory);
+ }
+
+ $tmpFileName = $fileName . '.' . uniqid('', true);
+
+ file_put_contents($tmpFileName, $proxyCode);
+ @chmod($tmpFileName, 0664);
+ rename($tmpFileName, $fileName);
+ }
+
+ /**
+ * @throws InvalidArgumentException
+ */
+ private function verifyClassCanBeProxied(ClassMetadata $class)
+ {
+ if ($class->getReflectionClass()->isFinal()) {
+ throw InvalidArgumentException::classMustNotBeFinal($class->getName());
+ }
+
+ if ($class->getReflectionClass()->isAbstract()) {
+ throw InvalidArgumentException::classMustNotBeAbstract($class->getName());
+ }
+ }
+
+ /**
+ * Generates the proxy short class name to be used in the template.
+ *
+ * @return string
+ */
+ private function generateProxyShortClassName(ClassMetadata $class)
+ {
+ $proxyClassName = ClassUtils::generateProxyClassName($class->getName(), $this->proxyNamespace);
+ $parts = explode('\\', strrev($proxyClassName), 2);
+
+ return strrev($parts[0]);
+ }
+
+ /**
+ * Generates the proxy namespace.
+ *
+ * @return string
+ */
+ private function generateNamespace(ClassMetadata $class)
+ {
+ $proxyClassName = ClassUtils::generateProxyClassName($class->getName(), $this->proxyNamespace);
+ $parts = explode('\\', strrev($proxyClassName), 2);
+
+ return strrev($parts[1]);
+ }
+
+ /**
+ * Generates the original class name.
+ *
+ * @return string
+ */
+ private function generateClassName(ClassMetadata $class)
+ {
+ return ltrim($class->getName(), '\\');
+ }
+
+ /**
+ * Generates the array representation of lazy loaded public properties and their default values.
+ *
+ * @return string
+ */
+ private function generateLazyPropertiesNames(ClassMetadata $class)
+ {
+ $lazyPublicProperties = $this->getLazyLoadedPublicPropertiesNames($class);
+ $values = [];
+
+ foreach ($lazyPublicProperties as $name) {
+ $values[$name] = null;
+ }
+
+ return var_export($values, true);
+ }
+
+ /**
+ * Generates the array representation of lazy loaded public properties names.
+ *
+ * @return string
+ */
+ private function generateLazyPropertiesDefaults(ClassMetadata $class)
+ {
+ return var_export($this->getLazyLoadedPublicProperties($class), true);
+ }
+
+ /**
+ * Generates the constructor code (un-setting public lazy loaded properties, setting identifier field values).
+ *
+ * @return string
+ */
+ private function generateConstructorImpl(ClassMetadata $class)
+ {
+ $constructorImpl = <<<'EOT'
+ public function __construct(?\Closure $initializer = null, ?\Closure $cloner = null)
+ {
+
+EOT;
+
+ $toUnset = array_map(static function (string $name): string {
+ return '$this->' . $name;
+ }, $this->getLazyLoadedPublicPropertiesNames($class));
+
+ return $constructorImpl . ($toUnset === [] ? '' : ' unset(' . implode(', ', $toUnset) . ");\n")
+ . <<<'EOT'
+
+ $this->__initializer__ = $initializer;
+ $this->__cloner__ = $cloner;
+ }
+EOT;
+ }
+
+ /**
+ * Generates the magic getter invoked when lazy loaded public properties are requested.
+ *
+ * @return string
+ */
+ private function generateMagicGet(ClassMetadata $class)
+ {
+ $lazyPublicProperties = $this->getLazyLoadedPublicPropertiesNames($class);
+ $reflectionClass = $class->getReflectionClass();
+ $hasParentGet = false;
+ $returnReference = '';
+ $inheritDoc = '';
+ $name = '$name';
+ $parametersString = '$name';
+ $returnTypeHint = null;
+
+ if ($reflectionClass->hasMethod('__get')) {
+ $hasParentGet = true;
+ $inheritDoc = '{@inheritDoc}';
+ $methodReflection = $reflectionClass->getMethod('__get');
+
+ if ($methodReflection->returnsReference()) {
+ $returnReference = '& ';
+ }
+
+ $methodParameters = $methodReflection->getParameters();
+ $name = '$' . $methodParameters[0]->getName();
+
+ $parametersString = $this->buildParametersString($methodReflection->getParameters(), ['name']);
+ $returnTypeHint = $this->getMethodReturnType($methodReflection);
+ }
+
+ if (empty($lazyPublicProperties) && ! $hasParentGet) {
+ return '';
+ }
+
+ $magicGet = <<<EOT
+ /**
+ * $inheritDoc
+ * @param string \$name
+ */
+ public function {$returnReference}__get($parametersString)$returnTypeHint
+ {
+
+EOT;
+
+ if (! empty($lazyPublicProperties)) {
+ $magicGet .= <<<'EOT'
+ if (\array_key_exists($name, self::$lazyPropertiesNames)) {
+ $this->__initializer__ && $this->__initializer__->__invoke($this, '__get', [$name]);
+EOT;
+
+ if ($returnTypeHint === ': void') {
+ $magicGet .= "\n return;";
+ } else {
+ $magicGet .= "\n return \$this->\$name;";
+ }
+
+ $magicGet .= <<<'EOT'
+
+ }
+
+
+EOT;
+ }
+
+ if ($hasParentGet) {
+ $magicGet .= <<<'EOT'
+ $this->__initializer__ && $this->__initializer__->__invoke($this, '__get', [$name]);
+EOT;
+
+ if ($returnTypeHint === ': void') {
+ $magicGet .= <<<'EOT'
+
+ parent::__get($name);
+ return;
+EOT;
+ } else {
+ $magicGet .= <<<'EOT'
+
+ return parent::__get($name);
+EOT;
+ }
+ } else {
+ $magicGet .= sprintf(<<<EOT
+ trigger_error(sprintf('Undefined property: %%s::$%%s', __CLASS__, %s), E_USER_NOTICE);
+
+EOT
+ , $name);
+ }
+
+ return $magicGet . "\n }";
+ }
+
+ /**
+ * Generates the magic setter (currently unused).
+ *
+ * @return string
+ */
+ private function generateMagicSet(ClassMetadata $class)
+ {
+ $lazyPublicProperties = $this->getLazyLoadedPublicPropertiesNames($class);
+ $reflectionClass = $class->getReflectionClass();
+ $hasParentSet = false;
+ $inheritDoc = '';
+ $parametersString = '$name, $value';
+ $returnTypeHint = null;
+
+ if ($reflectionClass->hasMethod('__set')) {
+ $hasParentSet = true;
+ $inheritDoc = '{@inheritDoc}';
+ $methodReflection = $reflectionClass->getMethod('__set');
+
+ $parametersString = $this->buildParametersString($methodReflection->getParameters(), ['name', 'value']);
+ $returnTypeHint = $this->getMethodReturnType($methodReflection);
+ }
+
+ if (empty($lazyPublicProperties) && ! $hasParentSet) {
+ return '';
+ }
+
+ $magicSet = <<<EOT
+ /**
+ * $inheritDoc
+ * @param string \$name
+ * @param mixed \$value
+ */
+ public function __set($parametersString)$returnTypeHint
+ {
+
+EOT;
+
+ if (! empty($lazyPublicProperties)) {
+ $magicSet .= <<<'EOT'
+ if (\array_key_exists($name, self::$lazyPropertiesNames)) {
+ $this->__initializer__ && $this->__initializer__->__invoke($this, '__set', [$name, $value]);
+
+ $this->$name = $value;
+
+ return;
+ }
+
+
+EOT;
+ }
+
+ if ($hasParentSet) {
+ $magicSet .= <<<'EOT'
+ $this->__initializer__ && $this->__initializer__->__invoke($this, '__set', [$name, $value]);
+EOT;
+
+ if ($returnTypeHint === ': void') {
+ $magicSet .= <<<'EOT'
+
+ parent::__set($name, $value);
+ return;
+EOT;
+ } else {
+ $magicSet .= <<<'EOT'
+
+ return parent::__set($name, $value);
+EOT;
+ }
+ } else {
+ $magicSet .= ' $this->$name = $value;';
+ }
+
+ return $magicSet . "\n }";
+ }
+
+ /**
+ * Generates the magic issetter invoked when lazy loaded public properties are checked against isset().
+ *
+ * @return string
+ */
+ private function generateMagicIsset(ClassMetadata $class)
+ {
+ $lazyPublicProperties = $this->getLazyLoadedPublicPropertiesNames($class);
+ $hasParentIsset = $class->getReflectionClass()->hasMethod('__isset');
+ $parametersString = '$name';
+ $returnTypeHint = null;
+
+ if ($hasParentIsset) {
+ $methodReflection = $class->getReflectionClass()->getMethod('__isset');
+ $parametersString = $this->buildParametersString($methodReflection->getParameters(), ['name']);
+ $returnTypeHint = $this->getMethodReturnType($methodReflection);
+ }
+
+ if (empty($lazyPublicProperties) && ! $hasParentIsset) {
+ return '';
+ }
+
+ $inheritDoc = $hasParentIsset ? '{@inheritDoc}' : '';
+ $magicIsset = <<<EOT
+ /**
+ * $inheritDoc
+ * @param string \$name
+ * @return boolean
+ */
+ public function __isset($parametersString)$returnTypeHint
+ {
+
+EOT;
+
+ if (! empty($lazyPublicProperties)) {
+ $magicIsset .= <<<'EOT'
+ if (\array_key_exists($name, self::$lazyPropertiesNames)) {
+ $this->__initializer__ && $this->__initializer__->__invoke($this, '__isset', [$name]);
+
+ return isset($this->$name);
+ }
+
+
+EOT;
+ }
+
+ if ($hasParentIsset) {
+ $magicIsset .= <<<'EOT'
+ $this->__initializer__ && $this->__initializer__->__invoke($this, '__isset', [$name]);
+
+ return parent::__isset($name);
+EOT;
+ } else {
+ $magicIsset .= ' return false;';
+ }
+
+ return $magicIsset . "\n }";
+ }
+
+ /**
+ * Generates implementation for the `__sleep` method of proxies.
+ *
+ * @return string
+ */
+ private function generateSleepImpl(ClassMetadata $class)
+ {
+ $reflectionClass = $class->getReflectionClass();
+
+ $hasParentSleep = $reflectionClass->hasMethod('__sleep');
+ $inheritDoc = $hasParentSleep ? '{@inheritDoc}' : '';
+ $returnTypeHint = $hasParentSleep ? $this->getMethodReturnType($reflectionClass->getMethod('__sleep')) : '';
+ $sleepImpl = <<<EOT
+ /**
+ * $inheritDoc
+ * @return array
+ */
+ public function __sleep()$returnTypeHint
+ {
+
+EOT;
+
+ if ($hasParentSleep) {
+ return $sleepImpl . <<<'EOT'
+ $properties = array_merge(['__isInitialized__'], parent::__sleep());
+
+ if ($this->__isInitialized__) {
+ $properties = array_diff($properties, array_keys(self::$lazyPropertiesNames));
+ }
+
+ return $properties;
+ }
+EOT;
+ }
+
+ $allProperties = ['__isInitialized__'];
+
+ foreach ($class->getReflectionClass()->getProperties() as $prop) {
+ assert($prop instanceof ReflectionProperty);
+ if ($prop->isStatic()) {
+ continue;
+ }
+
+ $allProperties[] = $prop->isPrivate()
+ ? "\0" . $prop->getDeclaringClass()->getName() . "\0" . $prop->getName()
+ : $prop->getName();
+ }
+
+ $lazyPublicProperties = $this->getLazyLoadedPublicPropertiesNames($class);
+ $protectedProperties = array_diff($allProperties, $lazyPublicProperties);
+
+ foreach ($allProperties as &$property) {
+ $property = var_export($property, true);
+ }
+
+ foreach ($protectedProperties as &$property) {
+ $property = var_export($property, true);
+ }
+
+ $allProperties = implode(', ', $allProperties);
+ $protectedProperties = implode(', ', $protectedProperties);
+
+ return $sleepImpl . <<<EOT
+ if (\$this->__isInitialized__) {
+ return [$allProperties];
+ }
+
+ return [$protectedProperties];
+ }
+EOT;
+ }
+
+ /**
+ * Generates implementation for the `__wakeup` method of proxies.
+ *
+ * @return string
+ */
+ private function generateWakeupImpl(ClassMetadata $class)
+ {
+ $reflectionClass = $class->getReflectionClass();
+
+ $hasParentWakeup = $reflectionClass->hasMethod('__wakeup');
+
+ $unsetPublicProperties = [];
+ foreach ($this->getLazyLoadedPublicPropertiesNames($class) as $lazyPublicProperty) {
+ $unsetPublicProperties[] = '$this->' . $lazyPublicProperty;
+ }
+
+ $shortName = $this->generateProxyShortClassName($class);
+ $inheritDoc = $hasParentWakeup ? '{@inheritDoc}' : '';
+ $returnTypeHint = $hasParentWakeup ? $this->getMethodReturnType($reflectionClass->getMethod('__wakeup')) : '';
+ $wakeupImpl = <<<EOT
+ /**
+ * $inheritDoc
+ */
+ public function __wakeup()$returnTypeHint
+ {
+ if ( ! \$this->__isInitialized__) {
+ \$this->__initializer__ = function ($shortName \$proxy) {
+ \$proxy->__setInitializer(null);
+ \$proxy->__setCloner(null);
+
+ \$existingProperties = get_object_vars(\$proxy);
+
+ foreach (\$proxy::\$lazyPropertiesDefaults as \$property => \$defaultValue) {
+ if ( ! array_key_exists(\$property, \$existingProperties)) {
+ \$proxy->\$property = \$defaultValue;
+ }
+ }
+ };
+
+EOT;
+
+ if (! empty($unsetPublicProperties)) {
+ $wakeupImpl .= "\n unset(" . implode(', ', $unsetPublicProperties) . ');';
+ }
+
+ $wakeupImpl .= "\n }";
+
+ if ($hasParentWakeup) {
+ $wakeupImpl .= "\n parent::__wakeup();";
+ }
+
+ $wakeupImpl .= "\n }";
+
+ return $wakeupImpl;
+ }
+
+ /**
+ * Generates implementation for the `__clone` method of proxies.
+ *
+ * @return string
+ */
+ private function generateCloneImpl(ClassMetadata $class)
+ {
+ $hasParentClone = $class->getReflectionClass()->hasMethod('__clone');
+ $inheritDoc = $hasParentClone ? '{@inheritDoc}' : '';
+ $callParentClone = $hasParentClone ? "\n parent::__clone();\n" : '';
+
+ return <<<EOT
+ /**
+ * $inheritDoc
+ */
+ public function __clone()
+ {
+ \$this->__cloner__ && \$this->__cloner__->__invoke(\$this, '__clone', []);
+$callParentClone }
+EOT;
+ }
+
+ /**
+ * Generates decorated methods by picking those available in the parent class.
+ *
+ * @return string
+ */
+ private function generateMethods(ClassMetadata $class)
+ {
+ $methods = '';
+ $methodNames = [];
+ $reflectionMethods = $class->getReflectionClass()->getMethods(ReflectionMethod::IS_PUBLIC);
+ $skippedMethods = [
+ '__sleep' => true,
+ '__clone' => true,
+ '__wakeup' => true,
+ '__get' => true,
+ '__set' => true,
+ '__isset' => true,
+ ];
+
+ foreach ($reflectionMethods as $method) {
+ $name = $method->getName();
+
+ if (
+ $method->isConstructor() ||
+ isset($skippedMethods[strtolower($name)]) ||
+ isset($methodNames[$name]) ||
+ $method->isFinal() ||
+ $method->isStatic() ||
+ ( ! $method->isPublic())
+ ) {
+ continue;
+ }
+
+ $methodNames[$name] = true;
+ $methods .= "\n /**\n"
+ . " * {@inheritDoc}\n"
+ . " */\n"
+ . ' public function ';
+
+ if ($method->returnsReference()) {
+ $methods .= '&';
+ }
+
+ $methods .= $name . '(' . $this->buildParametersString($method->getParameters()) . ')';
+ $methods .= $this->getMethodReturnType($method);
+ $methods .= "\n" . ' {' . "\n";
+
+ if ($this->isShortIdentifierGetter($method, $class)) {
+ $identifier = lcfirst(substr($name, 3));
+ $fieldType = $class->getTypeOfField($identifier);
+ $cast = in_array($fieldType, ['integer', 'smallint']) ? '(int) ' : '';
+
+ $methods .= ' if ($this->__isInitialized__ === false) {' . "\n";
+ $methods .= ' ';
+ $methods .= $this->shouldProxiedMethodReturn($method) ? 'return ' : '';
+ $methods .= $cast . ' parent::' . $method->getName() . "();\n";
+ $methods .= ' }' . "\n\n";
+ }
+
+ $invokeParamsString = implode(', ', $this->getParameterNamesForInvoke($method->getParameters()));
+ $callParamsString = implode(', ', $this->getParameterNamesForParentCall($method->getParameters()));
+
+ $methods .= "\n \$this->__initializer__ "
+ . '&& $this->__initializer__->__invoke($this, ' . var_export($name, true)
+ . ', [' . $invokeParamsString . ']);'
+ . "\n\n "
+ . ($this->shouldProxiedMethodReturn($method) ? 'return ' : '')
+ . 'parent::' . $name . '(' . $callParamsString . ');'
+ . "\n" . ' }' . "\n";
+ }
+
+ return $methods;
+ }
+
+ /**
+ * Generates the Proxy file name.
+ *
+ * @param string $className
+ * @param string $baseDirectory Optional base directory for proxy file name generation.
+ * If not specified, the directory configured on the Configuration of the
+ * EntityManager will be used by this factory.
+ *
+ * @return string
+ *
+ * @psalm-param class-string $className
+ */
+ public function getProxyFileName($className, $baseDirectory = null)
+ {
+ $baseDirectory = $baseDirectory ?: $this->proxyDirectory;
+
+ return rtrim($baseDirectory, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . Proxy::MARKER
+ . str_replace('\\', '', $className) . '.php';
+ }
+
+ /**
+ * Checks if the method is a short identifier getter.
+ *
+ * What does this mean? For proxy objects the identifier is already known,
+ * however accessing the getter for this identifier usually triggers the
+ * lazy loading, leading to a query that may not be necessary if only the
+ * ID is interesting for the userland code (for example in views that
+ * generate links to the entity, but do not display anything else).
+ *
+ * @param ReflectionMethod $method
+ *
+ * @return bool
+ */
+ private function isShortIdentifierGetter($method, ClassMetadata $class)
+ {
+ $identifier = lcfirst(substr($method->getName(), 3));
+ $startLine = $method->getStartLine();
+ $endLine = $method->getEndLine();
+ $cheapCheck = $method->getNumberOfParameters() === 0
+ && substr($method->getName(), 0, 3) === 'get'
+ && in_array($identifier, $class->getIdentifier(), true)
+ && $class->hasField($identifier)
+ && ($endLine - $startLine <= 4);
+
+ if ($cheapCheck) {
+ $code = file($method->getFileName());
+ $code = trim(implode(' ', array_slice($code, $startLine - 1, $endLine - $startLine + 1)));
+
+ $pattern = sprintf(self::PATTERN_MATCH_ID_METHOD, $method->getName(), $identifier);
+
+ if (preg_match($pattern, $code)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Generates the list of public properties to be lazy loaded.
+ *
+ * @return array<int, string>
+ */
+ private function getLazyLoadedPublicPropertiesNames(ClassMetadata $class): array
+ {
+ $properties = [];
+
+ foreach ($class->getReflectionClass()->getProperties(ReflectionProperty::IS_PUBLIC) as $property) {
+ $name = $property->getName();
+
+ if ((! $class->hasField($name) && ! $class->hasAssociation($name)) || $class->isIdentifier($name)) {
+ continue;
+ }
+
+ $properties[] = $name;
+ }
+
+ return $properties;
+ }
+
+ /**
+ * Generates the list of default values of public properties.
+ *
+ * @return mixed[]
+ */
+ private function getLazyLoadedPublicProperties(ClassMetadata $class)
+ {
+ $defaultProperties = $class->getReflectionClass()->getDefaultProperties();
+ $lazyLoadedPublicProperties = $this->getLazyLoadedPublicPropertiesNames($class);
+ $defaultValues = [];
+
+ foreach ($class->getReflectionClass()->getProperties(ReflectionProperty::IS_PUBLIC) as $property) {
+ $name = $property->getName();
+
+ if (! in_array($name, $lazyLoadedPublicProperties, true)) {
+ continue;
+ }
+
+ if (array_key_exists($name, $defaultProperties)) {
+ $defaultValues[$name] = $defaultProperties[$name];
+ } elseif (method_exists($property, 'getType')) {
+ $propertyType = $property->getType();
+ if ($propertyType !== null && $propertyType->allowsNull()) {
+ $defaultValues[$name] = null;
+ }
+ }
+ }
+
+ return $defaultValues;
+ }
+
+ /**
+ * @param ReflectionParameter[] $parameters
+ * @param string[] $renameParameters
+ *
+ * @return string
+ */
+ private function buildParametersString(array $parameters, array $renameParameters = [])
+ {
+ $parameterDefinitions = [];
+
+ $i = -1;
+ foreach ($parameters as $param) {
+ assert($param instanceof ReflectionParameter);
+ $i++;
+ $parameterDefinition = '';
+ $parameterType = $this->getParameterType($param);
+
+ if ($parameterType !== null) {
+ $parameterDefinition .= $parameterType . ' ';
+ }
+
+ if ($param->isPassedByReference()) {
+ $parameterDefinition .= '&';
+ }
+
+ if ($param->isVariadic()) {
+ $parameterDefinition .= '...';
+ }
+
+ $parameterDefinition .= '$' . ($renameParameters ? $renameParameters[$i] : $param->getName());
+
+ if ($param->isDefaultValueAvailable()) {
+ $parameterDefinition .= ' = ' . var_export($param->getDefaultValue(), true);
+ }
+
+ $parameterDefinitions[] = $parameterDefinition;
+ }
+
+ return implode(', ', $parameterDefinitions);
+ }
+
+ /**
+ * @return string|null
+ */
+ private function getParameterType(ReflectionParameter $parameter)
+ {
+ if (! $parameter->hasType()) {
+ return null;
+ }
+
+ $declaringFunction = $parameter->getDeclaringFunction();
+
+ assert($declaringFunction instanceof ReflectionMethod);
+
+ return $this->formatType($parameter->getType(), $declaringFunction, $parameter);
+ }
+
+ /**
+ * @param ReflectionParameter[] $parameters
+ *
+ * @return string[]
+ */
+ private function getParameterNamesForInvoke(array $parameters)
+ {
+ return array_map(
+ static function (ReflectionParameter $parameter) {
+ return '$' . $parameter->getName();
+ },
+ $parameters
+ );
+ }
+
+ /**
+ * @param ReflectionParameter[] $parameters
+ *
+ * @return string[]
+ */
+ private function getParameterNamesForParentCall(array $parameters)
+ {
+ return array_map(
+ static function (ReflectionParameter $parameter) {
+ $name = '';
+
+ if ($parameter->isVariadic()) {
+ $name .= '...';
+ }
+
+ $name .= '$' . $parameter->getName();
+
+ return $name;
+ },
+ $parameters
+ );
+ }
+
+ /**
+ * @return string
+ */
+ private function getMethodReturnType(ReflectionMethod $method)
+ {
+ if (! $method->hasReturnType()) {
+ return '';
+ }
+
+ return ': ' . $this->formatType($method->getReturnType(), $method);
+ }
+
+ /**
+ * @return bool
+ */
+ private function shouldProxiedMethodReturn(ReflectionMethod $method)
+ {
+ if (! $method->hasReturnType()) {
+ return true;
+ }
+
+ return strtolower($this->formatType($method->getReturnType(), $method)) !== 'void';
+ }
+
+ /**
+ * @return string
+ */
+ private function formatType(
+ ReflectionType $type,
+ ReflectionMethod $method,
+ ?ReflectionParameter $parameter = null
+ ) {
+ if ($type instanceof ReflectionUnionType) {
+ return implode('|', array_map(
+ function (ReflectionType $unionedType) use ($method, $parameter) {
+ return $this->formatType($unionedType, $method, $parameter);
+ },
+ $type->getTypes()
+ ));
+ }
+
+ assert($type instanceof ReflectionNamedType);
+
+ $name = $type->getName();
+ $nameLower = strtolower($name);
+
+ if ($nameLower === 'static') {
+ $name = 'static';
+ }
+
+ if ($nameLower === 'self') {
+ $name = $method->getDeclaringClass()->getName();
+ }
+
+ if ($nameLower === 'parent') {
+ $name = $method->getDeclaringClass()->getParentClass()->getName();
+ }
+
+ if (! $type->isBuiltin() && ! class_exists($name) && ! interface_exists($name) && $name !== 'static') {
+ if ($parameter !== null) {
+ throw UnexpectedValueException::invalidParameterTypeHint(
+ $method->getDeclaringClass()->getName(),
+ $method->getName(),
+ $parameter->getName()
+ );
+ }
+
+ throw UnexpectedValueException::invalidReturnTypeHint(
+ $method->getDeclaringClass()->getName(),
+ $method->getName()
+ );
+ }
+
+ if (! $type->isBuiltin() && $name !== 'static') {
+ $name = '\\' . $name;
+ }
+
+ if (
+ $type->allowsNull()
+ && ! in_array($name, ['mixed', 'null'], true)
+ && ($parameter === null || ! $parameter->isDefaultValueAvailable() || $parameter->getDefaultValue() !== null)
+ ) {
+ $name = '?' . $name;
+ }
+
+ return $name;
+ }
+}
+
+interface_exists(ClassMetadata::class);
diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Util/ClassUtils.php b/vendor/doctrine/common/lib/Doctrine/Common/Util/ClassUtils.php
new file mode 100644
index 0000000..d220232
--- /dev/null
+++ b/vendor/doctrine/common/lib/Doctrine/Common/Util/ClassUtils.php
@@ -0,0 +1,112 @@
+<?php
+
+namespace Doctrine\Common\Util;
+
+use Doctrine\Persistence\Proxy;
+use ReflectionClass;
+
+use function get_class;
+use function get_parent_class;
+use function ltrim;
+use function rtrim;
+use function strrpos;
+use function substr;
+
+/**
+ * Class and reflection related functionality for objects that
+ * might or not be proxy objects at the moment.
+ */
+class ClassUtils
+{
+ /**
+ * Gets the real class name of a class name that could be a proxy.
+ *
+ * @param string $className
+ *
+ * @return string
+ *
+ * @psalm-param class-string $className
+ * @psalm-return class-string
+ */
+ public static function getRealClass($className)
+ {
+ $pos = strrpos($className, '\\' . Proxy::MARKER . '\\');
+
+ if ($pos === false) {
+ return $className;
+ }
+
+ return substr($className, $pos + Proxy::MARKER_LENGTH + 2);
+ }
+
+ /**
+ * Gets the real class name of an object (even if its a proxy).
+ *
+ * @param object $object
+ *
+ * @return string
+ *
+ * @psalm-return class-string
+ */
+ public static function getClass($object)
+ {
+ return self::getRealClass(get_class($object));
+ }
+
+ /**
+ * Gets the real parent class name of a class or object.
+ *
+ * @param string $className
+ *
+ * @return string
+ *
+ * @psalm-param class-string $className
+ * @psalm-return class-string
+ */
+ public static function getParentClass($className)
+ {
+ return get_parent_class(self::getRealClass($className));
+ }
+
+ /**
+ * Creates a new reflection class.
+ *
+ * @param string $className
+ *
+ * @return ReflectionClass
+ *
+ * @psalm-param class-string $className
+ */
+ public static function newReflectionClass($className)
+ {
+ return new ReflectionClass(self::getRealClass($className));
+ }
+
+ /**
+ * Creates a new reflection object.
+ *
+ * @param object $object
+ *
+ * @return ReflectionClass
+ */
+ public static function newReflectionObject($object)
+ {
+ return self::newReflectionClass(self::getClass($object));
+ }
+
+ /**
+ * Given a class name and a proxy namespace returns the proxy name.
+ *
+ * @param string $className
+ * @param string $proxyNamespace
+ *
+ * @return string
+ *
+ * @psalm-param class-string $className
+ * @psalm-return class-string
+ */
+ public static function generateProxyClassName($className, $proxyNamespace)
+ {
+ return rtrim($proxyNamespace, '\\') . '\\' . Proxy::MARKER . '\\' . ltrim($className, '\\');
+ }
+}
diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php b/vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php
new file mode 100644
index 0000000..d21f700
--- /dev/null
+++ b/vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php
@@ -0,0 +1,185 @@
+<?php
+
+namespace Doctrine\Common\Util;
+
+use ArrayIterator;
+use ArrayObject;
+use DateTimeInterface;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\Persistence\Proxy;
+use stdClass;
+
+use function array_keys;
+use function count;
+use function end;
+use function explode;
+use function extension_loaded;
+use function get_class;
+use function html_entity_decode;
+use function ini_get;
+use function ini_set;
+use function is_array;
+use function is_object;
+use function method_exists;
+use function ob_end_clean;
+use function ob_get_contents;
+use function ob_start;
+use function spl_object_hash;
+use function strip_tags;
+use function var_dump;
+
+/**
+ * Static class containing most used debug methods.
+ *
+ * @deprecated The Debug class is deprecated, please use symfony/var-dumper instead.
+ *
+ * @link www.doctrine-project.org
+ */
+final class Debug
+{
+ /**
+ * Private constructor (prevents instantiation).
+ */
+ private function __construct()
+ {
+ }
+
+ /**
+ * Prints a dump of the public, protected and private properties of $var.
+ *
+ * @link https://xdebug.org/
+ *
+ * @param mixed $var The variable to dump.
+ * @param int $maxDepth The maximum nesting level for object properties.
+ * @param bool $stripTags Whether output should strip HTML tags.
+ * @param bool $echo Send the dumped value to the output buffer
+ *
+ * @return string
+ */
+ public static function dump($var, $maxDepth = 2, $stripTags = true, $echo = true)
+ {
+ $html = ini_get('html_errors');
+
+ if ($html !== true) {
+ ini_set('html_errors', 'on');
+ }
+
+ if (extension_loaded('xdebug')) {
+ ini_set('xdebug.var_display_max_depth', $maxDepth);
+ }
+
+ $var = self::export($var, $maxDepth);
+
+ ob_start();
+ var_dump($var);
+
+ $dump = ob_get_contents();
+
+ ob_end_clean();
+
+ $dumpText = ($stripTags ? strip_tags(html_entity_decode($dump)) : $dump);
+
+ ini_set('html_errors', $html);
+
+ if ($echo) {
+ echo $dumpText;
+ }
+
+ return $dumpText;
+ }
+
+ /**
+ * @param mixed $var
+ * @param int $maxDepth
+ *
+ * @return mixed
+ */
+ public static function export($var, $maxDepth)
+ {
+ $return = null;
+ $isObj = is_object($var);
+
+ if ($var instanceof Collection) {
+ $var = $var->toArray();
+ }
+
+ if (! $maxDepth) {
+ return is_object($var) ? get_class($var)
+ : (is_array($var) ? 'Array(' . count($var) . ')' : $var);
+ }
+
+ if (is_array($var)) {
+ $return = [];
+
+ foreach ($var as $k => $v) {
+ $return[$k] = self::export($v, $maxDepth - 1);
+ }
+
+ return $return;
+ }
+
+ if (! $isObj) {
+ return $var;
+ }
+
+ $return = new stdClass();
+ if ($var instanceof DateTimeInterface) {
+ $return->__CLASS__ = get_class($var);
+ $return->date = $var->format('c');
+ $return->timezone = $var->getTimezone()->getName();
+
+ return $return;
+ }
+
+ $return->__CLASS__ = ClassUtils::getClass($var);
+
+ if ($var instanceof Proxy) {
+ $return->__IS_PROXY__ = true;
+ $return->__PROXY_INITIALIZED__ = $var->__isInitialized();
+ }
+
+ if ($var instanceof ArrayObject || $var instanceof ArrayIterator) {
+ $return->__STORAGE__ = self::export($var->getArrayCopy(), $maxDepth - 1);
+ }
+
+ return self::fillReturnWithClassAttributes($var, $return, $maxDepth);
+ }
+
+ /**
+ * Fill the $return variable with class attributes
+ * Based on obj2array function from {@see https://secure.php.net/manual/en/function.get-object-vars.php#47075}
+ *
+ * @param object $var
+ * @param int $maxDepth
+ *
+ * @return mixed
+ */
+ private static function fillReturnWithClassAttributes($var, stdClass $return, $maxDepth)
+ {
+ $clone = (array) $var;
+
+ foreach (array_keys($clone) as $key) {
+ $aux = explode("\0", $key);
+ $name = end($aux);
+ if ($aux[0] === '') {
+ $name .= ':' . ($aux[1] === '*' ? 'protected' : $aux[1] . ':private');
+ }
+
+ $return->$name = self::export($clone[$key], $maxDepth - 1);
+ }
+
+ return $return;
+ }
+
+ /**
+ * Returns a string representation of an object.
+ *
+ * @param object $obj
+ *
+ * @return string
+ */
+ public static function toString($obj)
+ {
+ return method_exists($obj, '__toString') ? (string) $obj : get_class($obj) . '@' . spl_object_hash($obj);
+ }
+}