From d397b642242a68ad54f012e27d82222db3656c23 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Wed, 29 Nov 2023 22:32:33 +0100 Subject: [PATCH] Update phpcr-shell to Symfony 7 * Test with PHP 8.2 * Various type declaration fixes * Support Symfony 7 - refactor container aware - return null explicitly * Make path absolute for parent path handling --- .github/workflows/test-application.yaml | 21 +++++++- composer.json | 14 ++--- spec/PHPCR/Shell/Query/UpdateParserSpec.php | 24 ++++----- .../Console/Application/ShellApplication.php | 30 +++++------ .../Shell/Console/Command/BaseCommand.php | 7 ++- .../Console/Command/Phpcr/NodeListCommand.php | 3 +- .../Command/Phpcr/QueryUpdateCommand.php | 2 +- .../Shell/Console/Helper/EditorHelper.php | 4 +- src/PHPCR/Shell/Console/Helper/NodeHelper.php | 2 +- src/PHPCR/Shell/Console/Helper/PathHelper.php | 5 +- .../Shell/Console/Helper/RepositoryHelper.php | 3 +- .../Console/Helper/ResultFormatterHelper.php | 5 +- src/PHPCR/Shell/Console/Helper/TextHelper.php | 10 ++-- src/PHPCR/Shell/Console/Input/StringInput.php | 16 +++--- .../ContainerAwareInterface.php | 26 ++++++++++ src/PHPCR/Shell/Phpcr/PhpcrSession.php | 10 ++-- src/PHPCR/Shell/Query/UpdateParser.php | 52 ++++++++----------- src/PHPCR/Shell/Serializer/NodeNormalizer.php | 21 +++++--- src/PHPCR/Shell/Serializer/YamlEncoder.php | 2 +- src/PHPCR/Shell/Test/ContextBase.php | 4 +- 20 files changed, 149 insertions(+), 112 deletions(-) create mode 100644 src/PHPCR/Shell/DependencyInjection/ContainerAwareInterface.php diff --git a/.github/workflows/test-application.yaml b/.github/workflows/test-application.yaml index a328c500..22d7e697 100644 --- a/.github/workflows/test-application.yaml +++ b/.github/workflows/test-application.yaml @@ -57,6 +57,21 @@ jobs: dependencies: highest behat-suite: cli + - php-version: '8.3' + dependencies: highest + behat-suite: standalone + composer-stability: 'dev' + + - php-version: '8.3' + dependencies: highest + behat-suite: embedded + composer-stability: 'dev' + + - php-version: '8.3' + dependencies: highest + behat-suite: cli + composer-stability: 'dev' + steps: - name: Checkout project uses: actions/checkout@v4 @@ -74,6 +89,10 @@ jobs: php-version: ${{ matrix.php-version }} tools: 'composer:v2' + - name: Set composer stability + if: ${{ matrix.composer-stability }} + run: composer config minimum-stability ${{ matrix.composer-stability }} + - name: Install dependencies with Composer uses: ramsey/composer-install@v2 with: @@ -95,4 +114,4 @@ jobs: run: | vendor/bin/phpunit vendor/bin/phpspec run - vendor/bin/behat --suite=${{ matrix.behat-suite }} + vendor/bin/behat -vv --suite=${{ matrix.behat-suite }} diff --git a/composer.json b/composer.json index f9989f4e..e55fe9be 100644 --- a/composer.json +++ b/composer.json @@ -3,15 +3,15 @@ "description": "Shell for PHPCR", "require": { "php": "^8.0", - "symfony/console": "^5.0 || ^6.0", "jackalope/jackalope": "^1.3.4 || ^2.0", + "symfony/console": "^5.4 || ^6.4 || ^7.0", "phpcr/phpcr": "^2.1", - "phpcr/phpcr-utils": "^1.2", - "symfony/finder": "^5.0 || ^6.0", - "symfony/serializer": "^5.0 || ^6.0", - "symfony/yaml": "^5.0 || ^6.0", - "symfony/dependency-injection": "^5.0 || ^6.0", - "symfony/expression-language": "^5.0 || ^6.0", + "phpcr/phpcr-utils": "^1.2 || ^2.0", + "symfony/finder": "^5.4 || ^6.4 || ^7.0", + "symfony/serializer": "^5.4 || ^6.4 || ^7.0", + "symfony/yaml": "^5.4 || ^6.4 || ^7.0", + "symfony/dependency-injection": "^5.4 || ^6.4 || ^7.0", + "symfony/expression-language": "^5.4 || ^6.4 || ^7.0", "dantleech/glob-finder": "^1.0" }, "require-dev": { diff --git a/spec/PHPCR/Shell/Query/UpdateParserSpec.php b/spec/PHPCR/Shell/Query/UpdateParserSpec.php index 85df910f..09312ee5 100644 --- a/spec/PHPCR/Shell/Query/UpdateParserSpec.php +++ b/spec/PHPCR/Shell/Query/UpdateParserSpec.php @@ -19,7 +19,7 @@ use PHPCR\Query\QOM\PropertyValueInterface; use PHPCR\Query\QOM\QueryObjectModelConstantsInterface; use PHPCR\Query\QOM\QueryObjectModelFactoryInterface; -use PHPCR\Query\QOM\SourceInterface; +use PHPCR\Query\QOM\SelectorInterface; use PHPCR\Query\QueryInterface; use PhpSpec\ObjectBehavior; @@ -42,17 +42,17 @@ public function it_should_provide_a_qom_object_for_selecting( QueryObjectModelFactoryInterface $qomf, ChildNodeJoinConditionInterface $joinCondition, JoinInterface $join, - SourceInterface $parentSource, - SourceInterface $childSource, + SelectorInterface $parentSelector, + SelectorInterface $childSelector, PropertyValueInterface $childValue, LiteralInterface $literalValue, ComparisonInterface $comparison, QueryInterface $query ) { - $qomf->selector('parent', 'mgnl:page')->willReturn($parentSource); - $qomf->selector('child', 'mgnl:metaData')->willReturn($childSource); + $qomf->selector('parent', 'mgnl:page')->willReturn($parentSelector); + $qomf->selector('child', 'mgnl:metaData')->willReturn($childSelector); $qomf->childNodeJoinCondition('child', 'parent')->willReturn($joinCondition); - $qomf->join($parentSource, $childSource, QueryObjectModelConstantsInterface::JCR_JOIN_TYPE_INNER, $joinCondition)->willReturn($join); + $qomf->join($parentSelector, $childSelector, QueryObjectModelConstantsInterface::JCR_JOIN_TYPE_INNER, $joinCondition)->willReturn($join); $qomf->propertyValue('child', 'mgnl:template')->willReturn($childValue); $qomf->literal('standard-templating-kit:stkNews')->willReturn($literalValue); $qomf->comparison($childValue, QueryObjectModelConstantsInterface::JCR_OPERATOR_EQUAL_TO, $literalValue)->willReturn($comparison); @@ -68,9 +68,9 @@ public function it_should_provide_a_qom_object_for_selecting( WHERE child.[mgnl:template] = 'standard-templating-kit:stkNews' EOT; - $res = $this->parse($sql); + $res = $this->parseUpdate($sql); - $res->offsetGet(0)->shouldHaveType('PHPCR\Query\QueryInterface'); + $res->offsetGet(0)->shouldHaveType(QueryInterface::class); $res->offsetGet(1)->shouldReturn([ [ 'selector' => 'parent', @@ -87,7 +87,7 @@ public function it_should_provide_a_qom_object_for_selecting( public function it_should_parse_functions( QueryObjectModelFactoryInterface $qomf, - SourceInterface $source, + SelectorInterface $source, QueryInterface $query ) { $qomf->selector('a', 'dtl:article')->willReturn($source); @@ -96,14 +96,14 @@ public function it_should_parse_functions( $sql = <<<'EOT' UPDATE [dtl:article] AS a SET a.tags = array_replace(a.tags, 'asd', 'dsa') EOT; - $res = $this->parse($sql); + $res = $this->parseUpdate($sql); $res->offsetGet(0)->shouldHaveType('PHPCR\Query\QueryInterface'); } public function it_should_parse_apply( QueryObjectModelFactoryInterface $qomf, - SourceInterface $source, + SelectorInterface $source, QueryInterface $query ) { $qomf->selector('a', 'dtl:article')->willReturn($source); @@ -112,7 +112,7 @@ public function it_should_parse_apply( $sql = <<<'EOT' UPDATE [dtl:article] AS a APPLY nodetype_add('nt:barbar') EOT; - $res = $this->parse($sql); + $res = $this->parseUpdate($sql); $res->offsetGet(0)->shouldHaveType('PHPCR\Query\QueryInterface'); } diff --git a/src/PHPCR/Shell/Console/Application/ShellApplication.php b/src/PHPCR/Shell/Console/Application/ShellApplication.php index 1112543e..c2f0291c 100644 --- a/src/PHPCR/Shell/Console/Application/ShellApplication.php +++ b/src/PHPCR/Shell/Console/Application/ShellApplication.php @@ -15,18 +15,19 @@ use PHPCR\Shell\Console\Command\Phpcr as CommandPhpcr; use PHPCR\Shell\Console\Command\Phpcr\BasePhpcrCommand; use PHPCR\Shell\Console\Command\Shell as CommandShell; +use PHPCR\Shell\DependencyInjection\ContainerAwareInterface; use PHPCR\Shell\Event; use PHPCR\Shell\Event\ApplicationInitEvent; use PHPCR\Shell\Event\PhpcrShellEvents; use PHPCR\Shell\PhpcrShell; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\OutputFormatterInterface; use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\EventDispatcher\EventDispatcher; /** @@ -42,7 +43,7 @@ class ShellApplication extends Application protected $showUnsupported = false; /** - * @var Symfony\Component\DependencyInjection\ContainerBuilder + * @var ContainerBuilder */ protected $container; @@ -200,7 +201,7 @@ protected function registerShellCommands() /** * Configure the output formatter. */ - private function configureFormatter(OutputFormatter $formatter) + private function configureFormatter(OutputFormatterInterface $formatter) { $style = new OutputFormatterStyle('yellow', null, ['bold']); $formatter->setStyle('pathbold', $style); @@ -233,10 +234,7 @@ private function configureFormatter(OutputFormatter $formatter) $formatter->setStyle('exception', $style); } - /** - * {@inheritdoc} - */ - public function doRun(InputInterface $input, OutputInterface $output) + public function doRun(InputInterface $input, OutputInterface $output): int { $this->init(); @@ -278,19 +276,19 @@ protected function getDefaultCommand() * * {@inheritdoc} */ - public function add(Command $command) + public function add(Command $command): ?Command { if ($command instanceof ContainerAwareInterface) { $command->setContainer($this->container); } - if ($command instanceof BasePhpcrCommand) { - if ($this->showUnsupported || $command->isSupported()) { - parent::add($command); - } - } else { - parent::add($command); + if ($command instanceof BasePhpcrCommand + && ($this->showUnsupported || $command->isSupported()) + ) { + return parent::add($command); } + + return parent::add($command); } public function dispatchProfileInitEvent(InputInterface $sessionInput, OutputInterface $output) @@ -306,7 +304,7 @@ public function dispatchProfileInitEvent(InputInterface $sessionInput, OutputInt * * {@inheritdoc} */ - public function all($namespace = null) + public function all($namespace = null): array { $this->init(); diff --git a/src/PHPCR/Shell/Console/Command/BaseCommand.php b/src/PHPCR/Shell/Console/Command/BaseCommand.php index 4f4bc8a6..1e3ea5c0 100644 --- a/src/PHPCR/Shell/Console/Command/BaseCommand.php +++ b/src/PHPCR/Shell/Console/Command/BaseCommand.php @@ -12,15 +12,18 @@ namespace PHPCR\Shell\Console\Command; +use PHPCR\Shell\DependencyInjection\ContainerAwareInterface; use Symfony\Component\Console\Command\Command; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerInterface; class BaseCommand extends Command implements ContainerAwareInterface { + /** + * @var ContainerInterface + */ private $container; - public function setContainer(ContainerInterface $container = null) + public function setContainer(ContainerInterface $container = null): void { $this->container = $container; } diff --git a/src/PHPCR/Shell/Console/Command/Phpcr/NodeListCommand.php b/src/PHPCR/Shell/Console/Command/Phpcr/NodeListCommand.php index 8084896f..37d35805 100644 --- a/src/PHPCR/Shell/Console/Command/Phpcr/NodeListCommand.php +++ b/src/PHPCR/Shell/Console/Command/Phpcr/NodeListCommand.php @@ -100,12 +100,13 @@ public function execute(InputInterface $input, OutputInterface $output): int if (!$globHelper->isGlobbed($session->getAbsPath($path))) { throw $e; } + $path = $session->getAbsPath($path); $parentPath = $this->get('helper.path')->getParentPath($path); $filter = substr($path, strlen($parentPath)); - if ($filter[0] == '/') { + if ('/' === $filter[0]) { $filter = substr($filter, 1); } diff --git a/src/PHPCR/Shell/Console/Command/Phpcr/QueryUpdateCommand.php b/src/PHPCR/Shell/Console/Command/Phpcr/QueryUpdateCommand.php index a063e19e..5812a733 100644 --- a/src/PHPCR/Shell/Console/Command/Phpcr/QueryUpdateCommand.php +++ b/src/PHPCR/Shell/Console/Command/Phpcr/QueryUpdateCommand.php @@ -75,7 +75,7 @@ public function execute(InputInterface $input, OutputInterface $output): int $qm = $session->getWorkspace()->getQueryManager(); $updateParser = new UpdateParser($qm->getQOMFactory()); - $res = $updateParser->parse($sql); + $res = $updateParser->parseUpdate($sql); $query = $res->offsetGet(0); $updates = $res->offsetGet(1); $applies = $res->offsetGet(3); diff --git a/src/PHPCR/Shell/Console/Helper/EditorHelper.php b/src/PHPCR/Shell/Console/Helper/EditorHelper.php index 6942937f..ea027c7b 100644 --- a/src/PHPCR/Shell/Console/Helper/EditorHelper.php +++ b/src/PHPCR/Shell/Console/Helper/EditorHelper.php @@ -85,7 +85,7 @@ public function fromStringWithMessage($string, $message, $messagePrefix = '# ', $line = current($res); - while (0 === strpos($line, $messagePrefix)) { + while (str_starts_with($line, $messagePrefix)) { $line = next($res); } @@ -99,7 +99,7 @@ public function fromStringWithMessage($string, $message, $messagePrefix = '# ', return implode("\n", $out); } - public function getName() + public function getName(): string { return 'editor'; } diff --git a/src/PHPCR/Shell/Console/Helper/NodeHelper.php b/src/PHPCR/Shell/Console/Helper/NodeHelper.php index b26199e6..556cd174 100644 --- a/src/PHPCR/Shell/Console/Helper/NodeHelper.php +++ b/src/PHPCR/Shell/Console/Helper/NodeHelper.php @@ -45,7 +45,7 @@ public function assertNodeIsVersionable(NodeInterface $node) } } - public function getName() + public function getName(): string { return 'node'; } diff --git a/src/PHPCR/Shell/Console/Helper/PathHelper.php b/src/PHPCR/Shell/Console/Helper/PathHelper.php index 1d63465f..bba824c2 100644 --- a/src/PHPCR/Shell/Console/Helper/PathHelper.php +++ b/src/PHPCR/Shell/Console/Helper/PathHelper.php @@ -38,10 +38,7 @@ public function getNodeName($path) return StaticPathHelper::getNodeName($path); } - /** - * {@inheritdoc} - */ - public function getName() + public function getName(): string { return 'path'; } diff --git a/src/PHPCR/Shell/Console/Helper/RepositoryHelper.php b/src/PHPCR/Shell/Console/Helper/RepositoryHelper.php index 9ba57b02..7c962985 100644 --- a/src/PHPCR/Shell/Console/Helper/RepositoryHelper.php +++ b/src/PHPCR/Shell/Console/Helper/RepositoryHelper.php @@ -13,6 +13,7 @@ namespace PHPCR\Shell\Console\Helper; use PHPCR\Shell\Phpcr\SessionManager; +use PHPCR\Util\Console\Helper\PhpcrHelper; use Symfony\Component\Console\Helper\Helper; class RepositoryHelper extends Helper @@ -80,7 +81,7 @@ private function loadDescriptors() } } - public function getName() + public function getName(): string { return 'repository'; } diff --git a/src/PHPCR/Shell/Console/Helper/ResultFormatterHelper.php b/src/PHPCR/Shell/Console/Helper/ResultFormatterHelper.php index 54bc5299..59aa80ff 100644 --- a/src/PHPCR/Shell/Console/Helper/ResultFormatterHelper.php +++ b/src/PHPCR/Shell/Console/Helper/ResultFormatterHelper.php @@ -36,10 +36,7 @@ public function __construct(TextHelper $textHelper, Config $config) $this->config = $config; } - /** - * {@inheritdoc} - */ - public function getName() + public function getName(): string { return 'result_formatter'; } diff --git a/src/PHPCR/Shell/Console/Helper/TextHelper.php b/src/PHPCR/Shell/Console/Helper/TextHelper.php index 6ca9945c..31f39e89 100644 --- a/src/PHPCR/Shell/Console/Helper/TextHelper.php +++ b/src/PHPCR/Shell/Console/Helper/TextHelper.php @@ -31,7 +31,7 @@ class TextHelper extends Helper /** * {@inheritdoc} */ - public function getName() + public function getName(): string { return 'text'; } @@ -43,17 +43,15 @@ public function getName() * @param int $length Truncate to this length * @param string $alignment Align to the "left" or the "right" * @param string $delimString String to use to use to indicate the truncation - * - * @return string */ - public function truncate($string, $length = null, $alignment = null, $delimString = null) + public function truncate($string, $length = null, $alignment = null, $delimString = null): string { if (null === $length) { $length = $this->truncateLength; } - $alignment = $alignment === null ? 'left' : $alignment; - $delimString = $delimString === null ? '...' : $delimString; + $alignment = $alignment ?? 'left'; + $delimString = $delimString ?? '...'; $delimLen = strlen($delimString); if (!in_array($alignment, ['left', 'right'])) { diff --git a/src/PHPCR/Shell/Console/Input/StringInput.php b/src/PHPCR/Shell/Console/Input/StringInput.php index 2d92bd6a..d72b3851 100644 --- a/src/PHPCR/Shell/Console/Input/StringInput.php +++ b/src/PHPCR/Shell/Console/Input/StringInput.php @@ -33,17 +33,17 @@ public function __construct($command) { $this->rawCommand = trim($command); - if (strpos(strtolower($this->rawCommand), 'select') === 0) { + if (stripos($this->rawCommand, 'select') === 0) { $command = 'select'.substr($command, 6); $this->isQuery = true; } - if (strpos(strtolower($this->rawCommand), 'update') === 0) { + if (stripos($this->rawCommand, 'update') === 0) { $command = 'update'.substr($command, 6); $this->isQuery = true; } - if (strpos(strtolower($this->rawCommand), 'delete') === 0) { + if (stripos($this->rawCommand, 'delete') === 0) { $command = 'delete'.substr($command, 6); $this->isQuery = true; } @@ -63,10 +63,10 @@ public function getRawCommand() return $this->rawCommand; } - public function validate() + public function validate(): void { if (false === $this->isQuery()) { - return parent::validate(); + parent::validate(); } } @@ -75,10 +75,10 @@ public function validate() * * {@inheritdoc} */ - protected function parse() + protected function parse(): void { if (false === $this->isQuery()) { - return parent::parse(); + parent::parse(); } } @@ -87,7 +87,7 @@ protected function parse() * allowed by the default StringInput and we require * it for the "alias" feature. */ - protected function setTokens(array $tokens) + protected function setTokens(array $tokens): void { $this->tokens = $tokens; parent::setTokens($tokens); diff --git a/src/PHPCR/Shell/DependencyInjection/ContainerAwareInterface.php b/src/PHPCR/Shell/DependencyInjection/ContainerAwareInterface.php new file mode 100644 index 00000000..2069b494 --- /dev/null +++ b/src/PHPCR/Shell/DependencyInjection/ContainerAwareInterface.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PHPCR\Shell\DependencyInjection; + +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * This was removed from Symfony in version 7. + * + * We keep using the pattern in the shell commands for now to avoid a complicated refactor. + * + * @author Fabien Potencier + */ +interface ContainerAwareInterface +{ + public function setContainer(?ContainerInterface $container): void; +} diff --git a/src/PHPCR/Shell/Phpcr/PhpcrSession.php b/src/PHPCR/Shell/Phpcr/PhpcrSession.php index 736ab22d..6a07fecc 100644 --- a/src/PHPCR/Shell/Phpcr/PhpcrSession.php +++ b/src/PHPCR/Shell/Phpcr/PhpcrSession.php @@ -122,14 +122,12 @@ public function getAbsPath($path) return $this->getCwd(); } - if (substr($path, 0, 1) == '/') { + if (str_starts_with($path, '/')) { $absPath = $path; + } elseif ('/' === $this->cwd) { + $absPath = sprintf('/%s', $path); } else { - if ($this->cwd == '/') { - $absPath = sprintf('/%s', $path); - } else { - $absPath = sprintf('%s/%s', $this->getCwd(), $path); - } + $absPath = sprintf('%s/%s', $this->getCwd(), $path); } return $absPath; diff --git a/src/PHPCR/Shell/Query/UpdateParser.php b/src/PHPCR/Shell/Query/UpdateParser.php index ac0aa72c..2f146482 100644 --- a/src/PHPCR/Shell/Query/UpdateParser.php +++ b/src/PHPCR/Shell/Query/UpdateParser.php @@ -13,6 +13,8 @@ namespace PHPCR\Shell\Query; use PHPCR\Query\InvalidQueryException; +use PHPCR\Query\QOM\ConstraintInterface; +use PHPCR\Query\QOM\QueryObjectModelInterface; use PHPCR\Query\QOM\SourceInterface; use PHPCR\Util\QOM\Sql2Scanner; use PHPCR\Util\QOM\Sql2ToQomQueryConverter; @@ -27,14 +29,6 @@ */ class UpdateParser extends Sql2ToQomQueryConverter { - public function parse($sql2) - { - $this->scanner = new Sql2Scanner($sql2); - $this->sql2 = $sql2; - - return $this->doParse($sql2); - } - /** * Parse an "SQL2" UPDATE statement and construct a query builder * for selecting the rows and build a field => value mapping for the @@ -42,12 +36,14 @@ public function parse($sql2) * * @param string $sql2 * - * @return array($query, $updates) + * @return \ArrayObject{1: QueryObjectModelInterface, 2: array, 3: ?ConstraintInterface, 4: array} */ - private function doParse($sql2) + public function parseUpdate($sql2): \ArrayObject { - $this->implicitSelectorName = null; + $this->scanner = new Sql2Scanner($sql2); $this->sql2 = $sql2; + + $this->implicitSelectorName = null; $source = null; $constraint = null; $updates = []; @@ -82,9 +78,7 @@ private function doParse($sql2) $query = $this->factory->createQuery($source, $constraint); - $res = new \ArrayObject([$query, $updates, $constraint, $applies]); - - return $res; + return new \ArrayObject([$query, $updates, $constraint, $applies]); } /** @@ -92,15 +86,9 @@ private function doParse($sql2) * an array containing the property names ( , - * 'name' => , - * '' => , - * ) - * - * @return array + * @return array{'selector': string, 'name': string, 'value': mixed} */ - private function parseUpdates() + private function parseUpdates(): array { $updates = []; @@ -132,9 +120,9 @@ private function parseUpdates() $next = $this->scanner->lookupNextToken(); - if ($next == ',') { + if (',' === $next) { $next = $this->scanner->fetchNextToken(); - } elseif (strtolower($next) == 'where' || !$next) { + } elseif (strtolower($next) === 'where' || !$next) { break; } } @@ -144,11 +132,13 @@ private function parseUpdates() private function isLiteral($token) { - if (substr($token, 0, 1) === '\'') { + if (str_starts_with($token, '\'')) { return true; - } elseif (is_numeric($token)) { + } + if (is_numeric($token)) { return true; - } elseif (substr($token, 0, 1) === '"') { + } + if (str_starts_with($token, '"')) { return true; } @@ -159,7 +149,7 @@ private function parseOperand() { $token = strtoupper($this->scanner->lookupNextToken()); - if ($this->scanner->lookupNextToken(1) == '(') { + if ($this->scanner->lookupNextToken(1) === '(') { $functionData = $this->parseFunction(); return new FunctionOperand($functionData[0], $functionData[1]); @@ -187,7 +177,7 @@ private function parseApply() while (true) { $token = strtoupper($this->scanner->lookupNextToken()); - if ($this->scanner->lookupNextToken(1) == '(') { + if ($this->scanner->lookupNextToken(1) === '(') { $functionData = $this->parseFunction(); $functions[] = new FunctionOperand($functionData[0], $functionData[1]); @@ -195,9 +185,9 @@ private function parseApply() $next = $this->scanner->lookupNextToken(); - if ($next == ',') { + if (',' === $next) { $next = $this->scanner->fetchNextToken(); - } elseif (strtolower($next) == 'where' || !$next) { + } elseif (strtolower($next) === 'where' || !$next) { break; } } diff --git a/src/PHPCR/Shell/Serializer/NodeNormalizer.php b/src/PHPCR/Shell/Serializer/NodeNormalizer.php index 3735feb6..be7d068b 100644 --- a/src/PHPCR/Shell/Serializer/NodeNormalizer.php +++ b/src/PHPCR/Shell/Serializer/NodeNormalizer.php @@ -39,14 +39,21 @@ public function getNotes() return $this->notes; } + public function getSupportedTypes(?string $format): array + { + return [ + NodeInterface::class => true, + ]; + } + /** * {@inheritdoc} */ - public function normalize($node, $format = null, array $context = []) + public function normalize($object, $format = null, array $context = []): array { $res = []; - foreach ($node->getProperties() as $property) { + foreach ($object->getProperties() as $property) { if (false === $this->isPropertyEditable($property)) { continue; } @@ -85,7 +92,7 @@ public function normalize($node, $format = null, array $context = []) /** * {@inheritdoc} */ - public function supportsNormalization($data, $format = null) + public function supportsNormalization($data, $format = null, array $context = []): bool { return is_object($data) && $data instanceof NodeInterface; } @@ -93,7 +100,7 @@ public function supportsNormalization($data, $format = null) /** * {@inheritdoc} */ - public function denormalize($data, $class, $format = null, array $context = []) + public function denormalize($data, $class, $format = null, array $context = []): mixed { if (!$data) { throw new \InvalidArgumentException( @@ -147,7 +154,7 @@ public function denormalize($data, $class, $format = null, array $context = []) // Add new properties foreach ($data as $pName => $datum) { $datum = $this->normalizeDatum($datum); - $pValue = isset($datum['value']) ? $datum['value'] : null; + $pValue = $datum['value'] ?? null; $pType = isset($datum['type']) ? PropertyType::valueFromName($datum['type']) : null; if ($pValue !== null) { @@ -161,12 +168,14 @@ public function denormalize($data, $class, $format = null, array $context = []) implode("\n", $errors) )); } + + return null; } /** * {@inheritdoc} */ - public function supportsDenormalization($data, $type, $format = null) + public function supportsDenormalization($data, $type, $format = null, array $context = []): bool { return $type === 'PHPCR\NodeInterface'; } diff --git a/src/PHPCR/Shell/Serializer/YamlEncoder.php b/src/PHPCR/Shell/Serializer/YamlEncoder.php index e63667da..9f87aab3 100644 --- a/src/PHPCR/Shell/Serializer/YamlEncoder.php +++ b/src/PHPCR/Shell/Serializer/YamlEncoder.php @@ -33,7 +33,7 @@ public function encode($data, $format, array $context = []): string return Yaml::dump($data); } - public function decode($data, $format, array $context = []) + public function decode($data, $format, array $context = []): mixed { $arr = Yaml::parse($data); diff --git a/src/PHPCR/Shell/Test/ContextBase.php b/src/PHPCR/Shell/Test/ContextBase.php index 13868dc3..157adbd6 100644 --- a/src/PHPCR/Shell/Test/ContextBase.php +++ b/src/PHPCR/Shell/Test/ContextBase.php @@ -189,12 +189,12 @@ public function iShouldSeeATableContainingTheFollowingRows(TableNode $table) continue; } - if (false !== strpos($line, $cell)) { + if (str_contains($line, $cell)) { $foundCells++; } } - if ($foundCells == count($row)) { + if ($foundCells === count($row)) { $foundRows++; } }