diff --git a/api/migrations/schema/Version20250324224924.php b/api/migrations/schema/Version20250324224924.php new file mode 100644 index 0000000000..789a1c61a8 --- /dev/null +++ b/api/migrations/schema/Version20250324224924.php @@ -0,0 +1,27 @@ +addSql('ALTER TABLE content_node ALTER rootId SET NOT NULL'); + } + + public function down(Schema $schema): void { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE content_node ALTER rootid DROP NOT NULL'); + } +} diff --git a/api/src/Entity/ContentNode.php b/api/src/Entity/ContentNode.php index 736104c7d0..ebf2442f4c 100644 --- a/api/src/Entity/ContentNode.php +++ b/api/src/Entity/ContentNode.php @@ -62,7 +62,7 @@ abstract class ContentNode extends BaseEntity implements BelongsToContentNodeTre #[Gedmo\SortableGroup] // this is needed to avoid that all root nodes are in the same sort group (parent:null, slot: '') #[Groups(['read'])] #[ORM\ManyToOne(targetEntity: ColumnLayout::class, inversedBy: 'rootDescendants')] - #[ORM\JoinColumn(nullable: true, onDelete: 'CASCADE')] // TODO make not null in the DB using a migration, and get fixtures to run + #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')] public ?ColumnLayout $root = null; /** @@ -186,6 +186,11 @@ public function getParent(): ?HasParentInterface { return $this->parent; } + public function setParent(?ContentNode $parent) { + $this->parent = $parent; + $this->root ??= $parent?->root; + } + /** * Holds the actual data of the content node. */ diff --git a/api/tests/Api/ContentNodes/RootColumnLayout/CreateRootColumnLayoutTest.php b/api/tests/Api/ContentNodes/RootColumnLayout/CreateRootColumnLayoutTest.php index 8baf213391..dd74aa8e86 100644 --- a/api/tests/Api/ContentNodes/RootColumnLayout/CreateRootColumnLayoutTest.php +++ b/api/tests/Api/ContentNodes/RootColumnLayout/CreateRootColumnLayoutTest.php @@ -35,7 +35,7 @@ public function testCreateColumnLayoutValidatesMissingParent() { $this->assertJsonContains([ 'violations' => [ [ - 'propertyPath' => 'parent', + 'propertyPath' => 'root', 'message' => 'This value should not be null.', ], ], diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml index 0e7a0a4de4..b47bb34338 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml @@ -8428,9 +8428,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -8445,6 +8443,7 @@ components: - children - contentType - position + - root type: object ChecklistNode-write_create: deprecated: false @@ -8686,9 +8685,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -8703,6 +8700,7 @@ components: - children - contentType - position + - root type: object ChecklistNode.jsonhal-read: deprecated: false @@ -8795,9 +8793,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -8812,6 +8808,7 @@ components: - children - contentType - position + - root type: object ChecklistNode.jsonhal-write_create: deprecated: false @@ -9002,9 +8999,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -9019,6 +9014,7 @@ components: - children - contentType - position + - root type: object ChecklistNode.jsonld-write_create: deprecated: false @@ -9175,9 +9171,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -9192,6 +9186,7 @@ components: - contentType - data - position + - root type: object ColumnLayout-read_Activity.ActivityProgressLabel_Activity.ActivityResponsibles_Activity.ScheduleEntries: deprecated: false @@ -9273,9 +9268,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -9290,6 +9283,7 @@ components: - contentType - data - position + - root type: object ColumnLayout-read_Activity.Category_Activity.ActivityProgressLabel_Activity.ActivityResponsibles_Activity.ScheduleEntries_Activity.ContentNodes: deprecated: false @@ -9371,9 +9365,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -9388,6 +9380,7 @@ components: - contentType - data - position + - root type: object ColumnLayout-read_Category.PreferredContentTypes_Category.ContentNodes: deprecated: false @@ -9469,9 +9462,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -9486,6 +9477,7 @@ components: - contentType - data - position + - root type: object ColumnLayout-read_ScheduleEntry.Activity: deprecated: false @@ -9567,9 +9559,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -9584,6 +9574,7 @@ components: - contentType - data - position + - root type: object ColumnLayout-write_create: deprecated: false @@ -9792,9 +9783,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -9809,6 +9798,7 @@ components: - contentType - data - position + - root type: object ColumnLayout.jsonhal-read: deprecated: false @@ -9899,9 +9889,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -9916,6 +9904,7 @@ components: - contentType - data - position + - root type: object ColumnLayout.jsonhal-read_Activity.ActivityProgressLabel_Activity.ActivityResponsibles_Activity.ScheduleEntries: deprecated: false @@ -10006,9 +9995,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -10023,6 +10010,7 @@ components: - contentType - data - position + - root type: object ColumnLayout.jsonhal-read_Activity.Category_Activity.ActivityProgressLabel_Activity.ActivityResponsibles_Activity.ScheduleEntries_Activity.ContentNodes: deprecated: false @@ -10113,9 +10101,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -10130,6 +10116,7 @@ components: - contentType - data - position + - root type: object ColumnLayout.jsonhal-read_Category.PreferredContentTypes_Category.ContentNodes: deprecated: false @@ -10220,9 +10207,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -10237,6 +10222,7 @@ components: - contentType - data - position + - root type: object ColumnLayout.jsonhal-read_ScheduleEntry.Activity: deprecated: false @@ -10327,9 +10313,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -10344,6 +10328,7 @@ components: - contentType - data - position + - root type: object ColumnLayout.jsonhal-write_create: deprecated: false @@ -10525,9 +10510,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -10542,6 +10525,7 @@ components: - contentType - data - position + - root type: object ColumnLayout.jsonld-read_Activity.ActivityProgressLabel_Activity.ActivityResponsibles_Activity.ScheduleEntries: deprecated: false @@ -10646,9 +10630,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -10663,6 +10645,7 @@ components: - contentType - data - position + - root type: object ColumnLayout.jsonld-read_Activity.Category_Activity.ActivityProgressLabel_Activity.ActivityResponsibles_Activity.ScheduleEntries_Activity.ContentNodes: deprecated: false @@ -10767,9 +10750,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -10784,6 +10765,7 @@ components: - contentType - data - position + - root type: object ColumnLayout.jsonld-read_Category.PreferredContentTypes_Category.ContentNodes: deprecated: false @@ -10888,9 +10870,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -10905,6 +10885,7 @@ components: - contentType - data - position + - root type: object ColumnLayout.jsonld-read_ScheduleEntry.Activity: deprecated: false @@ -11009,9 +10990,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -11026,6 +11005,7 @@ components: - contentType - data - position + - root type: object ColumnLayout.jsonld-write_create: deprecated: false @@ -11174,9 +11154,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -11190,6 +11168,7 @@ components: - children - contentType - position + - root type: object ContentNode-read_Activity.Category_Activity.ActivityProgressLabel_Activity.ActivityResponsibles_Activity.ScheduleEntries_Activity.ContentNodes: deprecated: false @@ -11265,9 +11244,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -11281,6 +11258,7 @@ components: - children - contentType - position + - root type: object ContentNode-read_Category.PreferredContentTypes_Category.ContentNodes: deprecated: false @@ -11356,9 +11334,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -11372,6 +11348,7 @@ components: - children - contentType - position + - root type: object ContentNode.jsonapi: deprecated: false @@ -11453,9 +11430,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -11469,6 +11444,7 @@ components: - children - contentType - position + - root type: object ContentNode.jsonhal-read: deprecated: false @@ -11558,9 +11534,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -11574,6 +11548,7 @@ components: - children - contentType - position + - root type: object ContentNode.jsonhal-read_Activity.Category_Activity.ActivityProgressLabel_Activity.ActivityResponsibles_Activity.ScheduleEntries_Activity.ContentNodes: deprecated: false @@ -11658,9 +11633,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -11674,6 +11647,7 @@ components: - children - contentType - position + - root type: object ContentNode.jsonhal-read_Category.PreferredContentTypes_Category.ContentNodes: deprecated: false @@ -11758,9 +11732,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -11774,6 +11746,7 @@ components: - children - contentType - position + - root type: object ContentNode.jsonld-read: deprecated: false @@ -11860,9 +11833,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -11876,6 +11847,7 @@ components: - children - contentType - position + - root type: object ContentNode.jsonld-read_Activity.Category_Activity.ActivityProgressLabel_Activity.ActivityResponsibles_Activity.ScheduleEntries_Activity.ContentNodes: deprecated: false @@ -11974,9 +11946,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -11990,6 +11960,7 @@ components: - children - contentType - position + - root type: object ContentNode.jsonld-read_Category.PreferredContentTypes_Category.ContentNodes: deprecated: false @@ -12088,9 +12059,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -12104,6 +12073,7 @@ components: - children - contentType - position + - root type: object ContentType-read: deprecated: false @@ -14525,9 +14495,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -14542,6 +14510,7 @@ components: - contentType - materialItems - position + - root type: object MaterialNode-write_create: deprecated: false @@ -14735,9 +14704,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -14752,6 +14719,7 @@ components: - contentType - materialItems - position + - root type: object MaterialNode.jsonhal-read: deprecated: false @@ -14840,9 +14808,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -14857,6 +14823,7 @@ components: - contentType - materialItems - position + - root type: object MaterialNode.jsonhal-write_create: deprecated: false @@ -15029,9 +14996,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -15046,6 +15011,7 @@ components: - contentType - materialItems - position + - root type: object MaterialNode.jsonld-write_create: deprecated: false @@ -15188,9 +15154,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -15204,6 +15168,7 @@ components: - children - contentType - position + - root type: object MultiSelect-write_create: deprecated: false @@ -15411,9 +15376,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -15427,6 +15390,7 @@ components: - children - contentType - position + - root type: object MultiSelect.jsonhal-read: deprecated: false @@ -15517,9 +15481,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -15533,6 +15495,7 @@ components: - children - contentType - position + - root type: object MultiSelect.jsonhal-write_create: deprecated: false @@ -15713,9 +15676,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -15729,6 +15690,7 @@ components: - children - contentType - position + - root type: object MultiSelect.jsonld-write_create: deprecated: false @@ -18434,9 +18396,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -18451,6 +18411,7 @@ components: - contentType - data - position + - root type: object ResponsiveLayout-write_create: deprecated: false @@ -18668,9 +18629,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -18685,6 +18644,7 @@ components: - contentType - data - position + - root type: object ResponsiveLayout.jsonhal-read: deprecated: false @@ -18778,9 +18738,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -18795,6 +18753,7 @@ components: - contentType - data - position + - root type: object ResponsiveLayout.jsonhal-write_create: deprecated: false @@ -18982,9 +18941,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -18999,6 +18956,7 @@ components: - contentType - data - position + - root type: object ResponsiveLayout.jsonld-write_create: deprecated: false @@ -20675,9 +20633,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -20692,6 +20648,7 @@ components: - contentType - data - position + - root type: object SingleText-write_create: deprecated: false @@ -20891,9 +20848,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -20908,6 +20863,7 @@ components: - contentType - data - position + - root type: object SingleText.jsonhal-read: deprecated: false @@ -20995,9 +20951,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -21012,6 +20966,7 @@ components: - contentType - data - position + - root type: object SingleText.jsonhal-write_create: deprecated: false @@ -21187,9 +21142,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -21204,6 +21157,7 @@ components: - contentType - data - position + - root type: object SingleText.jsonld-write_create: deprecated: false @@ -21351,9 +21305,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -21367,6 +21319,7 @@ components: - children - contentType - position + - root type: object Storyboard-write_create: deprecated: false @@ -21577,9 +21530,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -21593,6 +21544,7 @@ components: - children - contentType - position + - root type: object Storyboard.jsonhal-read: deprecated: false @@ -21684,9 +21636,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -21700,6 +21650,7 @@ components: - children - contentType - position + - root type: object Storyboard.jsonhal-write_create: deprecated: false @@ -21882,9 +21833,7 @@ components: example: /content_nodes/1a2b3c4d format: iri-reference readOnly: true - type: - - 'null' - - string + type: string slot: description: |- The name of the slot in the parent in which this content node resides. The valid slot names @@ -21898,6 +21847,7 @@ components: - children - contentType - position + - root type: object Storyboard.jsonld-write_create: deprecated: false