Skip to content

Commit dd4c68d

Browse files
authored
Merge pull request #2170 from usu/feature/content-node-column-layout
Updated API Tests for ColumnLayout
2 parents 8b66bbe + beb1f5e commit dd4c68d

24 files changed

+315
-197
lines changed

api/fixtures/camps.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
App\Entity\Camp:
22
camp1:
3-
name: <word()>
3+
name: Camp1
44
title: <word()>
55
motto: <sentence()>
66
addressName: <word()>
@@ -12,7 +12,7 @@ App\Entity\Camp:
1212
isPrototype: false
1313
campPrototypeId: null
1414
camp2:
15-
name: <word()>
15+
name: Camp2
1616
title: <word()>
1717
motto: <sentence()>
1818
addressName: <word()>
@@ -24,7 +24,7 @@ App\Entity\Camp:
2424
isPrototype: false
2525
campPrototypeId: null
2626
campUnrelated:
27-
name: <word()>
27+
name: CampUnrelated
2828
title: <word()>
2929
motto: <sentence()>
3030
addressName: <word()>
@@ -36,7 +36,7 @@ App\Entity\Camp:
3636
isPrototype: false
3737
campPrototypeId: null
3838
campPrototype:
39-
name: <word()>
39+
name: CampPrototype
4040
title: <word()>
4141
motto: <sentence()>
4242
addressName: <word()>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DoctrineMigrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
/**
11+
* Auto-generated Migration: Please modify to your needs!
12+
*/
13+
final class Version20211030082112 extends AbstractMigration {
14+
public function getDescription(): string {
15+
return '';
16+
}
17+
18+
public function up(Schema $schema): void {
19+
// this up() migration is auto-generated, please modify it to your needs
20+
$this->addSql('ALTER TABLE content_node DROP CONSTRAINT FK_481D058010EE4CEE');
21+
$this->addSql('ALTER TABLE content_node ADD CONSTRAINT FK_481D058010EE4CEE FOREIGN KEY (parentId) REFERENCES content_node (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
22+
}
23+
24+
public function down(Schema $schema): void {
25+
// this down() migration is auto-generated, please modify it to your needs
26+
$this->addSql('CREATE SCHEMA public');
27+
$this->addSql('ALTER TABLE content_node DROP CONSTRAINT fk_481d058010ee4cee');
28+
$this->addSql('ALTER TABLE content_node ADD CONSTRAINT fk_481d058010ee4cee FOREIGN KEY (parentid) REFERENCES content_node (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
29+
}
30+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DoctrineMigrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
/**
11+
* Auto-generated Migration: Please modify to your needs!
12+
*/
13+
final class Version20211030110620 extends AbstractMigration {
14+
public function getDescription(): string {
15+
return '';
16+
}
17+
18+
public function up(Schema $schema): void {
19+
// this up() migration is auto-generated, please modify it to your needs
20+
$this->addSql('ALTER TABLE abstract_content_node_owner DROP CONSTRAINT FK_8E710AB4F886581C');
21+
$this->addSql('ALTER TABLE abstract_content_node_owner ADD CONSTRAINT FK_8E710AB4F886581C FOREIGN KEY (rootContentNodeId) REFERENCES content_node (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
22+
}
23+
24+
public function down(Schema $schema): void {
25+
// this down() migration is auto-generated, please modify it to your needs
26+
$this->addSql('CREATE SCHEMA public');
27+
$this->addSql('ALTER TABLE abstract_content_node_owner DROP CONSTRAINT fk_8e710ab4f886581c');
28+
$this->addSql('ALTER TABLE abstract_content_node_owner ADD CONSTRAINT fk_8e710ab4f886581c FOREIGN KEY (rootcontentnodeid) REFERENCES content_node (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
29+
}
30+
}

api/src/Entity/AbstractContentNodeOwner.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ abstract class AbstractContentNodeOwner extends BaseEntity {
1717
* exchanged, but all the contents attached to it can.
1818
*
1919
* @ORM\OneToOne(targetEntity="ContentNode", inversedBy="owner", cascade={"persist"})
20-
* @ORM\JoinColumn(nullable=false, unique=true)
20+
* @ORM\JoinColumn(nullable=false, unique=true, onDelete="cascade")
2121
*/
2222
#[Assert\DisableAutoMapping]
2323
#[ApiProperty(writable: false, example: '/content_nodes/1a2b3c4d')]

api/src/Entity/ContentNode.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
#[ApiFilter(SearchFilter::class, properties: ['parent'])]
4343
abstract class ContentNode extends BaseEntity implements BelongsToCampInterface {
4444
/**
45-
* @ORM\OneToOne(targetEntity="AbstractContentNodeOwner", mappedBy="rootContentNode", cascade={"persist", "remove"})
45+
* @ORM\OneToOne(targetEntity="AbstractContentNodeOwner", mappedBy="rootContentNode", cascade={"persist"})
4646
*/
4747
#[SerializedName('_owner')]
4848
#[ApiProperty(readable: false, writable: false)]
@@ -75,6 +75,7 @@ abstract class ContentNode extends BaseEntity implements BelongsToCampInterface
7575
* it has an owner.
7676
*
7777
* @ORM\ManyToOne(targetEntity="ContentNode", inversedBy="children")
78+
* @ORM\JoinColumn(onDelete="CASCADE")
7879
*/
7980
#[AssertEitherIsNull(
8081
other: 'owner',
@@ -166,13 +167,14 @@ public function getContentTypeName(): string {
166167
#[SerializedName('owner')]
167168
#[ApiProperty(writable: false, example: '/activities/1a2b3c4d')]
168169
#[Groups(['read'])]
169-
public function getRootOwner(): Activity|Category|AbstractContentNodeOwner {
170+
public function getRootOwner(): Activity|Category|AbstractContentNodeOwner|null {
170171
if (null !== $this->root) {
171172
return $this->root->owner;
172173
}
173174

174175
// this line is used during create process when $this->root is not yet set
175-
return $this->parent->root->owner;
176+
// returns null if parent is not set
177+
return $this->parent?->root->owner;
176178
}
177179

178180
/**

api/src/Entity/ContentNode/ColumnLayout.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@
55
use ApiPlatform\Core\Annotation\ApiProperty;
66
use ApiPlatform\Core\Annotation\ApiResource;
77
use App\Entity\ContentNode;
8+
use App\Repository\ColumnLayoutRepository;
89
use App\Validator\AssertJsonSchema;
910
use App\Validator\ColumnLayout\AssertColumWidthsSumTo12;
1011
use App\Validator\ColumnLayout\AssertNoOrphanChildren;
11-
use App\Validator\ColumnLayout\ColumnLayoutGroupSequence;
12+
use App\Validator\ColumnLayout\ColumnLayoutPatchGroupSequence;
13+
use App\Validator\ColumnLayout\ColumnLayoutPostGroupSequence;
1214
use Doctrine\ORM\Mapping as ORM;
1315
use Symfony\Component\Serializer\Annotation\Groups;
1416

1517
/**
16-
* @ORM\Entity
18+
* @ORM\Entity(repositoryClass=ColumnLayoutRepository::class)
1719
* @ORM\Table(name="content_node_columnlayout")
1820
*/
1921
#[ApiResource(
@@ -25,17 +27,17 @@
2527
'post' => [
2628
'denormalization_context' => ['groups' => ['write', 'create']],
2729
'security_post_denormalize' => 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)',
28-
'validation_groups' => ColumnLayoutGroupSequence::class,
30+
'validation_groups' => ColumnLayoutPostGroupSequence::class,
2931
],
3032
],
3133
itemOperations: [
3234
'get' => ['security' => 'is_granted("CAMP_COLLABORATOR", object) or is_granted("CAMP_IS_PROTOTYPE", object)'],
3335
'patch' => [
3436
'denormalization_context' => ['groups' => ['write', 'update']],
3537
'security' => 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)',
36-
'validation_groups' => ColumnLayoutGroupSequence::class,
38+
'validation_groups' => ColumnLayoutPatchGroupSequence::class,
3739
],
38-
'delete' => ['security' => 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)'],
40+
'delete' => ['security' => '(is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)) and object.owner === null'], // disallow delete when contentNode is a root node
3941
],
4042
denormalizationContext: ['groups' => ['write']],
4143
normalizationContext: ['groups' => ['read']],

api/src/Entity/ContentNode/MaterialNode.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,18 @@
2424
],
2525
'post' => [
2626
'denormalization_context' => ['groups' => ['write', 'create']],
27-
'security_post_denormalize' => 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)', ],
27+
'security_post_denormalize' => 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)',
28+
'validation_groups' => ['Default', 'create'],
29+
],
2830
],
2931
itemOperations: [
3032
'get' => ['security' => 'is_granted("CAMP_COLLABORATOR", object) or is_granted("CAMP_IS_PROTOTYPE", object)'],
3133
'patch' => [
3234
'denormalization_context' => ['groups' => ['write', 'update']],
3335
'security' => 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)',
36+
'validation_groups' => ['Default', 'update'],
3437
],
35-
'delete' => ['security' => 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)'],
38+
'delete' => ['security' => '(is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)) and object.owner === null'], // disallow delete when contentNode is a root node
3639
],
3740
denormalizationContext: ['groups' => ['write']],
3841
normalizationContext: ['groups' => ['read']],

api/src/Entity/ContentNode/SingleText.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,18 @@
2121
],
2222
'post' => [
2323
'denormalization_context' => ['groups' => ['write', 'create']],
24-
'security_post_denormalize' => 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)', ],
24+
'security_post_denormalize' => 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)',
25+
'validation_groups' => ['Default', 'create'],
26+
],
2527
],
2628
itemOperations: [
2729
'get' => ['security' => 'is_granted("CAMP_COLLABORATOR", object) or is_granted("CAMP_IS_PROTOTYPE", object)'],
2830
'patch' => [
2931
'denormalization_context' => ['groups' => ['write', 'update']],
3032
'security' => 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)',
33+
'validation_groups' => ['Default', 'update'],
3134
],
32-
'delete' => ['security' => 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)'],
35+
'delete' => ['security' => '(is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)) and object.owner === null'], // disallow delete when contentNode is a root node
3336
],
3437
denormalizationContext: ['groups' => ['write']],
3538
normalizationContext: ['groups' => ['read']],

