From 97d69d2837f03fab5b97f886e216ade4dd4a004b Mon Sep 17 00:00:00 2001 From: AlexP Date: Fri, 17 May 2024 15:40:12 +0500 Subject: [PATCH 1/7] STA-1046 | reqyiered requests for fulRestApi news & restaurants --- app/composer.json | 1 + app/src/News/Request/NewsCreateRequest.php | 50 +++++++++ .../News/Request/NewsFullUpdateRequest.php | 54 +++++++++ .../News/Request/NewsPartUpdateRequest.php | 48 ++++++++ .../Request/RestaurantCreateRequest.php | 100 +++++++++++++++++ .../Request/RestaurantFullUpdateRequest.php | 105 ++++++++++++++++++ .../Request/RestaurantPartUpdateRequest.php | 90 +++++++++++++++ .../Shared/Abstraction/AbstractRequest.php | 62 +++++++++++ .../Collection/ValidationErrorCollection.php | 16 +++ 9 files changed, 526 insertions(+) create mode 100644 app/src/News/Request/NewsCreateRequest.php create mode 100644 app/src/News/Request/NewsFullUpdateRequest.php create mode 100644 app/src/News/Request/NewsPartUpdateRequest.php create mode 100644 app/src/Restaurants/Request/RestaurantCreateRequest.php create mode 100644 app/src/Restaurants/Request/RestaurantFullUpdateRequest.php create mode 100644 app/src/Restaurants/Request/RestaurantPartUpdateRequest.php create mode 100644 app/src/Shared/Abstraction/AbstractRequest.php create mode 100644 app/src/Shared/Collection/ValidationErrorCollection.php diff --git a/app/composer.json b/app/composer.json index be399e9..a785c5a 100644 --- a/app/composer.json +++ b/app/composer.json @@ -13,6 +13,7 @@ "doctrine/orm": "^3.1", "phpdocumentor/reflection-docblock": "^5.3", "phpstan/phpdoc-parser": "^1.28", + "ramsey/uuid": "^4.7", "symfony/asset": "6.4.*", "symfony/asset-mapper": "6.4.*", "symfony/console": "6.4.*", diff --git a/app/src/News/Request/NewsCreateRequest.php b/app/src/News/Request/NewsCreateRequest.php new file mode 100644 index 0000000..084d874 --- /dev/null +++ b/app/src/News/Request/NewsCreateRequest.php @@ -0,0 +1,50 @@ + */ + #[All( + new Uuid() + )] + public $categories_uuid; + + #[Uuid] + public $detail_image; + + #[Uuid] + public $preview_image; +} diff --git a/app/src/News/Request/NewsPartUpdateRequest.php b/app/src/News/Request/NewsPartUpdateRequest.php new file mode 100644 index 0000000..b0a1423 --- /dev/null +++ b/app/src/News/Request/NewsPartUpdateRequest.php @@ -0,0 +1,48 @@ +populate(); + + if ($this->autoValidate) { + $this->validate(); + } + } + + protected function populate(): void + { + foreach ($this->getRequest()->toArray() as $property => $value) { + if (property_exists($this, $property)) { + $this->{$property} = $value; + } + } + } + + public function validate(): void + { + $errors = $this->validator->validate($this); + + $messages = new ValidationErrorCollection(); + + foreach ($errors as $error) { + $messages->add($this->errorDtoFactory->create($error)); + } + + if ($messages->count() > 0) { + $response = new JsonResponse($messages, 422); + $response->send(); + + throw new ValidatorException('Validation failed'); + } + } + + public function getRequest(): Request + { + return Request::createFromGlobals(); + } +} \ No newline at end of file diff --git a/app/src/Shared/Collection/ValidationErrorCollection.php b/app/src/Shared/Collection/ValidationErrorCollection.php new file mode 100644 index 0000000..346ae1a --- /dev/null +++ b/app/src/Shared/Collection/ValidationErrorCollection.php @@ -0,0 +1,16 @@ +collectionType, $data); + } +} \ No newline at end of file -- GitLab From 8b51d7319667ea58dea135dbe35dbcd8ca81a130 Mon Sep 17 00:00:00 2001 From: AlexP Date: Fri, 17 May 2024 15:41:12 +0500 Subject: [PATCH 2/7] STA-1046 | microfix request --- app/src/News/Request/NewsFullUpdateRequest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/News/Request/NewsFullUpdateRequest.php b/app/src/News/Request/NewsFullUpdateRequest.php index deb3343..b3b994a 100644 --- a/app/src/News/Request/NewsFullUpdateRequest.php +++ b/app/src/News/Request/NewsFullUpdateRequest.php @@ -38,9 +38,9 @@ class NewsFullUpdateRequest extends AbstractRequest public $detail_text; #[Uuid] - public $type_uuid; + #[Required] + public $type_id; - /** @var Collection */ #[All( new Uuid() )] -- GitLab From 6d7b525d6dd2ef401d395c4c6607856b484bf760 Mon Sep 17 00:00:00 2001 From: AlexP Date: Mon, 20 May 2024 12:11:09 +0500 Subject: [PATCH 3/7] STA-1046 | make fullRest news handles --- app/composer.json | 2 +- ...27114630.php => Version20240520053704.php} | 29 ++++- app/src/News/Controller/NewsController.php | 36 ++++++ app/src/News/Dto/NewsListDto.php | 6 +- .../NewsListingElementCollection.php | 16 +++ .../News/DtoFactory/NewsListDtoFactory.php | 4 +- .../NewsListingElementDtoFactory.php | 8 +- .../News/EntityFabric/NewsEntityFabric.php | 119 ++++++++++++++++++ app/src/News/Request/NewsCreateRequest.php | 17 ++- .../News/Request/NewsFullUpdateRequest.php | 5 +- .../News/Request/NewsPartUpdateRequest.php | 10 +- .../Service/NewsPrepareResponseService.php | 53 +++++++- app/src/News/UseCase/NewsCreateUseCase.php | 27 ++++ app/src/News/UseCase/NewsDeleteUseCase.php | 27 ++++ .../News/UseCase/NewsFullUpdateUseCase.php | 27 ++++ .../News/UseCase/NewsGetDetailMainUseCase.php | 4 +- app/src/News/UseCase/NewsGetDetailUseCase.php | 2 +- .../News/UseCase/NewsPartUpdateUseCase.php | 27 ++++ .../Request/RestaurantFullUpdateRequest.php | 2 +- .../Request/RestaurantPartUpdateRequest.php | 3 +- .../Shared/Collection/ListingCollection.php | 15 --- .../Collection/ValidationErrorCollection.php | 5 +- app/src/Shared/Entity/News.php | 17 ++- .../Shared/EventListener/NewsPerCreate.php | 28 +++++ app/src/Shared/Repository/NewsRepository.php | 33 ++++- 25 files changed, 455 insertions(+), 67 deletions(-) rename app/migrations/{Version20240427114630.php => Version20240520053704.php} (67%) create mode 100644 app/src/News/DtoCollection/NewsListingElementCollection.php create mode 100644 app/src/News/EntityFabric/NewsEntityFabric.php create mode 100644 app/src/News/UseCase/NewsCreateUseCase.php create mode 100644 app/src/News/UseCase/NewsDeleteUseCase.php create mode 100644 app/src/News/UseCase/NewsFullUpdateUseCase.php create mode 100644 app/src/News/UseCase/NewsPartUpdateUseCase.php delete mode 100644 app/src/Shared/Collection/ListingCollection.php create mode 100644 app/src/Shared/EventListener/NewsPerCreate.php diff --git a/app/composer.json b/app/composer.json index a785c5a..b948b37 100644 --- a/app/composer.json +++ b/app/composer.json @@ -4,7 +4,7 @@ "minimum-stability": "stable", "prefer-stable": true, "require": { - "php": ">=8.2", + "php": ">=8.3", "ext-ctype": "*", "ext-iconv": "*", "doctrine/dbal": "^3", diff --git a/app/migrations/Version20240427114630.php b/app/migrations/Version20240520053704.php similarity index 67% rename from app/migrations/Version20240427114630.php rename to app/migrations/Version20240520053704.php index 84378b7..3ba6389 100644 --- a/app/migrations/Version20240427114630.php +++ b/app/migrations/Version20240520053704.php @@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration; /** * Auto-generated Migration: Please modify to your needs! */ -final class Version20240427114630 extends AbstractMigration +final class Version20240520053704 extends AbstractMigration { public function getDescription(): string { @@ -20,9 +20,12 @@ final class Version20240427114630 extends AbstractMigration public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE TABLE file (id UUID NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255) NOT NULL, size INT NOT NULL, type VARCHAR(255) NOT NULL, url VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); $this->addSql('CREATE TABLE kitchens (id UUID NOT NULL, name VARCHAR(255) NOT NULL, code VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE TABLE news (id UUID NOT NULL, type_id UUID DEFAULT NULL, name VARCHAR(255) NOT NULL, code VARCHAR(255) NOT NULL, sort INT NOT NULL, active BOOLEAN NOT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, update_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, preview_image VARCHAR(255) DEFAULT NULL, preview_text VARCHAR(1000) DEFAULT NULL, detail_image VARCHAR(255) DEFAULT NULL, detail_text VARCHAR(255) DEFAULT NULL, main_page_render BOOLEAN NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE TABLE news (id UUID NOT NULL, type_id UUID DEFAULT NULL, detail_image_id UUID DEFAULT NULL, preview_image_id UUID DEFAULT NULL, name VARCHAR(255) NOT NULL, code VARCHAR(255) NOT NULL, sort INT NOT NULL, active BOOLEAN NOT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, update_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, preview_text VARCHAR(1000) DEFAULT NULL, detail_text VARCHAR(255) DEFAULT NULL, main_page_render BOOLEAN NOT NULL, PRIMARY KEY(id))'); $this->addSql('CREATE INDEX IDX_1DD39950C54C8C93 ON news (type_id)'); + $this->addSql('CREATE INDEX IDX_1DD39950CB7BCCB6 ON news (detail_image_id)'); + $this->addSql('CREATE INDEX IDX_1DD39950FAE957CD ON news (preview_image_id)'); $this->addSql('COMMENT ON COLUMN news.created_at IS \'(DC2Type:datetime_immutable)\''); $this->addSql('COMMENT ON COLUMN news.update_at IS \'(DC2Type:datetime_immutable)\''); $this->addSql('CREATE TABLE news_news_categories (news_id UUID NOT NULL, news_categories_id UUID NOT NULL, PRIMARY KEY(news_id, news_categories_id))'); @@ -31,15 +34,19 @@ final class Version20240427114630 extends AbstractMigration $this->addSql('CREATE TABLE news_categories (id UUID NOT NULL, name VARCHAR(255) NOT NULL, code VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); $this->addSql('CREATE TABLE news_type (id UUID NOT NULL, name VARCHAR(255) NOT NULL, code VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); $this->addSql('CREATE TABLE restaurant_types (id UUID NOT NULL, name VARCHAR(255) NOT NULL, code VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE TABLE restaurants (id UUID NOT NULL, type_id UUID DEFAULT NULL, settlement_id UUID DEFAULT NULL, active BOOLEAN NOT NULL, sort INT NOT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, update_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, name VARCHAR(255) NOT NULL, code VARCHAR(255) NOT NULL, description VARCHAR(255) NOT NULL, receipt VARCHAR(255) NOT NULL, receipt_info VARCHAR(255) NOT NULL, phone VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL, address VARCHAR(255) NOT NULL, tags VARCHAR(255) NOT NULL, site VARCHAR(255) NOT NULL, coordinates TEXT NOT NULL, preview_image VARCHAR(255) NOT NULL, detail_image VARCHAR(255) NOT NULL, gallery VARCHAR(255) NOT NULL, how_to_find VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE TABLE restaurants (id UUID NOT NULL, type_id UUID DEFAULT NULL, settlement_id UUID DEFAULT NULL, preview_image_id UUID DEFAULT NULL, detail_image_id UUID DEFAULT NULL, active BOOLEAN NOT NULL, sort INT NOT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, update_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, name VARCHAR(255) NOT NULL, code VARCHAR(255) NOT NULL, description VARCHAR(255) NOT NULL, receipt VARCHAR(255) NOT NULL, receipt_info VARCHAR(255) NOT NULL, phone VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL, address VARCHAR(255) NOT NULL, tags VARCHAR(255) NOT NULL, site VARCHAR(255) NOT NULL, coordinates VARCHAR(1000) NOT NULL, how_to_find VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); $this->addSql('CREATE INDEX IDX_AD837724C54C8C93 ON restaurants (type_id)'); $this->addSql('CREATE INDEX IDX_AD837724C2B9C425 ON restaurants (settlement_id)'); + $this->addSql('CREATE INDEX IDX_AD837724FAE957CD ON restaurants (preview_image_id)'); + $this->addSql('CREATE INDEX IDX_AD837724CB7BCCB6 ON restaurants (detail_image_id)'); $this->addSql('COMMENT ON COLUMN restaurants.created_at IS \'(DC2Type:datetime_immutable)\''); $this->addSql('COMMENT ON COLUMN restaurants.update_at IS \'(DC2Type:datetime_immutable)\''); - $this->addSql('COMMENT ON COLUMN restaurants.coordinates IS \'(DC2Type:array)\''); $this->addSql('CREATE TABLE restaurants_kitchens (restaurants_id UUID NOT NULL, kitchens_id UUID NOT NULL, PRIMARY KEY(restaurants_id, kitchens_id))'); $this->addSql('CREATE INDEX IDX_716464694DCA160A ON restaurants_kitchens (restaurants_id)'); $this->addSql('CREATE INDEX IDX_71646469E043FCBC ON restaurants_kitchens (kitchens_id)'); + $this->addSql('CREATE TABLE restaurants_file (restaurants_id UUID NOT NULL, file_id UUID NOT NULL, PRIMARY KEY(restaurants_id, file_id))'); + $this->addSql('CREATE INDEX IDX_EBC930974DCA160A ON restaurants_file (restaurants_id)'); + $this->addSql('CREATE INDEX IDX_EBC9309793CB796C ON restaurants_file (file_id)'); $this->addSql('CREATE TABLE settlements (id UUID NOT NULL, active BOOLEAN NOT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, update_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, name VARCHAR(255) NOT NULL, code VARCHAR(255) NOT NULL, coordinates TEXT NOT NULL, PRIMARY KEY(id))'); $this->addSql('COMMENT ON COLUMN settlements.created_at IS \'(DC2Type:datetime_immutable)\''); $this->addSql('COMMENT ON COLUMN settlements.update_at IS \'(DC2Type:datetime_immutable)\''); @@ -62,12 +69,18 @@ final class Version20240427114630 extends AbstractMigration $this->addSql('DROP TRIGGER IF EXISTS notify_trigger ON messenger_messages;'); $this->addSql('CREATE TRIGGER notify_trigger AFTER INSERT OR UPDATE ON messenger_messages FOR EACH ROW EXECUTE PROCEDURE notify_messenger_messages();'); $this->addSql('ALTER TABLE news ADD CONSTRAINT FK_1DD39950C54C8C93 FOREIGN KEY (type_id) REFERENCES news_type (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE news ADD CONSTRAINT FK_1DD39950CB7BCCB6 FOREIGN KEY (detail_image_id) REFERENCES file (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE news ADD CONSTRAINT FK_1DD39950FAE957CD FOREIGN KEY (preview_image_id) REFERENCES file (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE news_news_categories ADD CONSTRAINT FK_34AB0102B5A459A0 FOREIGN KEY (news_id) REFERENCES news (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE news_news_categories ADD CONSTRAINT FK_34AB0102F7F178F1 FOREIGN KEY (news_categories_id) REFERENCES news_categories (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE restaurants ADD CONSTRAINT FK_AD837724C54C8C93 FOREIGN KEY (type_id) REFERENCES restaurant_types (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE restaurants ADD CONSTRAINT FK_AD837724C2B9C425 FOREIGN KEY (settlement_id) REFERENCES settlements (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE restaurants ADD CONSTRAINT FK_AD837724FAE957CD FOREIGN KEY (preview_image_id) REFERENCES file (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE restaurants ADD CONSTRAINT FK_AD837724CB7BCCB6 FOREIGN KEY (detail_image_id) REFERENCES file (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE restaurants_kitchens ADD CONSTRAINT FK_716464694DCA160A FOREIGN KEY (restaurants_id) REFERENCES restaurants (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE restaurants_kitchens ADD CONSTRAINT FK_71646469E043FCBC FOREIGN KEY (kitchens_id) REFERENCES kitchens (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE restaurants_file ADD CONSTRAINT FK_EBC930974DCA160A FOREIGN KEY (restaurants_id) REFERENCES restaurants (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE restaurants_file ADD CONSTRAINT FK_EBC9309793CB796C FOREIGN KEY (file_id) REFERENCES file (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); } public function down(Schema $schema): void @@ -75,12 +88,19 @@ final class Version20240427114630 extends AbstractMigration // this down() migration is auto-generated, please modify it to your needs $this->addSql('CREATE SCHEMA public'); $this->addSql('ALTER TABLE news DROP CONSTRAINT FK_1DD39950C54C8C93'); + $this->addSql('ALTER TABLE news DROP CONSTRAINT FK_1DD39950CB7BCCB6'); + $this->addSql('ALTER TABLE news DROP CONSTRAINT FK_1DD39950FAE957CD'); $this->addSql('ALTER TABLE news_news_categories DROP CONSTRAINT FK_34AB0102B5A459A0'); $this->addSql('ALTER TABLE news_news_categories DROP CONSTRAINT FK_34AB0102F7F178F1'); $this->addSql('ALTER TABLE restaurants DROP CONSTRAINT FK_AD837724C54C8C93'); $this->addSql('ALTER TABLE restaurants DROP CONSTRAINT FK_AD837724C2B9C425'); + $this->addSql('ALTER TABLE restaurants DROP CONSTRAINT FK_AD837724FAE957CD'); + $this->addSql('ALTER TABLE restaurants DROP CONSTRAINT FK_AD837724CB7BCCB6'); $this->addSql('ALTER TABLE restaurants_kitchens DROP CONSTRAINT FK_716464694DCA160A'); $this->addSql('ALTER TABLE restaurants_kitchens DROP CONSTRAINT FK_71646469E043FCBC'); + $this->addSql('ALTER TABLE restaurants_file DROP CONSTRAINT FK_EBC930974DCA160A'); + $this->addSql('ALTER TABLE restaurants_file DROP CONSTRAINT FK_EBC9309793CB796C'); + $this->addSql('DROP TABLE file'); $this->addSql('DROP TABLE kitchens'); $this->addSql('DROP TABLE news'); $this->addSql('DROP TABLE news_news_categories'); @@ -89,6 +109,7 @@ final class Version20240427114630 extends AbstractMigration $this->addSql('DROP TABLE restaurant_types'); $this->addSql('DROP TABLE restaurants'); $this->addSql('DROP TABLE restaurants_kitchens'); + $this->addSql('DROP TABLE restaurants_file'); $this->addSql('DROP TABLE settlements'); $this->addSql('DROP TABLE users'); $this->addSql('DROP TABLE messenger_messages'); diff --git a/app/src/News/Controller/NewsController.php b/app/src/News/Controller/NewsController.php index 34e1dbb..10d4530 100644 --- a/app/src/News/Controller/NewsController.php +++ b/app/src/News/Controller/NewsController.php @@ -2,14 +2,22 @@ namespace App\News\Controller; +use App\News\Request\NewsCreateRequest; use App\News\Request\NewsDetailRequest; +use App\News\Request\NewsFullUpdateRequest; use App\News\Request\NewsListingRequest; +use App\News\Request\NewsPartUpdateRequest; +use App\News\UseCase\NewsCreateUseCase; +use App\News\UseCase\NewsDeleteUseCase; +use App\News\UseCase\NewsFullUpdateUseCase; use App\News\UseCase\NewsGetDetailMainUseCase; use App\News\UseCase\NewsGetDetailUseCase; use App\News\UseCase\NewsGetListingUseUseCase; use App\News\UseCase\NewsGetMainUseCase; +use App\News\UseCase\NewsPartUpdateUseCase; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; #[Route('/api/v1/news')] @@ -20,6 +28,10 @@ class NewsController extends AbstractController private readonly NewsGetDetailUseCase $getDetailNews, private readonly NewsGetMainUseCase $getMainNews, private readonly NewsGetDetailMainUseCase $getDetailMainNews, + private readonly NewsCreateUseCase $createNews, + private readonly NewsFullUpdateUseCase $fullUpdate, + private readonly NewsPartUpdateUseCase $partUpdate, + private readonly NewsDeleteUseCase $delete, ) { } @@ -46,4 +58,28 @@ class NewsController extends AbstractController { return $this->getDetailNews->execute($request); } + + #[Route('/create', name: 'createNews', methods: ['POST'])] + public function createNews(NewsCreateRequest $request): Response + { + return $this->createNews->execute($request); + } + + #[Route('/update', name: 'updateNews', methods: ['PUT'])] + public function fillUpdateNews(NewsFullUpdateRequest $request): Response + { + return $this->fullUpdate->execute($request); + } + + #[Route('/partUpdate', name: 'partUpdateNews', methods: ['PATCH'])] + public function partUpdateNews(NewsPartUpdateRequest $request): Response + { + return $this->partUpdate->execute($request); + } + + #[Route('/delete/{detailId}', name: 'deleteNews', methods: ['DELETE'])] + public function deleteNews(NewsDetailRequest $request): Response + { + return $this->delete->execute($request); + } } diff --git a/app/src/News/Dto/NewsListDto.php b/app/src/News/Dto/NewsListDto.php index 833a93c..ddb216b 100644 --- a/app/src/News/Dto/NewsListDto.php +++ b/app/src/News/Dto/NewsListDto.php @@ -2,19 +2,19 @@ namespace App\News\Dto; -use App\Shared\Collection\ListingCollection; +use App\News\DtoCollection\NewsListingElementCollection; use App\Shared\Dto\PaginationDto; class NewsListDto { /** * @param PaginationDto $pagination - * @param ListingCollection $list + * @param NewsListingElementCollection $list * @param NewsFilterVariantsDto $filterVariants */ public function __construct( public PaginationDto $pagination, - public ListingCollection $list, + public NewsListingElementCollection $list, public NewsFilterVariantsDto $filterVariants, ) { } diff --git a/app/src/News/DtoCollection/NewsListingElementCollection.php b/app/src/News/DtoCollection/NewsListingElementCollection.php new file mode 100644 index 0000000..0c266f1 --- /dev/null +++ b/app/src/News/DtoCollection/NewsListingElementCollection.php @@ -0,0 +1,16 @@ +collectionType, $data); + } +} \ No newline at end of file diff --git a/app/src/News/DtoFactory/NewsListDtoFactory.php b/app/src/News/DtoFactory/NewsListDtoFactory.php index 25613a7..4a0efcd 100644 --- a/app/src/News/DtoFactory/NewsListDtoFactory.php +++ b/app/src/News/DtoFactory/NewsListDtoFactory.php @@ -4,14 +4,14 @@ namespace App\News\DtoFactory; use App\News\Dto\NewsFilterVariantsDto; use App\News\Dto\NewsListDto; -use App\Shared\Collection\ListingCollection; +use App\News\DtoCollection\NewsListingElementCollection; use App\Shared\Dto\PaginationDto; class NewsListDtoFactory { public function create( PaginationDto $pagination, - ListingCollection $list, + NewsListingElementCollection $list, NewsFilterVariantsDto $filters, ): NewsListDto { return new NewsListDto( diff --git a/app/src/News/DtoFactory/NewsListingElementDtoFactory.php b/app/src/News/DtoFactory/NewsListingElementDtoFactory.php index 11d4412..6837bf2 100644 --- a/app/src/News/DtoFactory/NewsListingElementDtoFactory.php +++ b/app/src/News/DtoFactory/NewsListingElementDtoFactory.php @@ -3,7 +3,7 @@ namespace App\News\DtoFactory; use App\News\Dto\NewsListingElementDto; -use App\Shared\Collection\ListingCollection; +use App\News\DtoCollection\NewsListingElementCollection; use App\Shared\DtoFactory\FileDtoFactory; use App\Shared\Entity\News; use Ramsey\Collection\Collection; @@ -31,11 +31,11 @@ class NewsListingElementDtoFactory /** * @param Collection $news - * @return ListingCollection + * @return NewsListingElementCollection */ - public function createCollection(Collection $news): ListingCollection + public function createCollection(Collection $news): NewsListingElementCollection { - return new ListingCollection( + return new NewsListingElementCollection( $news->map(function (News $oneNews) { return $this->create($oneNews); }) diff --git a/app/src/News/EntityFabric/NewsEntityFabric.php b/app/src/News/EntityFabric/NewsEntityFabric.php new file mode 100644 index 0000000..65f36c8 --- /dev/null +++ b/app/src/News/EntityFabric/NewsEntityFabric.php @@ -0,0 +1,119 @@ + */ + private readonly Collection $newsSetters; + + public function __construct( + private readonly NewsRepository $newsRepository, + private readonly NewsTypeRepository $newsTypeRepository, + private readonly NewsCategoriesRepository $categoriesRepository, + private readonly FileRepository $fileRepository, + ) { + $this->newsSetters = $this->getSetters(); + } + + public function create(NewsCreateRequest $request): News + { + $news = new News(); + $news->setId(Uuid::uuid4()->toString()); + + foreach ($request as $key => $value) { + if ($value !== null) { + $this->newsSetters[$key]($value, $news); + } + } + + return $news; + } + + public function softUpdate(NewsFullUpdateRequest $request): News + { + $news = $this->newsRepository->find($request->id) ?? new News(); + + foreach ($request as $key => $value) { + if ($value !== null) { + $this->newsSetters[$key]($value, $news); + } + } + + return $news; + } + + public function hardUpdate(NewsPartUpdateRequest $request): News + { + $news = $this->newsRepository->find($request->id); + + if ($news === null) { + throw new NotFoundError('News entity for update not found'); + } + + foreach ($request as $key => $value) { + if ($value !== null) { + $this->newsSetters[$key]($value, $news); + } + } + + return $news; + } + + private function getSetters(): Collection + { + $newsSetters = new Collection('callable'); + + $newsSetters['id'] = function (string $id, News $news) { + $news->setId($id); + }; + $newsSetters['name'] = function (string $value, News $news) { + $news->setName($value); + }; + $newsSetters['code'] = function (string $value, News $news) { + $news->setCode($value); + }; + $newsSetters['active'] = function (bool $value, News $news) { + $news->setActive($value); + }; + $newsSetters['main_page_render'] = function (bool $value, News $news) { + $news->setMainPageRender($value); + }; + $newsSetters['preview_text'] = function (string $value, News $news) { + $news->setPreviewText($value); + }; + $newsSetters['detail_text'] = function (string $value, News $news) { + $news->setDetailText($value); + }; + $newsSetters['type_id'] = function (string $id, News $news) { + $news->setType($this->newsTypeRepository->find($id)); + }; + $newsSetters['categories_id'] = function (Collection $ids, News $news) { + foreach ($ids as $id) { + $news->addCategory( + $this->categoriesRepository->find($id) + ); + } + }; + $newsSetters['detail_image'] = function (string $id, News $news) { + $news->setDetailImage($this->fileRepository->find($id)); + }; + $newsSetters['preview_image'] = function (string $id, News $news) { + $news->setPreviewImage($this->fileRepository->find($id)); + }; + + return $newsSetters; + } +} diff --git a/app/src/News/Request/NewsCreateRequest.php b/app/src/News/Request/NewsCreateRequest.php index 084d874..87298f0 100644 --- a/app/src/News/Request/NewsCreateRequest.php +++ b/app/src/News/Request/NewsCreateRequest.php @@ -3,7 +3,6 @@ namespace App\News\Request; use App\Shared\Abstraction\AbstractRequest; -use Ramsey\Collection\Collection; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Constraints\Uuid; @@ -25,26 +24,24 @@ class NewsCreateRequest extends AbstractRequest #[Required] #[Type('bool')] - public bool $main_page_render; + public $main_page_render; - #[Uuid] - public ?string $preview_text; + public $preview_text; - #[Uuid] - public ?string $detail_text; + public $detail_text; #[Uuid] - public ?string $type_id; + public $type_id; #[Type('array')] #[All( new Uuid() )] - public$categories_id; + public $categories_id; #[Uuid] - public ?string $detail_image; + public $detail_image; #[Uuid] - public ?string $preview_image; + public $preview_image; } diff --git a/app/src/News/Request/NewsFullUpdateRequest.php b/app/src/News/Request/NewsFullUpdateRequest.php index b3b994a..0ec6fc9 100644 --- a/app/src/News/Request/NewsFullUpdateRequest.php +++ b/app/src/News/Request/NewsFullUpdateRequest.php @@ -3,7 +3,6 @@ namespace App\News\Request; use App\Shared\Abstraction\AbstractRequest; -use Ramsey\Collection\Collection; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Constraints\Uuid; @@ -13,7 +12,7 @@ class NewsFullUpdateRequest extends AbstractRequest { #[Required] #[Uuid] - public $uuid; + public $id; #[Required] #[Type('string')] @@ -31,10 +30,8 @@ class NewsFullUpdateRequest extends AbstractRequest #[Type('bool')] public $main_page_render; - #[Uuid] public $preview_text; - #[Uuid] public $detail_text; #[Uuid] diff --git a/app/src/News/Request/NewsPartUpdateRequest.php b/app/src/News/Request/NewsPartUpdateRequest.php index b0a1423..1a75fb8 100644 --- a/app/src/News/Request/NewsPartUpdateRequest.php +++ b/app/src/News/Request/NewsPartUpdateRequest.php @@ -3,7 +3,6 @@ namespace App\News\Request; use App\Shared\Abstraction\AbstractRequest; -use Ramsey\Collection\Collection; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Constraints\Uuid; @@ -12,7 +11,8 @@ use Symfony\Contracts\Service\Attribute\Required; class NewsPartUpdateRequest extends AbstractRequest { #[Uuid] - public $uuid; + #[Required] + public $id; #[Type('string')] public $name; @@ -26,19 +26,17 @@ class NewsPartUpdateRequest extends AbstractRequest #[Type('bool')] public bool $main_page_render; - #[Uuid] public $preview_text; - #[Uuid] public $detail_text; #[Uuid] - public $type_uuid; + public $type_id; #[All( new Uuid() )] - public $categories_uuid; + public $categories_id; #[Uuid] public $detail_image; diff --git a/app/src/News/Service/NewsPrepareResponseService.php b/app/src/News/Service/NewsPrepareResponseService.php index b652b1d..7836146 100644 --- a/app/src/News/Service/NewsPrepareResponseService.php +++ b/app/src/News/Service/NewsPrepareResponseService.php @@ -10,8 +10,12 @@ use App\News\DtoFactory\NewsDetailElementDtoFactory; use App\News\DtoFactory\NewsFilterVariantsDtoFactory; use App\News\DtoFactory\NewsListDtoFactory; use App\News\DtoFactory\NewsListingElementDtoFactory; +use App\News\EntityFabric\NewsEntityFabric; +use App\News\Request\NewsCreateRequest; use App\News\Request\NewsDetailRequest; +use App\News\Request\NewsFullUpdateRequest; use App\News\Request\NewsListingRequest; +use App\News\Request\NewsPartUpdateRequest; use App\Shared\DtoFactory\PaginationDtoFactory; use App\Shared\Error\NotFoundError; use App\Shared\Repository\NewsCategoriesRepository; @@ -27,12 +31,15 @@ class NewsPrepareResponseService private readonly NewsFilterVariantsDtoFactory $filterFactory, private readonly NewsListDtoFactory $listingFactory, private readonly NewsCategoryDtoFactory $categoryFactory, - private readonly NewsDetailElementDtoFactory $detailElementFactory + private readonly NewsDetailElementDtoFactory $detailElementFactory, + private readonly NewsEntityFabric $entityFabric, ) { } - public function bornListDto(NewsListingRequest $request): NewsListDto - { + public + function bornListDto( + NewsListingRequest $request + ): NewsListDto { $countOfNews = $this->news->getCountWithFilters( $request->news_category ); @@ -69,17 +76,21 @@ class NewsPrepareResponseService ); } - public function bornMainNews(): NewsListingElementDto + public + function bornMainNews(): NewsListingElementDto { return $this->listFactory->create($this->news->getMainNews()); } - public function bornDetailMainNews(): NewsDetailElementDto + public + function bornDetailMainNews(): NewsDetailElementDto { return $this->detailElementFactory->create($this->news->getMainNews()); } - public function bornDetailElement(NewsDetailRequest $request + public + function bornDetail( + NewsDetailRequest $request ): NewsDetailElementDto { $news = $this->news->find($request->detailId); @@ -89,4 +100,34 @@ class NewsPrepareResponseService return $this->detailElementFactory->create($news); } + + public + function unbirth( + NewsDetailRequest $request + ) { + $news = $this->news->find($request->detailId); + if ($news === null) { + throw new NotFoundError('News not found'); + } + + $this->news->remove($news); + } + + public function rebirth(NewsPartUpdateRequest $request):void + { + $news = $this->entityFabric->hardUpdate($request); + $this->news->createUpdate($news); + } + + public function reborn(NewsFullUpdateRequest $request): void + { + $news = $this->entityFabric->softUpdate($request); + $this->news->createUpdate($news); + } + + public function birth(NewsCreateRequest $request): void + { + $news = $this->entityFabric->create($request); + $this->news->createUpdate($news); + } } diff --git a/app/src/News/UseCase/NewsCreateUseCase.php b/app/src/News/UseCase/NewsCreateUseCase.php new file mode 100644 index 0000000..28d045d --- /dev/null +++ b/app/src/News/UseCase/NewsCreateUseCase.php @@ -0,0 +1,27 @@ +prepareRequestService->birth($request); + return new Response(); + } catch (Throwable) { + return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); + } + } +} diff --git a/app/src/News/UseCase/NewsDeleteUseCase.php b/app/src/News/UseCase/NewsDeleteUseCase.php new file mode 100644 index 0000000..b927794 --- /dev/null +++ b/app/src/News/UseCase/NewsDeleteUseCase.php @@ -0,0 +1,27 @@ +prepareRequestService->unbirth($request); + return new Response(); + } catch (Throwable) { + return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); + } + } +} diff --git a/app/src/News/UseCase/NewsFullUpdateUseCase.php b/app/src/News/UseCase/NewsFullUpdateUseCase.php new file mode 100644 index 0000000..2d4075c --- /dev/null +++ b/app/src/News/UseCase/NewsFullUpdateUseCase.php @@ -0,0 +1,27 @@ +prepareRequestService->reborn($request); + return new Response(); + } catch (Throwable) { + return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); + } + } +} diff --git a/app/src/News/UseCase/NewsGetDetailMainUseCase.php b/app/src/News/UseCase/NewsGetDetailMainUseCase.php index 92725a1..a59f958 100644 --- a/app/src/News/UseCase/NewsGetDetailMainUseCase.php +++ b/app/src/News/UseCase/NewsGetDetailMainUseCase.php @@ -14,7 +14,7 @@ class NewsGetDetailMainUseCase ) { } - public function execute(): ?JsonResponse + public function execute(): JsonResponse { try { return new JsonResponse( @@ -24,4 +24,4 @@ class NewsGetDetailMainUseCase return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); } } -} \ No newline at end of file +} diff --git a/app/src/News/UseCase/NewsGetDetailUseCase.php b/app/src/News/UseCase/NewsGetDetailUseCase.php index 2605bd9..0127279 100644 --- a/app/src/News/UseCase/NewsGetDetailUseCase.php +++ b/app/src/News/UseCase/NewsGetDetailUseCase.php @@ -22,7 +22,7 @@ class NewsGetDetailUseCase { try { return new JsonResponse( - $this->responsePrepareService->bornDetailElement($request) + $this->responsePrepareService->bornDetail($request) ); } catch (NotFoundError $error) { $errorDto = $this->errorFactory->create($error); diff --git a/app/src/News/UseCase/NewsPartUpdateUseCase.php b/app/src/News/UseCase/NewsPartUpdateUseCase.php new file mode 100644 index 0000000..2055035 --- /dev/null +++ b/app/src/News/UseCase/NewsPartUpdateUseCase.php @@ -0,0 +1,27 @@ +prepareRequestService->rebirth($request); + return new Response(); + } catch (Throwable) { + return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); + } + } +} \ No newline at end of file diff --git a/app/src/Restaurants/Request/RestaurantFullUpdateRequest.php b/app/src/Restaurants/Request/RestaurantFullUpdateRequest.php index ee81e8a..74f52f9 100644 --- a/app/src/Restaurants/Request/RestaurantFullUpdateRequest.php +++ b/app/src/Restaurants/Request/RestaurantFullUpdateRequest.php @@ -12,7 +12,7 @@ class RestaurantFullUpdateRequest extends AbstractRequest { #[Uuid] #[Required] - public $uuid; + public $id; #[Type('bool')] #[Required] diff --git a/app/src/Restaurants/Request/RestaurantPartUpdateRequest.php b/app/src/Restaurants/Request/RestaurantPartUpdateRequest.php index b615aba..21f9c57 100644 --- a/app/src/Restaurants/Request/RestaurantPartUpdateRequest.php +++ b/app/src/Restaurants/Request/RestaurantPartUpdateRequest.php @@ -6,7 +6,6 @@ use App\Shared\Abstraction\AbstractRequest; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Constraints\Uuid; -use Symfony\Contracts\Service\Attribute\Required; class RestaurantPartUpdateRequest extends AbstractRequest { @@ -26,7 +25,7 @@ class RestaurantPartUpdateRequest extends AbstractRequest public $code; #[Type('string')] - public $receipt; + public $check; #[Type('string')] public $receipt_info; diff --git a/app/src/Shared/Collection/ListingCollection.php b/app/src/Shared/Collection/ListingCollection.php deleted file mode 100644 index 9234de7..0000000 --- a/app/src/Shared/Collection/ListingCollection.php +++ /dev/null @@ -1,15 +0,0 @@ -collectionType, $data); - } -} diff --git a/app/src/Shared/Collection/ValidationErrorCollection.php b/app/src/Shared/Collection/ValidationErrorCollection.php index 346ae1a..4b328ed 100644 --- a/app/src/Shared/Collection/ValidationErrorCollection.php +++ b/app/src/Shared/Collection/ValidationErrorCollection.php @@ -2,12 +2,11 @@ namespace App\Shared\Collection; -use App\Shared\Dto\ErrorDto; -use App\Shared\Dto\FileDto; +use App\Shared\Dto\ValidateErrorDto; class ValidationErrorCollection extends DtoCollection { - private string $collectionType = ErrorDto::class; + private string $collectionType = ValidateErrorDto::class; public function __construct(array $data = []) { diff --git a/app/src/Shared/Entity/News.php b/app/src/Shared/Entity/News.php index d88a733..8d891ba 100644 --- a/app/src/Shared/Entity/News.php +++ b/app/src/Shared/Entity/News.php @@ -3,12 +3,14 @@ namespace App\Shared\Entity; use App\Shared\Repository\NewsRepository; +use DateTimeImmutable; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: NewsRepository::class)] +#[ORM\HasLifecycleCallbacks] class News { #[ORM\Id] @@ -242,4 +244,17 @@ class News return $this; } -} + + #[ORM\PrePersist] + public function setCreatedAtValue(): void + { + $this->createdAt = new DateTimeImmutable(); + $this->updateAt = new DateTimeImmutable(); + } + + #[ORM\PreUpdate] + public function setUpdateAtValue(): void + { + $this->updateAt = new DateTimeImmutable(); + } +} \ No newline at end of file diff --git a/app/src/Shared/EventListener/NewsPerCreate.php b/app/src/Shared/EventListener/NewsPerCreate.php new file mode 100644 index 0000000..41a5332 --- /dev/null +++ b/app/src/Shared/EventListener/NewsPerCreate.php @@ -0,0 +1,28 @@ +getSort() === null) { + $news->setSort($news->getSort() + 1); + } + + if ($news->isMainPageRender()) { + $mainNews = $this->newsRepository->getMainNews(); + $mainNews?->setMainPageRender(false); + } + } +} diff --git a/app/src/Shared/Repository/NewsRepository.php b/app/src/Shared/Repository/NewsRepository.php index 4dfe229..4b55634 100644 --- a/app/src/Shared/Repository/NewsRepository.php +++ b/app/src/Shared/Repository/NewsRepository.php @@ -24,13 +24,42 @@ class NewsRepository extends ServiceEntityRepository parent::__construct($registry, News::class); } - public function getMainNews(): News + public function createUpdate(News $news): void + { + $entityManager = $this->getEntityManager(); + $entityManager->persist($news); + $entityManager->flush(); + $entityManager->clear(); + } + + public function remove(News $news): void + { + $this->getEntityManager()->remove($news); + $this->getEntityManager()->flush(); + $this->getEntityManager()->clear(); + } + + public function getMaxValueSort(): int { return $this->createQueryBuilder('n') + ->select('MAX(n.sort)') + ->getQuery() + ->getSingleScalarResult(); + } + + public function getMainNews(): ?News + { + $mainNews = $this->createQueryBuilder('n') ->andWhere('n.mainPageRender = true') ->setMaxResults(1) ->getQuery() - ->getResult()[0]; + ->getResult(); + + if ($mainNews === []) { + return null; + } + + return $mainNews[0]; } public function getCountWithFilters(?string $categoryId): int -- GitLab From 50ed0116b12598e69495a43f9f75b34065138225 Mon Sep 17 00:00:00 2001 From: AlexP Date: Mon, 20 May 2024 12:16:26 +0500 Subject: [PATCH 4/7] STA-1046 | fix listing clollection --- .../Collection/RestaurantListingElementCollection.php | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 app/src/Restaurants/Collection/RestaurantListingElementCollection.php diff --git a/app/src/Restaurants/Collection/RestaurantListingElementCollection.php b/app/src/Restaurants/Collection/RestaurantListingElementCollection.php new file mode 100644 index 0000000..da84473 --- /dev/null +++ b/app/src/Restaurants/Collection/RestaurantListingElementCollection.php @@ -0,0 +1,8 @@ + Date: Mon, 20 May 2024 12:16:37 +0500 Subject: [PATCH 5/7] STA-1046 | fix listing clollection --- .../Collection/RestaurantListingElementCollection.php | 10 +++++++++- app/src/Restaurants/Dto/RestaurantListDto.php | 6 +++--- .../DtoFactory/RestaurantListDtoFactory.php | 6 +++--- .../DtoFactory/RestaurantListingElementDtoFactory.php | 8 ++++---- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/app/src/Restaurants/Collection/RestaurantListingElementCollection.php b/app/src/Restaurants/Collection/RestaurantListingElementCollection.php index da84473..8cc388c 100644 --- a/app/src/Restaurants/Collection/RestaurantListingElementCollection.php +++ b/app/src/Restaurants/Collection/RestaurantListingElementCollection.php @@ -2,7 +2,15 @@ namespace App\Restaurants\Collection; -class RestaurantLisitngElementCollection +use App\Restaurants\Dto\RestaurantListingElementDto; +use App\Shared\Collection\DtoCollection; + +class RestaurantListingElementCollection extends DtoCollection { + private string $collectionType = RestaurantListingElementDto::class; + public function __construct(array $data = []) + { + parent::__construct($this->collectionType, $data); + } } \ No newline at end of file diff --git a/app/src/Restaurants/Dto/RestaurantListDto.php b/app/src/Restaurants/Dto/RestaurantListDto.php index 1e6ac5d..8695625 100644 --- a/app/src/Restaurants/Dto/RestaurantListDto.php +++ b/app/src/Restaurants/Dto/RestaurantListDto.php @@ -2,19 +2,19 @@ namespace App\Restaurants\Dto; -use App\Shared\Collection\ListingCollection; +use App\Restaurants\Collection\RestaurantListingElementCollection; use App\Shared\Dto\PaginationDto; class RestaurantListDto { /** * @param PaginationDto $pagination - * @param ListingCollection $list + * @param RestaurantListingElementCollection $list * @param RestaurantFilterVariantsDto $filterVariants */ public function __construct( public PaginationDto $pagination, - public ListingCollection $list, + public RestaurantListingElementCollection $list, public RestaurantFilterVariantsDto $filterVariants, ) {} } diff --git a/app/src/Restaurants/DtoFactory/RestaurantListDtoFactory.php b/app/src/Restaurants/DtoFactory/RestaurantListDtoFactory.php index 66ca9e8..c28d740 100644 --- a/app/src/Restaurants/DtoFactory/RestaurantListDtoFactory.php +++ b/app/src/Restaurants/DtoFactory/RestaurantListDtoFactory.php @@ -2,23 +2,23 @@ namespace App\Restaurants\DtoFactory; +use App\Restaurants\Collection\RestaurantListingElementCollection; use App\Restaurants\Dto\RestaurantFilterVariantsDto; use App\Restaurants\Dto\RestaurantListDto; use App\Restaurants\Dto\RestaurantListingElementDto; -use App\Shared\Collection\ListingCollection; use App\Shared\Dto\PaginationDto; class RestaurantListDtoFactory { /** * @param PaginationDto $pagination - * @param ListingCollection $list + * @param RestaurantListingElementCollection $list * @param RestaurantFilterVariantsDto $filters * @return RestaurantListDto */ public function create( PaginationDto $pagination, - ListingCollection $list, + RestaurantListingElementCollection $list, RestaurantFilterVariantsDto $filters ): RestaurantListDto { return new RestaurantListDto( diff --git a/app/src/Restaurants/DtoFactory/RestaurantListingElementDtoFactory.php b/app/src/Restaurants/DtoFactory/RestaurantListingElementDtoFactory.php index 6fa858d..7c0066d 100644 --- a/app/src/Restaurants/DtoFactory/RestaurantListingElementDtoFactory.php +++ b/app/src/Restaurants/DtoFactory/RestaurantListingElementDtoFactory.php @@ -2,8 +2,8 @@ namespace App\Restaurants\DtoFactory; +use App\Restaurants\Collection\RestaurantListingElementCollection; use App\Restaurants\Dto\RestaurantListingElementDto; -use App\Shared\Collection\ListingCollection; use App\Shared\DtoFactory\FileDtoFactory; use App\Shared\Entity\Restaurants; use Ramsey\Collection\Collection; @@ -29,14 +29,14 @@ class RestaurantListingElementDtoFactory /** * @param Collection $restaurants - * @return ListingCollection + * @return RestaurantListingElementCollection */ - public function createCollection(Collection $restaurants): ListingCollection + public function createCollection(Collection $restaurants): RestaurantListingElementCollection { $restaurantsDto = $restaurants->map(function(Restaurants $restaurant) { return $this->create($restaurant); }); - return new ListingCollection($restaurantsDto->toArray()); + return new RestaurantListingElementCollection($restaurantsDto->toArray()); } } -- GitLab From d52d106ec06300e9751f3b380c730635ec93c25d Mon Sep 17 00:00:00 2001 From: AlexP Date: Mon, 20 May 2024 12:27:16 +0500 Subject: [PATCH 6/7] STA-1046 | sinc entity factories --- .../Service/NewsPrepareResponseService.php | 4 +-- app/src/Shared/Entity/Restaurants.php | 13 ++++++++++ .../EntityFactory/NewsEntityFactory.php} | 9 ++++--- .../EntityFactory/RestaurantEntityFactory.php | 17 +++++++++++++ .../Shared/EventListener/NewsPerCreate.php | 2 +- .../EventListener/RestaurantPerCreate.php | 25 +++++++++++++++++++ .../Repository/RestaurantsRepository.php | 8 ++++++ 7 files changed, 71 insertions(+), 7 deletions(-) rename app/src/{News/EntityFabric/NewsEntityFabric.php => Shared/EntityFactory/NewsEntityFactory.php} (94%) create mode 100644 app/src/Shared/EntityFactory/RestaurantEntityFactory.php create mode 100644 app/src/Shared/EventListener/RestaurantPerCreate.php diff --git a/app/src/News/Service/NewsPrepareResponseService.php b/app/src/News/Service/NewsPrepareResponseService.php index 7836146..24a680e 100644 --- a/app/src/News/Service/NewsPrepareResponseService.php +++ b/app/src/News/Service/NewsPrepareResponseService.php @@ -10,13 +10,13 @@ use App\News\DtoFactory\NewsDetailElementDtoFactory; use App\News\DtoFactory\NewsFilterVariantsDtoFactory; use App\News\DtoFactory\NewsListDtoFactory; use App\News\DtoFactory\NewsListingElementDtoFactory; -use App\News\EntityFabric\NewsEntityFabric; use App\News\Request\NewsCreateRequest; use App\News\Request\NewsDetailRequest; use App\News\Request\NewsFullUpdateRequest; use App\News\Request\NewsListingRequest; use App\News\Request\NewsPartUpdateRequest; use App\Shared\DtoFactory\PaginationDtoFactory; +use App\Shared\EntityFactory\NewsEntityFactory; use App\Shared\Error\NotFoundError; use App\Shared\Repository\NewsCategoriesRepository; use App\Shared\Repository\NewsRepository; @@ -32,7 +32,7 @@ class NewsPrepareResponseService private readonly NewsListDtoFactory $listingFactory, private readonly NewsCategoryDtoFactory $categoryFactory, private readonly NewsDetailElementDtoFactory $detailElementFactory, - private readonly NewsEntityFabric $entityFabric, + private readonly NewsEntityFactory $entityFabric, ) { } diff --git a/app/src/Shared/Entity/Restaurants.php b/app/src/Shared/Entity/Restaurants.php index 11033eb..7a8e894 100644 --- a/app/src/Shared/Entity/Restaurants.php +++ b/app/src/Shared/Entity/Restaurants.php @@ -393,4 +393,17 @@ class Restaurants return $this; } + + #[ORM\PrePersist] + public function setCreatedAtValue(): void + { + $this->createdAt = new DateTimeImmutable(); + $this->updateAt = new DateTimeImmutable(); + } + + #[ORM\PreUpdate] + public function setUpdateAtValue(): void + { + $this->updateAt = new DateTimeImmutable(); + } } diff --git a/app/src/News/EntityFabric/NewsEntityFabric.php b/app/src/Shared/EntityFactory/NewsEntityFactory.php similarity index 94% rename from app/src/News/EntityFabric/NewsEntityFabric.php rename to app/src/Shared/EntityFactory/NewsEntityFactory.php index 65f36c8..abcf0b6 100644 --- a/app/src/News/EntityFabric/NewsEntityFabric.php +++ b/app/src/Shared/EntityFactory/NewsEntityFactory.php @@ -1,6 +1,6 @@ */ private readonly Collection $newsSetters; @@ -25,7 +25,7 @@ class NewsEntityFabric private readonly NewsCategoriesRepository $categoriesRepository, private readonly FileRepository $fileRepository, ) { - $this->newsSetters = $this->getSetters(); + $this->newsSetters = $this->setNewsSetters(); } public function create(NewsCreateRequest $request): News @@ -72,7 +72,8 @@ class NewsEntityFabric return $news; } - private function getSetters(): Collection + /** @return Collection */ + private function setNewsSetters(): Collection { $newsSetters = new Collection('callable'); diff --git a/app/src/Shared/EntityFactory/RestaurantEntityFactory.php b/app/src/Shared/EntityFactory/RestaurantEntityFactory.php new file mode 100644 index 0000000..a38f1f7 --- /dev/null +++ b/app/src/Shared/EntityFactory/RestaurantEntityFactory.php @@ -0,0 +1,17 @@ + */ + private readonly Collection $restaurantSetters; + + /** @return Collection */ + private function setRestaurantSetters(): Collection + { + + } +} \ No newline at end of file diff --git a/app/src/Shared/EventListener/NewsPerCreate.php b/app/src/Shared/EventListener/NewsPerCreate.php index 41a5332..ffb29c0 100644 --- a/app/src/Shared/EventListener/NewsPerCreate.php +++ b/app/src/Shared/EventListener/NewsPerCreate.php @@ -17,7 +17,7 @@ class NewsPerCreate public function preFlush(News $news, PreFlushEventArgs $args) { if ($news->getSort() === null) { - $news->setSort($news->getSort() + 1); + $news->setSort($this->newsRepository->getMaxValueSort() + 1); } if ($news->isMainPageRender()) { diff --git a/app/src/Shared/EventListener/RestaurantPerCreate.php b/app/src/Shared/EventListener/RestaurantPerCreate.php new file mode 100644 index 0000000..72f1729 --- /dev/null +++ b/app/src/Shared/EventListener/RestaurantPerCreate.php @@ -0,0 +1,25 @@ +getSort() === null) { + $restaurant->setSort($this->restaurantsRepository->getMaxValueSort() + 1); + } + } +} diff --git a/app/src/Shared/Repository/RestaurantsRepository.php b/app/src/Shared/Repository/RestaurantsRepository.php index 48eef29..5bbf103 100644 --- a/app/src/Shared/Repository/RestaurantsRepository.php +++ b/app/src/Shared/Repository/RestaurantsRepository.php @@ -24,6 +24,14 @@ class RestaurantsRepository extends ServiceEntityRepository parent::__construct($registry, Restaurants::class); } + public function getMaxValueSort(): int + { + return $this->createQueryBuilder('r') + ->select('MAX(r.sort)') + ->getQuery() + ->getSingleScalarResult(); + } + /** @return Collection */ protected function toCollection(QueryBuilder $query): Collection { -- GitLab From 08f31a65c9c7cdb4e826aa22756795b72618d45f Mon Sep 17 00:00:00 2001 From: AlexP Date: Mon, 20 May 2024 13:49:44 +0500 Subject: [PATCH 7/7] STA-1046 | fullRest restaurant handles + small fixes --- app/src/News/Controller/NewsController.php | 28 +-- .../Service/NewsPrepareResponseService.php | 13 +- .../Controller/RestaurantsController.php | 36 ++++ .../Request/RestaurantCreateRequest.php | 65 +++---- .../Request/RestaurantFullUpdateRequest.php | 64 +++---- .../Request/RestaurantPartUpdateRequest.php | 65 +++---- ...p => RestaurantPrepareResponseService.php} | 43 ++++- .../UseCase/RestaurantCreateUseCase.php | 27 +++ .../UseCase/RestaurantDeleteUseCase.php | 27 +++ .../UseCase/RestaurantFullUpdateUseCase.php | 27 +++ .../UseCase/RestaurantGetDetailUseCase.php | 4 +- .../UseCase/RestaurantGetListingUseCase.php | 7 +- .../UseCase/RestaurantPartUpdateUseCase.php | 29 +++ app/src/Shared/Entity/Restaurants.php | 1 + .../EntityFactory/NewsEntityFactory.php | 2 +- .../EntityFactory/RestaurantEntityFactory.php | 180 +++++++++++++++++- app/src/Shared/Repository/NewsRepository.php | 2 +- .../Repository/RestaurantsRepository.php | 16 +- 18 files changed, 489 insertions(+), 147 deletions(-) rename app/src/Restaurants/Service/{RestaurantPrepareRequestService.php => RestaurantPrepareResponseService.php} (70%) create mode 100644 app/src/Restaurants/UseCase/RestaurantCreateUseCase.php create mode 100644 app/src/Restaurants/UseCase/RestaurantDeleteUseCase.php create mode 100644 app/src/Restaurants/UseCase/RestaurantFullUpdateUseCase.php create mode 100644 app/src/Restaurants/UseCase/RestaurantPartUpdateUseCase.php diff --git a/app/src/News/Controller/NewsController.php b/app/src/News/Controller/NewsController.php index 10d4530..a4bbc7f 100644 --- a/app/src/News/Controller/NewsController.php +++ b/app/src/News/Controller/NewsController.php @@ -25,13 +25,13 @@ class NewsController extends AbstractController { public function __construct( private readonly NewsGetListingUseUseCase $getListingUseCase, - private readonly NewsGetDetailUseCase $getDetailNews, - private readonly NewsGetMainUseCase $getMainNews, - private readonly NewsGetDetailMainUseCase $getDetailMainNews, - private readonly NewsCreateUseCase $createNews, - private readonly NewsFullUpdateUseCase $fullUpdate, - private readonly NewsPartUpdateUseCase $partUpdate, - private readonly NewsDeleteUseCase $delete, + private readonly NewsGetDetailUseCase $getDetailUseCase, + private readonly NewsGetMainUseCase $getMainUseCase, + private readonly NewsGetDetailMainUseCase $getDetailMainUseCase, + private readonly NewsCreateUseCase $createUseCase, + private readonly NewsFullUpdateUseCase $fullUpdateUseCase, + private readonly NewsPartUpdateUseCase $partUpdateUseCase, + private readonly NewsDeleteUseCase $deleteUseCase, ) { } @@ -44,42 +44,42 @@ class NewsController extends AbstractController #[Route('/mainNews', name: 'mainNews', methods: ['GET'])] public function mainNews(): JsonResponse { - return $this->getMainNews->execute(); + return $this->getMainUseCase->execute(); } #[Route('/search', name: 'searchNews', methods: ['GET'])] public function detailMainNews(): JsonResponse { - return $this->getDetailMainNews->execute(); + return $this->getDetailMainUseCase->execute(); } #[Route('/{detailId}', name: 'oneNews', methods: ['GET'])] public function oneNews(NewsDetailRequest $request): JsonResponse { - return $this->getDetailNews->execute($request); + return $this->getDetailUseCase->execute($request); } #[Route('/create', name: 'createNews', methods: ['POST'])] public function createNews(NewsCreateRequest $request): Response { - return $this->createNews->execute($request); + return $this->createUseCase->execute($request); } #[Route('/update', name: 'updateNews', methods: ['PUT'])] public function fillUpdateNews(NewsFullUpdateRequest $request): Response { - return $this->fullUpdate->execute($request); + return $this->fullUpdateUseCase->execute($request); } #[Route('/partUpdate', name: 'partUpdateNews', methods: ['PATCH'])] public function partUpdateNews(NewsPartUpdateRequest $request): Response { - return $this->partUpdate->execute($request); + return $this->partUpdateUseCase->execute($request); } #[Route('/delete/{detailId}', name: 'deleteNews', methods: ['DELETE'])] public function deleteNews(NewsDetailRequest $request): Response { - return $this->delete->execute($request); + return $this->deleteUseCase->execute($request); } } diff --git a/app/src/News/Service/NewsPrepareResponseService.php b/app/src/News/Service/NewsPrepareResponseService.php index 24a680e..5b8faba 100644 --- a/app/src/News/Service/NewsPrepareResponseService.php +++ b/app/src/News/Service/NewsPrepareResponseService.php @@ -32,7 +32,7 @@ class NewsPrepareResponseService private readonly NewsListDtoFactory $listingFactory, private readonly NewsCategoryDtoFactory $categoryFactory, private readonly NewsDetailElementDtoFactory $detailElementFactory, - private readonly NewsEntityFactory $entityFabric, + private readonly NewsEntityFactory $entityFactory, ) { } @@ -101,8 +101,7 @@ class NewsPrepareResponseService return $this->detailElementFactory->create($news); } - public - function unbirth( + public function unbirth( NewsDetailRequest $request ) { $news = $this->news->find($request->detailId); @@ -113,21 +112,21 @@ class NewsPrepareResponseService $this->news->remove($news); } - public function rebirth(NewsPartUpdateRequest $request):void + public function rebirth(NewsPartUpdateRequest $request): void { - $news = $this->entityFabric->hardUpdate($request); + $news = $this->entityFactory->hardUpdate($request); $this->news->createUpdate($news); } public function reborn(NewsFullUpdateRequest $request): void { - $news = $this->entityFabric->softUpdate($request); + $news = $this->entityFactory->softUpdate($request); $this->news->createUpdate($news); } public function birth(NewsCreateRequest $request): void { - $news = $this->entityFabric->create($request); + $news = $this->entityFactory->create($request); $this->news->createUpdate($news); } } diff --git a/app/src/Restaurants/Controller/RestaurantsController.php b/app/src/Restaurants/Controller/RestaurantsController.php index c589e3a..f8a2756 100644 --- a/app/src/Restaurants/Controller/RestaurantsController.php +++ b/app/src/Restaurants/Controller/RestaurantsController.php @@ -2,12 +2,20 @@ namespace App\Restaurants\Controller; +use App\Restaurants\Request\RestaurantCreateRequest; +use App\Restaurants\Request\RestaurantFullUpdateRequest; +use App\Restaurants\Request\RestaurantPartUpdateRequest; +use App\Restaurants\UseCase\RestaurantCreateUseCase; +use App\Restaurants\UseCase\RestaurantDeleteUseCase; +use App\Restaurants\UseCase\RestaurantFullUpdateUseCase; use App\Restaurants\UseCase\RestaurantGetListingUseCase; use App\Restaurants\Request\RestaurantDetailRequest; use App\Restaurants\Request\RestaurantListingRequest; use App\Restaurants\UseCase\RestaurantGetDetailUseCase; +use App\Restaurants\UseCase\RestaurantPartUpdateUseCase; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; #[Route('/api/v1/restaurants')] @@ -16,6 +24,10 @@ class RestaurantsController extends AbstractController public function __construct( private readonly RestaurantGetListingUseCase $getListingUseCase, private readonly RestaurantGetDetailUseCase $getDetailUseCase, + private readonly RestaurantCreateUseCase $createUseCase, + private readonly RestaurantFullUpdateUseCase $fullUpdateUseCase, + private readonly RestaurantDeleteUseCase $deleteUseCase, + private readonly RestaurantPartUpdateUseCase $partUpdateUseCase, ) { } @@ -30,4 +42,28 @@ class RestaurantsController extends AbstractController { return $this->getDetailUseCase->execute($request); } + + #[Route('/create', name: 'createRestaurant', methods: ['POST'])] + public function createRestaurant(RestaurantCreateRequest $request): Response + { + return $this->createUseCase->execute($request); + } + + #[Route('/update', name: 'updateRestaurant', methods: ['PUT'])] + public function fillUpdateRestaurant(RestaurantFullUpdateRequest $request + ): Response { + return $this->fullUpdateUseCase->execute($request); + } + + #[Route('/partUpdate', name: 'partUpdateRestaurant', methods: ['PATCH'])] + public function partUpdateRestaurant(RestaurantPartUpdateRequest $request + ): Response { + return $this->partUpdateUseCase->execute($request); + } + + #[Route('/delete/{detailId}', name: 'deleteRestaurant', methods: ['DELETE'])] + public function deleteRestaurant(RestaurantDetailRequest $request): Response + { + return $this->deleteUseCase->execute($request); + } } diff --git a/app/src/Restaurants/Request/RestaurantCreateRequest.php b/app/src/Restaurants/Request/RestaurantCreateRequest.php index f788e43..c35a7bf 100644 --- a/app/src/Restaurants/Request/RestaurantCreateRequest.php +++ b/app/src/Restaurants/Request/RestaurantCreateRequest.php @@ -10,6 +10,18 @@ use Symfony\Contracts\Service\Attribute\Required; class RestaurantCreateRequest extends AbstractRequest { + #[Uuid] + public $type_id; + + #[Uuid] + public $settlement_id; + + #[Uuid] + public $preview_image_id; + + #[Uuid] + public $detail_image_id; + #[Type('bool')] #[Required] public $active; @@ -20,48 +32,34 @@ class RestaurantCreateRequest extends AbstractRequest #[Type('string')] #[Required] - public $description; + public $code; #[Type('string')] #[Required] - public $code; + public $description; #[Type('string')] #[Required] - public $receipt; + public $check; #[Type('string')] #[Required] - public $receipt_info; + public $check_info; - #[Type('array')] - #[All( - new Type('string') - )] + + #[Type('string')] #[Required] public $phone; - #[Type('array')] - #[All( - new Type('string') - )] + #[Type('string')] #[Required] public $email; - #[Type('array')] - #[All( - new Type('string') - )] + #[Type('string')] #[Required] public $address; - #[Type('array')] - #[All([ - new Type('array'), - new All( - new Type('string') - ) - ])] + #[Type('string')] #[Required] public $tags; @@ -77,24 +75,15 @@ class RestaurantCreateRequest extends AbstractRequest #[Required] public $how_to_find; - #[Uuid] - public $type_id; - - #[Uuid] - public $settelement_id; - - #[Uuid] - public $preview_image_id; - - #[Uuid] - public $detail_inage_id; - - #[Uuid] + #[Type('array')] + #[All( + new UUid(), + )] public $kitchens_id; #[Type('array')] #[All( new UUid(), )] - public $gallery; -} \ No newline at end of file + public $gallery_id; +} diff --git a/app/src/Restaurants/Request/RestaurantFullUpdateRequest.php b/app/src/Restaurants/Request/RestaurantFullUpdateRequest.php index 74f52f9..7d6cad0 100644 --- a/app/src/Restaurants/Request/RestaurantFullUpdateRequest.php +++ b/app/src/Restaurants/Request/RestaurantFullUpdateRequest.php @@ -14,6 +14,18 @@ class RestaurantFullUpdateRequest extends AbstractRequest #[Required] public $id; + #[Uuid] + public $type_id; + + #[Uuid] + public $settlement_id; + + #[Uuid] + public $preview_image_id; + + #[Uuid] + public $detail_image_id; + #[Type('bool')] #[Required] public $active; @@ -24,48 +36,34 @@ class RestaurantFullUpdateRequest extends AbstractRequest #[Type('string')] #[Required] - public $description; + public $code; #[Type('string')] #[Required] - public $code; + public $description; #[Type('string')] #[Required] - public $receipt; + public $check; #[Type('string')] #[Required] - public $receipt_info; + public $check_info; - #[Type('array')] - #[All( - new Type('string') - )] + + #[Type('string')] #[Required] public $phone; - #[Type('array')] - #[All( - new Type('string') - )] + #[Type('string')] #[Required] public $email; - #[Type('array')] - #[All( - new Type('string') - )] + #[Type('string')] #[Required] public $address; - #[Type('array')] - #[All([ - new Type('array'), - new All( - new Type('string') - ) - ])] + #[Type('string')] #[Required] public $tags; @@ -81,25 +79,15 @@ class RestaurantFullUpdateRequest extends AbstractRequest #[Required] public $how_to_find; - #[Uuid] - public $type_id; - - #[Uuid] - public $settelement_id; - - #[Uuid] - public $preview_image_id; - - #[Uuid] - public $detail_inage_id; - - #[Uuid] + #[Type('array')] + #[All( + new UUid(), + )] public $kitchens_id; - #[Required] #[Type('array')] #[All( new UUid(), )] - public $gallery; + public $gallery_id; } \ No newline at end of file diff --git a/app/src/Restaurants/Request/RestaurantPartUpdateRequest.php b/app/src/Restaurants/Request/RestaurantPartUpdateRequest.php index 21f9c57..45a22e1 100644 --- a/app/src/Restaurants/Request/RestaurantPartUpdateRequest.php +++ b/app/src/Restaurants/Request/RestaurantPartUpdateRequest.php @@ -10,8 +10,20 @@ use Symfony\Component\Validator\Constraints\Uuid; class RestaurantPartUpdateRequest extends AbstractRequest { #[Uuid] - public $uuid; - + public $id; + + #[Uuid] + public $type_id; + + #[Uuid] + public $settlement_id; + + #[Uuid] + public $preview_image_id; + + #[Uuid] + public $detail_image_id; + #[Type('bool')] public $active; @@ -19,42 +31,28 @@ class RestaurantPartUpdateRequest extends AbstractRequest public $name; #[Type('string')] - public $description; + public $code; #[Type('string')] - public $code; + public $description; #[Type('string')] public $check; #[Type('string')] - public $receipt_info; + public $check_info; - #[Type('array')] - #[All( - new Type('string') - )] + + #[Type('string')] public $phone; - #[Type('array')] - #[All( - new Type('string') - )] + #[Type('string')] public $email; - #[Type('array')] - #[All( - new Type('string') - )] + #[Type('string')] public $address; - #[Type('array')] - #[All([ - new Type('array'), - new All( - new Type('string') - ) - ])] + #[Type('string')] public $tags; #[Type('string')] @@ -66,24 +64,15 @@ class RestaurantPartUpdateRequest extends AbstractRequest #[Type('string')] public $how_to_find; - #[Uuid] - public $type_id; - - #[Uuid] - public $settelement_id; - - #[Uuid] - public $preview_image_id; - - #[Uuid] - public $detail_inage_id; - - #[Uuid] + #[Type('array')] + #[All( + new UUid(), + )] public $kitchens_id; #[Type('array')] #[All( new UUid(), )] - public $gallery; + public $gallery_id; } \ No newline at end of file diff --git a/app/src/Restaurants/Service/RestaurantPrepareRequestService.php b/app/src/Restaurants/Service/RestaurantPrepareResponseService.php similarity index 70% rename from app/src/Restaurants/Service/RestaurantPrepareRequestService.php rename to app/src/Restaurants/Service/RestaurantPrepareResponseService.php index 9d24a6a..1e44bf7 100644 --- a/app/src/Restaurants/Service/RestaurantPrepareRequestService.php +++ b/app/src/Restaurants/Service/RestaurantPrepareResponseService.php @@ -10,16 +10,20 @@ use App\Restaurants\DtoFactory\RestaurantFilterVariantsDtoFactory; use App\Restaurants\DtoFactory\RestaurantListDtoFactory; use App\Restaurants\DtoFactory\RestaurantListingElementDtoFactory; use App\Restaurants\DtoFactory\RestaurantTypeDtoFactory; +use App\Restaurants\Request\RestaurantCreateRequest; use App\Restaurants\Request\RestaurantDetailRequest; +use App\Restaurants\Request\RestaurantFullUpdateRequest; use App\Restaurants\Request\RestaurantListingRequest; +use App\Restaurants\Request\RestaurantPartUpdateRequest; use App\Shared\DtoFactory\PaginationDtoFactory; +use App\Shared\EntityFactory\RestaurantEntityFactory; use App\Shared\Error\NotFoundError; use App\Shared\Repository\KitchensRepository; use App\Shared\Repository\RestaurantsRepository; use App\Shared\Repository\RestaurantTypesRepository; use JsonException; -class RestaurantPrepareRequestService +class RestaurantPrepareResponseService { public function __construct( private readonly RestaurantsRepository $restaurants, @@ -32,6 +36,7 @@ class RestaurantPrepareRequestService private readonly KitchenTypeDtoFactory $kitchenFactory, private readonly RestaurantListDtoFactory $listingFactory, private readonly RestaurantDetailElementDtoFactory $detailFactory, + private readonly RestaurantEntityFactory $entityFactory, ) { } @@ -39,7 +44,8 @@ class RestaurantPrepareRequestService * @param RestaurantListingRequest $request * @return RestaurantListDto */ - public function bornListDto(RestaurantListingRequest $request): RestaurantListDto { + public function bornListDto(RestaurantListingRequest $request + ): RestaurantListDto { $countOfRestaurants = $this ->restaurants ->getCountWithFilters( @@ -86,7 +92,9 @@ class RestaurantPrepareRequestService * @throws JsonException */ public - function bornDetailElement(RestaurantDetailRequest $request): RestaurantDetailElementDto { + function bornDetailElement( + RestaurantDetailRequest $request + ): RestaurantDetailElementDto { $restaurant = $this->restaurants->find($request->detailId); if ($restaurant === null) { @@ -95,4 +103,33 @@ class RestaurantPrepareRequestService return $this->detailFactory->create($restaurant); } + + public function unbirth( + RestaurantDetailRequest $request + ) { + $restaurants = $this->restaurants->find($request->detailId); + if ($restaurants === null) { + throw new NotFoundError('Restaurant not found'); + } + + $this->restaurants->remove($restaurants); + } + + public function rebirth(RestaurantPartUpdateRequest $request): void + { + $news = $this->entityFactory->hardUpdate($request); + $this->restaurants->createUpdate($news); + } + + public function reborn(RestaurantFullUpdateRequest $request): void + { + $news = $this->entityFactory->softUpdate($request); + $this->restaurants->createUpdate($news); + } + + public function birth(RestaurantCreateRequest $request): void + { + $news = $this->entityFactory->create($request); + $this->restaurants->createUpdate($news); + } } diff --git a/app/src/Restaurants/UseCase/RestaurantCreateUseCase.php b/app/src/Restaurants/UseCase/RestaurantCreateUseCase.php new file mode 100644 index 0000000..4f0a2b5 --- /dev/null +++ b/app/src/Restaurants/UseCase/RestaurantCreateUseCase.php @@ -0,0 +1,27 @@ +prepareRequestService->birth($request); + return new Response(); + } catch (Throwable) { + return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); + } + } +} diff --git a/app/src/Restaurants/UseCase/RestaurantDeleteUseCase.php b/app/src/Restaurants/UseCase/RestaurantDeleteUseCase.php new file mode 100644 index 0000000..f47f240 --- /dev/null +++ b/app/src/Restaurants/UseCase/RestaurantDeleteUseCase.php @@ -0,0 +1,27 @@ +prepareRequestService->unbirth($request); + return new Response(); + } catch (Throwable) { + return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); + } + } +} diff --git a/app/src/Restaurants/UseCase/RestaurantFullUpdateUseCase.php b/app/src/Restaurants/UseCase/RestaurantFullUpdateUseCase.php new file mode 100644 index 0000000..0018b05 --- /dev/null +++ b/app/src/Restaurants/UseCase/RestaurantFullUpdateUseCase.php @@ -0,0 +1,27 @@ +prepareRequestService->reborn($request); + return new Response(); + } catch (Throwable) { + return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); + } + } +} diff --git a/app/src/Restaurants/UseCase/RestaurantGetDetailUseCase.php b/app/src/Restaurants/UseCase/RestaurantGetDetailUseCase.php index e369415..513478e 100644 --- a/app/src/Restaurants/UseCase/RestaurantGetDetailUseCase.php +++ b/app/src/Restaurants/UseCase/RestaurantGetDetailUseCase.php @@ -3,7 +3,7 @@ namespace App\Restaurants\UseCase; use App\Restaurants\Request\RestaurantDetailRequest; -use App\Restaurants\Service\RestaurantPrepareRequestService; +use App\Restaurants\Service\RestaurantPrepareResponseService; use App\Shared\DtoFactory\ErrorDtoFactory; use App\Shared\Error\NotFoundError; use Symfony\Component\HttpFoundation\JsonResponse; @@ -13,7 +13,7 @@ use Throwable; class RestaurantGetDetailUseCase { public function __construct( - private readonly RestaurantPrepareRequestService $responsePrepareService, + private readonly RestaurantPrepareResponseService $responsePrepareService, private readonly ErrorDtoFactory $errorFactory, ) { } diff --git a/app/src/Restaurants/UseCase/RestaurantGetListingUseCase.php b/app/src/Restaurants/UseCase/RestaurantGetListingUseCase.php index 2b34a03..1dc52cb 100644 --- a/app/src/Restaurants/UseCase/RestaurantGetListingUseCase.php +++ b/app/src/Restaurants/UseCase/RestaurantGetListingUseCase.php @@ -3,7 +3,7 @@ namespace App\Restaurants\UseCase; use App\Restaurants\Request\RestaurantListingRequest; -use App\Restaurants\Service\RestaurantPrepareRequestService; +use App\Restaurants\Service\RestaurantPrepareResponseService; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; use Throwable; @@ -11,11 +11,12 @@ use Throwable; class RestaurantGetListingUseCase { public function __construct( - private readonly RestaurantPrepareRequestService $prepareRequestService, + private readonly RestaurantPrepareResponseService $prepareRequestService, ) { } - public function execute(RestaurantListingRequest $request): JsonResponse { + public function execute(RestaurantListingRequest $request): JsonResponse + { try { return new JsonResponse( $this->prepareRequestService->bornListDto($request) diff --git a/app/src/Restaurants/UseCase/RestaurantPartUpdateUseCase.php b/app/src/Restaurants/UseCase/RestaurantPartUpdateUseCase.php new file mode 100644 index 0000000..38221e7 --- /dev/null +++ b/app/src/Restaurants/UseCase/RestaurantPartUpdateUseCase.php @@ -0,0 +1,29 @@ +prepareRequestService->rebirth($request); + return new Response(); + } catch (Throwable) { + return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); + } + } +} diff --git a/app/src/Shared/Entity/Restaurants.php b/app/src/Shared/Entity/Restaurants.php index 7a8e894..444ead4 100644 --- a/app/src/Shared/Entity/Restaurants.php +++ b/app/src/Shared/Entity/Restaurants.php @@ -10,6 +10,7 @@ use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: RestaurantsRepository::class)] +#[ORM\HasLifecycleCallbacks] class Restaurants { #[ORM\Id] diff --git a/app/src/Shared/EntityFactory/NewsEntityFactory.php b/app/src/Shared/EntityFactory/NewsEntityFactory.php index abcf0b6..c4a8414 100644 --- a/app/src/Shared/EntityFactory/NewsEntityFactory.php +++ b/app/src/Shared/EntityFactory/NewsEntityFactory.php @@ -78,7 +78,7 @@ class NewsEntityFactory $newsSetters = new Collection('callable'); $newsSetters['id'] = function (string $id, News $news) { - $news->setId($id); + $news->setId($id); }; $newsSetters['name'] = function (string $value, News $news) { $news->setName($value); diff --git a/app/src/Shared/EntityFactory/RestaurantEntityFactory.php b/app/src/Shared/EntityFactory/RestaurantEntityFactory.php index a38f1f7..e0e8c8a 100644 --- a/app/src/Shared/EntityFactory/RestaurantEntityFactory.php +++ b/app/src/Shared/EntityFactory/RestaurantEntityFactory.php @@ -2,16 +2,194 @@ namespace App\Shared\EntityFactory; +use App\Restaurants\Request\RestaurantCreateRequest; +use App\Restaurants\Request\RestaurantFullUpdateRequest; +use App\Restaurants\Request\RestaurantPartUpdateRequest; +use App\Shared\Entity\Restaurants; +use App\Shared\Error\NotFoundError; +use App\Shared\Repository\FileRepository; +use App\Shared\Repository\KitchensRepository; +use App\Shared\Repository\RestaurantsRepository; +use App\Shared\Repository\RestaurantTypesRepository; +use App\Shared\Repository\SettlementsRepository; use Ramsey\Collection\Collection; +use Ramsey\Uuid\Uuid; class RestaurantEntityFactory { - /** @var Collection */ + /** @var Collection */ private readonly Collection $restaurantSetters; + public function __construct( + private readonly RestaurantsRepository $restaurantsRepository, + private readonly RestaurantTypesRepository $restaurantTypesRepository, + private readonly SettlementsRepository $settlementsRepository, + private readonly FileRepository $fileRepository, + private readonly KitchensRepository $kitchensRepository, + ) { + $this->restaurantSetters = $this->setRestaurantSetters(); + } + + public function create(RestaurantCreateRequest $request): Restaurants + { + $restaurants = new Restaurants(); + $restaurants->setId(Uuid::uuid4()->toString()); + + foreach ($request as $key => $value) { + if ($value !== null) { + $this->restaurantSetters[$key]($value, $restaurants); + } + } + + return $restaurants; + } + + public function softUpdate(RestaurantFullUpdateRequest $request + ): Restaurants { + $restaurants = $this->restaurantsRepository->find( + $request->id + ) ?? new Restaurants(); + + foreach ($request as $key => $value) { + if ($value !== null) { + $this->restaurantSetters[$key]($value, $restaurants); + } + } + + return $restaurants; + } + + public function hardUpdate(RestaurantPartUpdateRequest $request + ): Restaurants { + $restaurant = $this->restaurantsRepository->find($request->id); + + if ($restaurant === null) { + throw new NotFoundError('News entity for update not found'); + } + + foreach ($request as $key => $value) { + if ($value !== null) { + $this->restaurantSetters[$key]($value, $restaurant); + } + } + + return $restaurant; + } + /** @return Collection */ private function setRestaurantSetters(): Collection { + $setters = new Collection('callable'); + + $setters['id'] = function (string $value, Restaurants $restaurant) { + $restaurant->setId($value); + }; + $setters['type_id'] = function ( + string $value, + Restaurants $restaurant + ) { + $restaurant->setType( + $this->restaurantTypesRepository->find($value) + ); + }; + $setters['settlement_id'] = function ( + string $value, + Restaurants $restaurant + ) { + $restaurant->setSettlement( + $this->settlementsRepository->find($value) + ); + }; + $setters['preview_image_id'] = function ( + string $value, + Restaurants $restaurant + ) { + $restaurant->setPreviewImage($this->fileRepository->find($value)); + }; + $setters['detail_image_id'] = function ( + string $value, + Restaurants $restaurant + ) { + $restaurant->setDetailImage($this->fileRepository->find($value)); + }; + $setters['active'] = function (bool $value, Restaurants $restaurant) { + $restaurant->setActive($value); + }; + $setters['name'] = function (string $value, Restaurants $restaurant) { + $restaurant->setName($value); + }; + $setters['code'] = function (string $value, Restaurants $restaurant) { + $restaurant->setCode($value); + }; + $setters['description'] = function ( + string $value, + Restaurants $restaurant + ) { + $restaurant->setDescription($value); + }; + $setters['check'] = function (string $value, Restaurants $restaurant) { + $restaurant->setReceipt($value); + }; + $setters['check_info'] = function ( + string $value, + Restaurants $restaurant + ) { + $restaurant->setReceiptInfo($value); + }; + $setters['phone'] = function (string $value, Restaurants $restaurant) { + $restaurant->setPhone($value); + }; + $setters['email'] = function (string $value, Restaurants $restaurant) { + $restaurant->setEmail($value); + }; + $setters['address'] = function ( + string $value, + Restaurants $restaurant + ) { + $restaurant->setAddress($value); + }; + $setters['tags'] = function ( + string $value, + Restaurants $restaurant + ) { + $restaurant->setTags($value); + }; + $setters['site'] = function (string $value, Restaurants $restaurant) { + $restaurant->setSite($value); + }; + $setters['coordinates'] = function ( + string $value, + Restaurants $restaurant + ) { + $restaurant->setCoordinates($value); + }; + $setters['how_to_find'] = function ( + string $value, + Restaurants $restaurant + ) { + $restaurant->setHowToFind($value); + }; + $setters['kitchens_id'] = function ( + Collection $ids, + Restaurants $restaurant + ) { + foreach ($ids as $id) { + $restaurant->addKitchen( + $this->kitchensRepository->find($id) + ); + } + }; + $setters['gallery_id'] = function ( + Collection $ids, + Restaurants $restaurant + ) { + foreach ($ids as $id) { + $restaurant->addGallery( + $this->fileRepository->find($id) + ); + } + }; + return $setters; } } \ No newline at end of file diff --git a/app/src/Shared/Repository/NewsRepository.php b/app/src/Shared/Repository/NewsRepository.php index 4b55634..d7b05bb 100644 --- a/app/src/Shared/Repository/NewsRepository.php +++ b/app/src/Shared/Repository/NewsRepository.php @@ -39,7 +39,7 @@ class NewsRepository extends ServiceEntityRepository $this->getEntityManager()->clear(); } - public function getMaxValueSort(): int + public function getMaxValueSort(): ?int { return $this->createQueryBuilder('n') ->select('MAX(n.sort)') diff --git a/app/src/Shared/Repository/RestaurantsRepository.php b/app/src/Shared/Repository/RestaurantsRepository.php index 5bbf103..ab72e3e 100644 --- a/app/src/Shared/Repository/RestaurantsRepository.php +++ b/app/src/Shared/Repository/RestaurantsRepository.php @@ -24,7 +24,21 @@ class RestaurantsRepository extends ServiceEntityRepository parent::__construct($registry, Restaurants::class); } - public function getMaxValueSort(): int + public function createUpdate(Restaurants $restaurants): void + { + $this->getEntityManager()->persist($restaurants); + $this->getEntityManager()->flush(); + $this->getEntityManager()->clear(); + } + + public function remove(Restaurants $restaurants): void + { + $this->getEntityManager()->remove($restaurants); + $this->getEntityManager()->flush(); + $this->getEntityManager()->clear(); + } + + public function getMaxValueSort(): ?int { return $this->createQueryBuilder('r') ->select('MAX(r.sort)') -- GitLab