From 1c4f7ab3b838b23afb2ee4dab14acbf75956e952 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Tue, 22 Mar 2022 12:24:31 +0300 Subject: * add phpunit as a dev dependency * add some basic tests for UrlHelper::rewrite_relative() * fix UrlHelper::rewrite_relative() to work better on non-absolute relative URL paths --- .../Doubler/Generator/Node/ArgumentNode.php | 133 +++++++++++++ .../Doubler/Generator/Node/ArgumentTypeNode.php | 10 + .../Prophecy/Doubler/Generator/Node/ClassNode.php | 169 +++++++++++++++++ .../Prophecy/Doubler/Generator/Node/MethodNode.php | 210 +++++++++++++++++++++ .../Doubler/Generator/Node/ReturnTypeNode.php | 45 +++++ .../Doubler/Generator/Node/TypeNodeAbstract.php | 97 ++++++++++ 6 files changed, 664 insertions(+) create mode 100644 vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ArgumentNode.php create mode 100644 vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ArgumentTypeNode.php create mode 100644 vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ClassNode.php create mode 100644 vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/MethodNode.php create mode 100644 vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ReturnTypeNode.php create mode 100644 vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/TypeNodeAbstract.php (limited to 'vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node') diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ArgumentNode.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ArgumentNode.php new file mode 100644 index 000000000..da7fed4e1 --- /dev/null +++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ArgumentNode.php @@ -0,0 +1,133 @@ + + * Marcello Duarte + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Prophecy\Doubler\Generator\Node; + +/** + * Argument node. + * + * @author Konstantin Kudryashov + */ +class ArgumentNode +{ + private $name; + private $default; + private $optional = false; + private $byReference = false; + private $isVariadic = false; + + /** @var ArgumentTypeNode */ + private $typeNode; + + /** + * @param string $name + */ + public function __construct($name) + { + $this->name = $name; + $this->typeNode = new ArgumentTypeNode(); + } + + public function getName() + { + return $this->name; + } + + public function setTypeNode(ArgumentTypeNode $typeNode) + { + $this->typeNode = $typeNode; + } + + public function getTypeNode() : ArgumentTypeNode + { + return $this->typeNode; + } + + public function hasDefault() + { + return $this->isOptional() && !$this->isVariadic(); + } + + public function getDefault() + { + return $this->default; + } + + public function setDefault($default = null) + { + $this->optional = true; + $this->default = $default; + } + + public function isOptional() + { + return $this->optional; + } + + public function setAsPassedByReference($byReference = true) + { + $this->byReference = $byReference; + } + + public function isPassedByReference() + { + return $this->byReference; + } + + public function setAsVariadic($isVariadic = true) + { + $this->isVariadic = $isVariadic; + } + + public function isVariadic() + { + return $this->isVariadic; + } + + /** + * @deprecated use getArgumentTypeNode instead + * @return string|null + */ + public function getTypeHint() + { + $type = $this->typeNode->getNonNullTypes() ? $this->typeNode->getNonNullTypes()[0] : null; + + return $type ? ltrim($type, '\\') : null; + } + + /** + * @deprecated use setArgumentTypeNode instead + * @param string|null $typeHint + */ + public function setTypeHint($typeHint = null) + { + $this->typeNode = ($typeHint === null) ? new ArgumentTypeNode() : new ArgumentTypeNode($typeHint); + } + + /** + * @deprecated use getArgumentTypeNode instead + * @return bool + */ + public function isNullable() + { + return $this->typeNode->canUseNullShorthand(); + } + + /** + * @deprecated use getArgumentTypeNode instead + * @param bool $isNullable + */ + public function setAsNullable($isNullable = true) + { + $nonNullTypes = $this->typeNode->getNonNullTypes(); + $this->typeNode = $isNullable ? new ArgumentTypeNode('null', ...$nonNullTypes) : new ArgumentTypeNode(...$nonNullTypes); + } +} diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ArgumentTypeNode.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ArgumentTypeNode.php new file mode 100644 index 000000000..0a18b91e1 --- /dev/null +++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ArgumentTypeNode.php @@ -0,0 +1,10 @@ + + * Marcello Duarte + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Prophecy\Doubler\Generator\Node; + +use Prophecy\Exception\Doubler\MethodNotExtendableException; +use Prophecy\Exception\InvalidArgumentException; + +/** + * Class node. + * + * @author Konstantin Kudryashov + */ +class ClassNode +{ + private $parentClass = 'stdClass'; + private $interfaces = array(); + private $properties = array(); + private $unextendableMethods = array(); + + /** + * @var MethodNode[] + */ + private $methods = array(); + + public function getParentClass() + { + return $this->parentClass; + } + + /** + * @param string $class + */ + public function setParentClass($class) + { + $this->parentClass = $class ?: 'stdClass'; + } + + /** + * @return string[] + */ + public function getInterfaces() + { + return $this->interfaces; + } + + /** + * @param string $interface + */ + public function addInterface($interface) + { + if ($this->hasInterface($interface)) { + return; + } + + array_unshift($this->interfaces, $interface); + } + + /** + * @param string $interface + * + * @return bool + */ + public function hasInterface($interface) + { + return in_array($interface, $this->interfaces); + } + + public function getProperties() + { + return $this->properties; + } + + public function addProperty($name, $visibility = 'public') + { + $visibility = strtolower($visibility); + + if (!in_array($visibility, array('public', 'private', 'protected'))) { + throw new InvalidArgumentException(sprintf( + '`%s` property visibility is not supported.', $visibility + )); + } + + $this->properties[$name] = $visibility; + } + + /** + * @return MethodNode[] + */ + public function getMethods() + { + return $this->methods; + } + + public function addMethod(MethodNode $method, $force = false) + { + if (!$this->isExtendable($method->getName())){ + $message = sprintf( + 'Method `%s` is not extendable, so can not be added.', $method->getName() + ); + throw new MethodNotExtendableException($message, $this->getParentClass(), $method->getName()); + } + + if ($force || !isset($this->methods[$method->getName()])) { + $this->methods[$method->getName()] = $method; + } + } + + public function removeMethod($name) + { + unset($this->methods[$name]); + } + + /** + * @param string $name + * + * @return MethodNode|null + */ + public function getMethod($name) + { + return $this->hasMethod($name) ? $this->methods[$name] : null; + } + + /** + * @param string $name + * + * @return bool + */ + public function hasMethod($name) + { + return isset($this->methods[$name]); + } + + /** + * @return string[] + */ + public function getUnextendableMethods() + { + return $this->unextendableMethods; + } + + /** + * @param string $unextendableMethod + */ + public function addUnextendableMethod($unextendableMethod) + { + if (!$this->isExtendable($unextendableMethod)){ + return; + } + $this->unextendableMethods[] = $unextendableMethod; + } + + /** + * @param string $method + * @return bool + */ + public function isExtendable($method) + { + return !in_array($method, $this->unextendableMethods); + } +} diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/MethodNode.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/MethodNode.php new file mode 100644 index 000000000..ece652f9f --- /dev/null +++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/MethodNode.php @@ -0,0 +1,210 @@ + + * Marcello Duarte + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Prophecy\Doubler\Generator\Node; + +use Prophecy\Doubler\Generator\TypeHintReference; +use Prophecy\Exception\InvalidArgumentException; + +/** + * Method node. + * + * @author Konstantin Kudryashov + */ +class MethodNode +{ + private $name; + private $code; + private $visibility = 'public'; + private $static = false; + private $returnsReference = false; + + /** @var ReturnTypeNode */ + private $returnTypeNode; + + /** + * @var ArgumentNode[] + */ + private $arguments = array(); + + /** + * @param string $name + * @param string $code + */ + public function __construct($name, $code = null, TypeHintReference $typeHintReference = null) + { + $this->name = $name; + $this->code = $code; + $this->returnTypeNode = new ReturnTypeNode(); + } + + public function getVisibility() + { + return $this->visibility; + } + + /** + * @param string $visibility + */ + public function setVisibility($visibility) + { + $visibility = strtolower($visibility); + + if (!in_array($visibility, array('public', 'private', 'protected'))) { + throw new InvalidArgumentException(sprintf( + '`%s` method visibility is not supported.', $visibility + )); + } + + $this->visibility = $visibility; + } + + public function isStatic() + { + return $this->static; + } + + public function setStatic($static = true) + { + $this->static = (bool) $static; + } + + public function returnsReference() + { + return $this->returnsReference; + } + + public function setReturnsReference() + { + $this->returnsReference = true; + } + + public function getName() + { + return $this->name; + } + + public function addArgument(ArgumentNode $argument) + { + $this->arguments[] = $argument; + } + + /** + * @return ArgumentNode[] + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * @deprecated use getReturnTypeNode instead + * @return bool + */ + public function hasReturnType() + { + return (bool) $this->returnTypeNode->getNonNullTypes(); + } + + public function setReturnTypeNode(ReturnTypeNode $returnTypeNode): void + { + $this->returnTypeNode = $returnTypeNode; + } + + /** + * @deprecated use setReturnTypeNode instead + * @param string $type + */ + public function setReturnType($type = null) + { + $this->returnTypeNode = ($type === '' || $type === null) ? new ReturnTypeNode() : new ReturnTypeNode($type); + } + + /** + * @deprecated use setReturnTypeNode instead + * @param bool $bool + */ + public function setNullableReturnType($bool = true) + { + if ($bool) { + $this->returnTypeNode = new ReturnTypeNode('null', ...$this->returnTypeNode->getTypes()); + } + else { + $this->returnTypeNode = new ReturnTypeNode(...$this->returnTypeNode->getNonNullTypes()); + } + } + + /** + * @deprecated use getReturnTypeNode instead + * @return string|null + */ + public function getReturnType() + { + if ($types = $this->returnTypeNode->getNonNullTypes()) + { + return $types[0]; + } + + return null; + } + + public function getReturnTypeNode() : ReturnTypeNode + { + return $this->returnTypeNode; + } + + /** + * @deprecated use getReturnTypeNode instead + * @return bool + */ + public function hasNullableReturnType() + { + return $this->returnTypeNode->canUseNullShorthand(); + } + + /** + * @param string $code + */ + public function setCode($code) + { + $this->code = $code; + } + + public function getCode() + { + if ($this->returnsReference) + { + return "throw new \Prophecy\Exception\Doubler\ReturnByReferenceException('Returning by reference not supported', get_class(\$this), '{$this->name}');"; + } + + return (string) $this->code; + } + + public function useParentCode() + { + $this->code = sprintf( + 'return parent::%s(%s);', $this->getName(), implode(', ', + array_map(array($this, 'generateArgument'), $this->arguments) + ) + ); + } + + private function generateArgument(ArgumentNode $arg) + { + $argument = '$'.$arg->getName(); + + if ($arg->isVariadic()) { + $argument = '...'.$argument; + } + + return $argument; + } +} diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ReturnTypeNode.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ReturnTypeNode.php new file mode 100644 index 000000000..5b5824988 --- /dev/null +++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ReturnTypeNode.php @@ -0,0 +1,45 @@ +types['void']) && count($this->types) !== 1) { + throw new DoubleException('void cannot be part of a union'); + } + if (isset($this->types['never']) && count($this->types) !== 1) { + throw new DoubleException('never cannot be part of a union'); + } + + parent::guardIsValidType(); + } + + /** + * @deprecated use hasReturnStatement + */ + public function isVoid() + { + return $this->types == ['void' => 'void']; + } + + public function hasReturnStatement(): bool + { + return $this->types !== ['void' => 'void'] + && $this->types !== ['never' => 'never']; + } +} diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/TypeNodeAbstract.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/TypeNodeAbstract.php new file mode 100644 index 000000000..97fc54978 --- /dev/null +++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/TypeNodeAbstract.php @@ -0,0 +1,97 @@ +getRealType($type); + $this->types[$type] = $type; + } + + $this->guardIsValidType(); + } + + public function canUseNullShorthand(): bool + { + return isset($this->types['null']) && count($this->types) <= 2; + } + + public function getTypes(): array + { + return array_values($this->types); + } + + public function getNonNullTypes(): array + { + $nonNullTypes = $this->types; + unset($nonNullTypes['null']); + + return array_values($nonNullTypes); + } + + protected function prefixWithNsSeparator(string $type): string + { + return '\\' . ltrim($type, '\\'); + } + + protected function getRealType(string $type): string + { + switch ($type) { + // type aliases + case 'double': + case 'real': + return 'float'; + case 'boolean': + return 'bool'; + case 'integer': + return 'int'; + + // built in types + case 'self': + case 'static': + case 'array': + case 'callable': + case 'bool': + case 'false': + case 'float': + case 'int': + case 'string': + case 'iterable': + case 'object': + case 'null': + return $type; + case 'mixed': + return \PHP_VERSION_ID < 80000 ? $this->prefixWithNsSeparator($type) : $type; + + default: + return $this->prefixWithNsSeparator($type); + } + } + + protected function guardIsValidType() + { + if ($this->types == ['null' => 'null']) { + throw new DoubleException('Type cannot be standalone null'); + } + + if ($this->types == ['false' => 'false']) { + throw new DoubleException('Type cannot be standalone false'); + } + + if ($this->types == ['false' => 'false', 'null' => 'null']) { + throw new DoubleException('Type cannot be nullable false'); + } + + if (\PHP_VERSION_ID >= 80000 && isset($this->types['mixed']) && count($this->types) !== 1) { + throw new DoubleException('mixed cannot be part of a union'); + } + } +} -- cgit v1.2.3