api/src/Entity/ContentNode/Storyboard.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,18 @@
2323
],
2424
'post' => [
2525
'denormalization_context' => ['groups' => ['write', 'create']],
26-
'security_post_denormalize' => 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)', ],
26+
'security_post_denormalize' => 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)',
27+
'validation_groups' => ['Default', 'create'],
28+
],
2729
],
2830
itemOperations: [
2931
'get' => ['security' => 'is_granted("CAMP_COLLABORATOR", object) or is_granted("CAMP_IS_PROTOTYPE", object)'],
3032
'patch' => [
3133
'denormalization_context' => ['groups' => ['write', 'update']],
3234
'security' => 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)',
35+
'validation_groups' => ['Default', 'update'],
3336
],
34-
'delete' => ['security' => 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)'],
37+
'delete' => ['security' => '(is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)) and object.owner === null'], // disallow delete when contentNode is a root node
3538
],
3639
denormalizationContext: ['groups' => ['write']],
3740
normalizationContext: ['groups' => ['read']],
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace App\Repository;
4+
5+
use App\Entity\ContentNode\ColumnLayout;
6+
use Doctrine\Persistence\ManagerRegistry;
7+
8+
/**
9+
* @method null|ColumnLayout find($id, $lockMode = null, $lockVersion = null)
10+
* @method null|ColumnLayout findOneBy(array $criteria, array $orderBy = null)
11+
* @method ColumnLayout[] findAll()
12+
* @method ColumnLayout[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
13+
*/
14+
class ColumnLayoutRepository extends ContentNodeRepository {
15+
public function __construct(ManagerRegistry $registry) {
16+
parent::__construct($registry, ColumnLayout::class);
17+
}
18+
}

0 commit comments

Comments
 (0)