Skip to content

Commit

Permalink
Merge branch '9.0' into task/runPhpstormInspections
Browse files Browse the repository at this point in the history
  • Loading branch information
mhsdesign authored Feb 11, 2024
2 parents 7cf1df0 + b1e1d7b commit 2910ec2
Show file tree
Hide file tree
Showing 133 changed files with 3,200 additions and 1,314 deletions.
6 changes: 4 additions & 2 deletions .composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,16 @@
"@test:behat-cli -c Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/behat.yml.dist",
"../../flow doctrine:migrate --quiet; ../../flow cr:setup",
"@test:behat-cli -c Neos.Neos/Tests/Behavior/behat.yml",
"@test:behat-cli -c Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/behat.yml.dist"
"@test:behat-cli -c Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/behat.yml.dist",
"@test:behat-cli -c Neos.TimeableNodeVisibility/Tests/Behavior/behat.yml.dist"
],
"test:behavioral:stop-on-failure": [
"@test:behat-cli -vvv --stop-on-failure -c Neos.ContentRepository.BehavioralTests/Tests/Behavior/behat.yml.dist",
"@test:behat-cli -vvv --stop-on-failure -c Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/behat.yml.dist",
"../../flow doctrine:migrate --quiet; ../../flow cr:setup",
"@test:behat-cli -vvv --stop-on-failure -c Neos.Neos/Tests/Behavior/behat.yml",
"@test:behat-cli -vvv --stop-on-failure -c Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/behat.yml.dist"
"@test:behat-cli -vvv --stop-on-failure -c Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/behat.yml.dist",
"@test:behat-cli -vvv --stop-on-failure -c Neos.TimeableNodeVisibility/Tests/Behavior/behat.yml.dist"
],
"test": [
"@test:unit",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,26 @@ public function iChangeTheFollowingHierarchyRelationsDimensionSpacePointHash(Tab
);
}

/**
* @When /^I change the following hierarchy relation's name:$/
* @param TableNode $payloadTable
* @throws DBALException
*/
public function iChangeTheFollowingHierarchyRelationsEdgeName(TableNode $payloadTable): void
{
$dataset = $this->transformPayloadTableToDataset($payloadTable);
$record = $this->transformDatasetToHierarchyRelationRecord($dataset);
unset($record['position']);

$this->dbalClient->getConnection()->update(
$this->getTableNamePrefix() . '_hierarchyrelation',
[
'name' => $dataset['newName']
],
$record
);
}

/**
* @When /^I set the following position:$/
* @param TableNode $payloadTable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,16 @@ Feature: Run projection integrity violation detection regarding naming of tether
| originDimensionSpacePoint | {"language":"de"} |
| coveredDimensionSpacePoints | [{"language":"de"}] |
| parentNodeAggregateId | "sir-david-nodenborough" |
| nodeName | "to-be-hacked-to-null" |
| nodeAggregateClassification | "tethered" |
And the graph projection is fully up to date
And I change the following hierarchy relation's name:
| Key | Value |
| contentStreamId | "cs-identifier" |
| dimensionSpacePoint | {"language":"de"} |
| parentNodeAggregateId | "sir-david-nodenborough" |
| childNodeAggregateId | "nodewyn-tetherton" |
| newName | null |
And I run integrity violation detection
Then I expect the integrity violation detection result to contain exactly 1 errors
And I expect integrity violation detection result error number 1 to have code 1597923103
Original file line number Diff line number Diff line change
Expand Up @@ -461,15 +461,9 @@ public function countNodes(): int
}
}

/**
* @return array<string,mixed>
*/
public function jsonSerialize(): array
public function jsonSerialize(): ContentSubgraphIdentity
{
return [
'contentStreamId' => $this->contentStreamId,
'dimensionSpacePoint' => $this->dimensionSpacePoint
];
return $this->getIdentity();
}

/** ------------------------------------------- */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,14 +534,8 @@ private function getDatabaseConnection(): DatabaseConnection
return $this->databaseClient->getConnection();
}

