From 12b6d4121ee0f1e6a7dd23bee9996975be5b8f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anke=20H=C3=A4slich?= Date: Sun, 10 Mar 2024 13:26:33 +0100 Subject: [PATCH 1/4] TASK: Adjust usage of `hiddenInIndex` to use `hiddenInMenu` The internal property `hiddenInIndex` was renamed to `hiddenInMenu`. To match this renaming the fusion property `renderHiddenInIndex` is renamed to `renderHiddenInMenu`. Needs: https://github.com/neos/neos-development-collection/pull/4921 --- Classes/Fusion/XmlSitemapUrlsImplementation.php | 14 +++++++------- Resources/Private/Fusion/Helper/SitemapUrls.fusion | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Classes/Fusion/XmlSitemapUrlsImplementation.php b/Classes/Fusion/XmlSitemapUrlsImplementation.php index 786f3d12..42b136bc 100644 --- a/Classes/Fusion/XmlSitemapUrlsImplementation.php +++ b/Classes/Fusion/XmlSitemapUrlsImplementation.php @@ -42,7 +42,7 @@ class XmlSitemapUrlsImplementation extends AbstractFusionObject */ protected array $assetPropertiesByNodeType = []; - protected ?bool $renderHiddenInIndex = null; + protected ?bool $renderHiddenInMenu = null; protected ?bool $includeImageUrls = null; @@ -62,13 +62,13 @@ public function getIncludeImageUrls(): bool return $this->includeImageUrls; } - public function getRenderHiddenInIndex(): bool + public function getRenderHiddenInMenu(): bool { - if ($this->renderHiddenInIndex === null) { - $this->renderHiddenInIndex = (boolean)$this->fusionValue('renderHiddenInIndex'); + if ($this->renderHiddenInMenu === null) { + $this->renderHiddenInMenu = (boolean)$this->fusionValue('renderHiddenInMenu'); } - return $this->renderHiddenInIndex; + return $this->renderHiddenInMenu; } /** @@ -214,13 +214,13 @@ protected function resolveImages(Subtree $subtree, array &$item): void } /** - * Return TRUE/FALSE if the node is currently hidden; taking the "renderHiddenInIndex" configuration + * Return TRUE/FALSE if the node is currently hidden; taking the "renderHiddenInMenu" configuration * of the Menu Fusion object into account. */ protected function isDocumentNodeToBeIndexed(Node $node): bool { return !$this->getNodeType($node)->isOfType('Neos.Seo:NoindexMixin') - && ($this->getRenderHiddenInIndex() || $node->getProperty('hiddenInIndex') !== true) + && ($this->getRenderHiddenInMenu() || $node->getProperty('hiddenInMenu') !== true) && $node->getProperty('metaRobotsNoindex') !== true && ( (string)$node->getProperty('canonicalLink') === '' diff --git a/Resources/Private/Fusion/Helper/SitemapUrls.fusion b/Resources/Private/Fusion/Helper/SitemapUrls.fusion index 4c0c4352..795f486f 100644 --- a/Resources/Private/Fusion/Helper/SitemapUrls.fusion +++ b/Resources/Private/Fusion/Helper/SitemapUrls.fusion @@ -2,5 +2,5 @@ prototype(Neos.Seo:Helper.SitemapUrls) { @class = 'Neos\\Seo\\Fusion\\XmlSitemapUrlsImplementation' startingPoint = null includeImageUrls = false - renderHiddenInIndex = true + renderHiddenInMenu = true } From 32c8d5c9631ca9b6088b4b8036a805d940e47df9 Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Sun, 16 Jun 2024 21:54:15 +0200 Subject: [PATCH 2/4] TASK: Adjust to Removal of Node:: --- .../Fusion/XmlSitemapUrlsImplementation.php | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Classes/Fusion/XmlSitemapUrlsImplementation.php b/Classes/Fusion/XmlSitemapUrlsImplementation.php index 42b136bc..a1588da8 100644 --- a/Classes/Fusion/XmlSitemapUrlsImplementation.php +++ b/Classes/Fusion/XmlSitemapUrlsImplementation.php @@ -13,6 +13,7 @@ */ use Neos\ContentRepository\Core\NodeType\NodeType; +use Neos\ContentRepository\Core\NodeType\NodeTypeManager; use Neos\ContentRepository\Core\NodeType\NodeTypeName; use Neos\ContentRepository\Core\NodeType\NodeTypeNames; use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindSubtreeFilter; @@ -24,13 +25,10 @@ use Neos\Flow\Persistence\Doctrine\PersistenceManager; use Neos\Fusion\FusionObjects\AbstractFusionObject; use Neos\Media\Domain\Model\ImageInterface; -use Neos\Neos\Utility\NodeTypeWithFallbackProvider; use Neos\Utility\Exception\PropertyNotAccessibleException; class XmlSitemapUrlsImplementation extends AbstractFusionObject { - use NodeTypeWithFallbackProvider; - #[Flow\Inject] protected ContentRepositoryRegistry $contentRepositoryRegistry; @@ -97,14 +95,14 @@ public function evaluate(): array $startingPoint = $this->getStartingPoint(); $subgraph = $this->contentRepositoryRegistry->subgraphForNode($startingPoint); - $nodeTypeManager = $this->contentRepositoryRegistry->get($startingPoint->subgraphIdentity->contentRepositoryId)->getNodeTypeManager(); + $nodeTypeManager = $this->contentRepositoryRegistry->get($startingPoint->contentRepositoryId)->getNodeTypeManager(); $nodeTypeNames = NodeTypeNames::fromArray(array_map( fn(NodeType $nodeType): NodeTypeName => $nodeType->name, $nodeTypeManager->getSubNodeTypes('Neos.Neos:Document', false) )); $subtree = $subgraph->findSubtree( - $startingPoint->nodeAggregateId, + $startingPoint->aggregateId, FindSubtreeFilter::create(nodeTypes: NodeTypeCriteria::create($nodeTypeNames, NodeTypeNames::createEmpty())) ); @@ -143,8 +141,9 @@ private function getAssetPropertiesForNodeType(NodeType $nodeType): array protected function collectItems(array &$items, Subtree $subtree): void { $node = $subtree->node; + $nodeTypeManager = $this->contentRepositoryRegistry->get($node->contentRepositoryId)->getNodeTypeManager(); - if ($this->isDocumentNodeToBeIndexed($node)) { + if ($this->isDocumentNodeToBeIndexed($node, $nodeTypeManager)) { $item = [ 'node' => $node, 'lastModificationDateTime' => $node->timestamps->lastModified ?: $node->timestamps->created, @@ -156,7 +155,6 @@ protected function collectItems(array &$items, Subtree $subtree): void } if ($this->getIncludeImageUrls()) { - $nodeTypeManager = $this->contentRepositoryRegistry->get($node->subgraphIdentity->contentRepositoryId)->getNodeTypeManager(); $collectionNodeTypeNames = array_map( fn(NodeType $nodeType): NodeTypeName => $nodeType->name, $nodeTypeManager->getSubNodeTypes('Neos.Neos:ContentCollection', false) @@ -170,11 +168,11 @@ protected function collectItems(array &$items, Subtree $subtree): void $subgraph = $this->contentRepositoryRegistry->subgraphForNode($node); $contentSubtree = $subgraph->findSubtree( - $node->nodeAggregateId, + $node->aggregateId, FindSubtreeFilter::create(nodeTypes: NodeTypeCriteria::create($nodeTypeNames, NodeTypeNames::createEmpty())) ); - $this->resolveImages($contentSubtree, $item); + $this->resolveImages($contentSubtree, $item, $nodeTypeManager); } $items[] = $item; @@ -191,10 +189,11 @@ protected function collectItems(array &$items, Subtree $subtree): void * @return void * @throws PropertyNotAccessibleException */ - protected function resolveImages(Subtree $subtree, array &$item): void + protected function resolveImages(Subtree $subtree, array &$item, NodeTypeManager $nodeTypeManager): void { $node = $subtree->node; - $assetPropertiesForNodeType = $this->getAssetPropertiesForNodeType($this->getNodeType($node)); + $nodeType = $nodeTypeManager->getNodeType($node->nodeTypeName); + $assetPropertiesForNodeType = $nodeType ? $this->getAssetPropertiesForNodeType($nodeType) : []; foreach ($assetPropertiesForNodeType as $propertyName) { if (is_array($node->getProperty($propertyName)) && !empty($node->getProperty($propertyName))) { @@ -209,7 +208,7 @@ protected function resolveImages(Subtree $subtree, array &$item): void } foreach ($subtree->children as $childSubtree) { - $this->resolveImages($childSubtree, $item); + $this->resolveImages($childSubtree, $item, $nodeTypeManager); } } @@ -217,14 +216,15 @@ protected function resolveImages(Subtree $subtree, array &$item): void * Return TRUE/FALSE if the node is currently hidden; taking the "renderHiddenInMenu" configuration * of the Menu Fusion object into account. */ - protected function isDocumentNodeToBeIndexed(Node $node): bool + protected function isDocumentNodeToBeIndexed(Node $node, NodeTypeManager $nodeTypeManager): bool { - return !$this->getNodeType($node)->isOfType('Neos.Seo:NoindexMixin') + $nodeType = $nodeTypeManager->getNodeType($node->nodeTypeName); + return !$nodeType?->isOfType('Neos.Seo:NoindexMixin') && ($this->getRenderHiddenInMenu() || $node->getProperty('hiddenInMenu') !== true) && $node->getProperty('metaRobotsNoindex') !== true && ( (string)$node->getProperty('canonicalLink') === '' - || substr($node->getProperty('canonicalLink'), 7) === $node->nodeAggregateId->value + || substr($node->getProperty('canonicalLink'), 7) === $node->aggregateId->value ); } } From 1f9ffc0e954c6f73c25accbe6a689deff0181621 Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Tue, 18 Jun 2024 20:39:21 +0200 Subject: [PATCH 3/4] FEATURE: Introduce phpstan with level 8 --- .../Fusion/XmlSitemapUrlsImplementation.php | 35 ++++++++++++------- composer.json | 3 ++ phpstan.neon.dist | 4 +++ 3 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 phpstan.neon.dist diff --git a/Classes/Fusion/XmlSitemapUrlsImplementation.php b/Classes/Fusion/XmlSitemapUrlsImplementation.php index a1588da8..f558cc64 100644 --- a/Classes/Fusion/XmlSitemapUrlsImplementation.php +++ b/Classes/Fusion/XmlSitemapUrlsImplementation.php @@ -25,8 +25,16 @@ use Neos\Flow\Persistence\Doctrine\PersistenceManager; use Neos\Fusion\FusionObjects\AbstractFusionObject; use Neos\Media\Domain\Model\ImageInterface; -use Neos\Utility\Exception\PropertyNotAccessibleException; +/** + * @phpstan-type SitemapUrlItem array{ + * node: Node, + * lastModificationDateTime: \DateTimeImmutable, + * priority: string, + * images: array, + * changeFrequency?: true + * } + */ class XmlSitemapUrlsImplementation extends AbstractFusionObject { #[Flow\Inject] @@ -36,7 +44,7 @@ class XmlSitemapUrlsImplementation extends AbstractFusionObject protected PersistenceManager $persistenceManager; /** - * @var array> + * @var array> */ protected array $assetPropertiesByNodeType = []; @@ -47,7 +55,7 @@ class XmlSitemapUrlsImplementation extends AbstractFusionObject protected ?Node $startingPoint = null; /** - * @var array|null + * @var list|null */ protected ?array $items = null; @@ -84,8 +92,7 @@ public function getStartingPoint(): Node /** * Evaluate this Fusion object and return the result * - * @return array - * @throws PropertyNotAccessibleException + * @return list */ public function evaluate(): array { @@ -105,7 +112,9 @@ public function evaluate(): array $startingPoint->aggregateId, FindSubtreeFilter::create(nodeTypes: NodeTypeCriteria::create($nodeTypeNames, NodeTypeNames::createEmpty())) ); - + if (!$subtree) { + throw new \RuntimeException(sprintf('The "startingPoint" Node with identifier "%s" doesnt exist anymore.', $startingPoint->aggregateId->value), 1718735861); + } $this->collectItems($items, $subtree); $this->items = $items; } @@ -113,6 +122,9 @@ public function evaluate(): array return $this->items; } + /** + * @return list + */ private function getAssetPropertiesForNodeType(NodeType $nodeType): array { if (!array_key_exists($nodeType->name->value, $this->assetPropertiesByNodeType)) { @@ -136,7 +148,7 @@ private function getAssetPropertiesForNodeType(NodeType $nodeType): array } /** - * @throws PropertyNotAccessibleException + * @param list $items */ protected function collectItems(array &$items, Subtree $subtree): void { @@ -171,7 +183,9 @@ protected function collectItems(array &$items, Subtree $subtree): void $node->aggregateId, FindSubtreeFilter::create(nodeTypes: NodeTypeCriteria::create($nodeTypeNames, NodeTypeNames::createEmpty())) ); - + if (!$contentSubtree) { + throw new \RuntimeException(sprintf('The Node with identifier "%s" doesnt exist anymore.', $node->aggregateId->value), 1718735861); + } $this->resolveImages($contentSubtree, $item, $nodeTypeManager); } @@ -184,10 +198,7 @@ protected function collectItems(array &$items, Subtree $subtree): void } /** - * @param Subtree $subtree - * @param array & $item - * @return void - * @throws PropertyNotAccessibleException + * @param SitemapUrlItem $item */ protected function resolveImages(Subtree $subtree, array &$item, NodeTypeManager $nodeTypeManager): void { diff --git a/composer.json b/composer.json index ca8513cd..c1f084e3 100644 --- a/composer.json +++ b/composer.json @@ -7,6 +7,9 @@ "neos/neos": "^9.0", "neos/fusion-afx": "^9.0" }, + "scripts": { + "lint:phpstan": "../../../bin/phpstan analyse" + }, "autoload": { "psr-4": { "Neos\\Seo\\": "Classes" diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 00000000..d0cf7bd0 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,4 @@ +parameters: + level: 8 + paths: + - Classes From 8f437d21a52b181797c516a2dcdfdb941a224e25 Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Mon, 24 Jun 2024 21:35:20 +0200 Subject: [PATCH 4/4] FEATURE: Introduce PHPStan level 8 for CI --- .github/workflows/tests.yml | 64 +++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 .github/workflows/tests.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 00000000..2e286ac3 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,64 @@ +name: Tests + +on: + push: + branches: [ main, '[0-9]+.x' ] + pull_request: + branches: [ main, '[0-9]+.x' ] + workflow_dispatch: # Allow manual triggering on any branch via `gh workflow run tests.yml -r branch-name` + +jobs: + build: + env: + FLOW_PATH_ROOT: ../neos-base-distribution + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + include: + - php-version: "8.2" + neos-version: "9.0" + - php-version: "8.3" + neos-version: "9.0" + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + extensions: mbstring, xml, json, zlib, iconv, intl, pdo_sqlite, mysql + + - id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + shell: bash + + - uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Prepare Neos distribution + run: | + git clone --depth 1 --branch ${{ matrix.neos-version }} https://github.com/neos/neos-development-distribution.git ${FLOW_PATH_ROOT} + cd ${FLOW_PATH_ROOT} + composer config --no-plugins allow-plugins.neos/composer-plugin true + composer config repositories.package '{ "type": "path", "url": "../neos-seo", "options": { "symlink": false } }' + composer require --no-update --no-interaction neos/seo:@dev + composer require --dev --no-update --no-interaction phpstan/phpstan:^1.10 + + - name: Install dependencies + run: | + cd ${FLOW_PATH_ROOT} + rm -rf composer.lock + composer install --no-interaction --no-progress --prefer-dist + + - name: Linting + run: | + cd ${FLOW_PATH_ROOT}/Packages/Application/Neos.Seo + composer run lint:phpstan