diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml index aa14250c..1352013d 100644 --- a/.github/workflows/coding-standards.yml +++ b/.github/workflows/coding-standards.yml @@ -9,4 +9,4 @@ jobs: cs: uses: ray-di/.github/.github/workflows/coding-standards.yml@v1 with: - php_version: 8.1 + php_version: 8.2 diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index ffaa511b..9ae40e67 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -9,4 +9,4 @@ jobs: sa: uses: ray-di/.github/.github/workflows/static-analysis.yml@v1 with: - php_version: 8.1 + php_version: 8.2 diff --git a/.gitignore b/.gitignore index a101f5eb..27150ba5 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,4 @@ /composer.lock /coverage.xml /vendor-bin/**/vendor -/.phpunit-cache +/.phpunit.cache/ diff --git a/composer.json b/composer.json index 9872cb3a..309e7fd3 100644 --- a/composer.json +++ b/composer.json @@ -11,13 +11,15 @@ ], "require": { "php": "^7.2 || ^8.0", + "ext-hash": "*", + "ext-tokenizer": "*", "doctrine/annotations": "^1.12 || ^2.0", - "koriym/attributes": "^1.0.3", - "nikic/php-parser": "^4.16" + "koriym/attributes": "^1.0.3" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.4.1", - "phpunit/phpunit": "^8.5.23 || ^9.5.10" + "phpunit/phpunit": "^8.5.23 || ^9.5.10", + "nikic/php-parser": "^4.16" }, "config": { "sort-packages": true, diff --git a/phpcs.xml b/phpcs.xml index 15d1f034..68a24ee3 100755 --- a/phpcs.xml +++ b/phpcs.xml @@ -40,7 +40,6 @@ com - diff --git a/phpmd.xml b/phpmd.xml index b97e7d10..f0038972 100644 --- a/phpmd.xml +++ b/phpmd.xml @@ -5,7 +5,11 @@ xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd" xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"> - + + + + + @@ -27,7 +31,7 @@ - + diff --git a/phpstan.neon b/phpstan.neon index e05600cf..29b7ee3e 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,4 +1,5 @@ parameters: + phpVersion: 80200 level: max paths: - sl-src diff --git a/psalm.xml b/psalm.xml index 59c3c010..ed534dd4 100644 --- a/psalm.xml +++ b/psalm.xml @@ -5,7 +5,8 @@ xmlns="https://getpsalm.org/schema/config" xsi:schemaLocation="https://getpsalm.org/schema/config https://psalm.dev/schema/config" findUnusedBaselineEntry="true" - findUnusedCode="false" + phpVersion="8.2" + findUnusedCode = "false" > diff --git a/sl-src/CacheReader.php b/sl-src/CacheReader.php index 10e779fd..6ec584a8 100644 --- a/sl-src/CacheReader.php +++ b/sl-src/CacheReader.php @@ -15,6 +15,7 @@ use function array_merge; use function assert; use function filemtime; +use function is_string; use function max; use function rawurlencode; @@ -161,7 +162,7 @@ private function getLastModification(ReflectionClass $class): int // @phpstan-i $parent = $class->getParentClass(); $lastModification = max(array_merge( - [$filename ? filemtime($filename) : 0], + [is_string($filename) ? filemtime($filename) : 0], array_map(function (ReflectionClass $reflectionTrait): int { return $this->getTraitLastModificationTime($reflectionTrait); }, $class->getTraits()), @@ -185,7 +186,7 @@ private function getTraitLastModificationTime(ReflectionClass $reflectionTrait): } $lastModificationTime = max(array_merge( - [$fileName ? filemtime($fileName) : 0], + [is_string($fileName) ? filemtime($fileName) : 0], array_map(function (ReflectionClass $reflectionTrait): int { return $this->getTraitLastModificationTime($reflectionTrait); }, $reflectionTrait->getTraits()) diff --git a/src/AopClass.php b/src/AopClass.php deleted file mode 100644 index 5845084d..00000000 --- a/src/AopClass.php +++ /dev/null @@ -1,66 +0,0 @@ -aopClassName = $aopClassName; - $this->codeGenMethod = new CodeGenMethod($parser, $factory); - $this->traitStmt = $factory->useTrait('\Ray\Aop\InterceptTrait')->getNode(); - } - - /** - * {@inheritDoc} - * - * @param ReflectionClass $sourceClass - */ - public function __invoke(CodeVisitor $visitor, ReflectionClass $sourceClass, BindInterface $bind): Class_ - { - assert($visitor->class instanceof Class_); - $methods = $this->codeGenMethod->getMethods($sourceClass, $bind, $visitor); - $classStm = $visitor->class; - assert(class_exists($sourceClass->name)); - $newClassName = ($this->aopClassName)($sourceClass->name, (string) $bind); - $shortClassName = strpos($newClassName, '\\') === false ? $newClassName : substr((string) strrchr($newClassName, '\\'), 1); - $classStm->name = new Identifier($shortClassName); - $classStm->extends = new Name('\\' . $sourceClass->name); - $classStm->implements[] = new Name('\Ray\Aop\WeavedInterface'); - /** @var list $stmts */ - $stmts = array_merge([$this->traitStmt], $methods); - $classStm->stmts = $stmts; - - return $classStm; - } -} diff --git a/src/AopClassName.php b/src/AopClassName.php deleted file mode 100644 index 00892bdb..00000000 --- a/src/AopClassName.php +++ /dev/null @@ -1,28 +0,0 @@ -classDir = $classDir; - } - - /** @param class-string $class */ - public function __invoke(string $class, string $bindings): string - { - $fileTime = filemtime((string) (new ReflectionClass($class))->getFileName()); - - return sprintf('%s_%s', $class, crc32($fileTime . $bindings . $this->classDir)); - } -} diff --git a/src/AopCode.php b/src/AopCode.php new file mode 100644 index 00000000..831c09fc --- /dev/null +++ b/src/AopCode.php @@ -0,0 +1,193 @@ +_intercept(__FUNCTION__, func_get_args());'; + + /** @var string */ + private $code = ''; + + /** @var int */ + private $curlyBraceCount = 0; + + /** @var MethodSignatureString */ + private $methodSignature; + + public function __construct(MethodSignatureString $methodSignature) + { + $this->methodSignature = $methodSignature; + } + + /** @param ReflectionClass $sourceClass */ + public function generate(ReflectionClass $sourceClass, BindInterface $bind, string $postfix): string + { + $this->parseClass($sourceClass, $postfix); + $this->implementsInterface(WeavedInterface::class); + $this->addMethods($sourceClass, $bind); + + return $this->getCodeText(); + } + + /** @return void */ + private function add(string $text) + { + if ($text === '{') { + $this->curlyBraceCount++; + } + + if ($text === '}') { + // @codeCoverageIgnoreStart + $this->curlyBraceCount--; + // @codeCoverageIgnoreEnd + } + + $this->code .= $text; + } + + /** @param non-empty-string $code */ + private function insert(string $code): void + { + $replacement = $code . '}'; + $this->code = (string) preg_replace('/}\s*$/', $replacement, $this->code); + } + + private function addClassName(string $className, string $postfix): void + { + $newClassName = $className . $postfix; + $this->add($newClassName . ' extends ' . $className . ' '); + } + + /** @param ReflectionClass $sourceClass */ + private function parseClass(ReflectionClass $sourceClass, string $postfix): void + { + $fileName = (string) $sourceClass->getFileName(); + if (! file_exists($fileName)) { + throw new InvalidSourceClassException($sourceClass->getName()); + } + + $code = (string) file_get_contents($fileName); + /** @var array $tokens */ + $tokens = token_get_all($code); + $iterator = new TokenIterator($tokens); + $inClass = false; + $className = ''; + + for ($iterator->rewind(); $iterator->valid(); $iterator->next()) { + [$id, $text] = $iterator->getToken(); + $isClassKeyword = $id === T_CLASS; + if ($isClassKeyword) { + $inClass = true; + $this->add($text); + continue; + } + + $isClassName = $inClass && $id === T_STRING && empty($className); + if ($isClassName) { + $className = $text; + $this->addClassName($className, $postfix); + continue; + } + + $isExtendsKeyword = $id === T_EXTENDS; + if ($isExtendsKeyword) { + $iterator->skipExtends(); + continue; + } + + $isClassSignatureEnds = $inClass && $text === '{'; + if ($isClassSignatureEnds) { + $this->addIntercepterTrait(); + + return; + } + + $this->add($text); + } + } + + private function implementsInterface(string $interfaceName): void + { + $pattern = '/(class\s+[\w\s]+extends\s+\w+)(?:\s+implements\s+(.+))?/'; + $this->code = (string) preg_replace_callback($pattern, static function ($matches) use ($interfaceName) { + if (isset($matches[2])) { + // 既に implements が存在する場合 + // $match[0] class FakePhp8Types_test extends FakePhp8Types implements FakeNullInterface, \Ray\Aop\FakeNullInterface1 + // $match[1] class FakePhp8Types_test extends FakePhp8Types + // $match[2] FakeNullInterface, \Ray\Aop\FakeNullInterface1 + return sprintf('%s implements %s, \%s', $matches[1], $matches[2], $interfaceName); + } + + // implements が存在しない場合 + return sprintf('%s implements \%s', $matches[0], $interfaceName); + }, $this->code); + } + + /** @param ReflectionClass $class */ + private function addMethods(ReflectionClass $class, BindInterface $bind): void + { + $bindings = array_keys($bind->getBindings()); + + $parentMethods = $class->getMethods(); + $interceptedMethods = []; + foreach ($parentMethods as $method) { + if (! in_array($method->getName(), $bindings)) { + continue; + } + + $signature = $this->methodSignature->get($method); + $isVoid = false; + if ($method->hasReturnType() && (! $method->getReturnType() instanceof ReflectionUnionType)) { + $nt = $method->getReturnType(); + $isVoid = $nt instanceof ReflectionNamedType && $nt->getName() === 'void'; + } + + $return = $isVoid ? '' : 'return '; + $interceptedMethods[] = sprintf(" %s\n {\n %s%s\n }\n", $signature, $return, self::INTERCEPT_STATEMENT); + } + + if (! $interceptedMethods) { + return; + } + + $this->insert(implode("\n", $interceptedMethods)); + } + + private function addIntercepterTrait(): void + { + $this->add(sprintf("{\n use \%s;\n}\n", InterceptTrait::class)); + } + + private function getCodeText(): string + { + // close opened curly brace + while ($this->curlyBraceCount !== 0) { + $this->code .= '}'; + $this->curlyBraceCount--; + } + + return $this->code; + } +} diff --git a/src/AopPostfixClassName.php b/src/AopPostfixClassName.php new file mode 100644 index 00000000..a05c0f3f --- /dev/null +++ b/src/AopPostfixClassName.php @@ -0,0 +1,27 @@ +getFileName()); + $this->postFix = '_' . crc32($fileTime . $bindings); + $this->fqn = $class . $this->postFix; + } +} diff --git a/src/Bind.php b/src/Bind.php index 756ab063..9aeecb74 100644 --- a/src/Bind.php +++ b/src/Bind.php @@ -39,6 +39,10 @@ public function bind(string $class, array $pointcuts): BindInterface $reflectionClass = new ReflectionClass($class); $methods = $reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC); foreach ($methods as $method) { + if ($method->getName() === '__construct') { + continue; + } + $rayMethod = new ReflectionMethod($reflectionClass->getName(), $method->getName()); ($this->methodMatch)($reflectionClass, $rayMethod, $pointcuts); } diff --git a/src/CallIntercept.php b/src/CallIntercept.php deleted file mode 100644 index 10019c41..00000000 --- a/src/CallIntercept.php +++ /dev/null @@ -1,47 +0,0 @@ -_intercept(func_get_args(), __FUNCTION__); - * - * @var Expression - */ - private $expression; - - /** - * return $this->_intercept(func_get_args(), __FUNCTION__); - * - * @var Return_ - */ - private $return; - - public function __construct(BuilderFactory $factory) - { - $methodCall = $factory->methodCall( - $factory->var('this'), - '_intercept', - [$factory->funcCall('func_get_args'), $factory->constFetch('__FUNCTION__')] - ); - $this->expression = new Expression($methodCall); - $this->return = new Return_($methodCall); - } - - /** @return list|list */ - public function getStmts(?NodeAbstract $returnType): array - { - $isVoid = $returnType instanceof Identifier && ($returnType->name === 'void' || $returnType->name === 'never'); - - return $isVoid ? [$this->expression] : [$this->return]; - } -} diff --git a/src/Code.php b/src/Code.php deleted file mode 100644 index cf3cae73..00000000 --- a/src/Code.php +++ /dev/null @@ -1,46 +0,0 @@ - $stmt */ - public function __construct(array $stmt) - { - $this->code = (new Standard(['shortArraySyntax' => true]))->prettyPrintFile($stmt) . PHP_EOL; - } - - public function save(string $filename): string - { - $tmpFile = tempnam(dirname($filename), 'swap'); - if (is_string($tmpFile) && file_put_contents($tmpFile, $this->code) && rename($tmpFile, $filename)) { - return $filename; - } - - // @codeCoverageIgnoreStart - @unlink((string) $tmpFile); - - throw new NotWritableException(sprintf('swap: %s, file: %s', $tmpFile, $filename)); - - // @codeCoverageIgnoreEnd - } -} diff --git a/src/CodeGen.php b/src/CodeGen.php deleted file mode 100644 index 688fd0ac..00000000 --- a/src/CodeGen.php +++ /dev/null @@ -1,60 +0,0 @@ -factory = $factory; - $this->visitoryFactory = $visitorFactory; - $this->aopClass = $aopClass; - } - - /** - * {@inheritDoc} - * - * @param ReflectionClass $sourceClass - */ - public function generate(ReflectionClass $sourceClass, BindInterface $bind): Code - { - $visitor = ($this->visitoryFactory)($sourceClass); - $classStm = ($this->aopClass)($visitor, $sourceClass, $bind); - $ns = $this->getNamespace($visitor); - $stmt = $this->factory->namespace($ns) - ->addStmts($visitor->use) - ->addStmt($classStm) - ->getNode(); - - return new Code(array_merge($visitor->declare, [$stmt])); - } - - /** @return string|null */ - private function getNamespace(CodeVisitor $source) - { - $parts = isset($source->namespace->name) ? $source->namespace->name->getParts() : []; - $ns = implode('\\', $parts); - - return $ns ? $ns : null; - } -} diff --git a/src/CodeGenInterface.php b/src/CodeGenInterface.php deleted file mode 100644 index 349fbf81..00000000 --- a/src/CodeGenInterface.php +++ /dev/null @@ -1,13 +0,0 @@ - $sourceClass */ - public function generate(ReflectionClass $sourceClass, BindInterface $bind): Code; -} diff --git a/src/CodeGenMethod.php b/src/CodeGenMethod.php deleted file mode 100644 index 142848c9..00000000 --- a/src/CodeGenMethod.php +++ /dev/null @@ -1,82 +0,0 @@ -visitorFactory = new VisitorFactory($parser); - $this->callIntercept = new CallIntercept($factory); - } - - /** - * @param ReflectionClass $reflectionClass - * - * @return array - */ - public function getMethods(ReflectionClass $reflectionClass, BindInterface $bind, CodeVisitor $code): array - { - $bindingMethods = array_keys($bind->getBindings()); - $reflectionMethods = $reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC); - $methods = []; - foreach ($reflectionMethods as $reflectionMethod) { - $methodName = $reflectionMethod->getName(); - $isBindingMethod = in_array($methodName, $bindingMethods, true); - if ($isBindingMethod) { - $classMethod = $this->getClassMethod($reflectionClass, $reflectionMethod, $code); - // replace statements in the method - $classMethod->stmts = $this->callIntercept->getStmts($classMethod->getReturnType()); - $methods[] = new Nop(); - $methods[] = $classMethod; - } - } - - return $methods; - } - - /** @param ReflectionClass $sourceClass */ - private function getClassMethod( - ReflectionClass $sourceClass, - ReflectionMethod $bindingMethod, - CodeVisitor $code - ): ClassMethod { - $bindingMethodName = $bindingMethod->getName(); - foreach ($code->classMethod as $classMethod) { - if ($classMethod->name->name === $bindingMethodName) { - return $classMethod; - } - } - - $parentClass = $sourceClass->getParentClass(); - if ($parentClass === false) { - throw new InvalidSourceClassException($sourceClass->getName()); // @codeCoverageIgnore - } - - $code = ($this->visitorFactory)($parentClass); - - return $this->getClassMethod($parentClass, $bindingMethod, $code); - } -} diff --git a/src/CodeVisitor.php b/src/CodeVisitor.php deleted file mode 100644 index 25a70f9d..00000000 --- a/src/CodeVisitor.php +++ /dev/null @@ -1,91 +0,0 @@ -declare[] = $node; - - return null; - } - - if ($node instanceof Use_) { - $this->addUse($node); - - return null; - } - - if ($node instanceof Namespace_) { - $this->namespace = $node; - - return null; - } - - return $this->enterNodeClass($node); - } - - private function validateClass(Class_ $class): void - { - $isClassAlreadyDeclared = $this->class instanceof Class_; - if ($isClassAlreadyDeclared) { - $name = $class->name instanceof Node\Identifier ? $class->name->name : ''; - - throw new MultipleClassInOneFileException($name); - } - } - - /** @return null */ - private function enterNodeClass(Node $node) - { - if ($node instanceof Class_ && $node->name !== null) { - $this->validateClass($node); - $this->class = $node; - - return null; - } - - if ($node instanceof ClassMethod) { - $this->classMethod[] = $node; - } - - return null; - } - - private function addUse(Use_ $use): void - { - $index = implode('\\', $use->uses[0]->name->getParts()); - $this->use[$index] = $use; - } -} diff --git a/src/Compiler.php b/src/Compiler.php index c0ada691..2cd72cb5 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -5,29 +5,28 @@ namespace Ray\Aop; use Doctrine\Common\Annotations\AnnotationException; -use PhpParser\BuilderFactory; +use ParseError; +use Ray\Aop\Exception\CompilationFailedException; use Ray\Aop\Exception\NotWritableException; +use ReflectionClass; use function array_keys; use function assert; use function class_exists; use function file_exists; +use function file_put_contents; use function is_writable; use function method_exists; use function sprintf; use function str_replace; +use const PHP_VERSION_ID; + final class Compiler implements CompilerInterface { /** @var string */ public $classDir; - /** @var CodeGen */ - private $codeGen; - - /** @var AopClassName */ - private $aopClassName; - /** @throws AnnotationException */ public function __construct(string $classDir) { @@ -36,20 +35,6 @@ public function __construct(string $classDir) } $this->classDir = $classDir; - $this->aopClassName = new AopClassName($classDir); - $this->codeGen = $this->createCodeGen(); - } - - /** @return list */ - public function __sleep() - { - return ['classDir', 'aopClassName']; - } - - /** @throws AnnotationException */ - public function __wakeup() - { - $this->codeGen = $this->createCodeGen(); } /** @@ -80,15 +65,22 @@ public function compile(string $class, BindInterface $bind): string return $class; } - $aopClass = ($this->aopClassName)($class, (string) $bind); - if (class_exists($aopClass, false)) { - return $aopClass; + $className = new AopPostfixClassName($class, (string) $bind); + if (class_exists($className->fqn, false)) { + return $className->fqn; } - /** @var class-string $aopClass */ - $this->requireFile($aopClass, new ReflectionClass($class), $bind); + try { + $this->requireFile($className, new ReflectionClass($class), $bind); + // @codeCoverageIgnoreStart + } catch (ParseError $e) { + $msg = sprintf('class:%s Compilation failed in Ray.Aop. This is most likely a bug in Ray.Aop, please report it to the issue. https://github.com/ray-di/Ray.Aop/issues', $class); + + throw new CompilationFailedException($msg); + // @codeCoverageIgnoreEnd + } - return $aopClass; + return $className->fqn; } /** @param class-string $class */ @@ -105,29 +97,28 @@ private function hasBoundMethod(string $class, BindInterface $bind): bool $bindingMethods = array_keys($bind->getBindings()); $hasMethod = false; foreach ($bindingMethods as $bindingMethod) { - if (method_exists($class, $bindingMethod)) { - $hasMethod = true; + if (! method_exists($class, $bindingMethod)) { + continue; } + + $hasMethod = true; } return $hasMethod; } - /** - * @param class-string $aopClassName - * @param \ReflectionClass $sourceClass - */ - private function requireFile(string $aopClassName, \ReflectionClass $sourceClass, BindInterface $bind): void + /** @param ReflectionClass $sourceClass */ + private function requireFile(AopPostfixClassName $className, ReflectionClass $sourceClass, BindInterface $bind): void { - $file = $this->getFileName($aopClassName); + $file = $this->getFileName($className->fqn); if (! file_exists($file)) { - $code = $this->codeGen->generate($sourceClass, $bind); - $code->save($file); - assert(file_exists($file)); + $code = new AopCode(new MethodSignatureString(PHP_VERSION_ID)); + $aopCode = $code->generate($sourceClass, $bind, $className->postFix); + file_put_contents($file, $aopCode); } require_once $file; - class_exists($aopClassName); // ensure class is created + class_exists($className->fqn); // ensure class is created } private function getFileName(string $aopClassName): string @@ -136,16 +127,4 @@ private function getFileName(string $aopClassName): string return sprintf('%s/%s.php', $this->classDir, $flatName); } - - private function createCodeGen(): CodeGen - { - $parser = (new ParserFactory())->newInstance(); - $factory = new BuilderFactory(); - - return new CodeGen( - $factory, - new VisitorFactory($parser), - new AopClass($parser, $factory, $this->aopClassName) - ); - } } diff --git a/src/Exception/CompilationFailedException.php b/src/Exception/CompilationFailedException.php new file mode 100644 index 00000000..3d7291db --- /dev/null +++ b/src/Exception/CompilationFailedException.php @@ -0,0 +1,11 @@ + */ - private $bind; - - /** @var array */ + /** @var array>> */ public $bindings = []; /** @var bool */ @@ -26,7 +23,7 @@ trait InterceptTrait * * @SuppressWarnings(PHPMD.CamelCaseMethodName) */ - private function _intercept(array $args, string $func) // phpcs:ignore + private function _intercept(string $func, array $args) // phpcs:ignore { if (! $this->isAspect) { $this->isAspect = true; diff --git a/src/Matcher/AnyMatcher.php b/src/Matcher/AnyMatcher.php index ada1e8f2..2ba893f1 100644 --- a/src/Matcher/AnyMatcher.php +++ b/src/Matcher/AnyMatcher.php @@ -21,9 +21,11 @@ public function __construct() { parent::__construct(); - if (self::$builtinMethods === []) { - $this->setBuildInMethods(); + if (self::$builtinMethods !== []) { + return; } + + $this->setBuildInMethods(); } /** diff --git a/src/MethodMatch.php b/src/MethodMatch.php index 4929cb81..a066dda6 100644 --- a/src/MethodMatch.php +++ b/src/MethodMatch.php @@ -30,10 +30,12 @@ public function __invoke(ReflectionClass $class, \Ray\Aop\ReflectionMethod $meth $annotations = $method->getAnnotations(); // priority bind foreach ($pointcuts as $key => $pointcut) { - if ($pointcut instanceof PriorityPointcut) { - $this->annotatedMethodMatchBind($class, $method, $pointcut); - unset($pointcuts[$key]); + if (! ($pointcut instanceof PriorityPointcut)) { + continue; } + + $this->annotatedMethodMatchBind($class, $method, $pointcut); + unset($pointcuts[$key]); } $onion = $this->onionOrderMatch($class, $method, $pointcuts, $annotations); @@ -78,10 +80,12 @@ private function onionOrderMatch( // method bind in annotation order foreach ($annotations as $annotation) { $annotationIndex = get_class($annotation); - if (array_key_exists($annotationIndex, $pointcuts)) { - $this->annotatedMethodMatchBind($class, $method, $pointcuts[$annotationIndex]); - unset($pointcuts[$annotationIndex]); + if (! array_key_exists($annotationIndex, $pointcuts)) { + continue; } + + $this->annotatedMethodMatchBind($class, $method, $pointcuts[$annotationIndex]); + unset($pointcuts[$annotationIndex]); } return $pointcuts; diff --git a/src/MethodSignatureString.php b/src/MethodSignatureString.php new file mode 100644 index 00000000..c0dbea73 --- /dev/null +++ b/src/MethodSignatureString.php @@ -0,0 +1,111 @@ += 80000 ? 'null|' : '?'; + $this->typeString = new TypeString($nullableStr); + } + + /** + * @psalm-suppress MixedArgument + * @psalm-suppress MixedMethodCall + */ + public function get(ReflectionMethod $method): string + { + $signatureParts = []; + + // PHPDocを取得 + $docComment = $method->getDocComment(); + if (is_string($docComment)) { + $signatureParts[] = $docComment . PHP_EOL; + } + + // アトリビュートを取得 (PHP 8.0+ の場合のみ) + if (PHP_MAJOR_VERSION >= 8) { + /** @psalm-suppress MixedAssignment */ + foreach ($method->getAttributes() as $attribute) { + $argsList = $attribute->getArguments(); + $formattedArgs = []; + + foreach ($argsList as $name => $value) { + $formattedValue = preg_replace('/\s+/', ' ', var_export($value, true)); + $argRepresentation = is_numeric($name) ? $formattedValue : "{$name}: {$formattedValue}"; + $formattedArgs[] = $argRepresentation; + } + + $signatureParts[] = sprintf(' #[\\%s(%s)]', $attribute->getName(), implode(', ', $formattedArgs)) . PHP_EOL; + } + } + + if ($signatureParts) { + $signatureParts[] = ' '; // インデント追加 + } + + // アクセス修飾子を取得 + $modifier = implode(' ', Reflection::getModifierNames($method->getModifiers())); + $signatureParts[] = $modifier; + + // メソッド名とパラメータを取得 + $params = []; + foreach ($method->getParameters() as $param) { + $params[] = $this->generateParameterCode($param); + } + + $returnType = ''; + $rType = $method->getReturnType(); + if ($rType) { + $returnType = ': ' . ($this->typeString)($rType); + } + + $parmsList = implode(', ', $params); + + $signatureParts[] = sprintf('function %s(%s)%s', $method->getName(), $parmsList, $returnType); + + return implode(' ', $signatureParts); + } + + public function generateParameterCode(ReflectionParameter $param): string + { + $typeStr = ($this->typeString)($param->getType()); + $typeStrWithSpace = $typeStr ? $typeStr . ' ' : $typeStr; + // Variadicのチェック + $variadicStr = $param->isVariadic() ? '...' : ''; + + // 参照渡しのチェック + $referenceStr = $param->isPassedByReference() ? '&' : ''; + + // デフォルト値のチェック + $defaultStr = ''; + if ($param->isDefaultValueAvailable()) { + $default = var_export($param->getDefaultValue(), true); + $defaultStr = ' = ' . str_replace(["\r", "\n"], '', $default); + } + + return "{$typeStrWithSpace}{$referenceStr}{$variadicStr}\${$param->getName()}{$defaultStr}"; + } +} diff --git a/src/ParserFactory.php b/src/ParserFactory.php deleted file mode 100644 index 5a0371d0..00000000 --- a/src/ParserFactory.php +++ /dev/null @@ -1,16 +0,0 @@ -create(PhpParserFactory::PREFER_PHP7); - } -} diff --git a/src/ReflectionClass.php b/src/ReflectionClass.php index 6f1c7115..6e682309 100644 --- a/src/ReflectionClass.php +++ b/src/ReflectionClass.php @@ -5,6 +5,7 @@ namespace Ray\Aop; use Ray\ServiceLocator\ServiceLocator; +use ReturnTypeWillChange; use function get_class_methods; @@ -74,4 +75,17 @@ public function getConstructor(): ?ReflectionMethod return new ReflectionMethod($parent->class, $parent->name); } + + /** + * @return ReflectionClass|false + * + * @psalm-external-mutation-free + */ + #[ReturnTypeWillChange] + public function getParentClass() + { + $parent = \ReflectionClass::getParentClass(); + + return $parent instanceof \ReflectionClass ? (new ReflectionClass($parent->getName())) : false; + } } diff --git a/src/ReflectiveMethodInvocation.php b/src/ReflectiveMethodInvocation.php index 63168bf8..d5e835cc 100644 --- a/src/ReflectiveMethodInvocation.php +++ b/src/ReflectiveMethodInvocation.php @@ -8,7 +8,6 @@ use ReflectionClass; use ReflectionObject; -use function array_key_exists; use function array_shift; use function assert; use function call_user_func_array; @@ -87,11 +86,9 @@ public function getNamedArguments(): ArrayObject $namedParams = []; foreach ($params as $param) { $pos = $param->getPosition(); - if (array_key_exists($pos, (array) $args)) { - $name = $param->getName(); - /** @psalm-suppress MixedAssignment */ - $namedParams[$name] = $args[$pos]; - } + $name = $param->getName(); + /** @psalm-suppress MixedAssignment */ + $namedParams[$name] = $args[$pos]; } return new ArrayObject($namedParams); // @phpstan-ignore-line diff --git a/src/TokenIterator.php b/src/TokenIterator.php new file mode 100644 index 00000000..58c1b9dd --- /dev/null +++ b/src/TokenIterator.php @@ -0,0 +1,33 @@ + + */ +final class TokenIterator extends ArrayIterator +{ + /** @return array{int, string} */ + public function getToken(): array + { + /** @var array{int, string, int}|string $token */ + $token = $this->current(); + + return is_array($token) ? [$token[0], $token[1]] : [0, $token]; + } + + public function skipExtends(): void + { + $this->next(); // Skip extends keyword + $this->next(); // Skip parent class name + $this->next(); // Skip space + } +} diff --git a/src/TypeString.php b/src/TypeString.php new file mode 100644 index 00000000..98290819 --- /dev/null +++ b/src/TypeString.php @@ -0,0 +1,91 @@ +nullableStr = $nullableStr; + } + + public function __invoke(?ReflectionType $type): string + { + if (! $type) { + return ''; + } + + // PHP 8.0+ + if (class_exists('ReflectionUnionType') && $type instanceof ReflectionUnionType) { + return $this->getUnionType($type); + } + + if ($type instanceof ReflectionNamedType) { + $typeStr = self::getFqnType($type); + // Check for Nullable in single types + if ($type->allowsNull() && $type->getName() !== 'null') { + $typeStr = $this->nullableStr . $typeStr; + } + + return $typeStr; + } + + assert($type instanceof ReflectionIntersectionType); + + return $this->intersectionTypeToString($type); + } + + private function intersectionTypeToString(ReflectionIntersectionType $intersectionType): string + { + $types = $intersectionType->getTypes(); + /** @var array $types */ + $typeStrings = array_map(static function (ReflectionNamedType $type): string { + return '\\' . $type->getName(); + }, $types); + + return implode(' & ', $typeStrings); + } + + public function getUnionType(ReflectionUnionType $type): string + { + $types = array_map(static function ($t) { + if ($t instanceof ReflectionIntersectionType) { + $types = $t->getTypes(); + /** @var array $types */ + $intersectionTypes = array_map(static function (ReflectionNamedType $t): string { + return self::getFqnType($t); + }, $types); + + return sprintf('(%s)', implode('&', $intersectionTypes)); + } + + return self::getFqnType($t); + }, $type->getTypes()); + + return implode('|', $types); + } + + private static function getFqnType(ReflectionNamedType $namedType): string + { + $type = $namedType->getName(); + $isBuiltin = $namedType->isBuiltin() || $type === 'static' || $type === 'self'; + + return $isBuiltin ? $type : '\\' . $type; + } +} diff --git a/src/VisitorFactory.php b/src/VisitorFactory.php deleted file mode 100644 index b29ed534..00000000 --- a/src/VisitorFactory.php +++ /dev/null @@ -1,54 +0,0 @@ -parser = $parser; - } - - /** @param ReflectionClass $class */ - public function __invoke(ReflectionClass $class): CodeVisitor - { - $traverser = new NodeTraverser(); - $nameResolver = new NameResolver(); - $visitor = new CodeVisitor(); - $traverser->addVisitor($nameResolver); - $traverser->addVisitor($visitor); - $fileName = $class->getFileName(); - if (is_bool($fileName)) { - throw new InvalidSourceClassException(get_class($class)); - } - - $file = file_get_contents($fileName); - if ($file === false) { - throw new RuntimeException($fileName); // @codeCoverageIgnore - } - - $stmts = $this->parser->parse($file); - if (is_array($stmts)) { - $traverser->traverse($stmts); - } - - return $visitor; - } -} diff --git a/src/Weaver.php b/src/Weaver.php index 0306f1fa..dfb7ee62 100644 --- a/src/Weaver.php +++ b/src/Weaver.php @@ -21,9 +21,6 @@ final class Weaver /** @var string */ private $classDir; - /** @var AopClassName */ - private $aopClassName; - /** @var Compiler */ private $compiler; @@ -33,7 +30,6 @@ public function __construct(BindInterface $bind, string $classDir) $this->bindName = (string) $bind; $this->compiler = new Compiler($classDir); $this->classDir = $classDir; - $this->aopClassName = new AopClassName($classDir); } /** @@ -62,21 +58,21 @@ public function newInstance(string $class, array $args): object */ public function weave(string $class): string { - $aopClass = ($this->aopClassName)($class, $this->bindName); - if (class_exists($aopClass, false)) { - return $aopClass; + $aopClass = new AopPostfixClassName($class, $this->bindName); + if (class_exists($aopClass->fqn, false)) { + return $aopClass->fqn; } - if ($this->loadClass($aopClass)) { - assert(class_exists($aopClass)); + if ($this->loadClass($aopClass->fqn)) { + assert(class_exists($aopClass->fqn)); - return $aopClass; + return $aopClass->fqn; } $this->compiler->compile($class, $this->bind); - assert(class_exists($aopClass)); + assert(class_exists($aopClass->fqn)); - return $aopClass; + return $aopClass->fqn; } private function loadClass(string $class): bool diff --git a/tests/CodeGenPhp71Test.php b/tests-deprecated/CodeGenPhp71Test.php similarity index 95% rename from tests/CodeGenPhp71Test.php rename to tests-deprecated/CodeGenPhp71Test.php index 55a1e696..62e0cfe2 100644 --- a/tests/CodeGenPhp71Test.php +++ b/tests-deprecated/CodeGenPhp71Test.php @@ -2,11 +2,17 @@ declare(strict_types=1); -namespace Ray\Aop; use PhpParser\BuilderFactory; use PHPUnit\Framework\TestCase; -use ReflectionClass; +use Ray\Aop\AopClass; +use Ray\Aop\AopClassName; +use Ray\Aop\Bind; +use Ray\Aop\Code; +use Ray\Aop\CodeGen; +use Ray\Aop\FakePhp71NullableClass; +use Ray\Aop\ParserFactory; +use Ray\Aop\VisitorFactory; class CodeGenPhp71Test extends TestCase { diff --git a/tests/CodeGenTest.php b/tests-deprecated/CodeGenTest.php similarity index 88% rename from tests/CodeGenTest.php rename to tests-deprecated/CodeGenTest.php index 57ce33ee..ba739839 100644 --- a/tests/CodeGenTest.php +++ b/tests-deprecated/CodeGenTest.php @@ -2,13 +2,18 @@ declare(strict_types=1); -namespace Ray\Aop; use PhpParser\BuilderFactory; use PHPUnit\Framework\TestCase; +use Ray\Aop\AopClass; +use Ray\Aop\AopClassName; +use Ray\Aop\Bind; +use Ray\Aop\CodeGen; use Ray\Aop\Exception\InvalidSourceClassException; -use ReflectionClass; -use stdClass; +use Ray\Aop\FakePhp7Class; +use Ray\Aop\FakePhp7ReturnTypeClass; +use Ray\Aop\ParserFactory; +use Ray\Aop\VisitorFactory; class CodeGenTest extends TestCase { diff --git a/tests/ParserFactoryTest.php b/tests-deprecated/ParserFactoryTest.php similarity index 90% rename from tests/ParserFactoryTest.php rename to tests-deprecated/ParserFactoryTest.php index e999b965..6f9f38a3 100644 --- a/tests/ParserFactoryTest.php +++ b/tests-deprecated/ParserFactoryTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Ray\Aop; use PHPUnit\Framework\TestCase; +use Ray\Aop\ParserFactory; class ParserFactoryTest extends TestCase { diff --git a/tests/AopCodeTest.php b/tests/AopCodeTest.php new file mode 100644 index 00000000..71e0d92f --- /dev/null +++ b/tests/AopCodeTest.php @@ -0,0 +1,120 @@ +codeGen = new AopCode(new MethodSignatureString(PHP_VERSION_ID)); + } + + public function testTypeDeclarations(): void + { + $bind = new Bind(); + $bind->bindInterceptors('run', []); + $code = $this->codeGen->generate(new ReflectionClass(FakePhp7Class::class), $bind, '_test'); + $expected = 'function run(string $a, int $b, float $c, bool $d): array'; + $this->assertStringContainsString($expected, $code); + } + + public function testReturnType(): void + { + $bind = new Bind(); + $bind->bindInterceptors('returnTypeArray', []); + $code = $this->codeGen->generate(new ReflectionClass(FakePhp7ReturnTypeClass::class), $bind, '_test'); + $expected = 'function returnTypeArray(): array'; + $this->assertStringContainsString($expected, $code); + } + + /** @requires PHP 8.1 */ + public function testVariousMethodSignature(): void + { + $bind = new Bind(); + for ($i = 1; $i <= 22; $i++) { + $bind->bindInterceptors('method' . (string) $i, []); + } + + $code = $this->codeGen->generate(new ReflectionClass(FakePhp8Types::class), $bind, '_test'); + $tempFile = tempnam(sys_get_temp_dir(), 'tmp_') . '.php'; + file_put_contents($tempFile, $code); + require $tempFile; + unlink($tempFile); + $this->assertTrue(class_exists('\Ray\Aop\FakePhp8Types_test')); + + $this->assertStringContainsString('public function method1($param1)', $code); + $this->assertStringContainsString('public function method2(string $param1)', $code); + $this->assertStringContainsString('public function method3(int $param1)', $code); + $this->assertStringContainsString('public function method4(null|string $param1)', $code); + $this->assertStringContainsString('public function method5(null|int $param1)', $code); + $this->assertStringContainsString('public function method6(string $param1 = \'default\')', $code); + $this->assertStringContainsString('public function method7(null|int $param1 = NULL)', $code); + $this->assertStringContainsString('public function method8(&$param1)', $code); + $this->assertStringContainsString('public function method9(array $param1)', $code); + $this->assertStringContainsString('public function method10(null|array $param1)', $code); + $this->assertStringContainsString('public function method11(...$params)', $code); + $this->assertStringContainsString('public function method12(string|int $param1)', $code); + $this->assertStringContainsString('public function method13(\\DateTime|string $param1)', $code); + $this->assertStringContainsString('public function method14(string|int|null $param1)', $code); + $this->assertStringContainsString('public function method15(\DateTime|string|null $param1)', $code); + $this->assertStringContainsString('public function method16(): string', $code); + $this->assertStringContainsString('public function method17(): \\DateTime', $code); + $this->assertStringContainsString('public function method18(): string|int', $code); + $this->assertStringContainsString('public function method19(): string|int|null', $code); + $this->assertStringContainsString('public function method20(): \DateTime|string|null', $code); + $this->assertStringContainsString(' /** + * PHPDoc + */ + #[\\Ray\\Aop\\Annotation\\FakeMarker4(array ( 0 => 1, 1 => 2, ), 3)] + public function method21()', $code); + $this->assertStringContainsString('#[\\Ray\\Aop\\Annotation\\FakeMarkerName(a: 1, b: \'string\', c: true)] + public function method22()', $code); + } + + /** @requires PHP 8.2 */ + public function testVariousMethodSignaturePhp82(): void + { + $bind = new Bind(); + for ($i = 100; $i <= 106; $i++) { + $bind->bindInterceptors('method' . (string) $i, []); + } + + $code = $this->codeGen->generate(new ReflectionClass(FakePhp82Types::class), $bind, '_test'); + $tempFile = tempnam(sys_get_temp_dir(), 'tmp_') . '.php'; + file_put_contents($tempFile, $code); + require $tempFile; + unlink($tempFile); + $this->assertTrue(class_exists('\Ray\Aop\FakePhp82Types_test')); + $this->assertStringContainsString('public function method100(): false', $code); + $this->assertStringContainsString('public function method101(): true', $code); + $this->assertStringContainsString('public function method102(): null', $code); + $this->assertStringContainsString('public function method103(): \Ray\Aop\FakeNullInterface & \Ray\Aop\FakeNullInterface1', $code); + $this->assertStringContainsString('public function method104(): \Ray\Aop\FakeNullInterface|\Ray\Aop\FakeNullInterface1', $code); + $this->assertStringContainsString('public function method105(): \Ray\Aop\FakeNullInterface|string', $code); + $this->assertStringContainsString('public function method106(): (\Ray\Aop\FakeNullInterface&\Ray\Aop\FakeNullInterface1)|string', $code); + } + + public function testInvalidSourceClass(): void + { + $this->expectException(InvalidSourceClassException::class); + $this->codeGen->generate(new ReflectionClass(stdClass::class), new Bind(), '_test'); + } +} diff --git a/tests/BindTest.php b/tests/BindTest.php index 5d47919d..9866f66c 100644 --- a/tests/BindTest.php +++ b/tests/BindTest.php @@ -40,6 +40,15 @@ public function testBind(): void $this->assertSame($this->bind->getBindings()['getDouble'], $interceptors); } + public function testBindWithConstructor(): void + { + $interceptors = [new FakeDoubleInterceptor()]; + $pointcut = new Pointcut((new Matcher())->startsWith('Ray'), (new Matcher())->startsWith('get'), $interceptors); + $this->bind->bind(FakeConstructorClass::class, [$pointcut]); + $this->assertArrayHasKey('getDouble', $this->bind->getBindings()); + $this->assertSame($this->bind->getBindings()['getDouble'], $interceptors); + } + public function testBindUnmatched(): void { $interceptors = [new FakeDoubleInterceptor()]; diff --git a/tests/CompilerTest.php b/tests/CompilerTest.php index a6f6b196..364b6a65 100644 --- a/tests/CompilerTest.php +++ b/tests/CompilerTest.php @@ -12,7 +12,6 @@ use PHPUnit\Framework\TestCase; use Ray\Aop\Annotation\FakeMarker; use Ray\Aop\Annotation\FakeMarker3; -use Ray\Aop\Exception\MultipleClassInOneFileException; use Ray\Aop\Exception\NotWritableException; use ReflectionClass; use ReflectionMethod; @@ -116,8 +115,8 @@ public function testMethodReturnValue(FakeMock $weaved): void public function testParentMethodIntercept(): void { - $mock = $this->compiler->newInstance(FakeMockChild::class, [], $this->bind); - assert($mock instanceof FakeMockChild); + $mock = $this->compiler->newInstance(FakeMockGrandChild::class, [], $this->bind); + assert($mock instanceof FakeMockGrandChild); assert(property_exists($mock, 'bindings')); $mock->bindings = $this->bind->getBindings(); $result = $mock->returnSame(1); @@ -127,8 +126,8 @@ public function testParentMethodIntercept(): void public function testTypedParentMethodIntercept(): void { $bind = (new Bind())->bindInterceptors('passIterator', [new NullInterceptor()]); - $mock = $this->compiler->newInstance(FakeTypedMockChild::class, [], $bind); - assert($mock instanceof FakeTypedMockChild); + $mock = $this->compiler->newInstance(FakeTypedMockGrandChild::class, [], $bind); + assert($mock instanceof FakeTypedMockGrandChild); assert(property_exists($mock, 'bindings')); $mock->bindings = $bind->getBindings(); $result = $mock->passIterator(new ArrayIterator()); @@ -337,14 +336,6 @@ public function testVoidFunction(): void $this->assertTrue($mock->returnTypeVoidCalled); } - public function testCompileMultipleFile(): void - { - $this->expectException(MultipleClassInOneFileException::class); - $compiler = new Compiler(__DIR__ . '/tmp'); - $bind = (new Bind())->bindInterceptors('foo', [new FakeDoubleInterceptor()]); - $compiler->newInstance(FakeTwoClass::class, [], $bind); - } - public function testNewInstanceWithAnonymousClass(): void { $mock = $this->compiler->newInstance(FakeAnonymousClass::class, [], $this->bind); diff --git a/tests/Fake/Annotation/FakeMarker4.php b/tests/Fake/Annotation/FakeMarker4.php new file mode 100644 index 00000000..10063623 --- /dev/null +++ b/tests/Fake/Annotation/FakeMarker4.php @@ -0,0 +1,25 @@ +a = $a; + $this->b = $b; + } +} diff --git a/tests/Fake/Annotation/FakeMarkerName.php b/tests/Fake/Annotation/FakeMarkerName.php new file mode 100644 index 00000000..ebaf581b --- /dev/null +++ b/tests/Fake/Annotation/FakeMarkerName.php @@ -0,0 +1,33 @@ +a = $a; + $this->b = $b; + $this->c = $c; + } +} diff --git a/tests/Fake/FakeConstructorClass.php b/tests/Fake/FakeConstructorClass.php new file mode 100644 index 00000000..89dd9215 --- /dev/null +++ b/tests/Fake/FakeConstructorClass.php @@ -0,0 +1,17 @@ +assertInstanceOf(ReflectionMethod::class, $item); } } + + public function testGetParentClass(): void + { + $this->assertInstanceOf(ReflectionClass::class, (new ReflectionClass(FakeMockChild::class))->getParentClass()); + } } diff --git a/tests/tmp_unerase/Ray_Aop_FakeWeaverMock_2665014008.php b/tests/tmp_unerase/Ray_Aop_FakeWeaverMock_2665014008.php new file mode 100644 index 00000000..267215d5 --- /dev/null +++ b/tests/tmp_unerase/Ray_Aop_FakeWeaverMock_2665014008.php @@ -0,0 +1,35 @@ +_intercept(func_get_args(), __FUNCTION__); + } + + /** + * doc comment of getSub + */ + public function getSub($a, $b) + { + return $this->_intercept(func_get_args(), __FUNCTION__); + } + + public function returnValue(?\Ray\Aop\FakeNum $num = NULL) + { + return $this->_intercept(func_get_args(), __FUNCTION__); + } + + public function getPrivateVal() + { + return $this->_intercept(func_get_args(), __FUNCTION__); + } +} diff --git a/vendor-bin/tools/composer.lock b/vendor-bin/tools/composer.lock index da7f6cec..d8d68835 100644 --- a/vendor-bin/tools/composer.lock +++ b/vendor-bin/tools/composer.lock @@ -9,16 +9,16 @@ "packages-dev": [ { "name": "amphp/amp", - "version": "v2.6.2", + "version": "v2.6.4", "source": { "type": "git", "url": "https://github.com/amphp/amp.git", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb" + "reference": "ded3d9be08f526089eb7ee8d9f16a9768f9dec2d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", + "url": "https://api.github.com/repos/amphp/amp/zipball/ded3d9be08f526089eb7ee8d9f16a9768f9dec2d", + "reference": "ded3d9be08f526089eb7ee8d9f16a9768f9dec2d", "shasum": "" }, "require": { @@ -30,8 +30,8 @@ "ext-json": "*", "jetbrains/phpstorm-stubs": "^2019.3", "phpunit/phpunit": "^7 | ^8 | ^9", - "psalm/phar": "^3.11@dev", - "react/promise": "^2" + "react/promise": "^2", + "vimeo/psalm": "^3.12" }, "type": "library", "extra": { @@ -86,7 +86,7 @@ "support": { "irc": "irc://irc.freenode.org/amphp", "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v2.6.2" + "source": "https://github.com/amphp/amp/tree/v2.6.4" }, "funding": [ { @@ -94,20 +94,20 @@ "type": "github" } ], - "time": "2022-02-20T17:52:18+00:00" + "time": "2024-03-21T18:52:26+00:00" }, { "name": "amphp/byte-stream", - "version": "v1.8.1", + "version": "v1.8.2", "source": { "type": "git", "url": "https://github.com/amphp/byte-stream.git", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd" + "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/4f0e968ba3798a423730f567b1b50d3441c16ddc", + "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc", "shasum": "" }, "require": { @@ -123,11 +123,6 @@ "psalm/phar": "^3.11.4" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, "autoload": { "files": [ "lib/functions.php" @@ -151,7 +146,7 @@ } ], "description": "A stream abstraction to make working with non-blocking I/O simple.", - "homepage": "http://amphp.org/byte-stream", + "homepage": "https://amphp.org/byte-stream", "keywords": [ "amp", "amphp", @@ -161,9 +156,8 @@ "stream" ], "support": { - "irc": "irc://irc.freenode.org/amphp", "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v1.8.1" + "source": "https://github.com/amphp/byte-stream/tree/v1.8.2" }, "funding": [ { @@ -171,20 +165,20 @@ "type": "github" } ], - "time": "2021-03-30T17:13:30+00:00" + "time": "2024-04-13T18:00:56+00:00" }, { "name": "composer/pcre", - "version": "3.1.0", + "version": "3.1.3", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2" + "reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", - "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", + "url": "https://api.github.com/repos/composer/pcre/zipball/5b16e25a5355f1f3afdfc2f954a0a80aec4826a8", + "reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8", "shasum": "" }, "require": { @@ -226,7 +220,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.1.0" + "source": "https://github.com/composer/pcre/tree/3.1.3" }, "funding": [ { @@ -242,7 +236,7 @@ "type": "tidelift" } ], - "time": "2022-11-17T09:50:14+00:00" + "time": "2024-03-19T10:26:25+00:00" }, { "name": "composer/semver", @@ -327,16 +321,16 @@ }, { "name": "composer/xdebug-handler", - "version": "3.0.3", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "ced299686f41dce890debac69273b47ffe98a40c" + "reference": "4f988f8fdf580d53bdb2d1278fe93d1ed5462255" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", - "reference": "ced299686f41dce890debac69273b47ffe98a40c", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/4f988f8fdf580d53bdb2d1278fe93d1ed5462255", + "reference": "4f988f8fdf580d53bdb2d1278fe93d1ed5462255", "shasum": "" }, "require": { @@ -347,7 +341,7 @@ "require-dev": { "phpstan/phpstan": "^1.0", "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^6.0" + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" }, "type": "library", "autoload": { @@ -371,9 +365,9 @@ "performance" ], "support": { - "irc": "irc://irc.freenode.org/composer", + "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" + "source": "https://github.com/composer/xdebug-handler/tree/3.0.4" }, "funding": [ { @@ -389,7 +383,7 @@ "type": "tidelift" } ], - "time": "2022-02-25T21:32:43+00:00" + "time": "2024-03-26T18:29:49+00:00" }, { "name": "dealerdirect/phpcodesniffer-composer-installer", @@ -564,16 +558,16 @@ }, { "name": "doctrine/deprecations", - "version": "v1.1.1", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", - "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", "shasum": "" }, "require": { @@ -605,9 +599,9 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" + "source": "https://github.com/doctrine/deprecations/tree/1.1.3" }, - "time": "2023-06-03T09:27:29+00:00" + "time": "2024-01-30T19:34:25+00:00" }, { "name": "felixfbecker/advanced-json-rpc", @@ -712,16 +706,16 @@ }, { "name": "fidry/cpu-core-counter", - "version": "0.5.1", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "b58e5a3933e541dc286cc91fc4f3898bbc6f1623" + "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/b58e5a3933e541dc286cc91fc4f3898bbc6f1623", - "reference": "b58e5a3933e541dc286cc91fc4f3898bbc6f1623", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/f92996c4d5c1a696a6a970e20f7c4216200fcc42", + "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42", "shasum": "" }, "require": { @@ -729,13 +723,13 @@ }, "require-dev": { "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", "phpstan/extension-installer": "^1.2.0", "phpstan/phpstan": "^1.9.2", "phpstan/phpstan-deprecation-rules": "^1.0.0", "phpstan/phpstan-phpunit": "^1.2.2", "phpstan/phpstan-strict-rules": "^1.4.4", - "phpunit/phpunit": "^9.5.26 || ^8.5.31", - "theofidry/php-cs-fixer-config": "^1.0", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", "webmozarts/strict-phpunit": "^7.5" }, "type": "library", @@ -761,7 +755,7 @@ ], "support": { "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/0.5.1" + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.1.0" }, "funding": [ { @@ -769,20 +763,20 @@ "type": "github" } ], - "time": "2022-12-24T12:35:10+00:00" + "time": "2024-02-07T09:43:46+00:00" }, { "name": "netresearch/jsonmapper", - "version": "v4.2.0", + "version": "v4.4.1", "source": { "type": "git", "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "f60565f8c0566a31acf06884cdaa591867ecc956" + "reference": "132c75c7dd83e45353ebb9c6c9f591952995bbf0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/f60565f8c0566a31acf06884cdaa591867ecc956", - "reference": "f60565f8c0566a31acf06884cdaa591867ecc956", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/132c75c7dd83e45353ebb9c6c9f591952995bbf0", + "reference": "132c75c7dd83e45353ebb9c6c9f591952995bbf0", "shasum": "" }, "require": { @@ -793,7 +787,7 @@ "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", + "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0 || ~10.0", "squizlabs/php_codesniffer": "~3.5" }, "type": "library", @@ -818,27 +812,27 @@ "support": { "email": "cweiske@cweiske.de", "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.2.0" + "source": "https://github.com/cweiske/jsonmapper/tree/v4.4.1" }, - "time": "2023-04-09T17:37:40+00:00" + "time": "2024-01-31T06:18:54+00:00" }, { "name": "nikic/php-parser", - "version": "v4.17.1", + "version": "v4.19.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" + "reference": "4e1b88d21c69391150ace211e9eaf05810858d0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4e1b88d21c69391150ace211e9eaf05810858d0b", + "reference": "4e1b88d21c69391150ace211e9eaf05810858d0b", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=7.0" + "php": ">=7.1" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", @@ -874,34 +868,34 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.1" }, - "time": "2023-08-13T19:53:39+00:00" + "time": "2024-03-17T08:10:35+00:00" }, { "name": "pdepend/pdepend", - "version": "2.14.0", + "version": "2.16.2", "source": { "type": "git", "url": "https://github.com/pdepend/pdepend.git", - "reference": "1121d4b04af06e33e9659bac3a6741b91cab1de1" + "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pdepend/pdepend/zipball/1121d4b04af06e33e9659bac3a6741b91cab1de1", - "reference": "1121d4b04af06e33e9659bac3a6741b91cab1de1", + "url": "https://api.github.com/repos/pdepend/pdepend/zipball/f942b208dc2a0868454d01b29f0c75bbcfc6ed58", + "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58", "shasum": "" }, "require": { "php": ">=5.3.7", - "symfony/config": "^2.3.0|^3|^4|^5|^6.0", - "symfony/dependency-injection": "^2.3.0|^3|^4|^5|^6.0", - "symfony/filesystem": "^2.3.0|^3|^4|^5|^6.0" + "symfony/config": "^2.3.0|^3|^4|^5|^6.0|^7.0", + "symfony/dependency-injection": "^2.3.0|^3|^4|^5|^6.0|^7.0", + "symfony/filesystem": "^2.3.0|^3|^4|^5|^6.0|^7.0", + "symfony/polyfill-mbstring": "^1.19" }, "require-dev": { "easy-doc/easy-doc": "0.0.0|^1.2.3", "gregwar/rst": "^1.0", - "phpunit/phpunit": "^4.8.36|^5.7.27", "squizlabs/php_codesniffer": "^2.0.0" }, "bin": [ @@ -931,7 +925,7 @@ ], "support": { "issues": "https://github.com/pdepend/pdepend/issues", - "source": "https://github.com/pdepend/pdepend/tree/2.14.0" + "source": "https://github.com/pdepend/pdepend/tree/2.16.2" }, "funding": [ { @@ -939,7 +933,7 @@ "type": "tidelift" } ], - "time": "2023-05-26T13:15:18+00:00" + "time": "2023-12-17T18:09:59+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -996,28 +990,35 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", + "version": "5.4.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" + "reference": "298d2febfe79d03fe714eb871d5538da55205b1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/298d2febfe79d03fe714eb871d5538da55205b1a", + "reference": "298d2febfe79d03fe714eb871d5538da55205b1a", "shasum": "" }, "require": { + "doctrine/deprecations": "^1.1", "ext-filter": "*", - "php": "^7.2 || ^8.0", + "php": "^7.4 || ^8.0", "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7", "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" + "mockery/mockery": "~1.3.5", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^5.13" }, "type": "library", "extra": { @@ -1041,33 +1042,33 @@ }, { "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" + "email": "opensource@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.0" }, - "time": "2021-10-19T17:43:47+00:00" + "time": "2024-04-09T21:13:58+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.7.3", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419" + "reference": "153ae662783729388a584b4361f2545e4d841e3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", - "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", + "reference": "153ae662783729388a584b4361f2545e4d841e3c", "shasum": "" }, "require": { "doctrine/deprecations": "^1.0", - "php": "^7.4 || ^8.0", + "php": "^7.3 || ^8.0", "phpdocumentor/reflection-common": "^2.0", "phpstan/phpdoc-parser": "^1.13" }, @@ -1105,28 +1106,28 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.3" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" }, - "time": "2023-08-12T11:01:26+00:00" + "time": "2024-02-23T11:10:43+00:00" }, { "name": "phpmd/phpmd", - "version": "2.13.0", + "version": "2.15.0", "source": { "type": "git", "url": "https://github.com/phpmd/phpmd.git", - "reference": "dad0228156856b3ad959992f9748514fa943f3e3" + "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpmd/phpmd/zipball/dad0228156856b3ad959992f9748514fa943f3e3", - "reference": "dad0228156856b3ad959992f9748514fa943f3e3", + "url": "https://api.github.com/repos/phpmd/phpmd/zipball/74a1f56e33afad4128b886e334093e98e1b5e7c0", + "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0", "shasum": "" }, "require": { "composer/xdebug-handler": "^1.0 || ^2.0 || ^3.0", "ext-xml": "*", - "pdepend/pdepend": "^2.12.1", + "pdepend/pdepend": "^2.16.1", "php": ">=5.3.9" }, "require-dev": { @@ -1135,8 +1136,7 @@ "ext-simplexml": "*", "gregwar/rst": "^1.0", "mikey179/vfsstream": "^1.6.8", - "phpunit/phpunit": "^4.8.36 || ^5.7.27", - "squizlabs/php_codesniffer": "^2.0" + "squizlabs/php_codesniffer": "^2.9.2 || ^3.7.2" }, "bin": [ "src/bin/phpmd" @@ -1173,6 +1173,7 @@ "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", "homepage": "https://phpmd.org/", "keywords": [ + "dev", "mess detection", "mess detector", "pdepend", @@ -1182,7 +1183,7 @@ "support": { "irc": "irc://irc.freenode.org/phpmd", "issues": "https://github.com/phpmd/phpmd/issues", - "source": "https://github.com/phpmd/phpmd/tree/2.13.0" + "source": "https://github.com/phpmd/phpmd/tree/2.15.0" }, "funding": [ { @@ -1190,7 +1191,7 @@ "type": "tidelift" } ], - "time": "2022-09-10T08:44:15+00:00" + "time": "2023-12-11T08:22:20+00:00" }, { "name": "phpmetrics/phpmetrics", @@ -1262,16 +1263,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.24.0", + "version": "1.28.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "3510b0a6274cc42f7219367cb3abfc123ffa09d6" + "reference": "cd06d6b1a1b3c75b0b83f97577869fd85a3cd4fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/3510b0a6274cc42f7219367cb3abfc123ffa09d6", - "reference": "3510b0a6274cc42f7219367cb3abfc123ffa09d6", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/cd06d6b1a1b3c75b0b83f97577869fd85a3cd4fb", + "reference": "cd06d6b1a1b3c75b0b83f97577869fd85a3cd4fb", "shasum": "" }, "require": { @@ -1303,22 +1304,22 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.28.0" }, - "time": "2023-09-07T20:46:32+00:00" + "time": "2024-04-03T18:51:33+00:00" }, { "name": "phpstan/phpstan", - "version": "1.10.33", + "version": "1.10.67", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "03b1cf9f814ba0863c4e9affea49a4d1ed9a2ed1" + "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/03b1cf9f814ba0863c4e9affea49a4d1ed9a2ed1", - "reference": "03b1cf9f814ba0863c4e9affea49a4d1ed9a2ed1", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/16ddbe776f10da6a95ebd25de7c1dbed397dc493", + "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493", "shasum": "" }, "require": { @@ -1361,13 +1362,9 @@ { "url": "https://github.com/phpstan", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" } ], - "time": "2023-09-04T12:20:53+00:00" + "time": "2024-04-16T07:22:02+00:00" }, { "name": "psr/container", @@ -1474,29 +1471,29 @@ }, { "name": "sebastian/diff", - "version": "5.0.3", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b" + "reference": "ab83243ecc233de5655b76f577711de9f842e712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b", - "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ab83243ecc233de5655b76f577711de9f842e712", + "reference": "ab83243ecc233de5655b76f577711de9f842e712", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0", + "phpunit/phpunit": "^11.0", "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1529,7 +1526,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.0.3" + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.1" }, "funding": [ { @@ -1537,36 +1534,36 @@ "type": "github" } ], - "time": "2023-05-01T07:48:21+00:00" + "time": "2024-03-02T07:30:33+00:00" }, { "name": "slevomat/coding-standard", - "version": "8.13.4", + "version": "8.15.0", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", - "reference": "4b2af2fb17773656d02fbfb5d18024ebd19fe322" + "reference": "7d1d957421618a3803b593ec31ace470177d7817" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/4b2af2fb17773656d02fbfb5d18024ebd19fe322", - "reference": "4b2af2fb17773656d02fbfb5d18024ebd19fe322", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/7d1d957421618a3803b593ec31ace470177d7817", + "reference": "7d1d957421618a3803b593ec31ace470177d7817", "shasum": "" }, "require": { "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0", "php": "^7.2 || ^8.0", - "phpstan/phpdoc-parser": "^1.23.0", - "squizlabs/php_codesniffer": "^3.7.1" + "phpstan/phpdoc-parser": "^1.23.1", + "squizlabs/php_codesniffer": "^3.9.0" }, "require-dev": { "phing/phing": "2.17.4", "php-parallel-lint/php-parallel-lint": "1.3.2", - "phpstan/phpstan": "1.10.26", - "phpstan/phpstan-deprecation-rules": "1.1.3", - "phpstan/phpstan-phpunit": "1.3.13", - "phpstan/phpstan-strict-rules": "1.5.1", - "phpunit/phpunit": "7.5.20|8.5.21|9.6.8|10.2.6" + "phpstan/phpstan": "1.10.60", + "phpstan/phpstan-deprecation-rules": "1.1.4", + "phpstan/phpstan-phpunit": "1.3.16", + "phpstan/phpstan-strict-rules": "1.5.2", + "phpunit/phpunit": "8.5.21|9.6.8|10.5.11" }, "type": "phpcodesniffer-standard", "extra": { @@ -1590,7 +1587,7 @@ ], "support": { "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/8.13.4" + "source": "https://github.com/slevomat/coding-standard/tree/8.15.0" }, "funding": [ { @@ -1602,20 +1599,20 @@ "type": "tidelift" } ], - "time": "2023-07-25T10:28:55+00:00" + "time": "2024-03-09T15:20:58+00:00" }, { "name": "spatie/array-to-xml", - "version": "3.2.0", + "version": "3.2.3", "source": { "type": "git", "url": "https://github.com/spatie/array-to-xml.git", - "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7" + "reference": "c95fd4db94ec199f798d4b5b4a81757bd20d88ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/f9ab39c808500c347d5a8b6b13310bd5221e39e7", - "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/c95fd4db94ec199f798d4b5b4a81757bd20d88ab", + "reference": "c95fd4db94ec199f798d4b5b4a81757bd20d88ab", "shasum": "" }, "require": { @@ -1653,7 +1650,7 @@ "xml" ], "support": { - "source": "https://github.com/spatie/array-to-xml/tree/3.2.0" + "source": "https://github.com/spatie/array-to-xml/tree/3.2.3" }, "funding": [ { @@ -1665,20 +1662,20 @@ "type": "github" } ], - "time": "2023-07-19T18:30:26+00:00" + "time": "2024-02-07T10:39:02+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.7.2", + "version": "3.9.1", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879" + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "267a4405fff1d9c847134db3a3c92f1ab7f77909" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879", - "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/267a4405fff1d9c847134db3a3c92f1ab7f77909", + "reference": "267a4405fff1d9c847134db3a3c92f1ab7f77909", "shasum": "" }, "require": { @@ -1688,11 +1685,11 @@ "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, "bin": [ - "bin/phpcs", - "bin/phpcbf" + "bin/phpcbf", + "bin/phpcs" ], "type": "library", "extra": { @@ -1707,53 +1704,76 @@ "authors": [ { "name": "Greg Sherwood", - "role": "lead" + "role": "Former lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" } ], "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "keywords": [ "phpcs", "standards", "static analysis" ], "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" }, - "time": "2023-02-22T23:07:41+00:00" + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + } + ], + "time": "2024-03-31T21:03:09+00:00" }, { "name": "symfony/config", - "version": "v6.3.2", + "version": "v7.0.6", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "b47ca238b03e7b0d7880ffd1cf06e8d637ca1467" + "reference": "7fc7e18a73ec8125fd95928c0340470d64760deb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/b47ca238b03e7b0d7880ffd1cf06e8d637ca1467", - "reference": "b47ca238b03e7b0d7880ffd1cf06e8d637ca1467", + "url": "https://api.github.com/repos/symfony/config/zipball/7fc7e18a73ec8125fd95928c0340470d64760deb", + "reference": "7fc7e18a73ec8125fd95928c0340470d64760deb", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/filesystem": "^5.4|^6.0", + "symfony/filesystem": "^6.4|^7.0", "symfony/polyfill-ctype": "~1.8" }, "conflict": { - "symfony/finder": "<5.4", + "symfony/finder": "<6.4", "symfony/service-contracts": "<2.5" }, "require-dev": { - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/messenger": "^5.4|^6.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^5.4|^6.0" + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -1781,7 +1801,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v6.3.2" + "source": "https://github.com/symfony/config/tree/v7.0.6" }, "funding": [ { @@ -1797,47 +1817,50 @@ "type": "tidelift" } ], - "time": "2023-07-19T20:22:16+00:00" + "time": "2024-03-27T19:55:25+00:00" }, { "name": "symfony/console", - "version": "v6.3.4", + "version": "v7.0.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6" + "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6", - "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6", + "url": "https://api.github.com/repos/symfony/console/zipball/fde915cd8e7eb99b3d531d3d5c09531429c3f9e5", + "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.2", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0" + "symfony/string": "^6.4|^7.0" }, "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/lock": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -1871,7 +1894,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.3.4" + "source": "https://github.com/symfony/console/tree/v7.0.6" }, "funding": [ { @@ -1887,44 +1910,43 @@ "type": "tidelift" } ], - "time": "2023-08-16T10:10:12+00:00" + "time": "2024-04-01T11:04:53+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.3.4", + "version": "v7.0.6", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "68a5a9570806a087982f383f6109c5e925892a49" + "reference": "ff57b5c7d518c39eeb4e69dc0d1ec70723a117b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/68a5a9570806a087982f383f6109c5e925892a49", - "reference": "68a5a9570806a087982f383f6109c5e925892a49", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/ff57b5c7d518c39eeb4e69dc0d1ec70723a117b9", + "reference": "ff57b5c7d518c39eeb4e69dc0d1ec70723a117b9", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/container": "^1.1|^2.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/service-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.2.10" + "symfony/service-contracts": "^3.3", + "symfony/var-exporter": "^6.4|^7.0" }, "conflict": { "ext-psr": "<1.1|>=2", - "symfony/config": "<6.1", - "symfony/finder": "<5.4", - "symfony/proxy-manager-bridge": "<6.3", - "symfony/yaml": "<5.4" + "symfony/config": "<6.4", + "symfony/finder": "<6.4", + "symfony/yaml": "<6.4" }, "provide": { "psr/container-implementation": "1.1|2.0", "symfony/service-implementation": "1.1|2.0|3.0" }, "require-dev": { - "symfony/config": "^6.1", - "symfony/expression-language": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" + "symfony/config": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -1952,7 +1974,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.3.4" + "source": "https://github.com/symfony/dependency-injection/tree/v7.0.6" }, "funding": [ { @@ -1968,11 +1990,11 @@ "type": "tidelift" } ], - "time": "2023-08-16T17:55:17+00:00" + "time": "2024-03-28T09:20:36+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.3.0", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", @@ -2019,7 +2041,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" }, "funding": [ { @@ -2039,20 +2061,20 @@ }, { "name": "symfony/filesystem", - "version": "v6.3.1", + "version": "v7.0.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" + "reference": "408105dff4c104454100730bdfd1a9cdd993f04d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", - "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/408105dff4c104454100730bdfd1a9cdd993f04d", + "reference": "408105dff4c104454100730bdfd1a9cdd993f04d", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, @@ -2082,7 +2104,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.3.1" + "source": "https://github.com/symfony/filesystem/tree/v7.0.6" }, "funding": [ { @@ -2098,20 +2120,20 @@ "type": "tidelift" } ], - "time": "2023-06-01T08:30:39+00:00" + "time": "2024-03-21T19:37:36+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", "shasum": "" }, "require": { @@ -2125,9 +2147,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -2164,7 +2183,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" }, "funding": [ { @@ -2180,20 +2199,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "875e90aeea2777b6f135677f618529449334a612" + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", - "reference": "875e90aeea2777b6f135677f618529449334a612", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", "shasum": "" }, "require": { @@ -2204,9 +2223,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -2245,7 +2261,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" }, "funding": [ { @@ -2261,20 +2277,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", "shasum": "" }, "require": { @@ -2285,9 +2301,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -2329,7 +2342,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" }, "funding": [ { @@ -2345,20 +2358,20 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", "shasum": "" }, "require": { @@ -2372,9 +2385,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -2412,7 +2422,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" }, "funding": [ { @@ -2428,25 +2438,25 @@ "type": "tidelift" } ], - "time": "2023-07-28T09:04:16+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.3.0", + "version": "v3.4.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4" + "reference": "11bbf19a0fb7b36345861e85c5768844c552906e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", - "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/11bbf19a0fb7b36345861e85c5768844c552906e", + "reference": "11bbf19a0fb7b36345861e85c5768844c552906e", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^2.0" + "psr/container": "^1.1|^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -2494,7 +2504,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.2" }, "funding": [ { @@ -2510,24 +2520,24 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2023-12-19T21:51:00+00:00" }, { "name": "symfony/string", - "version": "v6.3.2", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "53d1a83225002635bca3482fcbf963001313fb68" + "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/53d1a83225002635bca3482fcbf963001313fb68", - "reference": "53d1a83225002635bca3482fcbf963001313fb68", + "url": "https://api.github.com/repos/symfony/string/zipball/f5832521b998b0bec40bee688ad5de98d4cf111b", + "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", @@ -2537,11 +2547,11 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/intl": "^6.2", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0" + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -2580,7 +2590,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.3.2" + "source": "https://github.com/symfony/string/tree/v7.0.4" }, "funding": [ { @@ -2596,27 +2606,29 @@ "type": "tidelift" } ], - "time": "2023-07-05T08:41:27+00:00" + "time": "2024-02-01T13:17:36+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.3.4", + "version": "v7.0.6", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "df1f8aac5751871b83d30bf3e2c355770f8f0691" + "reference": "c74c568d2a15a1d407cf40d61ea82bc2d521e27b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/df1f8aac5751871b83d30bf3e2c355770f8f0691", - "reference": "df1f8aac5751871b83d30bf3e2c355770f8f0691", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/c74c568d2a15a1d407cf40d61ea82bc2d521e27b", + "reference": "c74c568d2a15a1d407cf40d61ea82bc2d521e27b", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "symfony/var-dumper": "^5.4|^6.0" + "symfony/property-access": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -2654,7 +2666,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.3.4" + "source": "https://github.com/symfony/var-exporter/tree/v7.0.6" }, "funding": [ { @@ -2670,20 +2682,20 @@ "type": "tidelift" } ], - "time": "2023-08-16T18:14:47+00:00" + "time": "2024-03-20T21:25:22+00:00" }, { "name": "vimeo/psalm", - "version": "5.15.0", + "version": "5.23.1", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352" + "reference": "8471a896ccea3526b26d082f4461eeea467f10a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/5c774aca4746caf3d239d9c8cadb9f882ca29352", - "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/8471a896ccea3526b26d082f4461eeea467f10a4", + "reference": "8471a896ccea3526b26d082f4461eeea467f10a4", "shasum": "" }, "require": { @@ -2702,14 +2714,14 @@ "ext-tokenizer": "*", "felixfbecker/advanced-json-rpc": "^3.1", "felixfbecker/language-server-protocol": "^1.5.2", - "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1", + "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1 || ^1.0.0", "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", "nikic/php-parser": "^4.16", "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", - "sebastian/diff": "^4.0 || ^5.0", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0", "spatie/array-to-xml": "^2.17.0 || ^3.0", - "symfony/console": "^4.1.6 || ^5.0 || ^6.0", - "symfony/filesystem": "^5.4 || ^6.0" + "symfony/console": "^4.1.6 || ^5.0 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0" }, "conflict": { "nikic/php-parser": "4.17.0" @@ -2731,7 +2743,7 @@ "psalm/plugin-phpunit": "^0.18", "slevomat/coding-standard": "^8.4", "squizlabs/php_codesniffer": "^3.6", - "symfony/process": "^4.4 || ^5.0 || ^6.0" + "symfony/process": "^4.4 || ^5.0 || ^6.0 || ^7.0" }, "suggest": { "ext-curl": "In order to send data to shepherd", @@ -2744,7 +2756,7 @@ "psalm-refactor", "psalter" ], - "type": "library", + "type": "project", "extra": { "branch-alias": { "dev-master": "5.x-dev", @@ -2776,10 +2788,11 @@ "static analysis" ], "support": { + "docs": "https://psalm.dev/docs", "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/5.15.0" + "source": "https://github.com/vimeo/psalm" }, - "time": "2023-08-20T23:07:30+00:00" + "time": "2024-03-11T20:33:46+00:00" }, { "name": "webmozart/assert", @@ -2847,5 +2860,5 @@ "prefer-lowest": false, "platform": [], "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" }