/**
* @return array<string,mixed>
*/
public function jsonSerialize(): array
public function jsonSerialize(): ContentSubgraphIdentity
{
return [
'contentStreamId' => $this->contentStreamId,
'dimensionSpacePoint' => $this->dimensionSpacePoint
];
return $this->getIdentity();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,30 @@ public function processNode(Node $node, Scope $scope): array
{
assert($node instanceof Node\Expr\CallLike);

if ($scope->getNamespace() && str_starts_with($scope->getNamespace(), 'Neos\ContentRepository\Core')) {
// Core is allowed to call all namespaces
// TODO !!! ONLY FROM WITHIN OWN PACKAGE!!!!
if (
$scope->getNamespace()
&& (
str_starts_with($scope->getNamespace(), 'Neos\ContentRepository\Core')
|| str_starts_with($scope->getNamespace(), 'Neos\ContentGraph\DoctrineDbalAdapter')
|| str_starts_with($scope->getNamespace(), 'Neos\ContentRepository\BehavioralTests')
|| str_starts_with($scope->getNamespace(), 'Neos\ContentRepository\Export')
|| str_starts_with($scope->getNamespace(), 'Neos\ContentRepository\LegacyNodeMigration')
|| str_starts_with($scope->getNamespace(), 'Neos\ContentRepository\StructureAdjustment')
)
) {
// todo this rule was intended to enforce the internal annotations from the Neos\ContentRepository\Core from all call sites.
// this is currently not achievable and thus we grant a few packages BUT NOT NEOS.NEOS free access.
// that is a good compromise between having this rule not enabled at all or cluttering everything with a baseline.
return [];
}
if ($node instanceof Node\Expr\MethodCall) {
$methodCallTargetClass = $scope->getType($node->var);
if ($methodCallTargetClass instanceof ObjectType) {
$targetClassName = $methodCallTargetClass->getClassName();
// TODO: also extend to more packages
if (
!str_starts_with($targetClassName, 'Neos\ContentRepository\Core')
) {
// currently only access to methods on the cr core is protected.
return [];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
*
* @api
*/
final class ContentRepositoryId
final class ContentRepositoryId implements \JsonSerializable
{
private function __construct(
public readonly string $value
Expand Down Expand Up @@ -47,4 +47,9 @@ public function equals(self $other): bool
{
return $this->value === $other->value;
}

public function jsonSerialize(): mixed
{
return $this->value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,6 @@ public function splitByScope(NodeType $nodeType): array
);
}

/**
* @phpstan-assert-if-true !null $this->getProperty()
*/
public function propertyExists(string $propertyName): bool
{
return isset($this->values[$propertyName]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ private static function isFilterEmpty(object $filter): bool
return array_filter(get_object_vars($filter), static fn ($value) => $value !== null) === [];
}

public function jsonSerialize(): mixed
public function jsonSerialize(): ContentSubgraphIdentity
{
return $this->wrappedContentSubgraph->jsonSerialize();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
*
* @api
*/
final class ContentSubgraphIdentity
final class ContentSubgraphIdentity implements \JsonSerializable
{
private function __construct(
public readonly ContentRepositoryId $contentRepositoryId,
Expand Down Expand Up @@ -90,4 +90,17 @@ public function withVisibilityConstraints(VisibilityConstraints $visibilityConst
$visibilityConstraints
);
}

/**
* @return array<string,mixed>
*/
public function jsonSerialize(): array
{
return [
'contentRepositoryId' => $this->contentRepositoryId,
'contentStreamId' => $this->contentStreamId,
'dimensionSpacePoint' => $this->dimensionSpacePoint,
'visibilityConstraints' => $this->visibilityConstraints
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -204,4 +204,6 @@ public function retrieveNodePath(NodeAggregateId $nodeAggregateId): AbsoluteNode
* @internal this method might change without further notice.
*/
public function countNodes(): int;

public function jsonSerialize(): ContentSubgraphIdentity;
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ private function __construct(
public ?NodeName $nodeName,
public Timestamps $timestamps,
) {
if ($this->classification->isTethered() && $this->nodeName === null) {
throw new \InvalidArgumentException('The NodeName must be set if the Node is tethered.', 1695118377);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
*
* @api
*/
final class VisibilityConstraints
final class VisibilityConstraints implements \JsonSerializable
{
protected bool $disabledContentShown = false;

Expand Down Expand Up @@ -49,4 +49,9 @@ public static function frontend(): VisibilityConstraints
{
return new VisibilityConstraints(false);
}

public function jsonSerialize(): string
{
return $this->getHash();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ private function exportEvent(EventInterface $event): void
);
assert($this->eventFileResource !== null);
fwrite($this->eventFileResource, $exportedEvent->toJson() . chr(10));
$this->numberOfExportedEvents ++;
$this->numberOfExportedEvents++;
}

/**
Expand Down Expand Up @@ -287,7 +287,7 @@ public function processNodeDataWithoutFallbackToEmptyDimension(NodeAggregateId $
$this->exportEvent(new NodeAggregateWithNodeWasCreated($this->contentStreamId, $nodeAggregateId, $nodeTypeName, $originDimensionSpacePoint, $this->interDimensionalVariationGraph->getSpecializationSet($originDimensionSpacePoint->toDimensionSpacePoint()), $parentNodeAggregate->nodeAggregateId, $nodeName, $serializedPropertyValuesAndReferences->serializedPropertyValues, NodeAggregateClassification::CLASSIFICATION_REGULAR, null));
}
// nodes are hidden via NodeAggregateWasDisabled event
if ($nodeDataRow['hidden']) {
if ($this->isNodeHidden($nodeDataRow)) {
$this->exportEvent(new NodeAggregateWasDisabled($this->contentStreamId, $nodeAggregateId, $this->interDimensionalVariationGraph->getSpecializationSet($originDimensionSpacePoint->toDimensionSpacePoint(), true, $this->visitedNodes->alreadyVisitedOriginDimensionSpacePoints($nodeAggregateId)->toDimensionSpacePointSet())));
}
foreach ($serializedPropertyValuesAndReferences->references as $referencePropertyName => $destinationNodeAggregateIds) {
Expand Down Expand Up @@ -353,6 +353,21 @@ public function extractPropertyValuesAndReferences(array $nodeDataRow, NodeType
$properties['_hiddenInIndex'] = true;
}

if ($nodeType->isOfType(NodeTypeName::fromString('Neos.TimeableNodeVisibility:Timeable'))) {
// hiddenbeforedatetime is stored as separate column in the nodedata table, but we need it as property
if ($nodeDataRow['hiddenbeforedatetime']) {
$properties['enableAfterDateTime'] = $nodeDataRow['hiddenbeforedatetime'];
}
// hiddenafterdatetime is stored as separate column in the nodedata table, but we need it as property
if ($nodeDataRow['hiddenafterdatetime']) {
$properties['disableAfterDateTime'] = $nodeDataRow['hiddenafterdatetime'];
}
} else {
if ($nodeDataRow['hiddenbeforedatetime'] || $nodeDataRow['hiddenafterdatetime']) {
$this->dispatch(Severity::WARNING, 'Skipped the migration of your "hiddenBeforeDateTime" and "hiddenAfterDateTime" properties as your target NodeTypes do not inherit "Neos.TimeableNodeVisibility:Timeable". Please install neos/timeable-node-visibility, if you want to migrate them.');
}
}

return new SerializedPropertyValuesAndReferences($this->propertyConverter->serializePropertyValues(PropertyValuesToWrite::fromArray($properties), $nodeType), $references);
}

Expand Down Expand Up @@ -444,4 +459,47 @@ private function dispatch(Severity $severity, string $message, mixed ...$args):
$callback($severity, $renderedMessage);
}
}

/**
* Determines actual hidden state based on "hidden", "hiddenafterdatetime" and "hiddenbeforedatetime"
*
* @param array<string, mixed> $nodeDataRow
*/
private function isNodeHidden(array $nodeDataRow): bool
{
// Already hidden
if ($nodeDataRow['hidden']) {
return true;
}

$now = new \DateTimeImmutable();
$hiddenAfterDateTime = $nodeDataRow['hiddenafterdatetime'] ? new \DateTimeImmutable($nodeDataRow['hiddenafterdatetime']) : null;
$hiddenBeforeDateTime = $nodeDataRow['hiddenbeforedatetime'] ? new \DateTimeImmutable($nodeDataRow['hiddenbeforedatetime']) : null;

// Hidden after a date time, without getting already re-enabled by hidden before date time - afterward
if ($hiddenAfterDateTime != null
&& $hiddenAfterDateTime < $now
&& (
$hiddenBeforeDateTime == null
|| $hiddenBeforeDateTime > $now
|| $hiddenBeforeDateTime<= $hiddenAfterDateTime
)
) {
return true;
}

// Hidden before a date time, without getting enabled by hidden after date time - before
if ($hiddenBeforeDateTime != null
&& $hiddenBeforeDateTime > $now
&& (
$hiddenAfterDateTime == null
|| $hiddenAfterDateTime > $hiddenBeforeDateTime
)
) {
return true;
}

return false;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ public function iHaveTheFollowingNodeDataRows(TableNode $nodeDataRows): void
'properties' => !empty($row['Properties']) ? $row['Properties'] : '{}',
'dimensionvalues' => !empty($row['Dimension Values']) ? $row['Dimension Values'] : '{}',
'hiddeninindex' => $row['Hidden in index'] ?? '0',
'hiddenbeforedatetime' => !empty($row['Hidden before DateTime']) ? ($row['Hidden before DateTime']): null,
'hiddenafterdatetime' => !empty($row['Hidden after DateTime']) ? ($row['Hidden after DateTime']) : null,
'hidden' => $row['Hidden'] ?? '0',
];
}, $nodeDataRows->getHash());
Expand Down
Loading

0 comments on commit 2910ec2

Please sign in to comment.