| @@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration; | |||||
| /** | /** | ||||
| * Auto-generated Migration: Please modify to your needs! | * Auto-generated Migration: Please modify to your needs! | ||||
| */ | */ | ||||
| final class Version20240404115740 extends AbstractMigration | |||||
| final class Version20240408091731 extends AbstractMigration | |||||
| { | { | ||||
| public function getDescription(): string | public function getDescription(): string | ||||
| { | { | ||||
| @@ -35,6 +35,7 @@ final class Version20240404115740 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 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 task_note (id INT AUTO_INCREMENT NOT NULL, owner_id INT NOT NULL, task_id INT NOT NULL, message LONGTEXT NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_BC0E6E6F7E3C61F9 (owner_id), INDEX IDX_BC0E6E6F8DB60186 (task_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); | $this->addSql('CREATE TABLE task_note (id INT AUTO_INCREMENT NOT NULL, owner_id INT NOT NULL, task_id INT NOT NULL, message LONGTEXT NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_BC0E6E6F7E3C61F9 (owner_id), INDEX IDX_BC0E6E6F8DB60186 (task_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('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('CREATE TABLE user_product (id INT AUTO_INCREMENT NOT NULL, user_id INT NOT NULL, product_id INT NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_8B471AA7A76ED395 (user_id), INDEX IDX_8B471AA74584665A (product_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_9474526C7E3C61F9 FOREIGN KEY (owner_id) REFERENCES `user` (id)'); | ||||
| $this->addSql('ALTER TABLE comment ADD CONSTRAINT FK_9474526C9AE985F6 FOREIGN KEY (posting_id) REFERENCES posting (id) ON DELETE CASCADE'); | $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_4C62E6389393F8FE FOREIGN KEY (partner_id) REFERENCES partner (id) ON DELETE CASCADE'); | ||||
| @@ -71,6 +72,8 @@ final class Version20240404115740 extends AbstractMigration | |||||
| $this->addSql('ALTER TABLE task_note ADD CONSTRAINT FK_BC0E6E6F7E3C61F9 FOREIGN KEY (owner_id) REFERENCES `user` (id) ON DELETE CASCADE'); | $this->addSql('ALTER TABLE task_note ADD CONSTRAINT FK_BC0E6E6F7E3C61F9 FOREIGN KEY (owner_id) REFERENCES `user` (id) ON DELETE CASCADE'); | ||||
| $this->addSql('ALTER TABLE task_note ADD CONSTRAINT FK_BC0E6E6F8DB60186 FOREIGN KEY (task_id) REFERENCES task (id) ON DELETE CASCADE'); | $this->addSql('ALTER TABLE task_note ADD CONSTRAINT FK_BC0E6E6F8DB60186 FOREIGN KEY (task_id) REFERENCES task (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'); | $this->addSql('ALTER TABLE `user` ADD CONSTRAINT FK_8D93D6493DA5256D FOREIGN KEY (image_id) REFERENCES media_object (id) ON DELETE SET NULL'); | ||||
| $this->addSql('ALTER TABLE user_product ADD CONSTRAINT FK_8B471AA7A76ED395 FOREIGN KEY (user_id) REFERENCES `user` (id)'); | |||||
| $this->addSql('ALTER TABLE user_product ADD CONSTRAINT FK_8B471AA74584665A FOREIGN KEY (product_id) REFERENCES product (id)'); | |||||
| } | } | ||||
| public function down(Schema $schema): void | public function down(Schema $schema): void | ||||
| @@ -112,6 +115,8 @@ final class Version20240404115740 extends AbstractMigration | |||||
| $this->addSql('ALTER TABLE task_note DROP FOREIGN KEY FK_BC0E6E6F7E3C61F9'); | $this->addSql('ALTER TABLE task_note DROP FOREIGN KEY FK_BC0E6E6F7E3C61F9'); | ||||
| $this->addSql('ALTER TABLE task_note DROP FOREIGN KEY FK_BC0E6E6F8DB60186'); | $this->addSql('ALTER TABLE task_note DROP FOREIGN KEY FK_BC0E6E6F8DB60186'); | ||||
| $this->addSql('ALTER TABLE `user` DROP FOREIGN KEY FK_8D93D6493DA5256D'); | $this->addSql('ALTER TABLE `user` DROP FOREIGN KEY FK_8D93D6493DA5256D'); | ||||
| $this->addSql('ALTER TABLE user_product DROP FOREIGN KEY FK_8B471AA7A76ED395'); | |||||
| $this->addSql('ALTER TABLE user_product DROP FOREIGN KEY FK_8B471AA74584665A'); | |||||
| $this->addSql('DROP TABLE comment'); | $this->addSql('DROP TABLE comment'); | ||||
| $this->addSql('DROP TABLE contact'); | $this->addSql('DROP TABLE contact'); | ||||
| $this->addSql('DROP TABLE contact_partner_product'); | $this->addSql('DROP TABLE contact_partner_product'); | ||||
| @@ -127,5 +132,6 @@ final class Version20240404115740 extends AbstractMigration | |||||
| $this->addSql('DROP TABLE task'); | $this->addSql('DROP TABLE task'); | ||||
| $this->addSql('DROP TABLE task_note'); | $this->addSql('DROP TABLE task_note'); | ||||
| $this->addSql('DROP TABLE `user`'); | $this->addSql('DROP TABLE `user`'); | ||||
| $this->addSql('DROP TABLE user_product'); | |||||
| } | } | ||||
| } | } | ||||
| @@ -71,7 +71,6 @@ class CommentApi implements OwnerInterface | |||||
| public function getOwner(): ?UserApi | public function getOwner(): ?UserApi | ||||
| { | { | ||||
| //dd($this->owner); | |||||
| return $this->owner; | return $this->owner; | ||||
| } | } | ||||
| } | } | ||||
| @@ -15,6 +15,7 @@ use ApiPlatform\Metadata\ApiResource; | |||||
| use App\Entity\Partner; | use App\Entity\Partner; | ||||
| use App\Entity\PartnerFollow; | use App\Entity\PartnerFollow; | ||||
| use App\Entity\User; | use App\Entity\User; | ||||
| use App\Interface\OwnerInterface; | |||||
| use App\State\EntityClassDtoStateProcessor; | use App\State\EntityClassDtoStateProcessor; | ||||
| use App\State\EntityToDtoStateProvider; | use App\State\EntityToDtoStateProvider; | ||||
| use ApiPlatform\Metadata\Delete; | use ApiPlatform\Metadata\Delete; | ||||
| @@ -37,7 +38,7 @@ use Symfony\Component\Validator\Constraints\NotBlank; | |||||
| security: 'is_granted("ROLE_USER")', | security: 'is_granted("ROLE_USER")', | ||||
| ), | ), | ||||
| new Delete( | new Delete( | ||||
| security: 'is_granted("ROLE_USER")', | |||||
| security: 'is_granted("EDIT", object)', | |||||
| ) | ) | ||||
| ], | ], | ||||
| security: 'is_granted("ROLE_USER")', | security: 'is_granted("ROLE_USER")', | ||||
| @@ -46,7 +47,7 @@ use Symfony\Component\Validator\Constraints\NotBlank; | |||||
| stateOptions: new Options(entityClass: PartnerFollow::class), | stateOptions: new Options(entityClass: PartnerFollow::class), | ||||
| )] | )] | ||||
| #[ApiFilter(SearchFilter::class, properties: ['partner' => 'exact', 'user' => 'exact'])] | #[ApiFilter(SearchFilter::class, properties: ['partner' => 'exact', 'user' => 'exact'])] | ||||
| class PartnerFollowApi | |||||
| class PartnerFollowApi implements OwnerInterface | |||||
| { | { | ||||
| #[ApiProperty(readable: false, writable: false, identifier: true)] | #[ApiProperty(readable: false, writable: false, identifier: true)] | ||||
| public ?int $id = null; | public ?int $id = null; | ||||
| @@ -65,4 +66,9 @@ class PartnerFollowApi | |||||
| #[ApiProperty(writable: false)] | #[ApiProperty(writable: false)] | ||||
| public ?\DateTimeImmutable $createdAt = null; | public ?\DateTimeImmutable $createdAt = null; | ||||
| public function getOwner(): ?UserApi | |||||
| { | |||||
| return $this->user; | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,72 @@ | |||||
| <?php | |||||
| /** | |||||
| * @author Daniel Knudsen <d.knudsen@spawntree.de> | |||||
| * @date 12.12.23 | |||||
| */ | |||||
| namespace App\ApiResource; | |||||
| use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; | |||||
| use ApiPlatform\Doctrine\Orm\State\Options; | |||||
| use ApiPlatform\Metadata\ApiFilter; | |||||
| use ApiPlatform\Metadata\ApiProperty; | |||||
| use ApiPlatform\Metadata\ApiResource; | |||||
| use App\Entity\PartnerProduct; | |||||
| use App\Entity\UserProduct; | |||||
| use App\Interface\OwnerInterface; | |||||
| use App\State\EntityClassDtoStateProcessor; | |||||
| use App\State\EntityToDtoStateProvider; | |||||
| use ApiPlatform\Metadata\Delete; | |||||
| use ApiPlatform\Metadata\Get; | |||||
| use ApiPlatform\Metadata\GetCollection; | |||||
| use ApiPlatform\Metadata\Post; | |||||
| use Symfony\Component\Validator\Constraints\NotBlank; | |||||
| #[ApiResource( | |||||
| shortName: 'UserProduct', | |||||
| operations: [ | |||||
| new Get( | |||||
| security: 'is_granted("ROLE_USER")' | |||||
| ), | |||||
| new GetCollection( | |||||
| security: 'is_granted("ROLE_USER")', | |||||
| ), | |||||
| new Post( | |||||
| security: 'is_granted("ROLE_USER")', | |||||
| ), | |||||
| new Delete( | |||||
| security: 'is_granted("EDIT", object)', | |||||
| ) | |||||
| ], | |||||
| security: 'is_granted("ROLE_USER")', | |||||
| provider: EntityToDtoStateProvider::class, | |||||
| processor: EntityClassDtoStateProcessor::class, | |||||
| stateOptions: new Options(entityClass: UserProduct::class), | |||||
| )] | |||||
| #[ApiFilter(SearchFilter::class, properties: ['partner' => 'exact', 'product' => 'exact'])] | |||||
| class UserProductApi implements OwnerInterface | |||||
| { | |||||
| #[ApiProperty(readable: false, writable: false, identifier: true)] | |||||
| public ?int $id = null; | |||||
| #[ApiProperty(writable: false)] | |||||
| public ?UserApi $user = null; | |||||
| #[ApiProperty(writable: false)] | |||||
| public ?string $userName = null; | |||||
| #[NotBlank] | |||||
| public ?ProductApi $product = null; | |||||
| #[ApiProperty(writable: false)] | |||||
| public ?string $productName = null; | |||||
| #[ApiProperty(writable: false)] | |||||
| public ?\DateTimeImmutable $createdAt = null; | |||||
| public function getOwner(): ?UserApi | |||||
| { | |||||
| return $this->user; | |||||
| } | |||||
| } | |||||
| @@ -22,6 +22,7 @@ use App\Factory\SaleFactory; | |||||
| use App\Factory\TaskFactory; | use App\Factory\TaskFactory; | ||||
| use App\Factory\TaskNoteFactory; | use App\Factory\TaskNoteFactory; | ||||
| use App\Factory\UserFactory; | use App\Factory\UserFactory; | ||||
| use App\Factory\UserProductFactory; | |||||
| use Doctrine\Bundle\FixturesBundle\Fixture; | use Doctrine\Bundle\FixturesBundle\Fixture; | ||||
| use Doctrine\Persistence\ObjectManager; | use Doctrine\Persistence\ObjectManager; | ||||
| use Symfony\Component\HttpKernel\KernelInterface; | use Symfony\Component\HttpKernel\KernelInterface; | ||||
| @@ -189,6 +190,24 @@ class AppFixtures extends Fixture | |||||
| } | } | ||||
| } | } | ||||
| $users = UserFactory::all(); | |||||
| foreach ($users as $user) { | |||||
| $productsPicked = []; | |||||
| for ($i = 0; $i < 3; $i++) { | |||||
| $product = $products[array_rand($products)]; | |||||
| $productsPicked[$product->getId()] = $product; | |||||
| } | |||||
| foreach ($productsPicked as $item) { | |||||
| UserProductFactory::createOne( | |||||
| [ | |||||
| 'user' => $user, | |||||
| 'product' => $item | |||||
| ] | |||||
| ); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -45,6 +45,9 @@ class Product | |||||
| #[ORM\OneToMany(mappedBy: 'product', targetEntity: PartnerProduct::class)] | #[ORM\OneToMany(mappedBy: 'product', targetEntity: PartnerProduct::class)] | ||||
| private Collection $partnerProducts; | private Collection $partnerProducts; | ||||
| #[ORM\OneToMany(mappedBy: 'product', targetEntity: UserProduct::class)] | |||||
| private Collection $userProducts; | |||||
| public function __construct(User $createdBy) | public function __construct(User $createdBy) | ||||
| { | { | ||||
| $this->createdBy = $createdBy; | $this->createdBy = $createdBy; | ||||
| @@ -53,6 +56,7 @@ class Product | |||||
| $this->documentObjects = new ArrayCollection(); | $this->documentObjects = new ArrayCollection(); | ||||
| $this->postings = new ArrayCollection(); | $this->postings = new ArrayCollection(); | ||||
| $this->partnerProducts = new ArrayCollection(); | $this->partnerProducts = new ArrayCollection(); | ||||
| $this->userProducts = new ArrayCollection(); | |||||
| } | } | ||||
| public function getId(): ?int | public function getId(): ?int | ||||
| @@ -225,4 +229,34 @@ class Product | |||||
| return $this; | return $this; | ||||
| } | } | ||||
| /** | |||||
| * @return Collection<int, UserProduct> | |||||
| */ | |||||
| public function getUserProducts(): Collection | |||||
| { | |||||
| return $this->userProducts; | |||||
| } | |||||
| public function addUserProduct(UserProduct $userProduct): static | |||||
| { | |||||
| if (!$this->userProducts->contains($userProduct)) { | |||||
| $this->userProducts->add($userProduct); | |||||
| $userProduct->setProduct($this); | |||||
| } | |||||
| return $this; | |||||
| } | |||||
| public function removeUserProduct(UserProduct $userProduct): static | |||||
| { | |||||
| if ($this->userProducts->removeElement($userProduct)) { | |||||
| // set the owning side to null (unless already changed) | |||||
| if ($userProduct->getProduct() === $this) { | |||||
| $userProduct->setProduct(null); | |||||
| } | |||||
| } | |||||
| return $this; | |||||
| } | |||||
| } | } | ||||
| @@ -61,6 +61,9 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface | |||||
| #[ORM\OneToMany(mappedBy: 'createdBy', targetEntity: Document::class)] | #[ORM\OneToMany(mappedBy: 'createdBy', targetEntity: Document::class)] | ||||
| private Collection $documentObjects; | private Collection $documentObjects; | ||||
| #[ORM\OneToMany(mappedBy: 'user', targetEntity: UserProduct::class)] | |||||
| private Collection $userProducts; | |||||
| public function __construct() | public function __construct() | ||||
| { | { | ||||
| @@ -71,6 +74,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface | |||||
| $this->sales = new ArrayCollection(); | $this->sales = new ArrayCollection(); | ||||
| $this->partnerFollows = new ArrayCollection(); | $this->partnerFollows = new ArrayCollection(); | ||||
| $this->documentObjects = new ArrayCollection(); | $this->documentObjects = new ArrayCollection(); | ||||
| $this->userProducts = new ArrayCollection(); | |||||
| } | } | ||||
| public function getId(): ?int | public function getId(): ?int | ||||
| @@ -348,4 +352,34 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface | |||||
| return $this; | return $this; | ||||
| } | } | ||||
| /** | |||||
| * @return Collection<int, UserProduct> | |||||
| */ | |||||
| public function getUserProducts(): Collection | |||||
| { | |||||
| return $this->userProducts; | |||||
| } | |||||
| public function addUserProduct(UserProduct $userProduct): static | |||||
| { | |||||
| if (!$this->userProducts->contains($userProduct)) { | |||||
| $this->userProducts->add($userProduct); | |||||
| $userProduct->setUser($this); | |||||
| } | |||||
| return $this; | |||||
| } | |||||
| public function removeUserProduct(UserProduct $userProduct): static | |||||
| { | |||||
| if ($this->userProducts->removeElement($userProduct)) { | |||||
| // set the owning side to null (unless already changed) | |||||
| if ($userProduct->getUser() === $this) { | |||||
| $userProduct->setUser(null); | |||||
| } | |||||
| } | |||||
| return $this; | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,74 @@ | |||||
| <?php | |||||
| namespace App\Entity; | |||||
| use App\Repository\UserProductRepository; | |||||
| use Doctrine\ORM\Mapping as ORM; | |||||
| #[ORM\Entity(repositoryClass: UserProductRepository::class)] | |||||
| class UserProduct | |||||
| { | |||||
| #[ORM\Id] | |||||
| #[ORM\GeneratedValue] | |||||
| #[ORM\Column] | |||||
| private ?int $id = null; | |||||
| #[ORM\ManyToOne(inversedBy: 'userProducts')] | |||||
| #[ORM\JoinColumn(nullable: false)] | |||||
| private ?User $user = null; | |||||
| #[ORM\ManyToOne(inversedBy: 'userProducts')] | |||||
| #[ORM\JoinColumn(nullable: false)] | |||||
| private ?Product $product = null; | |||||
| #[ORM\Column] | |||||
| private ?\DateTimeImmutable $createdAt = null; | |||||
| public function __construct(User $user, Product $product) | |||||
| { | |||||
| $this->user = $user; | |||||
| $this->product = $product; | |||||
| $this->createdAt = new \DateTimeImmutable(); | |||||
| } | |||||
| public function getId(): ?int | |||||
| { | |||||
| return $this->id; | |||||
| } | |||||
| public function getUser(): ?User | |||||
| { | |||||
| return $this->user; | |||||
| } | |||||
| public function setUser(?User $user): static | |||||
| { | |||||
| $this->user = $user; | |||||
| return $this; | |||||
| } | |||||
| public function getProduct(): ?Product | |||||
| { | |||||
| return $this->product; | |||||
| } | |||||
| public function setProduct(?Product $product): static | |||||
| { | |||||
| $this->product = $product; | |||||
| return $this; | |||||
| } | |||||
| public function getCreatedAt(): ?\DateTimeImmutable | |||||
| { | |||||
| return $this->createdAt; | |||||
| } | |||||
| public function setCreatedAt(\DateTimeImmutable $createdAt): static | |||||
| { | |||||
| $this->createdAt = $createdAt; | |||||
| return $this; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,70 @@ | |||||
| <?php | |||||
| namespace App\Factory; | |||||
| use App\Entity\UserProduct; | |||||
| use App\Repository\UserProductRepository; | |||||
| use Zenstruck\Foundry\ModelFactory; | |||||
| use Zenstruck\Foundry\Proxy; | |||||
| use Zenstruck\Foundry\RepositoryProxy; | |||||
| /** | |||||
| * @extends ModelFactory<UserProduct> | |||||
| * | |||||
| * @method UserProduct|Proxy create(array|callable $attributes = []) | |||||
| * @method static UserProduct|Proxy createOne(array $attributes = []) | |||||
| * @method static UserProduct|Proxy find(object|array|mixed $criteria) | |||||
| * @method static UserProduct|Proxy findOrCreate(array $attributes) | |||||
| * @method static UserProduct|Proxy first(string $sortedField = 'id') | |||||
| * @method static UserProduct|Proxy last(string $sortedField = 'id') | |||||
| * @method static UserProduct|Proxy random(array $attributes = []) | |||||
| * @method static UserProduct|Proxy randomOrCreate(array $attributes = []) | |||||
| * @method static UserProductRepository|RepositoryProxy repository() | |||||
| * @method static UserProduct[]|Proxy[] all() | |||||
| * @method static UserProduct[]|Proxy[] createMany(int $number, array|callable $attributes = []) | |||||
| * @method static UserProduct[]|Proxy[] createSequence(iterable|callable $sequence) | |||||
| * @method static UserProduct[]|Proxy[] findBy(array $attributes) | |||||
| * @method static UserProduct[]|Proxy[] randomRange(int $min, int $max, array $attributes = []) | |||||
| * @method static UserProduct[]|Proxy[] randomSet(int $number, array $attributes = []) | |||||
| */ | |||||
| final class UserProductFactory extends ModelFactory | |||||
| { | |||||
| /** | |||||
| * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services | |||||
| * | |||||
| * @todo inject services if required | |||||
| */ | |||||
| public function __construct() | |||||
| { | |||||
| parent::__construct(); | |||||
| } | |||||
| /** | |||||
| * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories | |||||
| * | |||||
| * @todo add your default values here | |||||
| */ | |||||
| protected function getDefaults(): array | |||||
| { | |||||
| return [ | |||||
| 'createdAt' => \DateTimeImmutable::createFromMutable(self::faker()->dateTime()), | |||||
| 'user' => UserFactory::new(), | |||||
| 'product' => ProductFactory::new(), | |||||
| ]; | |||||
| } | |||||
| /** | |||||
| * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization | |||||
| */ | |||||
| protected function initialize(): self | |||||
| { | |||||
| return $this | |||||
| // ->afterInstantiate(function(UserProduct $userProduct): void {}) | |||||
| ; | |||||
| } | |||||
| protected static function getClass(): string | |||||
| { | |||||
| return UserProduct::class; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,63 @@ | |||||
| <?php | |||||
| namespace App\Mapper; | |||||
| use App\ApiResource\UserProductApi; | |||||
| use App\Entity\Product; | |||||
| use App\Entity\User; | |||||
| use App\Entity\UserProduct; | |||||
| use App\Repository\UserProductRepository; | |||||
| use Symfony\Bundle\SecurityBundle\Security; | |||||
| use Symfonycasts\MicroMapper\AsMapper; | |||||
| use Symfonycasts\MicroMapper\MapperInterface; | |||||
| use Symfonycasts\MicroMapper\MicroMapperInterface; | |||||
| #[AsMapper(from: UserProductApi::class, to: UserProduct::class)] | |||||
| class UserProductApiToEntityMapper implements MapperInterface | |||||
| { | |||||
| public function __construct( | |||||
| private UserProductRepository $repository, | |||||
| private Security $security, | |||||
| private MicroMapperInterface $microMapper, | |||||
| ) | |||||
| { | |||||
| } | |||||
| public function load(object $from, string $toClass, array $context): object | |||||
| { | |||||
| $dto = $from; | |||||
| assert($dto instanceof UserProductApi); | |||||
| if ($dto->id) { | |||||
| $entity = $this->repository->find($dto->id); | |||||
| } else { | |||||
| $user = $this->security->getUser(); | |||||
| assert($user instanceof User); | |||||
| if ($dto->product === null) { | |||||
| throw new \Exception('Product missing'); | |||||
| } | |||||
| $product = $this->microMapper->map($dto->product, Product::class, [ | |||||
| MicroMapperInterface::MAX_DEPTH => 1, | |||||
| ]); | |||||
| assert($product instanceof Product); | |||||
| $entity = new UserProduct($user, $product); | |||||
| } | |||||
| if (!$entity) { | |||||
| throw new \Exception('UserProduct not found'); | |||||
| } | |||||
| return $entity; | |||||
| } | |||||
| public function populate(object $from, object $to, array $context): object | |||||
| { | |||||
| $dto = $from; | |||||
| assert($dto instanceof UserProductApi); | |||||
| $entity = $to; | |||||
| assert($entity instanceof UserProduct); | |||||
| return $entity; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,54 @@ | |||||
| <?php | |||||
| namespace App\Mapper; | |||||
| use App\ApiResource\ProductApi; | |||||
| use App\ApiResource\UserApi; | |||||
| use App\ApiResource\UserProductApi; | |||||
| use App\Entity\UserProduct; | |||||
| use Symfonycasts\MicroMapper\AsMapper; | |||||
| use Symfonycasts\MicroMapper\MapperInterface; | |||||
| use Symfonycasts\MicroMapper\MicroMapperInterface; | |||||
| #[AsMapper(from: UserProduct::class, to: UserProductApi::class)] | |||||
| class UserProductEntityToApiMapper implements MapperInterface | |||||
| { | |||||
| public function __construct( | |||||
| private MicroMapperInterface $microMapper | |||||
| ) | |||||
| { | |||||
| } | |||||
| public function load(object $from, string $toClass, array $context): object | |||||
| { | |||||
| $entity = $from; | |||||
| assert($entity instanceof UserProduct); | |||||
| $dto = new UserProductApi(); | |||||
| $dto->id = $entity->getId(); | |||||
| return $dto; | |||||
| } | |||||
| public function populate(object $from, object $to, array $context): object | |||||
| { | |||||
| $entity = $from; | |||||
| $dto = $to; | |||||
| assert($entity instanceof UserProduct); | |||||
| assert($dto instanceof UserProductApi); | |||||
| $dto->user = $this->microMapper->map($entity->getUser(), UserApi::class, [ | |||||
| MicroMapperInterface::MAX_DEPTH => 1, | |||||
| ]); | |||||
| $dto->userName = $entity->getUser()?->getFirstName()." ".$entity->getUser()?->getLastName(); | |||||
| $dto->product = $this->microMapper->map($entity->getProduct(), ProductApi::class, [ | |||||
| MicroMapperInterface::MAX_DEPTH => 1, | |||||
| ]); | |||||
| $dto->productName = $entity->getProduct()?->getName(); | |||||
| $dto->createdAt = $entity->getCreatedAt(); | |||||
| return $dto; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,48 @@ | |||||
| <?php | |||||
| namespace App\Repository; | |||||
| use App\Entity\UserProduct; | |||||
| use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; | |||||
| use Doctrine\Persistence\ManagerRegistry; | |||||
| /** | |||||
| * @extends ServiceEntityRepository<UserProduct> | |||||
| * | |||||
| * @method UserProduct|null find($id, $lockMode = null, $lockVersion = null) | |||||
| * @method UserProduct|null findOneBy(array $criteria, array $orderBy = null) | |||||
| * @method UserProduct[] findAll() | |||||
| * @method UserProduct[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) | |||||
| */ | |||||
| class UserProductRepository extends ServiceEntityRepository | |||||
| { | |||||
| public function __construct(ManagerRegistry $registry) | |||||
| { | |||||
| parent::__construct($registry, UserProduct::class); | |||||
| } | |||||
| // /** | |||||
| // * @return UserProduct[] Returns an array of UserProduct objects | |||||
| // */ | |||||
| // public function findByExampleField($value): array | |||||
| // { | |||||
| // return $this->createQueryBuilder('u') | |||||
| // ->andWhere('u.exampleField = :val') | |||||
| // ->setParameter('val', $value) | |||||
| // ->orderBy('u.id', 'ASC') | |||||
| // ->setMaxResults(10) | |||||
| // ->getQuery() | |||||
| // ->getResult() | |||||
| // ; | |||||
| // } | |||||
| // public function findOneBySomeField($value): ?UserProduct | |||||
| // { | |||||
| // return $this->createQueryBuilder('u') | |||||
| // ->andWhere('u.exampleField = :val') | |||||
| // ->setParameter('val', $value) | |||||
| // ->getQuery() | |||||
| // ->getOneOrNullResult() | |||||
| // ; | |||||
| // } | |||||
| } | |||||