From d4f5ec9b3b8e0eafbf9b04586fdd21d2a9adcd11 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 18 Mar 2024 17:25:08 +0100 Subject: [PATCH] tasks post, patch, delete --- .ddev/config.yaml | 1 + .ddev/docker-compose.xdebug.yaml | 15 ++++++++++++ .ddev/php/xdebug.ini | 4 ++++ ...12084330.php => Version20240318162352.php} | 16 ++++++------- src/ApiResource/PartnerApi.php | 6 +++++ src/ApiResource/TaskApi.php | 3 +-- src/Controller/TesController.php | 1 + src/Entity/Comment.php | 2 +- src/Entity/Contact.php | 4 ++-- src/Entity/Partner.php | 5 ++-- src/Entity/Posting.php | 7 +++--- src/Entity/Task.php | 4 ++-- src/Entity/User.php | 4 ++-- src/Mapper/PartnerEntityToApiMapper.php | 7 ++++++ src/Mapper/TaskApiToEntityMapper.php | 24 ++++++++++++++----- src/State/EntityClassDtoStateProcessor.php | 2 +- tests/Functional/CommentResourceTest.php | 12 ++++++++++ tests/Functional/ContactResourceTest.php | 1 - 18 files changed, 88 insertions(+), 30 deletions(-) create mode 100644 .ddev/docker-compose.xdebug.yaml create mode 100644 .ddev/php/xdebug.ini rename migrations/{Version20240312084330.php => Version20240318162352.php} (93%) diff --git a/.ddev/config.yaml b/.ddev/config.yaml index 7b0992c..a44d76c 100644 --- a/.ddev/config.yaml +++ b/.ddev/config.yaml @@ -11,6 +11,7 @@ additional_fqdns: [] database: type: mariadb version: "10.4" +webimage_extra_packages: [php8.2-xdebug] use_dns_when_possible: true composer_version: "2" web_environment: [] diff --git a/.ddev/docker-compose.xdebug.yaml b/.ddev/docker-compose.xdebug.yaml new file mode 100644 index 0000000..cdfaa3d --- /dev/null +++ b/.ddev/docker-compose.xdebug.yaml @@ -0,0 +1,15 @@ +# For docker-toolbox users; Docker has not yet supported the "host.docker.internal" +# convention that is used from ddev v0.18.0. But if you add this file as +# .ddev/docker-compose.xdebug.yaml it should sort that out. +# Note that the IP address in your environment might not be 192.168.99.1, +# Find out what address to use with "docker-machine ip default" +# It will probably give 192.168.99.100. +# Replace the last digit of the ip with "1", so 192.168.99.100 becomes 192.168.99.1 +version: "3.6" +services: + web: + extra_hosts: + - "host.docker.internal:192.168.65.254" + # Find out what address to use with "docker-machine ip default" + # It will probably give 192.168.99.100. + # Replace the last digit of the ip with "1", so 192.168.99.100 becomes 192.168.99.1 diff --git a/.ddev/php/xdebug.ini b/.ddev/php/xdebug.ini new file mode 100644 index 0000000..f6b8643 --- /dev/null +++ b/.ddev/php/xdebug.ini @@ -0,0 +1,4 @@ +xdebug.mode=debug +xdebug.start_with_request=yes +xdebug.output_dir=/var/www/html/.ddev/xdebug +xdebug.profiler_output_name=trace.%c%p%r%u.out \ No newline at end of file diff --git a/migrations/Version20240312084330.php b/migrations/Version20240318162352.php similarity index 93% rename from migrations/Version20240312084330.php rename to migrations/Version20240318162352.php index 5e33df2..1b6f5a8 100644 --- a/migrations/Version20240312084330.php +++ b/migrations/Version20240318162352.php @@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration; /** * Auto-generated Migration: Please modify to your needs! */ -final class Version20240312084330 extends AbstractMigration +final class Version20240318162352 extends AbstractMigration { public function getDescription(): string { @@ -29,18 +29,18 @@ final class Version20240312084330 extends AbstractMigration $this->addSql('CREATE TABLE task (id INT AUTO_INCREMENT NOT NULL, created_by_id INT NOT NULL, assigned_to_id INT NOT NULL, partner_id INT DEFAULT NULL, contact_id INT DEFAULT NULL, headline VARCHAR(255) NOT NULL, description LONGTEXT DEFAULT NULL, due_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', prio VARCHAR(255) NOT NULL, completed TINYINT(1) NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_527EDB25B03A8386 (created_by_id), INDEX IDX_527EDB25F4BD7827 (assigned_to_id), INDEX IDX_527EDB259393F8FE (partner_id), INDEX IDX_527EDB25E7A1254A (contact_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE `user` (id INT AUTO_INCREMENT NOT NULL, image_id INT DEFAULT NULL, email VARCHAR(180) NOT NULL, first_name VARCHAR(255) NOT NULL, last_name VARCHAR(255) NOT NULL, roles JSON NOT NULL COMMENT \'(DC2Type:json)\', password VARCHAR(255) NOT NULL, active TINYINT(1) NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', UNIQUE INDEX UNIQ_8D93D649E7927C74 (email), INDEX IDX_8D93D6493DA5256D (image_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('ALTER TABLE comment ADD CONSTRAINT FK_9474526C7E3C61F9 FOREIGN KEY (owner_id) REFERENCES `user` (id)'); - $this->addSql('ALTER TABLE comment ADD CONSTRAINT FK_9474526C9AE985F6 FOREIGN KEY (posting_id) REFERENCES posting (id)'); - $this->addSql('ALTER TABLE contact ADD CONSTRAINT FK_4C62E6389393F8FE FOREIGN KEY (partner_id) REFERENCES partner (id)'); + $this->addSql('ALTER TABLE comment ADD CONSTRAINT FK_9474526C9AE985F6 FOREIGN KEY (posting_id) REFERENCES posting (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE contact ADD CONSTRAINT FK_4C62E6389393F8FE FOREIGN KEY (partner_id) REFERENCES partner (id) ON DELETE CASCADE'); $this->addSql('ALTER TABLE contact ADD CONSTRAINT FK_4C62E6383DA5256D FOREIGN KEY (image_id) REFERENCES media_object (id) ON DELETE SET NULL'); $this->addSql('ALTER TABLE partner ADD CONSTRAINT FK_312B3E16F98F144A FOREIGN KEY (logo_id) REFERENCES media_object (id) ON DELETE SET NULL'); - $this->addSql('ALTER TABLE posting ADD CONSTRAINT FK_BD275D737E3C61F9 FOREIGN KEY (owner_id) REFERENCES `user` (id)'); - $this->addSql('ALTER TABLE posting ADD CONSTRAINT FK_BD275D739393F8FE FOREIGN KEY (partner_id) REFERENCES partner (id)'); - $this->addSql('ALTER TABLE posting ADD CONSTRAINT FK_BD275D73E7A1254A FOREIGN KEY (contact_id) REFERENCES contact (id)'); + $this->addSql('ALTER TABLE posting ADD CONSTRAINT FK_BD275D737E3C61F9 FOREIGN KEY (owner_id) REFERENCES `user` (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE posting ADD CONSTRAINT FK_BD275D739393F8FE FOREIGN KEY (partner_id) REFERENCES partner (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE posting ADD CONSTRAINT FK_BD275D73E7A1254A FOREIGN KEY (contact_id) REFERENCES contact (id) ON DELETE CASCADE'); $this->addSql('ALTER TABLE product ADD CONSTRAINT FK_D34A04AD3DA5256D FOREIGN KEY (image_id) REFERENCES media_object (id) ON DELETE SET NULL'); $this->addSql('ALTER TABLE task ADD CONSTRAINT FK_527EDB25B03A8386 FOREIGN KEY (created_by_id) REFERENCES `user` (id)'); $this->addSql('ALTER TABLE task ADD CONSTRAINT FK_527EDB25F4BD7827 FOREIGN KEY (assigned_to_id) REFERENCES `user` (id)'); - $this->addSql('ALTER TABLE task ADD CONSTRAINT FK_527EDB259393F8FE FOREIGN KEY (partner_id) REFERENCES partner (id) ON DELETE SET NULL'); - $this->addSql('ALTER TABLE task ADD CONSTRAINT FK_527EDB25E7A1254A FOREIGN KEY (contact_id) REFERENCES contact (id) ON DELETE SET NULL'); + $this->addSql('ALTER TABLE task ADD CONSTRAINT FK_527EDB259393F8FE FOREIGN KEY (partner_id) REFERENCES partner (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE task ADD CONSTRAINT FK_527EDB25E7A1254A FOREIGN KEY (contact_id) REFERENCES contact (id) ON DELETE CASCADE'); $this->addSql('ALTER TABLE `user` ADD CONSTRAINT FK_8D93D6493DA5256D FOREIGN KEY (image_id) REFERENCES media_object (id) ON DELETE SET NULL'); } diff --git a/src/ApiResource/PartnerApi.php b/src/ApiResource/PartnerApi.php index cba0a4e..415f147 100644 --- a/src/ApiResource/PartnerApi.php +++ b/src/ApiResource/PartnerApi.php @@ -82,6 +82,12 @@ class PartnerApi #[ApiProperty(writable: false)] public ?\DateTimeImmutable $createdAt = null; + /** + * @var array + */ + #[ApiProperty(writable: false)] + public array $posts = []; + /** * @var array */ diff --git a/src/ApiResource/TaskApi.php b/src/ApiResource/TaskApi.php index 2ec8a25..6502822 100644 --- a/src/ApiResource/TaskApi.php +++ b/src/ApiResource/TaskApi.php @@ -35,7 +35,7 @@ use Symfony\Component\Validator\Constraints as Assert; validationContext: ['groups' => ['Default', 'postValidation']] ), new Patch( - security: 'is_granted("is_granted("EDIT", object)")' + security: 'is_granted("ROLE_USER")' ), new Delete( security: 'is_granted("ROLE_USER")', @@ -45,7 +45,6 @@ use Symfony\Component\Validator\Constraints as Assert; provider: EntityToDtoStateProvider::class, processor: EntityClassDtoStateProcessor::class, stateOptions: new Options(entityClass: Task::class), - )] class TaskApi { diff --git a/src/Controller/TesController.php b/src/Controller/TesController.php index 520490e..f104472 100644 --- a/src/Controller/TesController.php +++ b/src/Controller/TesController.php @@ -23,6 +23,7 @@ class TesController extends AbstractController #[Route('/foo')] public function test2() { + phpinfo(); return new JsonResponse('nenene'); } } \ No newline at end of file diff --git a/src/Entity/Comment.php b/src/Entity/Comment.php index b1c9b61..b2c91b7 100644 --- a/src/Entity/Comment.php +++ b/src/Entity/Comment.php @@ -22,7 +22,7 @@ class Comment private ?User $owner = null; #[ORM\ManyToOne(inversedBy: 'comments')] - #[ORM\JoinColumn(nullable: false)] + #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')] private ?Posting $posting = null; #[ORM\Column] diff --git a/src/Entity/Contact.php b/src/Entity/Contact.php index 80ee7c4..4596151 100644 --- a/src/Entity/Contact.php +++ b/src/Entity/Contact.php @@ -24,7 +24,7 @@ class Contact private ?string $lastName = null; #[ORM\ManyToOne(inversedBy: 'contacts')] - #[ORM\JoinColumn(nullable: false)] + #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')] private ?Partner $partner = null; #[ORM\Column(type: Types::DATE_MUTABLE, nullable: true)] @@ -46,7 +46,7 @@ class Contact #[ORM\Column] private ?\DateTimeImmutable $createdAt = null; - #[ORM\OneToMany(mappedBy: 'contact', targetEntity: Posting::class, orphanRemoval: true)] + #[ORM\OneToMany(mappedBy: 'contact', targetEntity: Posting::class)] private Collection $posts; public function __construct(Partner $partner) diff --git a/src/Entity/Partner.php b/src/Entity/Partner.php index aca57d9..b55e088 100644 --- a/src/Entity/Partner.php +++ b/src/Entity/Partner.php @@ -43,14 +43,15 @@ class Partner #[ORM\Column] private ?\DateTimeImmutable $createdAt = null; - #[ORM\OneToMany(mappedBy: 'partner', targetEntity: Contact::class, orphanRemoval: true)] + #[ORM\OneToMany(mappedBy: 'partner', targetEntity: Contact::class)] private Collection $contacts; #[ORM\ManyToOne(targetEntity: MediaObject::class)] #[ORM\JoinColumn(nullable: true, onDelete: "SET NULL")] private ?MediaObject $logo = null; - #[ORM\OneToMany(mappedBy: 'partner', targetEntity: Posting::class, orphanRemoval: true)] + //#[ORM\OneToMany(mappedBy: 'partner', targetEntity: Posting::class, orphanRemoval: true)] + #[ORM\OneToMany(mappedBy: 'partner', targetEntity: Posting::class)] private Collection $postings; public function __construct() diff --git a/src/Entity/Posting.php b/src/Entity/Posting.php index 998951b..46d1a93 100644 --- a/src/Entity/Posting.php +++ b/src/Entity/Posting.php @@ -23,20 +23,21 @@ class Posting private ?string $message = null; #[ORM\ManyToOne(inversedBy: 'postings')] - #[ORM\JoinColumn(nullable: false)] + #[ORM\JoinColumn(nullable: false, onDelete: "CASCADE")] private ?User $owner = null; #[ORM\ManyToOne(inversedBy: 'postings')] - #[ORM\JoinColumn(nullable: false)] + #[ORM\JoinColumn(nullable: false, onDelete: "CASCADE")] private ?Partner $partner = null; #[ORM\ManyToOne(inversedBy: 'postings')] + #[ORM\JoinColumn(nullable: true, onDelete: "CASCADE")] private ?Contact $contact = null; #[ORM\Column] private ?\DateTimeImmutable $createdAt = null; - #[ORM\OneToMany(mappedBy: 'posting', targetEntity: Comment::class, orphanRemoval: true)] + #[ORM\OneToMany(mappedBy: 'posting', targetEntity: Comment::class)] private Collection $comments; public function __construct(User $owner, Partner $partner, Contact $contact = null) diff --git a/src/Entity/Task.php b/src/Entity/Task.php index fabc718..ccc9c1b 100644 --- a/src/Entity/Task.php +++ b/src/Entity/Task.php @@ -33,11 +33,11 @@ class Task private ?\DateTimeImmutable $dueAt = null; #[ORM\ManyToOne] - #[ORM\JoinColumn(nullable: true, onDelete: "SET NULL")] + #[ORM\JoinColumn(nullable: true, onDelete: "CASCADE")] private ?Partner $partner = null; #[ORM\ManyToOne] - #[ORM\JoinColumn(nullable: true, onDelete: "SET NULL")] + #[ORM\JoinColumn(nullable: true, onDelete: "CASCADE")] private ?Contact $contact = null; #[ORM\Column(type: 'string', enumType: PrioType::class)] diff --git a/src/Entity/User.php b/src/Entity/User.php index 8c96145..037b7df 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -46,10 +46,10 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface #[ORM\Column] private ?\DateTimeImmutable $createdAt = null; - #[ORM\OneToMany(mappedBy: 'owner', targetEntity: Posting::class, orphanRemoval: true)] + #[ORM\OneToMany(mappedBy: 'owner', targetEntity: Posting::class)] private Collection $postings; - #[ORM\OneToMany(mappedBy: 'owner', targetEntity: Comment::class, orphanRemoval: true)] + #[ORM\OneToMany(mappedBy: 'owner', targetEntity: Comment::class)] private Collection $comments; diff --git a/src/Mapper/PartnerEntityToApiMapper.php b/src/Mapper/PartnerEntityToApiMapper.php index 5442c34..e6144fb 100644 --- a/src/Mapper/PartnerEntityToApiMapper.php +++ b/src/Mapper/PartnerEntityToApiMapper.php @@ -4,8 +4,10 @@ namespace App\Mapper; use App\ApiResource\ContactApi; use App\ApiResource\PartnerApi; +use App\ApiResource\PostingApi; use App\Entity\Contact; use App\Entity\Partner; +use App\Entity\Posting; use App\Service\FileUrlService; use Symfonycasts\MicroMapper\AsMapper; use Symfonycasts\MicroMapper\MapperInterface; @@ -50,6 +52,11 @@ class PartnerEntityToApiMapper implements MapperInterface $dto->logo = $entity->getLogo(); $dto->logoUrl = $this->fileUrlService->getFileUrl($entity->getLogo()); $dto->createdAt = $entity->getCreatedAt(); + $dto->posts = array_map(function(Posting $posting) { + return $this->microMapper->map($posting, PostingApi::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ]); + }, $entity->getPostings()->getValues()); $dto->contacts = array_map(function(Contact $contact) { return $this->microMapper->map($contact, ContactApi::class, [ MicroMapperInterface::MAX_DEPTH => 1, diff --git a/src/Mapper/TaskApiToEntityMapper.php b/src/Mapper/TaskApiToEntityMapper.php index 1550e1d..bc4be6b 100644 --- a/src/Mapper/TaskApiToEntityMapper.php +++ b/src/Mapper/TaskApiToEntityMapper.php @@ -2,6 +2,8 @@ namespace App\Mapper; +use App\ApiResource\ContactApi; +use App\ApiResource\PartnerApi; use App\ApiResource\TaskApi; use App\Entity\Contact; use App\Entity\Partner; @@ -63,12 +65,22 @@ class TaskApiToEntityMapper implements MapperInterface $entity->setHeadline($dto->headline); $entity->setDescription($dto->description); $entity->setDueAt($dto->dueAt); - $entity->setPartner($this->microMapper->map($dto->partner, Partner::class, [ - MicroMapperInterface::MAX_DEPTH => 1, - ])); - $entity->setContact($this->microMapper->map($dto->contact, Contact::class, [ - MicroMapperInterface::MAX_DEPTH => 1, - ])); + $entity->setPartner(null); + if ($dto->partner !== null) { + assert($dto->partner instanceof PartnerApi); + $entity->setPartner($this->microMapper->map($dto->partner, Partner::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ])); + } + + $entity->setContact(null); + if ($dto->contact !== null) { + assert($dto->contact instanceof ContactApi); + $entity->setContact($this->microMapper->map($dto->contact, Contact::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ])); + } + $entity->setPrio($dto->prio); $entity->setCompleted($dto->completed); return $entity; diff --git a/src/State/EntityClassDtoStateProcessor.php b/src/State/EntityClassDtoStateProcessor.php index 4705645..4187f26 100644 --- a/src/State/EntityClassDtoStateProcessor.php +++ b/src/State/EntityClassDtoStateProcessor.php @@ -42,7 +42,7 @@ class EntityClassDtoStateProcessor implements ProcessorInterface return null; } - + //dd($entity, $operation, $uriVariables, $context); $this->persistProcessor->process($entity, $operation, $uriVariables, $context); $data->id = $entity->getId(); diff --git a/tests/Functional/CommentResourceTest.php b/tests/Functional/CommentResourceTest.php index 8cd0292..a62a3f6 100644 --- a/tests/Functional/CommentResourceTest.php +++ b/tests/Functional/CommentResourceTest.php @@ -51,6 +51,18 @@ class CommentResourceTest extends KernelTestCase $token = $this->JWTManager->create($user->object()); + $this->browser() + ->get('/api/comments', [ + 'headers' => [ + 'Authorization' => 'Bearer ' . $token, + ], + ]) + ->assertSuccessful() + ->assertJsonMatches('"hydra:totalItems"', 1) + //->assertJsonMatches('"hydra:member"[0].message', 'my comment') + ; + + $this->browser() ->post('/api/comments' , [ 'json' => [ diff --git a/tests/Functional/ContactResourceTest.php b/tests/Functional/ContactResourceTest.php index 8484b5d..0a30c63 100644 --- a/tests/Functional/ContactResourceTest.php +++ b/tests/Functional/ContactResourceTest.php @@ -7,7 +7,6 @@ namespace App\Tests\Functional; -use App\Enum\PartnerType; use App\Factory\MediaObjectLogoFactory; use App\Factory\MediaObjectContactFactory; use App\Factory\PartnerFactory;