diff --git a/config/set/contentrepository-90.php b/config/set/contentrepository-90.php
index dc78bca..e616338 100644
--- a/config/set/contentrepository-90.php
+++ b/config/set/contentrepository-90.php
@@ -1,23 +1,34 @@
compatible with ES CR node (nothing to do)
+ $fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_label', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_label")" to "VARIABLE.label". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// setProperty
// hasProperty -> compatible with ES CR Node (nothing to do)
// getProperty -> compatible with ES CR Node (nothing to do)
@@ -123,56 +129,64 @@
// setNodeType
// getNodeType: NodeType
$methodCallToPropertyFetches[] = new MethodCallToPropertyFetch(NodeLegacyStub::class, 'getNodeType', 'nodeType');
+ $fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_nodeType', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_nodeType")" to "VARIABLE.nodeType". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// setHidden
// isHidden
$rectorConfig->rule(NodeIsHiddenRector::class);
+ $fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_hidden', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_hidden")". Use the NodeHiddenStateFinder of CR to determine the hidden state. ');
// TODO: Fusion NodeAccess
// setHiddenBeforeDateTime
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'setHiddenBeforeDateTime', '!! Node::setHiddenBeforeDateTime() is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
// getHiddenBeforeDateTime
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'getHiddenBeforeDateTime', '!! Node::getHiddenBeforeDateTime() is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
$fusionNodePropertyPathToWarningComments[] = new FusionNodePropertyPathToWarningComment('hiddenBeforeDateTime', 'Line %LINE: !! node.hiddenBeforeDateTime is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
+ $fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_hiddenBeforeDateTime', 'Line %LINE: !! "q(VARIABLE).property("_hiddenBeforeDateTime")" is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
// setHiddenAfterDateTime
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'setHiddenAfterDateTime', '!! Node::setHiddenAfterDateTime() is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
// getHiddenAfterDateTime
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'getHiddenAfterDateTime', '!! Node::getHiddenAfterDateTime() is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
$fusionNodePropertyPathToWarningComments[] = new FusionNodePropertyPathToWarningComment('hiddenAfterDateTime', 'Line %LINE: !! node.hiddenAfterDateTime is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
+ $fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_hiddenAfterDateTime', 'Line %LINE: !! "q(VARIABLE).property("_hiddenAfterDateTime")" is not supported by the new CR. Timed publishing will be implemented not on the read model, but by dispatching commands at a given time.');
// setHiddenInIndex
// isHiddenInIndex
$rectorConfig->rule(NodeIsHiddenInIndexRector::class);
// Fusion: .hiddenInIndex -> node.properties._hiddenInIndex
$rectorConfig->rule(FusionNodeHiddenInIndexRector::class);
+ $fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_hiddenInIndex', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_hiddenInIndex")" to "VARIABLE.properties._hiddenInIndex". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// setAccessRoles
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'setAccessRoles', '!! Node::setAccessRoles() is not supported by the new CR.');
// getAccessRoles
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'getAccessRoles', '!! Node::getAccessRoles() is not supported by the new CR.');
// getPath
$rectorConfig->rule(NodeGetPathRector::class);
- // Fusion: .depth -> Neos.NodeAccess.depth(node)
$rectorConfig->rule(FusionNodePathRector::class);
+ $fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_path', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_path")" to "Neos.Node.path(VARIABLE)". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// getContextPath
// TODO: PHP
- // TODO: Fusion
- // - NodeAddress + LOG (WARNING)
+ $rectorConfig->rule(FusionNodeContextPathRector::class);
+ $fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_contextPath', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_contextPath")" to "Neos.Node.serializedNodeAddress(VARIABLE)". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// getDepth
$rectorConfig->rule(NodeGetDepthRector::class);
- // Fusion: .depth -> Neos.Node.depth(node)
$rectorConfig->rule(FusionNodeDepthRector::class);
+ $fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_depth', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_depth")" to "Neos.Node.depth(VARIABLE)". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// setWorkspace -> internal
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'setWorkspace', '!! Node::setWorkspace() was always internal, and the workspace system has been fundamentally changed with the new CR. Try to rewrite your code around Content Streams.');
// getWorkspace
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'getWorkspace', '!! Node::getWorkspace() does not make sense anymore concept-wise. In Neos < 9, it pointed to the workspace where the node was *at home at*. Now, the closest we have here is the node identity.');
+ $fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_workspace', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_workspace")". It does not make sense anymore concept-wise. In Neos < 9, it pointed to the workspace where the node was *at home at*. Now, the closest we have here is the node identity.');
// getIdentifier
$rectorConfig->rule(NodeGetIdentifierRector::class);
$rectorConfig->rule(FusionNodeIdentifierRector::class);
+ $fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_identifier', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_identifier")" to "VARIABLE.nodeAggregateId.value". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// setIndex -> internal
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'setIndex', '!! Node::setIndex() was always internal. To reorder nodes, use the "MoveNodeAggregate" command');
// getIndex
$methodCallToWarningComments[] = new MethodCallToWarningComment(NodeLegacyStub::class, 'getIndex', '!! Node::getIndex() is not supported. You can fetch all siblings and inspect the ordering');
+ $fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_index', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_index")". You can fetch all siblings and inspect the ordering.');
// getParent -> Node
$rectorConfig->rule(NodeGetParentRector::class);
- // Fusion: .parent -> Neos.NodeAccess.findParent(node)
$rectorConfig->rule(FusionNodeParentRector::class);
+ $fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_parent', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_parent")" to "q(VARIABLE).parent().get(0)". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
// getParentPath - deprecated
// createNode
// createSingleNode -> internal
@@ -211,8 +225,15 @@
// TODO: Fusion
// createVariantForContext()
// isAutoCreated()
+ // TODO: PHP
+ $rectorConfig->rule(FusionNodeAutoCreatedRector::class);
+ $fusionFlowQueryPropertyToComments[] = new FusionFlowQueryNodePropertyToWarningComment('_autoCreated', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_autoCreated")" to "VARIABLE.classification.tethered". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.');
+
// getOtherNodeVariants()
+ $rectorConfig->ruleWithConfiguration(FusionNodePropertyPathToWarningCommentRector::class, $fusionFlowQueryPropertyToComments);
+
+
/**
* Neos\ContentRepository\Domain\Projection\Content\NodeInterface
*/
diff --git a/src/ContentRepository90/Rules/FusionNodeAutoCreatedRector.php b/src/ContentRepository90/Rules/FusionNodeAutoCreatedRector.php
new file mode 100644
index 0000000..8b00d80
--- /dev/null
+++ b/src/ContentRepository90/Rules/FusionNodeAutoCreatedRector.php
@@ -0,0 +1,33 @@
+process(fn(string $eelExpression) => preg_replace(
+ '/(node|documentNode|site)\.autoCreated/',
+ '$1.classification.tethered',
+ $eelExpression
+ ))
+ ->addCommentsIfRegexMatches(
+ '/\.autoCreated/',
+ '// TODO 9.0 migration: Line %LINE: !! You very likely need to rewrite "VARIABLE.autoCreated" to "VARIABLE.classification.tethered". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.'
+ )->getProcessedContent();
+ }
+}
diff --git a/src/ContentRepository90/Rules/FusionNodeContextPathRector.php b/src/ContentRepository90/Rules/FusionNodeContextPathRector.php
new file mode 100644
index 0000000..336e73b
--- /dev/null
+++ b/src/ContentRepository90/Rules/FusionNodeContextPathRector.php
@@ -0,0 +1,33 @@
+process(fn(string $eelExpression) => preg_replace(
+ '/(node|documentNode|site)\.contextPath/',
+ 'Neos.Node.serializedNodeAddress($1)',
+ $eelExpression
+ ))
+ ->addCommentsIfRegexMatches(
+ '/\.contextPath/',
+ '// TODO 9.0 migration: Line %LINE: !! You very likely need to rewrite "VARIABLE.contextPath" to "Neos.Node.serializedNodeAddress(VARIABLE)". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.'
+ )->getProcessedContent();
+ }
+}
diff --git a/src/Generic/Rules/FusionFlowQueryNodePropertyToWarningCommentRector.php b/src/Generic/Rules/FusionFlowQueryNodePropertyToWarningCommentRector.php
new file mode 100644
index 0000000..3a919af
--- /dev/null
+++ b/src/Generic/Rules/FusionFlowQueryNodePropertyToWarningCommentRector.php
@@ -0,0 +1,64 @@
+fusionFlowQueryNodePropertyToWarningComments as $flowQueryNodePropertyToWarningComment) {
+ $property = $flowQueryNodePropertyToWarningComment->property;
+ $regexWarningMessagePairs[] = new RegexCommentTemplatePair(
+ "/\.property\(('|\")$property('|\")\)/",
+ (string)self::todoCommentAttribute($flowQueryNodePropertyToWarningComment->warningMessage)
+ );
+
+ }
+
+ return EelExpressionTransformer::parse($fileContent)
+ ->addCommentsIfRegexesMatch($regexWarningMessagePairs)
+ ->getProcessedContent();
+
+ }
+
+ /**
+ * @param FusionFlowQueryNodePropertyToWarningComment[] $configuration
+ */
+ public function configure(array $configuration): void
+ {
+ Assert::allIsAOf($configuration, FusionFlowQueryNodePropertyToWarningComment::class);
+ $this->fusionFlowQueryNodePropertyToWarningComments = $configuration;
+ }
+}
diff --git a/src/Generic/ValueObject/FusionFlowQueryNodePropertyToWarningComment.php b/src/Generic/ValueObject/FusionFlowQueryNodePropertyToWarningComment.php
new file mode 100644
index 0000000..00cf664
--- /dev/null
+++ b/src/Generic/ValueObject/FusionFlowQueryNodePropertyToWarningComment.php
@@ -0,0 +1,17 @@
+ -1}
+ checked.@process.checkMultiValue.@if.hasValue = ${field.hasCurrentValue()}
+ checked.@process.checkMultiValue.@if.isMultiple = ${field.isMultiple()}
+ checked.@process.checkSingleValue = ${field.getCurrentValueStringified() == field.getTargetValueStringified()}
+ checked.@process.checkSingleValue.@if.hasValue = ${field.hasCurrentValue()}
+ checked.@process.checkSingleValue.@if.isSingle = ${!field.isMultiple()}
+
+ renderer = afx`
+
+ `
+ }
+}
+-----
+// TODO 9.0 migration: Line 26: !! You very likely need to rewrite "VARIABLE.autoCreated" to "VARIABLE.classification.tethered". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.
+prototype(Neos.Fusion.Form:Checkbox) < prototype(Neos.Fusion.Form:Component.Field) {
+
+ renderer = Neos.Fusion:Component {
+
+ #
+ # pass down props
+ #
+ attributes = ${node.classification.tethered || documentNode.classification.tethered}
+
+ #
+ # the `checked` state is calculated outside the renderer to allow` overriding via `attributes`
+ #
+ checked = false
+ checked.@process.checkMultiValue = ${Array.indexOf(field.getCurrentMultivalueStringified(), field.getTargetValueStringified()) > -1}
+ checked.@process.checkMultiValue.@if.hasValue = ${field.hasCurrentValue()}
+ checked.@process.checkMultiValue.@if.isMultiple = ${field.isMultiple()}
+ checked.@process.checkSingleValue = ${field.getCurrentValueStringified() == field.getTargetValueStringified()}
+ checked.@process.checkSingleValue.@if.hasValue = ${field.hasCurrentValue()}
+ checked.@process.checkSingleValue.@if.isSingle = ${!field.isMultiple()}
+
+ renderer = afx`
+
+ `
+ }
+}
diff --git a/tests/ContentRepository90/Rules/FusionNodeAutoCreatedRector/FusionNodeAutoCreatedRectorTest.php b/tests/ContentRepository90/Rules/FusionNodeAutoCreatedRector/FusionNodeAutoCreatedRectorTest.php
new file mode 100644
index 0000000..5efd9aa
--- /dev/null
+++ b/tests/ContentRepository90/Rules/FusionNodeAutoCreatedRector/FusionNodeAutoCreatedRectorTest.php
@@ -0,0 +1,31 @@
+doTestFile($fileInfo);
+ }
+
+ /**
+ * @return \Iterator
+ */
+ public function provideData(): \Iterator
+ {
+ return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture', '*.fusion.inc');
+ }
+
+ public function provideConfigFilePath(): string
+ {
+ return __DIR__ . '/config/configured_rule.php';
+ }
+}
diff --git a/tests/ContentRepository90/Rules/FusionNodeAutoCreatedRector/config/configured_rule.php b/tests/ContentRepository90/Rules/FusionNodeAutoCreatedRector/config/configured_rule.php
new file mode 100644
index 0000000..ef9ec1d
--- /dev/null
+++ b/tests/ContentRepository90/Rules/FusionNodeAutoCreatedRector/config/configured_rule.php
@@ -0,0 +1,19 @@
+services();
+ $services->defaults()
+ ->public()
+ ->autowire()
+ ->autoconfigure();
+ $services->set(FusionFileProcessor::class);
+ $rectorConfig->disableParallel(); // does not work for fusion files - see https://github.com/rectorphp/rector-src/pull/2597#issuecomment-1190120688
+
+ $rectorConfig->rule(FusionNodeAutoCreatedRector::class);
+};
diff --git a/tests/ContentRepository90/Rules/FusionNodeContextPathRector/Fixture/some_file.fusion.inc b/tests/ContentRepository90/Rules/FusionNodeContextPathRector/Fixture/some_file.fusion.inc
new file mode 100644
index 0000000..d522cb6
--- /dev/null
+++ b/tests/ContentRepository90/Rules/FusionNodeContextPathRector/Fixture/some_file.fusion.inc
@@ -0,0 +1,64 @@
+prototype(Neos.Fusion.Form:Checkbox) < prototype(Neos.Fusion.Form:Component.Field) {
+
+ renderer = Neos.Fusion:Component {
+
+ #
+ # pass down props
+ #
+ attributes = ${node.contextPath || documentNode.contextPath}
+
+ #
+ # the `checked` state is calculated outside the renderer to allow` overriding via `attributes`
+ #
+ checked = false
+ checked.@process.checkMultiValue = ${Array.indexOf(field.getCurrentMultivalueStringified(), field.getTargetValueStringified()) > -1}
+ checked.@process.checkMultiValue.@if.hasValue = ${field.hasCurrentValue()}
+ checked.@process.checkMultiValue.@if.isMultiple = ${field.isMultiple()}
+ checked.@process.checkSingleValue = ${field.getCurrentValueStringified() == field.getTargetValueStringified()}
+ checked.@process.checkSingleValue.@if.hasValue = ${field.hasCurrentValue()}
+ checked.@process.checkSingleValue.@if.isSingle = ${!field.isMultiple()}
+
+ renderer = afx`
+
+ `
+ }
+}
+-----
+// TODO 9.0 migration: Line 26: !! You very likely need to rewrite "VARIABLE.contextPath" to "Neos.Node.serializedNodeAddress(VARIABLE)". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.
+prototype(Neos.Fusion.Form:Checkbox) < prototype(Neos.Fusion.Form:Component.Field) {
+
+ renderer = Neos.Fusion:Component {
+
+ #
+ # pass down props
+ #
+ attributes = ${Neos.Node.serializedNodeAddress(node) || Neos.Node.serializedNodeAddress(documentNode)}
+
+ #
+ # the `checked` state is calculated outside the renderer to allow` overriding via `attributes`
+ #
+ checked = false
+ checked.@process.checkMultiValue = ${Array.indexOf(field.getCurrentMultivalueStringified(), field.getTargetValueStringified()) > -1}
+ checked.@process.checkMultiValue.@if.hasValue = ${field.hasCurrentValue()}
+ checked.@process.checkMultiValue.@if.isMultiple = ${field.isMultiple()}
+ checked.@process.checkSingleValue = ${field.getCurrentValueStringified() == field.getTargetValueStringified()}
+ checked.@process.checkSingleValue.@if.hasValue = ${field.hasCurrentValue()}
+ checked.@process.checkSingleValue.@if.isSingle = ${!field.isMultiple()}
+
+ renderer = afx`
+
+ `
+ }
+}
diff --git a/tests/ContentRepository90/Rules/FusionNodeContextPathRector/FusionNodeContextPathRectorTest.php b/tests/ContentRepository90/Rules/FusionNodeContextPathRector/FusionNodeContextPathRectorTest.php
new file mode 100644
index 0000000..8d8888f
--- /dev/null
+++ b/tests/ContentRepository90/Rules/FusionNodeContextPathRector/FusionNodeContextPathRectorTest.php
@@ -0,0 +1,31 @@
+doTestFile($fileInfo);
+ }
+
+ /**
+ * @return \Iterator
+ */
+ public function provideData(): \Iterator
+ {
+ return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture', '*.fusion.inc');
+ }
+
+ public function provideConfigFilePath(): string
+ {
+ return __DIR__ . '/config/configured_rule.php';
+ }
+}
diff --git a/tests/ContentRepository90/Rules/FusionNodeContextPathRector/config/configured_rule.php b/tests/ContentRepository90/Rules/FusionNodeContextPathRector/config/configured_rule.php
new file mode 100644
index 0000000..b05ebef
--- /dev/null
+++ b/tests/ContentRepository90/Rules/FusionNodeContextPathRector/config/configured_rule.php
@@ -0,0 +1,19 @@
+services();
+ $services->defaults()
+ ->public()
+ ->autowire()
+ ->autoconfigure();
+ $services->set(FusionFileProcessor::class);
+ $rectorConfig->disableParallel(); // does not work for fusion files - see https://github.com/rectorphp/rector-src/pull/2597#issuecomment-1190120688
+
+ $rectorConfig->rule(FusionNodeContextPathRector::class);
+};
diff --git a/tests/Generic/Rules/FusionFlowQueryNodePropertyToWarningCommentRector/Fixture/some_file.fusion.inc b/tests/Generic/Rules/FusionFlowQueryNodePropertyToWarningCommentRector/Fixture/some_file.fusion.inc
new file mode 100644
index 0000000..7648c27
--- /dev/null
+++ b/tests/Generic/Rules/FusionFlowQueryNodePropertyToWarningCommentRector/Fixture/some_file.fusion.inc
@@ -0,0 +1,27 @@
+prototype(Neos.Fusion.Form:Checkbox) < prototype(Neos.Fusion.Form:Component.Field) {
+
+ renderer = Neos.Fusion:Component {
+
+ attributes = ${q(node).property('_autoCreated') || q(site).property("_contextPath")}
+ attributes2 = ${q(site).property('_autoCreated') || q(site).property("_contextPath")}
+ attributes3 = ${q(node).parent().property('_autoCreated') || q(node).parent().property("_contextPath")}
+
+ }
+}
+-----
+// TODO 9.0 migration: Line 11: !! You very likely need to rewrite "q(VARIABLE).property("_autoCreated")" to "VARIABLE.classification.tethered". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.
+// TODO 9.0 migration: Line 12: !! You very likely need to rewrite "q(VARIABLE).property("_autoCreated")" to "VARIABLE.classification.tethered". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.
+// TODO 9.0 migration: Line 13: !! You very likely need to rewrite "q(VARIABLE).property("_autoCreated")" to "VARIABLE.classification.tethered". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.
+// TODO 9.0 migration: Line 11: !! You very likely need to rewrite "q(VARIABLE).property("_contextPath")" to "Neos.Node.serializedNodeAddress(VARIABLE)". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.
+// TODO 9.0 migration: Line 12: !! You very likely need to rewrite "q(VARIABLE).property("_contextPath")" to "Neos.Node.serializedNodeAddress(VARIABLE)". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.
+// TODO 9.0 migration: Line 13: !! You very likely need to rewrite "q(VARIABLE).property("_contextPath")" to "Neos.Node.serializedNodeAddress(VARIABLE)". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.
+prototype(Neos.Fusion.Form:Checkbox) < prototype(Neos.Fusion.Form:Component.Field) {
+
+ renderer = Neos.Fusion:Component {
+
+ attributes = ${q(node).property('_autoCreated') || q(site).property("_contextPath")}
+ attributes2 = ${q(site).property('_autoCreated') || q(site).property("_contextPath")}
+ attributes3 = ${q(node).parent().property('_autoCreated') || q(node).parent().property("_contextPath")}
+
+ }
+}
diff --git a/tests/Generic/Rules/FusionFlowQueryNodePropertyToWarningCommentRector/FusionFlowQueryNodePropertyToWarningCommentRectorTest.php b/tests/Generic/Rules/FusionFlowQueryNodePropertyToWarningCommentRector/FusionFlowQueryNodePropertyToWarningCommentRectorTest.php
new file mode 100644
index 0000000..c374713
--- /dev/null
+++ b/tests/Generic/Rules/FusionFlowQueryNodePropertyToWarningCommentRector/FusionFlowQueryNodePropertyToWarningCommentRectorTest.php
@@ -0,0 +1,31 @@
+doTestFile($fileInfo);
+ }
+
+ /**
+ * @return \Iterator
+ */
+ public function provideData(): \Iterator
+ {
+ return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture', '*.fusion.inc');
+ }
+
+ public function provideConfigFilePath(): string
+ {
+ return __DIR__ . '/config/configured_rule.php';
+ }
+}
diff --git a/tests/Generic/Rules/FusionFlowQueryNodePropertyToWarningCommentRector/config/configured_rule.php b/tests/Generic/Rules/FusionFlowQueryNodePropertyToWarningCommentRector/config/configured_rule.php
new file mode 100644
index 0000000..2a330e2
--- /dev/null
+++ b/tests/Generic/Rules/FusionFlowQueryNodePropertyToWarningCommentRector/config/configured_rule.php
@@ -0,0 +1,23 @@
+services();
+ $services->defaults()
+ ->public()
+ ->autowire()
+ ->autoconfigure();
+ $services->set(FusionFileProcessor::class);
+ $rectorConfig->disableParallel(); // does not work for fusion files - see https://github.com/rectorphp/rector-src/pull/2597#issuecomment-1190120688
+
+ $rectorConfig->ruleWithConfiguration(FusionFlowQueryNodePropertyToWarningCommentRector::class, [
+ new FusionFlowQueryNodePropertyToWarningComment('_autoCreated', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_autoCreated")" to "VARIABLE.classification.tethered". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.'),
+ new FusionFlowQueryNodePropertyToWarningComment('_contextPath', 'Line %LINE: !! You very likely need to rewrite "q(VARIABLE).property("_contextPath")" to "Neos.Node.serializedNodeAddress(VARIABLE)". We did not auto-apply this migration because we cannot be sure whether the variable is a Node.'),
+ ]);
+};