From 135275632aa44d06f5d401fc033a6f193e4ed05c Mon Sep 17 00:00:00 2001 From: "Alex. Plokhikh" Date: Fri, 3 May 2024 14:23:59 +0500 Subject: [PATCH 01/12] STA-960|create some DTO --- app/src/Controller/RestaurantsController.php | 20 ++++++++++++++++++++ app/src/DTO/RestaurantListDTO.php | 10 ++++++++++ app/src/DTO/RestaurantListingElementDTO.php | 15 +++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 app/src/Controller/RestaurantsController.php create mode 100644 app/src/DTO/RestaurantListDTO.php create mode 100644 app/src/DTO/RestaurantListingElementDTO.php diff --git a/app/src/Controller/RestaurantsController.php b/app/src/Controller/RestaurantsController.php new file mode 100644 index 0000000..52248bb --- /dev/null +++ b/app/src/Controller/RestaurantsController.php @@ -0,0 +1,20 @@ + Date: Thu, 9 May 2024 04:50:01 +0500 Subject: [PATCH 02/12] STA-960 | clean-up --- app/migrations/Version20240427114630.php | 96 -------------------- app/src/Controller/RestaurantsController.php | 20 ---- app/src/DTO/RestaurantListDTO.php | 10 -- app/src/DTO/RestaurantListingElementDTO.php | 15 --- 4 files changed, 141 deletions(-) delete mode 100644 app/migrations/Version20240427114630.php delete mode 100644 app/src/Controller/RestaurantsController.php delete mode 100644 app/src/DTO/RestaurantListDTO.php delete mode 100644 app/src/DTO/RestaurantListingElementDTO.php diff --git a/app/migrations/Version20240427114630.php b/app/migrations/Version20240427114630.php deleted file mode 100644 index 84378b7..0000000 --- a/app/migrations/Version20240427114630.php +++ /dev/null @@ -1,96 +0,0 @@ -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 INDEX IDX_1DD39950C54C8C93 ON news (type_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))'); - $this->addSql('CREATE INDEX IDX_34AB0102B5A459A0 ON news_news_categories (news_id)'); - $this->addSql('CREATE INDEX IDX_34AB0102F7F178F1 ON news_news_categories (news_categories_id)'); - $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 INDEX IDX_AD837724C54C8C93 ON restaurants (type_id)'); - $this->addSql('CREATE INDEX IDX_AD837724C2B9C425 ON restaurants (settlement_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 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)\''); - $this->addSql('COMMENT ON COLUMN settlements.coordinates IS \'(DC2Type:array)\''); - $this->addSql('CREATE TABLE users (id UUID NOT NULL, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL, phone VARCHAR(255) NOT NULL, is_male BOOLEAN NOT NULL, address VARCHAR(255) NOT NULL, birthday DATE NOT NULL, PRIMARY KEY(id))'); - $this->addSql('COMMENT ON COLUMN users.birthday IS \'(DC2Type:date_immutable)\''); - $this->addSql('CREATE TABLE messenger_messages (id BIGSERIAL NOT NULL, body TEXT NOT NULL, headers TEXT NOT NULL, queue_name VARCHAR(190) NOT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, available_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, delivered_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE INDEX IDX_75EA56E0FB7336F0 ON messenger_messages (queue_name)'); - $this->addSql('CREATE INDEX IDX_75EA56E0E3BD61CE ON messenger_messages (available_at)'); - $this->addSql('CREATE INDEX IDX_75EA56E016BA31DB ON messenger_messages (delivered_at)'); - $this->addSql('COMMENT ON COLUMN messenger_messages.created_at IS \'(DC2Type:datetime_immutable)\''); - $this->addSql('COMMENT ON COLUMN messenger_messages.available_at IS \'(DC2Type:datetime_immutable)\''); - $this->addSql('COMMENT ON COLUMN messenger_messages.delivered_at IS \'(DC2Type:datetime_immutable)\''); - $this->addSql('CREATE OR REPLACE FUNCTION notify_messenger_messages() RETURNS TRIGGER AS $$ - BEGIN - PERFORM pg_notify(\'messenger_messages\', NEW.queue_name::text); - RETURN NEW; - END; - $$ LANGUAGE plpgsql;'); - $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_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_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'); - } - - public function down(Schema $schema): void - { - // 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_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_kitchens DROP CONSTRAINT FK_716464694DCA160A'); - $this->addSql('ALTER TABLE restaurants_kitchens DROP CONSTRAINT FK_71646469E043FCBC'); - $this->addSql('DROP TABLE kitchens'); - $this->addSql('DROP TABLE news'); - $this->addSql('DROP TABLE news_news_categories'); - $this->addSql('DROP TABLE news_categories'); - $this->addSql('DROP TABLE news_type'); - $this->addSql('DROP TABLE restaurant_types'); - $this->addSql('DROP TABLE restaurants'); - $this->addSql('DROP TABLE restaurants_kitchens'); - $this->addSql('DROP TABLE settlements'); - $this->addSql('DROP TABLE users'); - $this->addSql('DROP TABLE messenger_messages'); - } -} diff --git a/app/src/Controller/RestaurantsController.php b/app/src/Controller/RestaurantsController.php deleted file mode 100644 index 52248bb..0000000 --- a/app/src/Controller/RestaurantsController.php +++ /dev/null @@ -1,20 +0,0 @@ - Date: Thu, 9 May 2024 06:19:04 +0500 Subject: [PATCH 03/12] STA-960 | fix repo & entity & some small fixes --- app/migrations/Version20240427114630.php | 96 ++++++ app/src/Controller/RestaurantsController.php | 20 ++ app/src/DTO/RestaurantListDTO.php | 10 + app/src/DTO/RestaurantListingElementDTO.php | 15 + app/src/Entity/File.php | 291 ++++++++++++++++++ app/src/Entity/Kitchens.php | 2 +- app/src/Entity/News.php | 21 +- app/src/Entity/NewsCategories.php | 2 +- app/src/Entity/NewsType.php | 2 +- app/src/Entity/RestaurantTypes.php | 2 +- app/src/Entity/Restaurants.php | 96 +++--- app/src/Entity/Settlements.php | 2 +- app/src/Repository/FileRepository.php | 23 ++ app/src/Repository/KitchensRepository.php | 30 +- .../Repository/NewsCategoriesRepository.php | 33 +- app/src/Repository/NewsRepository.php | 83 +++-- app/src/Repository/NewsTypeRepository.php | 30 +- .../Repository/RestaurantTypesRepository.php | 32 +- app/src/Repository/RestaurantsRepository.php | 83 +++-- app/src/Repository/SettlementsRepository.php | 25 -- app/src/Repository/UsersRepository.php | 25 -- docker-compose.yml | 4 +- 22 files changed, 674 insertions(+), 253 deletions(-) create mode 100644 app/migrations/Version20240427114630.php create mode 100644 app/src/Controller/RestaurantsController.php create mode 100644 app/src/DTO/RestaurantListDTO.php create mode 100644 app/src/DTO/RestaurantListingElementDTO.php create mode 100644 app/src/Entity/File.php create mode 100644 app/src/Repository/FileRepository.php diff --git a/app/migrations/Version20240427114630.php b/app/migrations/Version20240427114630.php new file mode 100644 index 0000000..84378b7 --- /dev/null +++ b/app/migrations/Version20240427114630.php @@ -0,0 +1,96 @@ +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 INDEX IDX_1DD39950C54C8C93 ON news (type_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))'); + $this->addSql('CREATE INDEX IDX_34AB0102B5A459A0 ON news_news_categories (news_id)'); + $this->addSql('CREATE INDEX IDX_34AB0102F7F178F1 ON news_news_categories (news_categories_id)'); + $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 INDEX IDX_AD837724C54C8C93 ON restaurants (type_id)'); + $this->addSql('CREATE INDEX IDX_AD837724C2B9C425 ON restaurants (settlement_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 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)\''); + $this->addSql('COMMENT ON COLUMN settlements.coordinates IS \'(DC2Type:array)\''); + $this->addSql('CREATE TABLE users (id UUID NOT NULL, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL, phone VARCHAR(255) NOT NULL, is_male BOOLEAN NOT NULL, address VARCHAR(255) NOT NULL, birthday DATE NOT NULL, PRIMARY KEY(id))'); + $this->addSql('COMMENT ON COLUMN users.birthday IS \'(DC2Type:date_immutable)\''); + $this->addSql('CREATE TABLE messenger_messages (id BIGSERIAL NOT NULL, body TEXT NOT NULL, headers TEXT NOT NULL, queue_name VARCHAR(190) NOT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, available_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, delivered_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_75EA56E0FB7336F0 ON messenger_messages (queue_name)'); + $this->addSql('CREATE INDEX IDX_75EA56E0E3BD61CE ON messenger_messages (available_at)'); + $this->addSql('CREATE INDEX IDX_75EA56E016BA31DB ON messenger_messages (delivered_at)'); + $this->addSql('COMMENT ON COLUMN messenger_messages.created_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN messenger_messages.available_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN messenger_messages.delivered_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('CREATE OR REPLACE FUNCTION notify_messenger_messages() RETURNS TRIGGER AS $$ + BEGIN + PERFORM pg_notify(\'messenger_messages\', NEW.queue_name::text); + RETURN NEW; + END; + $$ LANGUAGE plpgsql;'); + $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_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_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'); + } + + public function down(Schema $schema): void + { + // 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_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_kitchens DROP CONSTRAINT FK_716464694DCA160A'); + $this->addSql('ALTER TABLE restaurants_kitchens DROP CONSTRAINT FK_71646469E043FCBC'); + $this->addSql('DROP TABLE kitchens'); + $this->addSql('DROP TABLE news'); + $this->addSql('DROP TABLE news_news_categories'); + $this->addSql('DROP TABLE news_categories'); + $this->addSql('DROP TABLE news_type'); + $this->addSql('DROP TABLE restaurant_types'); + $this->addSql('DROP TABLE restaurants'); + $this->addSql('DROP TABLE restaurants_kitchens'); + $this->addSql('DROP TABLE settlements'); + $this->addSql('DROP TABLE users'); + $this->addSql('DROP TABLE messenger_messages'); + } +} diff --git a/app/src/Controller/RestaurantsController.php b/app/src/Controller/RestaurantsController.php new file mode 100644 index 0000000..52248bb --- /dev/null +++ b/app/src/Controller/RestaurantsController.php @@ -0,0 +1,20 @@ + + */ + #[ORM\OneToMany(targetEntity: Restaurants::class, mappedBy: 'previewImage')] + private Collection $restaurantsPreview; + + /** + * @var Collection + */ + #[ORM\OneToMany(targetEntity: Restaurants::class, mappedBy: 'detailImage')] + private Collection $restaurantsDetail; + + /** + * @var Collection + */ + #[ORM\ManyToMany(targetEntity: Restaurants::class, mappedBy: 'gallery')] + private Collection $restaurantsGallery; + + /** + * @var Collection + */ + #[ORM\OneToMany(targetEntity: News::class, mappedBy: 'detailImage')] + + private Collection $newsDetail; + + /** + * @var Collection + */ + #[ORM\OneToMany(targetEntity: News::class, mappedBy: 'previewImage')] + private Collection $newsPreview; + + public function __construct() + { + $this->restaurantsPreview = new ArrayCollection(); + $this->restaurantsDetail = new ArrayCollection(); + $this->restaurantsGallery = new ArrayCollection(); + $this->newsDetail = new ArrayCollection(); + $this->newsPreview = new ArrayCollection(); + } + + public function getId(): ?string + { + return $this->id; + } + + public function setId(string $id): static + { + $this->id = $id; + + return $this; + } + + public function getName(): ?string + { + return $this->name; + } + + public function setName(string $name): static + { + $this->name = $name; + + return $this; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function setDescription(string $description): static + { + $this->description = $description; + + return $this; + } + + public function getSize(): ?int + { + return $this->size; + } + + public function setSize(int $size): static + { + $this->size = $size; + + return $this; + } + + public function getType(): ?string + { + return $this->type; + } + + public function setType(string $type): static + { + $this->type = $type; + + return $this; + } + + public function getUrl(): ?string + { + return $this->url; + } + + public function setUrl(string $url): static + { + $this->url = $url; + + return $this; + } + + /** + * @return Collection + */ + public function getRestaurantsPreview(): Collection + { + return $this->restaurantsPreview; + } + + public function addRestaurantsPreview(Restaurants $restaurantsPreview): static + { + if (!$this->restaurantsPreview->contains($restaurantsPreview)) { + $this->restaurantsPreview->add($restaurantsPreview); + $restaurantsPreview->setPreviewImage($this); + } + + return $this; + } + + public function removeRestaurantsPreview(Restaurants $restaurantsPreview): static + { + if ($this->restaurantsPreview->removeElement($restaurantsPreview)) { + // set the owning side to null (unless already changed) + if ($restaurantsPreview->getPreviewImage() === $this) { + $restaurantsPreview->setPreviewImage(null); + } + } + + return $this; + } + + /** + * @return Collection + */ + public function getRestaurantsDetail(): Collection + { + return $this->restaurantsDetail; + } + + public function addRestaurantsDetail(Restaurants $restaurantsDetail): static + { + if (!$this->restaurantsDetail->contains($restaurantsDetail)) { + $this->restaurantsDetail->add($restaurantsDetail); + $restaurantsDetail->setDetailImage($this); + } + + return $this; + } + + public function removeRestaurantsDetail(Restaurants $restaurantsDetail): static + { + if ($this->restaurantsDetail->removeElement($restaurantsDetail)) { + // set the owning side to null (unless already changed) + if ($restaurantsDetail->getDetailImage() === $this) { + $restaurantsDetail->setDetailImage(null); + } + } + + return $this; + } + + /** + * @return Collection + */ + public function getRestaurantsGallery(): Collection + { + return $this->restaurantsGallery; + } + + public function addRestaurantsGallery(Restaurants $restaurantsGallery): static + { + if (!$this->restaurantsGallery->contains($restaurantsGallery)) { + $this->restaurantsGallery->add($restaurantsGallery); + $restaurantsGallery->addGallery($this); + } + + return $this; + } + + public function removeRestaurantsGallery(Restaurants $restaurantsGallery): static + { + if ($this->restaurantsGallery->removeElement($restaurantsGallery)) { + $restaurantsGallery->removeGallery($this); + } + + return $this; + } + + /** + * @return Collection + */ + public function getNewsDetail(): Collection + { + return $this->newsDetail; + } + + public function addNewsDetail(News $newsDetail): static + { + if (!$this->newsDetail->contains($newsDetail)) { + $this->newsDetail->add($newsDetail); + $newsDetail->setDetailImage($this); + } + + return $this; + } + + public function removeNewsDetail(News $newsDetail): static + { + if ($this->newsDetail->removeElement($newsDetail)) { + // set the owning side to null (unless already changed) + if ($newsDetail->getDetailImage() === $this) { + $newsDetail->setDetailImage(null); + } + } + + return $this; + } + + /** + * @return Collection + */ + public function getNewsPreview(): Collection + { + return $this->newsPreview; + } + + public function addNewsPreview(News $newsPreview): static + { + if (!$this->newsPreview->contains($newsPreview)) { + $this->newsPreview->add($newsPreview); + $newsPreview->setPreviewImage($this); + } + + return $this; + } + + public function removeNewsPreview(News $newsPreview): static + { + if ($this->newsPreview->removeElement($newsPreview)) { + // set the owning side to null (unless already changed) + if ($newsPreview->getPreviewImage() === $this) { + $newsPreview->setPreviewImage(null); + } + } + + return $this; + } +} diff --git a/app/src/Entity/Kitchens.php b/app/src/Entity/Kitchens.php index 29ac790..c5dc4aa 100644 --- a/app/src/Entity/Kitchens.php +++ b/app/src/Entity/Kitchens.php @@ -32,7 +32,7 @@ class Kitchens $this->restaurants = new ArrayCollection(); } - public function getId(): ?int + public function getId(): ?string { return $this->id; } diff --git a/app/src/Entity/News.php b/app/src/Entity/News.php index cd6d609..5011c6d 100644 --- a/app/src/Entity/News.php +++ b/app/src/Entity/News.php @@ -33,15 +33,9 @@ class News #[ORM\Column] private ?\DateTimeImmutable $updateAt = null; - #[ORM\Column(length: 255, nullable: true)] - private ?string $previewImage = null; - #[ORM\Column(length: 1000, nullable: true)] private ?string $previewText = null; - #[ORM\Column(length: 255, nullable: true)] - private ?string $detailImage = null; - #[ORM\Column(length: 255, nullable: true)] private ?string $detailText = null; @@ -57,6 +51,11 @@ class News #[ORM\Column] private ?bool $mainPageRender = null; + #[ORM\ManyToOne(inversedBy: 'newsDetail')] + private ?File $detailImage = null; + + #[ORM\ManyToOne(inversedBy: 'newsPreview')] + private ?File $previewImage = null; public function __construct() @@ -64,7 +63,7 @@ class News $this->categories = new ArrayCollection(); } - public function getId(): ?int + public function getId(): ?string { return $this->id; } @@ -148,12 +147,12 @@ class News return $this; } - public function getPreviewImage(): ?string + public function getPreviewImage(): ?File { return $this->previewImage; } - public function setPreviewImage(?string $previewImage): static + public function setPreviewImage(?File $previewImage): static { $this->previewImage = $previewImage; @@ -172,12 +171,12 @@ class News return $this; } - public function getDetailImage(): ?string + public function getDetailImage(): ?File { return $this->detailImage; } - public function setDetailImage(?string $detailImage): static + public function setDetailImage(?File $detailImage): static { $this->detailImage = $detailImage; diff --git a/app/src/Entity/NewsCategories.php b/app/src/Entity/NewsCategories.php index aa5bf02..fb41930 100644 --- a/app/src/Entity/NewsCategories.php +++ b/app/src/Entity/NewsCategories.php @@ -32,7 +32,7 @@ class NewsCategories $this->news = new ArrayCollection(); } - public function getId(): ?int + public function getId(): ?string { return $this->id; } diff --git a/app/src/Entity/NewsType.php b/app/src/Entity/NewsType.php index f5764f2..493fff0 100644 --- a/app/src/Entity/NewsType.php +++ b/app/src/Entity/NewsType.php @@ -32,7 +32,7 @@ class NewsType $this->news = new ArrayCollection(); } - public function getId(): ?int + public function getId(): ?string { return $this->id; } diff --git a/app/src/Entity/RestaurantTypes.php b/app/src/Entity/RestaurantTypes.php index fc3c1b0..12d132e 100644 --- a/app/src/Entity/RestaurantTypes.php +++ b/app/src/Entity/RestaurantTypes.php @@ -33,7 +33,7 @@ class RestaurantTypes $this->restaurants = new ArrayCollection(); } - public function getId(): ?int + public function getId(): ?string { return $this->id; } diff --git a/app/src/Entity/Restaurants.php b/app/src/Entity/Restaurants.php index 4419b81..8f3380d 100644 --- a/app/src/Entity/Restaurants.php +++ b/app/src/Entity/Restaurants.php @@ -27,10 +27,10 @@ class Restaurants #[ORM\Column] private ?\DateTimeImmutable $updateAt = null; - #[ORM\ManyToOne(inversedBy: 'restaurants')] + #[ORM\ManyToOne(inversedBy: 'restaurantsTypes')] private ?RestaurantTypes $type = null; - #[ORM\ManyToOne(inversedBy: 'restaurants')] + #[ORM\ManyToOne(inversedBy: 'restaurantsSettlements')] private ?Settlements $settlement = null; #[ORM\Column(length: 255)] @@ -63,17 +63,8 @@ class Restaurants #[ORM\Column(length: 255)] private ?string $site = null; - #[ORM\Column(type: Types::ARRAY)] - private array $coordinates = []; - - #[ORM\Column(length: 255)] - private ?string $previewImage = null; - - #[ORM\Column(length: 255)] - private ?string $detailImage = null; - - #[ORM\Column(length: 255)] - private ?string $gallery = null; + #[ORM\Column(length: 1000)] + private ?string $coordinates = null; #[ORM\Column(length: 255)] private ?string $howToFind = null; @@ -84,12 +75,25 @@ class Restaurants #[ORM\ManyToMany(targetEntity: Kitchens::class, inversedBy: 'restaurants')] private Collection $kitchens; + #[ORM\ManyToOne(inversedBy: 'restaurantsPreview')] + private ?File $previewImage = null; + + #[ORM\ManyToOne(inversedBy: 'restaurantsDetail')] + private ?File $detailImage = null; + + /** + * @var Collection + */ + #[ORM\ManyToMany(targetEntity: File::class, inversedBy: 'restaurantsGallery')] + private Collection $gallery; + public function __construct() { $this->kitchens = new ArrayCollection(); + $this->gallery = new ArrayCollection(); } - public function getId(): ?int + public function getId(): ?string { return $this->id; } @@ -293,86 +297,98 @@ class Restaurants return $this; } - public function getCoordinates(): array + public function getCoordinates(): string { return $this->coordinates; } - public function setCoordinates(array $coordinates): static + public function setCoordinates(string $coordinates): static { $this->coordinates = $coordinates; return $this; } - public function getPreviewImage(): ?string + public function getHowToFind(): ?string { - return $this->previewImage; + return $this->howToFind; } - public function setPreviewImage(string $previewImage): static + public function setHowToFind(string $howToFind): static { - $this->previewImage = $previewImage; + $this->howToFind = $howToFind; return $this; } - public function getDetailImage(): ?string + /** + * @return Collection + */ + public function getKitchens(): Collection { - return $this->detailImage; + return $this->kitchens; } - public function setDetailImage(string $detailImage): static + public function addKitchen(Kitchens $kitchen): static { - $this->detailImage = $detailImage; + if (!$this->kitchens->contains($kitchen)) { + $this->kitchens->add($kitchen); + } return $this; } - public function getGallery(): ?string + public function removeKitchen(Kitchens $kitchen): static { - return $this->gallery; + $this->kitchens->removeElement($kitchen); + + return $this; } - public function setGallery(string $gallery): static + public function getPreviewImage(): ?File { - $this->gallery = $gallery; + return $this->previewImage; + } + + public function setPreviewImage(?File $previewImage): static + { + $this->previewImage = $previewImage; return $this; } - public function getHowToFind(): ?string + public function getDetailImage(): ?File { - return $this->howToFind; + return $this->detailImage; } - public function setHowToFind(string $howToFind): static + public function setDetailImage(?File $detailImage): static { - $this->howToFind = $howToFind; + $this->detailImage = $detailImage; return $this; } /** - * @return Collection + * @return Collection */ - public function getKitchens(): Collection + public function getGallery(): Collection { - return $this->kitchens; + return $this->gallery; } - public function addKitchen(Kitchens $kitchen): static + public function addGallery(File $gallery): static { - if (!$this->kitchens->contains($kitchen)) { - $this->kitchens->add($kitchen); + if (!$this->gallery->contains($gallery)) { + $this->gallery->add($gallery); } return $this; } - public function removeKitchen(Kitchens $kitchen): static + public function removeGallery(File $gallery): static { - $this->kitchens->removeElement($kitchen); + $this->gallery->removeElement($gallery); return $this; } diff --git a/app/src/Entity/Settlements.php b/app/src/Entity/Settlements.php index 304a26c..6f6dc92 100644 --- a/app/src/Entity/Settlements.php +++ b/app/src/Entity/Settlements.php @@ -44,7 +44,7 @@ class Settlements $this->restaurants = new ArrayCollection(); } - public function getId(): ?int + public function getId(): ?string { return $this->id; } diff --git a/app/src/Repository/FileRepository.php b/app/src/Repository/FileRepository.php new file mode 100644 index 0000000..567fb59 --- /dev/null +++ b/app/src/Repository/FileRepository.php @@ -0,0 +1,23 @@ + + * + * @method File|null find($id, $lockMode = null, $lockVersion = null) + * @method File|null findOneBy(array $criteria, array $orderBy = null) + * @method File[] findAll() + * @method File[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class FileRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, File::class); + } +} diff --git a/app/src/Repository/KitchensRepository.php b/app/src/Repository/KitchensRepository.php index b65972f..cd53ebd 100644 --- a/app/src/Repository/KitchensRepository.php +++ b/app/src/Repository/KitchensRepository.php @@ -5,6 +5,7 @@ namespace App\Repository; use App\Entity\Kitchens; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; +use Ramsey\Collection\Collection; /** * @extends ServiceEntityRepository @@ -21,28 +22,9 @@ class KitchensRepository extends ServiceEntityRepository parent::__construct($registry, Kitchens::class); } - // /** - // * @return Kitchens[] Returns an array of Kitchens objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('k') - // ->andWhere('k.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('k.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?Kitchens - // { - // return $this->createQueryBuilder('k') - // ->andWhere('k.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } + /** @return Collection */ + public function getAll(): Collection + { + return new Collection(Kitchens::class, $this->findAll()); + } } diff --git a/app/src/Repository/NewsCategoriesRepository.php b/app/src/Repository/NewsCategoriesRepository.php index cb2bf88..215cbe3 100644 --- a/app/src/Repository/NewsCategoriesRepository.php +++ b/app/src/Repository/NewsCategoriesRepository.php @@ -5,6 +5,7 @@ namespace App\Repository; use App\Entity\NewsCategories; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; +use Ramsey\Collection\Collection; /** * @extends ServiceEntityRepository @@ -21,28 +22,12 @@ class NewsCategoriesRepository extends ServiceEntityRepository parent::__construct($registry, NewsCategories::class); } - // /** - // * @return NewsCategories[] Returns an array of NewsCategories objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('n') - // ->andWhere('n.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('n.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?NewsCategories - // { - // return $this->createQueryBuilder('n') - // ->andWhere('n.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } + /** + * Возвращает все сущности + * @return Collection + */ + public function getAll(): Collection + { + return new Collection(NewsCategories::class, $this->findAll()); + } } diff --git a/app/src/Repository/NewsRepository.php b/app/src/Repository/NewsRepository.php index c74af62..b5031de 100644 --- a/app/src/Repository/NewsRepository.php +++ b/app/src/Repository/NewsRepository.php @@ -3,8 +3,12 @@ namespace App\Repository; use App\Entity\News; +use App\Entity\Restaurants; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\ORM\Query\Expr\Join; +use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ManagerRegistry; +use Ramsey\Collection\Collection; /** * @extends ServiceEntityRepository @@ -21,28 +25,59 @@ class NewsRepository extends ServiceEntityRepository parent::__construct($registry, News::class); } - // /** - // * @return News[] Returns an array of News objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('n') - // ->andWhere('n.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('n.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?News - // { - // return $this->createQueryBuilder('n') - // ->andWhere('n.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } + /** + * @param QueryBuilder $query + * @return Collection + */ + protected function toCollection(QueryBuilder $query): Collection + { + return new Collection( + News::class, + $query + ->orderBy('n.sort', 'ASC') + ->getQuery() + ->getResult() + ); + } + + protected function getByFilters(?string $categoryId, QueryBuilder $query): QueryBuilder + { + if ($categoryId !== null) { + $query = $query + ->innerJoin('n.categories', 'c', Join::WITH, 'c.id = :typeId') + ->setParameter('typeId', $categoryId); + } + return $query; + } + + public function getCountWithFilters(?string $categoryId): int + { + $query = $this->createQueryBuilder('n'); + $query = $this->getByFilters($categoryId, $query); + return $query->select('COUNT(n.id)')->getQuery()->getSingleScalarResult(); + } + + /** @return Collection */ + public function findByFilters(?string $categoryId, int $limit): Collection + { + $query = $this->createQueryBuilder('n'); + $query = $this->getByFilters($categoryId, $query); + $query = $query->setMaxResults($limit); + return $this->toCollection($query); + } + + /** @return Collection */ + public function getAll(): Collection + { + return $this->toCollection($this->createQueryBuilder('n')); + } + + public function getMain(): News + { + return $this->createQueryBuilder('n') + ->andWhere('n.mainPageRender = true') + ->setMaxResults(1) + ->getQuery() + ->getResult()[0]; + } } diff --git a/app/src/Repository/NewsTypeRepository.php b/app/src/Repository/NewsTypeRepository.php index dabf301..e2acd17 100644 --- a/app/src/Repository/NewsTypeRepository.php +++ b/app/src/Repository/NewsTypeRepository.php @@ -5,6 +5,7 @@ namespace App\Repository; use App\Entity\NewsType; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; +use Ramsey\Collection\Collection; /** * @extends ServiceEntityRepository @@ -21,28 +22,9 @@ class NewsTypeRepository extends ServiceEntityRepository parent::__construct($registry, NewsType::class); } - // /** - // * @return NewsType[] Returns an array of NewsType objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('n') - // ->andWhere('n.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('n.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?NewsType - // { - // return $this->createQueryBuilder('n') - // ->andWhere('n.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } + /** @return Collection */ + public function getAll(): Collection + { + return new Collection(NewsType::class, $this->findAll()); + } } diff --git a/app/src/Repository/RestaurantTypesRepository.php b/app/src/Repository/RestaurantTypesRepository.php index 8a2f3c3..3f5eb7d 100644 --- a/app/src/Repository/RestaurantTypesRepository.php +++ b/app/src/Repository/RestaurantTypesRepository.php @@ -2,9 +2,12 @@ namespace App\Repository; +use App\Entity\Restaurants; use App\Entity\RestaurantTypes; +use Cassandra\FutureSession; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; +use Ramsey\Collection\Collection; /** * @extends ServiceEntityRepository @@ -21,28 +24,9 @@ class RestaurantTypesRepository extends ServiceEntityRepository parent::__construct($registry, RestaurantTypes::class); } - // /** - // * @return RestaurantTypes[] Returns an array of RestaurantTypes objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('r') - // ->andWhere('r.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('r.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?RestaurantTypes - // { - // return $this->createQueryBuilder('r') - // ->andWhere('r.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } + /** @return Collection */ + public function getAll(): Collection + { + return new Collection(RestaurantTypes::class, $this->findAll()); + } } diff --git a/app/src/Repository/RestaurantsRepository.php b/app/src/Repository/RestaurantsRepository.php index f540695..b80d4af 100644 --- a/app/src/Repository/RestaurantsRepository.php +++ b/app/src/Repository/RestaurantsRepository.php @@ -2,9 +2,13 @@ namespace App\Repository; +use App\DTO\CollectionDTO; use App\Entity\Restaurants; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\ORM\Query\Expr\Join; +use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ManagerRegistry; +use Ramsey\Collection\Collection; /** * @extends ServiceEntityRepository @@ -21,28 +25,59 @@ class RestaurantsRepository extends ServiceEntityRepository parent::__construct($registry, Restaurants::class); } -// /** -// * @return Restaurants[] Returns an array of Restaurants objects -// */ -// public function findByExampleField($value): array -// { -// return $this->createQueryBuilder('r') -// ->andWhere('r.exampleField = :val') -// ->setParameter('val', $value) -// ->orderBy('r.id', 'ASC') -// ->setMaxResults(10) -// ->getQuery() -// ->getResult() -// ; -// } - -// public function findOneBySomeField($value): ?Restaurants -// { -// return $this->createQueryBuilder('r') -// ->andWhere('r.exampleField = :val') -// ->setParameter('val', $value) -// ->getQuery() -// ->getOneOrNullResult() -// ; -// } + /** @return Collection */ + protected function toCollection(QueryBuilder $query): Collection + { + return new Collection( + Restaurants::class, + $query + ->orderBy('n.sort', 'ASC') + ->getQuery() + ->getResult() + ); + } + + protected function filterByKitchen(?string $kitchenId, QueryBuilder $query): QueryBuilder + { + if ($kitchenId === null) { + $query = $query + ->innerJoin('r.categories', 'k', Join::WITH, 'k.id = :kitchenId') + ->setParameter('kitchenId', $kitchenId); + } + return $query; + } + + protected function filterByType(?string $typeId, QueryBuilder $query): QueryBuilder + { + if ($typeId === null) { + $query = $query + ->where('r.type.id = :typeId') + ->setParameter('typeId', $typeId); + } + return $query; + } + + public function getCountWithFilters(?string $categoryId, ?string $typeId): int + { + $query = $this->createQueryBuilder('r'); + $query = $this->filterByKitchen($categoryId, $query); + $query = $this->filterByType($typeId, $query); + return $query->select('COUNT(n.id)')->getQuery()->getSingleScalarResult(); + } + + /** @return Collection */ + public function findByFilters(?string $categoryId, ?string $typeId, int $limit): Collection + { + $query = $this->createQueryBuilder('r'); + $query = $this->filterByKitchen($categoryId, $query); + $query = $this->filterByType($typeId, $query); + $query = $query->setMaxResults($limit); + return $this->toCollection($query); + } + + /** @return Collection */ + public function getAll(): Collection + { + return $this->toCollection($this->createQueryBuilder('r')); + } } diff --git a/app/src/Repository/SettlementsRepository.php b/app/src/Repository/SettlementsRepository.php index 4e84a18..66a2f2d 100644 --- a/app/src/Repository/SettlementsRepository.php +++ b/app/src/Repository/SettlementsRepository.php @@ -20,29 +20,4 @@ class SettlementsRepository extends ServiceEntityRepository { parent::__construct($registry, Settlements::class); } - - // /** - // * @return Settlements[] Returns an array of Settlements objects - // */ - // public function findByExampleField($value): array - // { - // return $this->createQueryBuilder('s') - // ->andWhere('s.exampleField = :val') - // ->setParameter('val', $value) - // ->orderBy('s.id', 'ASC') - // ->setMaxResults(10) - // ->getQuery() - // ->getResult() - // ; - // } - - // public function findOneBySomeField($value): ?Settlements - // { - // return $this->createQueryBuilder('s') - // ->andWhere('s.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } } diff --git a/app/src/Repository/UsersRepository.php b/app/src/Repository/UsersRepository.php index a151d1b..dfbe45b 100644 --- a/app/src/Repository/UsersRepository.php +++ b/app/src/Repository/UsersRepository.php @@ -20,29 +20,4 @@ class UsersRepository extends ServiceEntityRepository { parent::__construct($registry, Users::class); } - - // /** - // * @return Users[] Returns an array of Users 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): ?Users - // { - // return $this->createQueryBuilder('u') - // ->andWhere('u.exampleField = :val') - // ->setParameter('val', $value) - // ->getQuery() - // ->getOneOrNullResult() - // ; - // } } diff --git a/docker-compose.yml b/docker-compose.yml index dcc482e..caddeb2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.1' - services: db: image: postgres:16.2 @@ -44,4 +42,4 @@ services: networks: app: - driver: bridge \ No newline at end of file + driver: bridge -- GitLab From 7121b9d18cc8ff6e5081220fb96e958904fa9c3e Mon Sep 17 00:00:00 2001 From: AlexP Date: Thu, 9 May 2024 23:54:52 +0500 Subject: [PATCH 04/12] STA-960 | add dto and cast from entities --- app/src/DTO/RestaurantListDTO.php | 10 -- app/src/DTO/RestaurantListingElementDTO.php | 15 --- app/src/Dto/DtoCollection.php | 29 +++++ app/src/Dto/DtoInterface.php | 6 + app/src/Dto/ErrorDto.php | 12 ++ app/src/Dto/FileDto.php | 18 +++ app/src/Dto/KitchenTypeDto.php | 12 ++ app/src/Dto/NewsCategoryDto.php | 12 ++ app/src/Dto/NewsDetailElementDto.php | 19 ++++ app/src/Dto/NewsFilterVariants.php | 9 ++ app/src/Dto/NewsListDto.php | 13 +++ app/src/Dto/NewsListingElementDto.php | 19 ++++ app/src/Dto/PaginationDto.php | 10 ++ app/src/Dto/RestaurantDetailElementDto.php | 45 ++++++++ app/src/Dto/RestaurantFilterVariantsDto.php | 14 +++ app/src/Dto/RestaurantListDto.php | 15 +++ app/src/Dto/RestaurantListingElementDto.php | 20 ++++ app/src/Dto/RestaurantTypeDto.php | 12 ++ app/src/Dto/TagDto.php | 11 ++ app/src/Dto/ValidateErrorDto.php | 5 + app/src/Entity/File.php | 19 +++- app/src/Entity/Kitchens.php | 16 ++- app/src/Entity/News.php | 35 +++++- app/src/Entity/NewsCategories.php | 16 ++- app/src/Entity/NewsType.php | 1 + app/src/Entity/PrototypeDto.php | 11 ++ app/src/Entity/PrototypeElementDto.php | 14 +++ app/src/Entity/RestaurantTypes.php | 15 ++- app/src/Entity/Restaurants.php | 120 +++++++++++++++++++- 29 files changed, 522 insertions(+), 31 deletions(-) delete mode 100644 app/src/DTO/RestaurantListDTO.php delete mode 100644 app/src/DTO/RestaurantListingElementDTO.php create mode 100644 app/src/Dto/DtoCollection.php create mode 100644 app/src/Dto/DtoInterface.php create mode 100644 app/src/Dto/ErrorDto.php create mode 100644 app/src/Dto/FileDto.php create mode 100644 app/src/Dto/KitchenTypeDto.php create mode 100644 app/src/Dto/NewsCategoryDto.php create mode 100644 app/src/Dto/NewsDetailElementDto.php create mode 100644 app/src/Dto/NewsFilterVariants.php create mode 100644 app/src/Dto/NewsListDto.php create mode 100644 app/src/Dto/NewsListingElementDto.php create mode 100644 app/src/Dto/PaginationDto.php create mode 100644 app/src/Dto/RestaurantDetailElementDto.php create mode 100644 app/src/Dto/RestaurantFilterVariantsDto.php create mode 100644 app/src/Dto/RestaurantListDto.php create mode 100644 app/src/Dto/RestaurantListingElementDto.php create mode 100644 app/src/Dto/RestaurantTypeDto.php create mode 100644 app/src/Dto/TagDto.php create mode 100644 app/src/Dto/ValidateErrorDto.php create mode 100644 app/src/Entity/PrototypeDto.php create mode 100644 app/src/Entity/PrototypeElementDto.php diff --git a/app/src/DTO/RestaurantListDTO.php b/app/src/DTO/RestaurantListDTO.php deleted file mode 100644 index 2cd51f0..0000000 --- a/app/src/DTO/RestaurantListDTO.php +++ /dev/null @@ -1,10 +0,0 @@ -collectionType; + } + + /** Метод для сериализации коллекции в JSON */ + public function jsonSerialize(): array + { + return $this->data; + } +} diff --git a/app/src/Dto/DtoInterface.php b/app/src/Dto/DtoInterface.php new file mode 100644 index 0000000..fc79608 --- /dev/null +++ b/app/src/Dto/DtoInterface.php @@ -0,0 +1,6 @@ + */ + public DtoCollection $category; +} diff --git a/app/src/Dto/NewsListDto.php b/app/src/Dto/NewsListDto.php new file mode 100644 index 0000000..93928bf --- /dev/null +++ b/app/src/Dto/NewsListDto.php @@ -0,0 +1,13 @@ + */ + public DtoCollection $list; + + public NewsFilterVariants $filterVariants; +} diff --git a/app/src/Dto/NewsListingElementDto.php b/app/src/Dto/NewsListingElementDto.php new file mode 100644 index 0000000..ef41fea --- /dev/null +++ b/app/src/Dto/NewsListingElementDto.php @@ -0,0 +1,19 @@ +|null */ + public ?DtoCollection $kitchen; + + /** @var DtoCollection|null */ + public ?DtoCollection $phone; + + /** @var DtoCollection|null */ + public ?DtoCollection $email; + + /** @var DtoCollection|null */ + public ?DtoCollection $address; + + /** @var DtoCollection|null */ + public ?DtoCollection $tags; + + public ?string $site; + + /** @var FileDto|null Превью фото */ + public ?FileDto $image; + + /** @var DtoCollection|null */ + public ?DtoCollection $gallery; +} diff --git a/app/src/Dto/RestaurantFilterVariantsDto.php b/app/src/Dto/RestaurantFilterVariantsDto.php new file mode 100644 index 0000000..612cd5c --- /dev/null +++ b/app/src/Dto/RestaurantFilterVariantsDto.php @@ -0,0 +1,14 @@ + */ + public DtoCollection $type; + + /** @var DtoCollection */ + public DtoCollection $kitchen; +} diff --git a/app/src/Dto/RestaurantListDto.php b/app/src/Dto/RestaurantListDto.php new file mode 100644 index 0000000..87c6e61 --- /dev/null +++ b/app/src/Dto/RestaurantListDto.php @@ -0,0 +1,15 @@ + */ + public DtoCollection $list; + + public RestaurantFilterVariantsDto $filterVariants; +} diff --git a/app/src/Dto/RestaurantListingElementDto.php b/app/src/Dto/RestaurantListingElementDto.php new file mode 100644 index 0000000..3b575da --- /dev/null +++ b/app/src/Dto/RestaurantListingElementDto.php @@ -0,0 +1,20 @@ + */ + public DtoCollection $list; +} diff --git a/app/src/Dto/ValidateErrorDto.php b/app/src/Dto/ValidateErrorDto.php new file mode 100644 index 0000000..307b43e --- /dev/null +++ b/app/src/Dto/ValidateErrorDto.php @@ -0,0 +1,5 @@ +id = $this->getId(); + $dto->name = $this->getName(); + $dto->description = $this->getDescription(); + $dto->size = $this->getSize(); + $dto->type = $this->getType(); + $dto->url = $this->getUrl(); + + return $dto; + } } diff --git a/app/src/Entity/Kitchens.php b/app/src/Entity/Kitchens.php index c5dc4aa..d45bf0a 100644 --- a/app/src/Entity/Kitchens.php +++ b/app/src/Entity/Kitchens.php @@ -2,6 +2,8 @@ namespace App\Entity; +use App\Dto\DtoInterface; +use App\Dto\KitchenTypeDto; use App\Repository\KitchensRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -9,7 +11,7 @@ use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: KitchensRepository::class)] -class Kitchens +class Kitchens implements PrototypeDto { #[ORM\Id] #[ORM\Column(type: Types::GUID)] @@ -94,4 +96,16 @@ class Kitchens return $this; } + + /** @inheritDoc */ + public function getDto(): DtoInterface + { + $dto = new KitchenTypeDto(); + + $dto->id = $this->getId(); + $dto->name = $this->getName(); + $dto->code = $this->getCode(); + + return $dto; + } } diff --git a/app/src/Entity/News.php b/app/src/Entity/News.php index 5011c6d..e84bdc8 100644 --- a/app/src/Entity/News.php +++ b/app/src/Entity/News.php @@ -2,6 +2,9 @@ namespace App\Entity; +use App\Dto\DtoInterface; +use App\Dto\NewsDetailElementDto; +use App\Dto\NewsListingElementDto; use App\Repository\NewsRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -9,7 +12,7 @@ use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: NewsRepository::class)] -class News +class News implements PrototypeElementDto { #[ORM\Id] #[ORM\Column(type: Types::GUID)] @@ -242,4 +245,34 @@ class News return $this; } + + /** @inheritDoc */ + public function getDto(): DtoInterface + { + $entity = new NewsListingElementDto(); + + $entity->id = $this->getId(); + $entity->name = $this->getName(); + $entity->description = $this->getDetailText(); + $entity->image = $this->getPreviewImage()?->getDto(); + $entity->create_at = $this->getCreatedAt(); + $entity->detail_link = "api/v1/restaurants/" . $this->getId(); + + return $entity; + } + + /** @inheritDoc */ + public function getExtendedDto(): DtoInterface + { + $entity = new NewsDetailElementDto(); + + $entity->id = $this->getId(); + $entity->name = $this->getName(); + $entity->description = $this->getPreviewText(); + $entity->text = $this->getDetailText(); + $entity->image = $this->getPreviewImage()?->getDto(); + $entity->create_at = $this->getCreatedAt(); + + return $entity; + } } diff --git a/app/src/Entity/NewsCategories.php b/app/src/Entity/NewsCategories.php index fb41930..0f77fd1 100644 --- a/app/src/Entity/NewsCategories.php +++ b/app/src/Entity/NewsCategories.php @@ -2,6 +2,8 @@ namespace App\Entity; +use App\Dto\DtoInterface; +use App\Dto\NewsCategoryDto; use App\Repository\NewsCategoriesRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -9,7 +11,7 @@ use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: NewsCategoriesRepository::class)] -class NewsCategories +class NewsCategories implements PrototypeDto { #[ORM\Id] #[ORM\Column(type: Types::GUID)] @@ -94,4 +96,16 @@ class NewsCategories return $this; } + + /** @inheritDoc */ + public function getDto(): DtoInterface + { + $dto = new NewsCategoryDto(); + + $dto->id = $this->getId(); + $dto->name = $this->getName(); + $dto->code = $this->getCode(); + + return $dto; + } } diff --git a/app/src/Entity/NewsType.php b/app/src/Entity/NewsType.php index 493fff0..8331456 100644 --- a/app/src/Entity/NewsType.php +++ b/app/src/Entity/NewsType.php @@ -2,6 +2,7 @@ namespace App\Entity; +use App\Dto\DtoInterface; use App\Repository\NewsTypeRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; diff --git a/app/src/Entity/PrototypeDto.php b/app/src/Entity/PrototypeDto.php new file mode 100644 index 0000000..19c8822 --- /dev/null +++ b/app/src/Entity/PrototypeDto.php @@ -0,0 +1,11 @@ +id = $this->getId(); + $dto->name = $this->getName(); + $dto->code = $this->getCode(); + + return $dto; + } } diff --git a/app/src/Entity/Restaurants.php b/app/src/Entity/Restaurants.php index 8f3380d..ec816f7 100644 --- a/app/src/Entity/Restaurants.php +++ b/app/src/Entity/Restaurants.php @@ -2,14 +2,22 @@ namespace App\Entity; +use App\Dto\DtoCollection; +use App\Dto\DtoInterface; +use App\Dto\FileDto; +use App\Dto\KitchenTypeDto; +use App\Dto\RestaurantDetailElementDto; +use App\Dto\RestaurantListingElementDto; +use App\Dto\TagDto; use App\Repository\RestaurantsRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Ramsey\Collection\Collection as RamseyCollection; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: RestaurantsRepository::class)] -class Restaurants +class Restaurants implements PrototypeElementDto { #[ORM\Id] #[ORM\Column(type: Types::GUID)] @@ -392,4 +400,114 @@ class Restaurants return $this; } + + /** @inheritDoc */ + public function getDto(): DtoInterface + { + $dto = new RestaurantListingElementDto(); + + $dto->id = $this->getId(); + $dto->name = $this->getName(); + $dto->code = $this->getCode(); + $dto->type = $this->getType()->getDto(); + $dto->check = $this->getReceipt(); + $dto->image = $this->getPreviewImage()?->getDto(); + $dto->detail_link = 'api/v1/restaurants/' . $this->getId(); + + return $dto; + } + + /** @inheritDoc + * @throws \JsonException Если получен неправильный json с бд + */ + public function getExtendedDto(): DtoInterface + { + $dto = new RestaurantDetailElementDto(); + + $dto->id = $this->getId(); + $dto->name = $this->getName(); + $dto->code = $this->getCode(); + $dto->coordinates = $this->getCoordinates(); + $dto->type = $this->getType()->getDto(); + $dto->check = $this->getReceipt(); + $dto->check_info = $this->getReceiptInfo(); + + $dto->kitchen = new DtoCollection( + KitchenTypeDto::class, + $this->getKitchens() + ->map(function(Kitchens $kitchen) { + return $kitchen->getDto(); + }) + ->toArray() + ); + + $dto->phone = $this->decode($this->getPhone(), 'phone'); + $dto->email = $this->decode($this->getEmail(), 'email'); + $dto->address = $this->decode($this->getAddress(), 'address'); + $dto->tags = $this->decodeTags($this->getTags()); + $dto->site = $this->getSite(); + $dto->image = $this->getPreviewImage()?->getDto(); + $dto->gallery = new DtoCollection( + FileDto::class, + $this->getGallery() + ->map(function(File $file) { + return $file->getDto(); + }) + ->toArray() + ); + + return $dto; + } + + /** + * @throws \JsonException Если получен неправильный json с бд + * @return ?DtoCollection + */ + private function decode(?string $jsonString, string $name): ?DtoCollection + { + if ($jsonString === null) { + return null; + } + return new DtoCollection( + 'string|null', + json_decode( + $jsonString, + true, + 512, + JSON_THROW_ON_ERROR + )[$name] + ); + } + + private function decodeTags(?string $jsonString): ?DtoCollection + { + if ($jsonString === null) { + return null; + } + + $jsonCollection = new RamseyCollection( + 'array', + json_decode( + $jsonString, + true, + 512, + JSON_THROW_ON_ERROR + ) + ); + + return new DtoCollection( + TagDto::class, + $jsonCollection + ->map(function(array $tag) { + $tagDto = new TagDto(); + $tagDto->name = key($tag); + $tagDto->list = new DtoCollection( + 'string', + $tag + ); + return $tagDto; + }) + ->toArray() + ); + } } -- GitLab From 57862f7a972b9cb46d9de9208f3291ac65c8bf98 Mon Sep 17 00:00:00 2001 From: AlexP Date: Fri, 10 May 2024 06:11:49 +0500 Subject: [PATCH 05/12] STA-960 | controller&handle for restaurant listing --- app/src/Controller/AbstractController.php | 27 ++++++ app/src/Controller/RestaurantsController.php | 21 +++-- app/src/Dto/ErrorDto.php | 6 +- app/src/Dto/PaginationDto.php | 13 ++- app/src/Dto/RestaurantFilterVariantsDto.php | 14 ++- app/src/Dto/RestaurantListDto.php | 17 ++-- app/src/Dto/ValidateErrorDto.php | 13 ++- app/src/Repository/KitchensRepository.php | 2 +- .../KitchensRepositoryInterface.php | 11 +++ .../RestaurantTypeRepositoryInterface.php | 12 +++ .../Repository/RestaurantTypesRepository.php | 4 +- app/src/Repository/RestaurantsRepository.php | 28 +++--- .../RestaurantsRepositoryInterface.php | 14 +++ app/src/Request/AbstractRequest.php | 74 ++++++++++++++++ app/src/Request/RestaurantListingRequest.php | 35 ++++++++ app/src/Service/RestaurantListingService.php | 88 +++++++++++++++++++ app/src/Service/ServiceInterface.php | 11 +++ 17 files changed, 346 insertions(+), 44 deletions(-) create mode 100644 app/src/Controller/AbstractController.php create mode 100644 app/src/Repository/KitchensRepositoryInterface.php create mode 100644 app/src/Repository/RestaurantTypeRepositoryInterface.php create mode 100644 app/src/Repository/RestaurantsRepositoryInterface.php create mode 100644 app/src/Request/AbstractRequest.php create mode 100644 app/src/Request/RestaurantListingRequest.php create mode 100644 app/src/Service/RestaurantListingService.php create mode 100644 app/src/Service/ServiceInterface.php diff --git a/app/src/Controller/AbstractController.php b/app/src/Controller/AbstractController.php new file mode 100644 index 0000000..534d4dd --- /dev/null +++ b/app/src/Controller/AbstractController.php @@ -0,0 +1,27 @@ +service->serve($request)); +// } catch (Throwable $exception) { +// $error = new ErrorDto(); +// return new JsonResponse($error, $error->status); +// } + } +} diff --git a/app/src/Controller/RestaurantsController.php b/app/src/Controller/RestaurantsController.php index 52248bb..5840dbf 100644 --- a/app/src/Controller/RestaurantsController.php +++ b/app/src/Controller/RestaurantsController.php @@ -2,19 +2,24 @@ namespace App\Controller; -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; -use Symfony\Component\HttpFoundation\Response; +use App\Request\RestaurantListingRequest; +use App\Service\RestaurantListingService; +use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpKernel\Attribute\MapQueryParameter; use Symfony\Component\Routing\Attribute\Route; +#[Route('/api/v1/restaurants/')] class RestaurantsController extends AbstractController { - /*** - * Листинг ресторанов - * @return Response - */ - #[Route('/restaurants/', name: 'restaurants')] - public function restaurants(): Response + public function __construct(RestaurantListingService $service) { + parent::__construct($service); + } + /** Листинг ресторанов */ + #[Route(name: 'restaurants')] + public function index(RestaurantListingRequest $request): JsonResponse + { + return $this->build($request); } } diff --git a/app/src/Dto/ErrorDto.php b/app/src/Dto/ErrorDto.php index 8ac836d..e54f5cd 100644 --- a/app/src/Dto/ErrorDto.php +++ b/app/src/Dto/ErrorDto.php @@ -4,9 +4,9 @@ namespace App\Dto; class ErrorDto implements DtoInterface { - public string $status; + public string $status = '500'; - public string $message; + public string $message = 'Something went wrong'; - public string $code; + public string $code = '100'; } diff --git a/app/src/Dto/PaginationDto.php b/app/src/Dto/PaginationDto.php index 7bd5a5c..abfd5eb 100644 --- a/app/src/Dto/PaginationDto.php +++ b/app/src/Dto/PaginationDto.php @@ -6,5 +6,16 @@ class PaginationDto implements DtoInterface { public int $current_page = 1; public int $pages; - public int $page_size; + public int $page_size = 12; + + public function __construct(int $page, int $limit, int $total) + { + $this->pages = ceil($total/$limit); + + if (($page > 1) && ($page <= $this->pages)) { + $this->current_page = $page; + } + + $this->page_size = $limit; + } } diff --git a/app/src/Dto/RestaurantFilterVariantsDto.php b/app/src/Dto/RestaurantFilterVariantsDto.php index 612cd5c..8fd5a95 100644 --- a/app/src/Dto/RestaurantFilterVariantsDto.php +++ b/app/src/Dto/RestaurantFilterVariantsDto.php @@ -6,9 +6,15 @@ use Ramsey\Collection\Collection; class RestaurantFilterVariantsDto implements DtoInterface { - /** @var DtoCollection */ - public DtoCollection $type; + /** + * @param DtoCollection $type + * @param DtoCollection $kitchen + */ + public function __construct( + /** @var DtoCollection */ + public DtoCollection $type, - /** @var DtoCollection */ - public DtoCollection $kitchen; + /** @var DtoCollection */ + public DtoCollection $kitchen, + ) {} } diff --git a/app/src/Dto/RestaurantListDto.php b/app/src/Dto/RestaurantListDto.php index 87c6e61..fd500cb 100644 --- a/app/src/Dto/RestaurantListDto.php +++ b/app/src/Dto/RestaurantListDto.php @@ -2,14 +2,19 @@ namespace App\Dto; -use Ramsey\Collection\Collection; - class RestaurantListDto implements DtoInterface { - public PaginationDto $pagination; + /** + * @param PaginationDto $pagination + * @param DtoCollection $list + * @param RestaurantFilterVariantsDto $filterVariants + */ + public function __construct( + public PaginationDto $pagination, - /** @var DtoCollection */ - public DtoCollection $list; + /** @var DtoCollection */ + public DtoCollection $list, - public RestaurantFilterVariantsDto $filterVariants; + public RestaurantFilterVariantsDto $filterVariants, + ) {} } diff --git a/app/src/Dto/ValidateErrorDto.php b/app/src/Dto/ValidateErrorDto.php index 307b43e..c6331f6 100644 --- a/app/src/Dto/ValidateErrorDto.php +++ b/app/src/Dto/ValidateErrorDto.php @@ -2,4 +2,15 @@ namespace App\Dto; -class ValidateErrorDto extends ErrorDto {} +use Symfony\Component\Validator\ConstraintViolationInterface; + +class ValidateErrorDto extends ErrorDto +{ + public string $status = '422'; + + public function __construct(ConstraintViolationInterface $violation) + { + $this->message = $violation->getPropertyPath() . ':' . $violation->getMessage(); + $this->code = $violation->getCode(); + } +} diff --git a/app/src/Repository/KitchensRepository.php b/app/src/Repository/KitchensRepository.php index cd53ebd..39c355b 100644 --- a/app/src/Repository/KitchensRepository.php +++ b/app/src/Repository/KitchensRepository.php @@ -15,7 +15,7 @@ use Ramsey\Collection\Collection; * @method Kitchens[] findAll() * @method Kitchens[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ -class KitchensRepository extends ServiceEntityRepository +class KitchensRepository extends ServiceEntityRepository implements KitchensRepositoryInterface { public function __construct(ManagerRegistry $registry) { diff --git a/app/src/Repository/KitchensRepositoryInterface.php b/app/src/Repository/KitchensRepositoryInterface.php new file mode 100644 index 0000000..afba82d --- /dev/null +++ b/app/src/Repository/KitchensRepositoryInterface.php @@ -0,0 +1,11 @@ + */ + public function getAll(): Collection; +} diff --git a/app/src/Repository/RestaurantTypesRepository.php b/app/src/Repository/RestaurantTypesRepository.php index 3f5eb7d..cecf853 100644 --- a/app/src/Repository/RestaurantTypesRepository.php +++ b/app/src/Repository/RestaurantTypesRepository.php @@ -2,9 +2,7 @@ namespace App\Repository; -use App\Entity\Restaurants; use App\Entity\RestaurantTypes; -use Cassandra\FutureSession; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; use Ramsey\Collection\Collection; @@ -17,7 +15,7 @@ use Ramsey\Collection\Collection; * @method RestaurantTypes[] findAll() * @method RestaurantTypes[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ -class RestaurantTypesRepository extends ServiceEntityRepository +class RestaurantTypesRepository extends ServiceEntityRepository implements RestaurantTypeRepositoryInterface { public function __construct(ManagerRegistry $registry) { diff --git a/app/src/Repository/RestaurantsRepository.php b/app/src/Repository/RestaurantsRepository.php index b80d4af..188e4db 100644 --- a/app/src/Repository/RestaurantsRepository.php +++ b/app/src/Repository/RestaurantsRepository.php @@ -2,7 +2,6 @@ namespace App\Repository; -use App\DTO\CollectionDTO; use App\Entity\Restaurants; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\ORM\Query\Expr\Join; @@ -18,7 +17,7 @@ use Ramsey\Collection\Collection; * @method Restaurants[] findAll() * @method Restaurants[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ -class RestaurantsRepository extends ServiceEntityRepository +class RestaurantsRepository extends ServiceEntityRepository implements RestaurantsRepositoryInterface { public function __construct(ManagerRegistry $registry) { @@ -31,7 +30,7 @@ class RestaurantsRepository extends ServiceEntityRepository return new Collection( Restaurants::class, $query - ->orderBy('n.sort', 'ASC') + ->orderBy('r.sort', 'ASC') ->getQuery() ->getResult() ); @@ -39,9 +38,9 @@ class RestaurantsRepository extends ServiceEntityRepository protected function filterByKitchen(?string $kitchenId, QueryBuilder $query): QueryBuilder { - if ($kitchenId === null) { + if ($kitchenId !== null) { $query = $query - ->innerJoin('r.categories', 'k', Join::WITH, 'k.id = :kitchenId') + ->innerJoin('r.kitchens', 'k', Join::WITH, 'k.id = :kitchenId') ->setParameter('kitchenId', $kitchenId); } return $query; @@ -49,7 +48,7 @@ class RestaurantsRepository extends ServiceEntityRepository protected function filterByType(?string $typeId, QueryBuilder $query): QueryBuilder { - if ($typeId === null) { + if ($typeId !== null) { $query = $query ->where('r.type.id = :typeId') ->setParameter('typeId', $typeId); @@ -57,27 +56,22 @@ class RestaurantsRepository extends ServiceEntityRepository return $query; } - public function getCountWithFilters(?string $categoryId, ?string $typeId): int + public function getCountWithFilters(?string $kitchenId, ?string $typeId): int { $query = $this->createQueryBuilder('r'); - $query = $this->filterByKitchen($categoryId, $query); + $query = $this->filterByKitchen($kitchenId, $query); $query = $this->filterByType($typeId, $query); - return $query->select('COUNT(n.id)')->getQuery()->getSingleScalarResult(); + return $query->select('COUNT(r.id)')->getQuery()->getSingleScalarResult(); } /** @return Collection */ - public function findByFilters(?string $categoryId, ?string $typeId, int $limit): Collection + public function findByFilters(?string $kitchenId, ?string $typeId, int $limit, int $offset): Collection { $query = $this->createQueryBuilder('r'); - $query = $this->filterByKitchen($categoryId, $query); + $query = $this->filterByKitchen($kitchenId, $query); $query = $this->filterByType($typeId, $query); $query = $query->setMaxResults($limit); + $query = $query->setFirstResult($offset); return $this->toCollection($query); } - - /** @return Collection */ - public function getAll(): Collection - { - return $this->toCollection($this->createQueryBuilder('r')); - } } diff --git a/app/src/Repository/RestaurantsRepositoryInterface.php b/app/src/Repository/RestaurantsRepositoryInterface.php new file mode 100644 index 0000000..d2337ad --- /dev/null +++ b/app/src/Repository/RestaurantsRepositoryInterface.php @@ -0,0 +1,14 @@ + */ + public function findByFilters(?string $kitchenId, ?string $typeId, int $limit, int $offset): Collection; +} diff --git a/app/src/Request/AbstractRequest.php b/app/src/Request/AbstractRequest.php new file mode 100644 index 0000000..9ddccd5 --- /dev/null +++ b/app/src/Request/AbstractRequest.php @@ -0,0 +1,74 @@ +populate(); + + if (self::AUTO_VALIDATE) { + $this->validate(); + } + } + + /** + * Маппинг реквеста + * @return void + */ + protected function populate(): void + { + foreach ($this->getRequest()->toArray() as $property => $value) { + if (property_exists($this, $property)) { + $this->{$property} = $value; + } + } + } + + /** + * Валидация и выброкса ошибки при валидации + * @return void + */ + public function validate(): void + { + $errors = $this->validator->validate($this); + + + $messages = new DtoCollection(ValidateErrorDto::class); + + foreach ($errors as $error) { + $messages->add(new ValidateErrorDto($error)); + } + + if ($messages->count() > 0) { + $response = new JsonResponse($messages, 422); + $response->send(); + + throw new ValidatorException('Validation failed', $messages); + } + } + + /** + * Возвращает HttpFoundation реквест + * @return Request + */ + public function getRequest(): Request + { + return Request::createFromGlobals(); + } +} diff --git a/app/src/Request/RestaurantListingRequest.php b/app/src/Request/RestaurantListingRequest.php new file mode 100644 index 0000000..403a3a9 --- /dev/null +++ b/app/src/Request/RestaurantListingRequest.php @@ -0,0 +1,35 @@ +getRequest(); + foreach ($request->query->getIterator() as $property => $value) { + if (property_exists($this, $property)) { + $this->{$property} = $value; + } + } + } +} diff --git a/app/src/Service/RestaurantListingService.php b/app/src/Service/RestaurantListingService.php new file mode 100644 index 0000000..d24741a --- /dev/null +++ b/app/src/Service/RestaurantListingService.php @@ -0,0 +1,88 @@ +restaurants + ->getCountWithFilters( + $request->restaurant_type_id, + $request->kitchen_id + ); + + $pagination = new PaginationDto( + $request->page, + $request->limit, + $countOfRestaurants, + ); + + $offset = min($pagination->page_size, $countOfRestaurants) * ($pagination->current_page - 1); + + $list = new DtoCollection( + RestaurantListingElementDto::class, + $this + ->restaurants + ->findByFilters( + $request + ->restaurant_type_id, + $request->kitchen_id, + $request->limit, + $offset, + ) + ->map(function (Restaurants $restaurant) { + return $restaurant->getDto(); + }) + ->toArray() + ); + + $filters = new RestaurantFilterVariantsDto( + new DtoCollection( + RestaurantTypeDto::class, + $this->types->getAll() + ->map(function(RestaurantTypes $types) { + return $types->getDto(); + }) + ->toArray() + ), + new DtoCollection( + KitchenTypeDto::class, + $this->kitchens->getAll() + ->map(function(Kitchens $kitchen) { + return $kitchen->getDto(); + }) + ->toArray() + ), + ); + + return new RestaurantListDto( + $pagination, + $list, + $filters, + ); + } +} diff --git a/app/src/Service/ServiceInterface.php b/app/src/Service/ServiceInterface.php new file mode 100644 index 0000000..f52194d --- /dev/null +++ b/app/src/Service/ServiceInterface.php @@ -0,0 +1,11 @@ + Date: Fri, 10 May 2024 07:48:16 +0500 Subject: [PATCH 06/12] STA-960 | controller&handle for request detail info --- app/src/Controller/AbstractController.php | 23 ++++++++++---- .../Controller/RestaurantDetailController.php | 24 +++++++++++++++ app/src/Dto/PaginationDto.php | 6 ++-- app/src/Entity/Restaurants.php | 12 ++++---- app/src/Error/AbstractError.php | 10 +++++++ app/src/Error/NotFoundError.php | 16 ++++++++++ .../RestaurantsRepositoryInterface.php | 6 ++++ app/src/Request/RestaurantDetailRequest.php | 25 ++++++++++++++++ app/src/Service/RestaurantDetailService.php | 30 +++++++++++++++++++ 9 files changed, 137 insertions(+), 15 deletions(-) create mode 100644 app/src/Controller/RestaurantDetailController.php create mode 100644 app/src/Error/AbstractError.php create mode 100644 app/src/Error/NotFoundError.php create mode 100644 app/src/Request/RestaurantDetailRequest.php create mode 100644 app/src/Service/RestaurantDetailService.php diff --git a/app/src/Controller/AbstractController.php b/app/src/Controller/AbstractController.php index 534d4dd..82b5969 100644 --- a/app/src/Controller/AbstractController.php +++ b/app/src/Controller/AbstractController.php @@ -3,13 +3,14 @@ namespace App\Controller; use App\Dto\ErrorDto; +use App\Error\AbstractError; use App\Request\AbstractRequest; use App\Service\ServiceInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Throwable; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as BundleController; -class AbstractController extends BundleController +abstract class AbstractController extends BundleController { public function __construct( private readonly ServiceInterface $service @@ -17,11 +18,21 @@ class AbstractController extends BundleController protected function build(AbstractRequest $request): JsonResponse { -// try { + try { return new JsonResponse($this->service->serve($request)); -// } catch (Throwable $exception) { -// $error = new ErrorDto(); -// return new JsonResponse($error, $error->status); -// } + + } catch (AbstractError $error) { + $errorDto = new ErrorDto(); + + $errorDto->message = $error->message; + $errorDto->code = $error->code; + $errorDto->status = $error->status; + + return new JsonResponse($errorDto, $error->status); + + } catch (Throwable $exception) { + $error = new ErrorDto(); + return new JsonResponse($error, $error->status); + } } } diff --git a/app/src/Controller/RestaurantDetailController.php b/app/src/Controller/RestaurantDetailController.php new file mode 100644 index 0000000..b297bac --- /dev/null +++ b/app/src/Controller/RestaurantDetailController.php @@ -0,0 +1,24 @@ +build($request); + } +} \ No newline at end of file diff --git a/app/src/Dto/PaginationDto.php b/app/src/Dto/PaginationDto.php index abfd5eb..a784dfd 100644 --- a/app/src/Dto/PaginationDto.php +++ b/app/src/Dto/PaginationDto.php @@ -10,12 +10,12 @@ class PaginationDto implements DtoInterface public function __construct(int $page, int $limit, int $total) { - $this->pages = ceil($total/$limit); + $this->page_size = $limit > 0 ? $limit : 12; + + $this->pages = ceil($total / $this->page_size); if (($page > 1) && ($page <= $this->pages)) { $this->current_page = $page; } - - $this->page_size = $limit; } } diff --git a/app/src/Entity/Restaurants.php b/app/src/Entity/Restaurants.php index ec816f7..a6208fe 100644 --- a/app/src/Entity/Restaurants.php +++ b/app/src/Entity/Restaurants.php @@ -441,9 +441,9 @@ class Restaurants implements PrototypeElementDto ->toArray() ); - $dto->phone = $this->decode($this->getPhone(), 'phone'); - $dto->email = $this->decode($this->getEmail(), 'email'); - $dto->address = $this->decode($this->getAddress(), 'address'); + $dto->phone = $this->decode($this->getPhone()); + $dto->email = $this->decode($this->getEmail()); + $dto->address = $this->decode($this->getAddress()); $dto->tags = $this->decodeTags($this->getTags()); $dto->site = $this->getSite(); $dto->image = $this->getPreviewImage()?->getDto(); @@ -463,19 +463,19 @@ class Restaurants implements PrototypeElementDto * @throws \JsonException Если получен неправильный json с бд * @return ?DtoCollection */ - private function decode(?string $jsonString, string $name): ?DtoCollection + private function decode(?string $jsonString): ?DtoCollection { if ($jsonString === null) { return null; } return new DtoCollection( - 'string|null', + 'string', json_decode( $jsonString, true, 512, JSON_THROW_ON_ERROR - )[$name] + ) ); } diff --git a/app/src/Error/AbstractError.php b/app/src/Error/AbstractError.php new file mode 100644 index 0000000..0827a2e --- /dev/null +++ b/app/src/Error/AbstractError.php @@ -0,0 +1,10 @@ +message = $message . ' ' . $this->message; + parent::__construct($this->message); + } +} diff --git a/app/src/Repository/RestaurantsRepositoryInterface.php b/app/src/Repository/RestaurantsRepositoryInterface.php index d2337ad..e5e2f2f 100644 --- a/app/src/Repository/RestaurantsRepositoryInterface.php +++ b/app/src/Repository/RestaurantsRepositoryInterface.php @@ -3,8 +3,14 @@ namespace App\Repository; use App\Entity\Restaurants; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Ramsey\Collection\Collection; +/** + * @extends ServiceEntityRepository + * + * @method Restaurants|null find($id, $lockMode = null, $lockVersion = null) + */ interface RestaurantsRepositoryInterface { public function getCountWithFilters(?string $kitchenId, string $typeId): int; diff --git a/app/src/Request/RestaurantDetailRequest.php b/app/src/Request/RestaurantDetailRequest.php new file mode 100644 index 0000000..05b07e0 --- /dev/null +++ b/app/src/Request/RestaurantDetailRequest.php @@ -0,0 +1,25 @@ +getRequest()->getUri(); + $index = strrpos($requestUrl, "/") + 1; + + $restaurantId = substr($requestUrl, $index); + + if (property_exists($this, "restaurantId")) { + $this->{"restaurantId"} = $restaurantId; + } + } +} diff --git a/app/src/Service/RestaurantDetailService.php b/app/src/Service/RestaurantDetailService.php new file mode 100644 index 0000000..5cc7111 --- /dev/null +++ b/app/src/Service/RestaurantDetailService.php @@ -0,0 +1,30 @@ +restaurants->find($request->restaurantId); + + if ($restaurant === null) { + throw new NotFoundError('Restaurant'); + } + + return $restaurant->getExtendedDto(); + } +} -- GitLab From a78e29e96376958bb64f180a10c1bf7622c35dd4 Mon Sep 17 00:00:00 2001 From: AlexP Date: Sun, 12 May 2024 21:58:33 +0500 Subject: [PATCH 07/12] STA-960 | make all news controllers&handles & fix some restauranst issues --- app/src/Controller/AbstractController.php | 30 ++++---- app/src/Controller/NewsController.php | 23 ++++++ app/src/Controller/NewsDetailController.php | 23 ++++++ app/src/Controller/NewsMainNewsController.php | 23 ++++++ app/src/Controller/NewsSearchController.php | 23 ++++++ .../Controller/RestaurantDetailController.php | 9 ++- app/src/Controller/RestaurantsController.php | 1 - app/src/Dto/NewsFilterVariants.php | 10 ++- app/src/Dto/NewsListDto.php | 15 ++-- app/src/Entity/News.php | 4 +- .../Repository/NewsCategoriesRepository.php | 2 +- .../NewsCategoriesRepositoryInterface.php | 12 ++++ app/src/Repository/NewsRepository.php | 58 ++++++++------- .../Repository/NewsRepositoryInterface.php | 20 ++++++ ...antDetailRequest.php => DetailRequest.php} | 10 +-- app/src/Request/EmptyRequest.php | 8 +++ app/src/Request/NewsListingRequest.php | 30 ++++++++ app/src/Service/NewsDetailService.php | 26 +++++++ app/src/Service/NewsListingService.php | 71 +++++++++++++++++++ app/src/Service/NewsMainNewsService.php | 19 +++++ app/src/Service/NewsSearchService.php | 18 +++++ app/src/Service/RestaurantDetailService.php | 2 +- 22 files changed, 377 insertions(+), 60 deletions(-) create mode 100644 app/src/Controller/NewsController.php create mode 100644 app/src/Controller/NewsDetailController.php create mode 100644 app/src/Controller/NewsMainNewsController.php create mode 100644 app/src/Controller/NewsSearchController.php create mode 100644 app/src/Repository/NewsCategoriesRepositoryInterface.php create mode 100644 app/src/Repository/NewsRepositoryInterface.php rename app/src/Request/{RestaurantDetailRequest.php => DetailRequest.php} (57%) create mode 100644 app/src/Request/EmptyRequest.php create mode 100644 app/src/Request/NewsListingRequest.php create mode 100644 app/src/Service/NewsDetailService.php create mode 100644 app/src/Service/NewsListingService.php create mode 100644 app/src/Service/NewsMainNewsService.php create mode 100644 app/src/Service/NewsSearchService.php diff --git a/app/src/Controller/AbstractController.php b/app/src/Controller/AbstractController.php index 82b5969..61d805e 100644 --- a/app/src/Controller/AbstractController.php +++ b/app/src/Controller/AbstractController.php @@ -18,21 +18,21 @@ abstract class AbstractController extends BundleController protected function build(AbstractRequest $request): JsonResponse { - try { +// try { return new JsonResponse($this->service->serve($request)); - - } catch (AbstractError $error) { - $errorDto = new ErrorDto(); - - $errorDto->message = $error->message; - $errorDto->code = $error->code; - $errorDto->status = $error->status; - - return new JsonResponse($errorDto, $error->status); - - } catch (Throwable $exception) { - $error = new ErrorDto(); - return new JsonResponse($error, $error->status); - } +// +// } catch (AbstractError $error) { +// $errorDto = new ErrorDto(); +// +// $errorDto->message = $error->message; +// $errorDto->code = $error->code; +// $errorDto->status = $error->status; +// +// return new JsonResponse($errorDto, $error->status); +// +// } catch (Throwable $exception) { +// $error = new ErrorDto(); +// return new JsonResponse($error, $error->status); +// } } } diff --git a/app/src/Controller/NewsController.php b/app/src/Controller/NewsController.php new file mode 100644 index 0000000..b321457 --- /dev/null +++ b/app/src/Controller/NewsController.php @@ -0,0 +1,23 @@ +build($request); + } +} diff --git a/app/src/Controller/NewsDetailController.php b/app/src/Controller/NewsDetailController.php new file mode 100644 index 0000000..e236d8c --- /dev/null +++ b/app/src/Controller/NewsDetailController.php @@ -0,0 +1,23 @@ +build($request); + } +} diff --git a/app/src/Controller/NewsMainNewsController.php b/app/src/Controller/NewsMainNewsController.php new file mode 100644 index 0000000..2595dfe --- /dev/null +++ b/app/src/Controller/NewsMainNewsController.php @@ -0,0 +1,23 @@ +build($request); + } +} \ No newline at end of file diff --git a/app/src/Controller/NewsSearchController.php b/app/src/Controller/NewsSearchController.php new file mode 100644 index 0000000..a6b0fa6 --- /dev/null +++ b/app/src/Controller/NewsSearchController.php @@ -0,0 +1,23 @@ +build($request); + } +} \ No newline at end of file diff --git a/app/src/Controller/RestaurantDetailController.php b/app/src/Controller/RestaurantDetailController.php index b297bac..8b547ae 100644 --- a/app/src/Controller/RestaurantDetailController.php +++ b/app/src/Controller/RestaurantDetailController.php @@ -2,7 +2,7 @@ namespace App\Controller; -use App\Request\RestaurantDetailRequest; +use App\Request\DetailRequest; use App\Service\RestaurantDetailService; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Attribute\Route; @@ -15,10 +15,9 @@ class RestaurantDetailController extends AbstractController parent::__construct($service); } - /** Листинг ресторанов */ - #[Route('{restaurantId}', name: 'restaurant')] - public function index(RestaurantDetailRequest $request): JsonResponse + #[Route('{detailId}', name: 'restaurant')] + public function index(DetailRequest $request): JsonResponse { return $this->build($request); } -} \ No newline at end of file +} diff --git a/app/src/Controller/RestaurantsController.php b/app/src/Controller/RestaurantsController.php index 5840dbf..3be1890 100644 --- a/app/src/Controller/RestaurantsController.php +++ b/app/src/Controller/RestaurantsController.php @@ -5,7 +5,6 @@ namespace App\Controller; use App\Request\RestaurantListingRequest; use App\Service\RestaurantListingService; use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpKernel\Attribute\MapQueryParameter; use Symfony\Component\Routing\Attribute\Route; #[Route('/api/v1/restaurants/')] diff --git a/app/src/Dto/NewsFilterVariants.php b/app/src/Dto/NewsFilterVariants.php index b1d55e4..2a48144 100644 --- a/app/src/Dto/NewsFilterVariants.php +++ b/app/src/Dto/NewsFilterVariants.php @@ -4,6 +4,12 @@ namespace App\Dto; class NewsFilterVariants implements DtoInterface { - /** @var DtoCollection */ - public DtoCollection $category; + + /** + * @param DtoCollection $category + */ + public function __construct( + /** @var DtoCollection */ + public DtoCollection $category, + ) {} } diff --git a/app/src/Dto/NewsListDto.php b/app/src/Dto/NewsListDto.php index 93928bf..ae4971e 100644 --- a/app/src/Dto/NewsListDto.php +++ b/app/src/Dto/NewsListDto.php @@ -4,10 +4,17 @@ namespace App\Dto; class NewsListDto implements DtoInterface { - public PaginationDto $pagination; + /** + * @param PaginationDto $pagination + * @param DtoCollection $list + * @param NewsFilterVariants $filterVariants + */ + public function __construct( + public PaginationDto $pagination, - /** @var DtoCollection */ - public DtoCollection $list; + /** @var DtoCollection */ + public DtoCollection $list, - public NewsFilterVariants $filterVariants; + public NewsFilterVariants $filterVariants, + ) {} } diff --git a/app/src/Entity/News.php b/app/src/Entity/News.php index e84bdc8..53a1595 100644 --- a/app/src/Entity/News.php +++ b/app/src/Entity/News.php @@ -255,7 +255,7 @@ class News implements PrototypeElementDto $entity->name = $this->getName(); $entity->description = $this->getDetailText(); $entity->image = $this->getPreviewImage()?->getDto(); - $entity->create_at = $this->getCreatedAt(); + $entity->create_at = $this->getCreatedAt()->format('Y-m-d H:i:s'); $entity->detail_link = "api/v1/restaurants/" . $this->getId(); return $entity; @@ -271,7 +271,7 @@ class News implements PrototypeElementDto $entity->description = $this->getPreviewText(); $entity->text = $this->getDetailText(); $entity->image = $this->getPreviewImage()?->getDto(); - $entity->create_at = $this->getCreatedAt(); + $entity->create_at = $this->getCreatedAt()->format('Y-m-d H:i:s'); return $entity; } diff --git a/app/src/Repository/NewsCategoriesRepository.php b/app/src/Repository/NewsCategoriesRepository.php index 215cbe3..fb73900 100644 --- a/app/src/Repository/NewsCategoriesRepository.php +++ b/app/src/Repository/NewsCategoriesRepository.php @@ -15,7 +15,7 @@ use Ramsey\Collection\Collection; * @method NewsCategories[] findAll() * @method NewsCategories[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ -class NewsCategoriesRepository extends ServiceEntityRepository +class NewsCategoriesRepository extends ServiceEntityRepository implements NewsCategoriesRepositoryInterface { public function __construct(ManagerRegistry $registry) { diff --git a/app/src/Repository/NewsCategoriesRepositoryInterface.php b/app/src/Repository/NewsCategoriesRepositoryInterface.php new file mode 100644 index 0000000..a3c7cfe --- /dev/null +++ b/app/src/Repository/NewsCategoriesRepositoryInterface.php @@ -0,0 +1,12 @@ + */ + public function getAll(): Collection; +} diff --git a/app/src/Repository/NewsRepository.php b/app/src/Repository/NewsRepository.php index b5031de..44e4ef4 100644 --- a/app/src/Repository/NewsRepository.php +++ b/app/src/Repository/NewsRepository.php @@ -18,36 +18,20 @@ use Ramsey\Collection\Collection; * @method News[] findAll() * @method News[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ -class NewsRepository extends ServiceEntityRepository +class NewsRepository extends ServiceEntityRepository implements NewsRepositoryInterface { public function __construct(ManagerRegistry $registry) { parent::__construct($registry, News::class); } - /** - * @param QueryBuilder $query - * @return Collection - */ - protected function toCollection(QueryBuilder $query): Collection - { - return new Collection( - News::class, - $query - ->orderBy('n.sort', 'ASC') - ->getQuery() - ->getResult() - ); - } - - protected function getByFilters(?string $categoryId, QueryBuilder $query): QueryBuilder + public function getMainNews(): News { - if ($categoryId !== null) { - $query = $query - ->innerJoin('n.categories', 'c', Join::WITH, 'c.id = :typeId') - ->setParameter('typeId', $categoryId); - } - return $query; + return $this->createQueryBuilder('n') + ->andWhere('n.mainPageRender = true') + ->setMaxResults(1) + ->getQuery() + ->getResult()[0]; } public function getCountWithFilters(?string $categoryId): int @@ -58,11 +42,12 @@ class NewsRepository extends ServiceEntityRepository } /** @return Collection */ - public function findByFilters(?string $categoryId, int $limit): Collection + public function findByFilters(?string $categoryId, int $limit, int $offset): Collection { $query = $this->createQueryBuilder('n'); $query = $this->getByFilters($categoryId, $query); $query = $query->setMaxResults($limit); + $query = $query->setFirstResult($offset); return $this->toCollection($query); } @@ -80,4 +65,29 @@ class NewsRepository extends ServiceEntityRepository ->getQuery() ->getResult()[0]; } + + /** + * @param QueryBuilder $query + * @return Collection + */ + protected function toCollection(QueryBuilder $query): Collection + { + return new Collection( + News::class, + $query + ->orderBy('n.sort', 'ASC') + ->getQuery() + ->getResult() + ); + } + + protected function getByFilters(?string $categoryId, QueryBuilder $query): QueryBuilder + { + if ($categoryId !== null) { + $query = $query + ->innerJoin('n.categories', 'c', Join::WITH, 'c.id = :typeId') + ->setParameter('typeId', $categoryId); + } + return $query; + } } diff --git a/app/src/Repository/NewsRepositoryInterface.php b/app/src/Repository/NewsRepositoryInterface.php new file mode 100644 index 0000000..b67c875 --- /dev/null +++ b/app/src/Repository/NewsRepositoryInterface.php @@ -0,0 +1,20 @@ + + * + * @method News|null find($id, $lockMode = null, $lockVersion = null) + */ +interface NewsRepositoryInterface +{ + public function getMainNews(): News; + public function getCountWithFilters(?string $categoryId): int; + + /** @return Collection */ + public function findByFilters(?string $categoryId, int $limit, int $offset): Collection; +} diff --git a/app/src/Request/RestaurantDetailRequest.php b/app/src/Request/DetailRequest.php similarity index 57% rename from app/src/Request/RestaurantDetailRequest.php rename to app/src/Request/DetailRequest.php index 05b07e0..ac690b8 100644 --- a/app/src/Request/RestaurantDetailRequest.php +++ b/app/src/Request/DetailRequest.php @@ -5,21 +5,21 @@ namespace App\Request; use Symfony\Component\Validator\Constraints\Uuid; use Symfony\Contracts\Service\Attribute\Required; -class RestaurantDetailRequest extends AbstractRequest +class DetailRequest extends AbstractRequest { #[Required] #[Uuid] - public $restaurantId; + public $detailId; protected function populate(): void { $requestUrl = $this->getRequest()->getUri(); $index = strrpos($requestUrl, "/") + 1; - $restaurantId = substr($requestUrl, $index); + $detailId = substr($requestUrl, $index); - if (property_exists($this, "restaurantId")) { - $this->{"restaurantId"} = $restaurantId; + if (property_exists($this, "detailId")) { + $this->{"detailId"} = $detailId; } } } diff --git a/app/src/Request/EmptyRequest.php b/app/src/Request/EmptyRequest.php new file mode 100644 index 0000000..9ea7ad0 --- /dev/null +++ b/app/src/Request/EmptyRequest.php @@ -0,0 +1,8 @@ +getRequest(); + foreach ($request->query->getIterator() as $property => $value) { + if (property_exists($this, $property)) { + $this->{$property} = $value; + } + } + } +} \ No newline at end of file diff --git a/app/src/Service/NewsDetailService.php b/app/src/Service/NewsDetailService.php new file mode 100644 index 0000000..19c394d --- /dev/null +++ b/app/src/Service/NewsDetailService.php @@ -0,0 +1,26 @@ +news->find($request->detailId); + + if ($news === null) { + throw new NotFoundError('News'); + } + + return $news->getExtendedDto(); + } +} diff --git a/app/src/Service/NewsListingService.php b/app/src/Service/NewsListingService.php new file mode 100644 index 0000000..6d75636 --- /dev/null +++ b/app/src/Service/NewsListingService.php @@ -0,0 +1,71 @@ +news-> + getCountWithFilters($request->news_category); + + $pagination = new PaginationDto( + $request->page, + $request->limit, + $countOfRestaurants + ); + + $offset = min($pagination->page_size, $countOfRestaurants) * ($pagination->current_page - 1); + + $list = new DtoCollection( + NewsListingElementDto::class, + $this + ->news + ->findByFilters( + $request->news_category, + $request->limit, $offset + ) + ->map(function(News $news) { + return $news->getDto(); + }) + ->toArray() + ); + + $filters = new NewsFilterVariants( + new DtoCollection( + NewsCategoryDto::class, + $this->newsCategories->getAll() + ->map(function(NewsCategories $category) { + return $category->getDto(); + }) + ->toArray() + ), + ); + + return new NewsListDto( + $pagination, + $list, + $filters + ); + } +} diff --git a/app/src/Service/NewsMainNewsService.php b/app/src/Service/NewsMainNewsService.php new file mode 100644 index 0000000..16037d3 --- /dev/null +++ b/app/src/Service/NewsMainNewsService.php @@ -0,0 +1,19 @@ +news->getMainNews()->getDto(); + } +} diff --git a/app/src/Service/NewsSearchService.php b/app/src/Service/NewsSearchService.php new file mode 100644 index 0000000..ff9713e --- /dev/null +++ b/app/src/Service/NewsSearchService.php @@ -0,0 +1,18 @@ +news->getMainNews()->getExtendedDto(); + } +} diff --git a/app/src/Service/RestaurantDetailService.php b/app/src/Service/RestaurantDetailService.php index 5cc7111..2547cfa 100644 --- a/app/src/Service/RestaurantDetailService.php +++ b/app/src/Service/RestaurantDetailService.php @@ -19,7 +19,7 @@ class RestaurantDetailService implements ServiceInterface */ public function serve(AbstractRequest $request): DtoInterface { - $restaurant = $this->restaurants->find($request->restaurantId); + $restaurant = $this->restaurants->find($request->detailId); if ($restaurant === null) { throw new NotFoundError('Restaurant'); -- GitLab From a0a2dda6c69f1bc9dd46c92212a4d9c1ec8857f7 Mon Sep 17 00:00:00 2001 From: AlexP Date: Sun, 12 May 2024 23:16:47 +0500 Subject: [PATCH 08/12] STA-960 | refactor abstract factory pattern --- .../{AbstractController.php => Handle.php} | 14 ++----- app/src/Controller/NewsController.php | 40 +++++++++++++++---- app/src/Controller/NewsDetailController.php | 23 ----------- app/src/Controller/NewsMainNewsController.php | 23 ----------- app/src/Controller/NewsSearchController.php | 23 ----------- .../Controller/RestaurantDetailController.php | 23 ----------- app/src/Controller/RestaurantsController.php | 24 +++++++---- app/src/Request/EmptyRequest.php | 2 + 8 files changed, 55 insertions(+), 117 deletions(-) rename app/src/Controller/{AbstractController.php => Handle.php} (59%) delete mode 100644 app/src/Controller/NewsDetailController.php delete mode 100644 app/src/Controller/NewsMainNewsController.php delete mode 100644 app/src/Controller/NewsSearchController.php delete mode 100644 app/src/Controller/RestaurantDetailController.php diff --git a/app/src/Controller/AbstractController.php b/app/src/Controller/Handle.php similarity index 59% rename from app/src/Controller/AbstractController.php rename to app/src/Controller/Handle.php index 61d805e..97f6715 100644 --- a/app/src/Controller/AbstractController.php +++ b/app/src/Controller/Handle.php @@ -2,24 +2,18 @@ namespace App\Controller; -use App\Dto\ErrorDto; -use App\Error\AbstractError; use App\Request\AbstractRequest; use App\Service\ServiceInterface; use Symfony\Component\HttpFoundation\JsonResponse; -use Throwable; -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as BundleController; -abstract class AbstractController extends BundleController +class Handle { - public function __construct( - private readonly ServiceInterface $service - ) {} + public function __construct(private readonly ServiceInterface $service) {} - protected function build(AbstractRequest $request): JsonResponse + public function handle(AbstractRequest $request): JsonResponse { // try { - return new JsonResponse($this->service->serve($request)); + return new JsonResponse($this->service->serve($request)); // // } catch (AbstractError $error) { // $errorDto = new ErrorDto(); diff --git a/app/src/Controller/NewsController.php b/app/src/Controller/NewsController.php index b321457..90c6a8c 100644 --- a/app/src/Controller/NewsController.php +++ b/app/src/Controller/NewsController.php @@ -2,22 +2,48 @@ namespace App\Controller; +use App\Request\DetailRequest; +use App\Request\EmptyRequest; use App\Request\NewsListingRequest; +use App\Service\NewsDetailService; use App\Service\NewsListingService; +use App\Service\NewsMainNewsService; +use App\Service\NewsSearchService; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as BundleController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Attribute\Route; -#[Route('api/v1/news')] -class NewsController extends AbstractController +#[Route('/api/v1/news')] +class NewsController extends BundleController { - public function __construct(NewsListingService $service) + public function __construct( + private readonly NewsDetailService $detailService, + private readonly NewsListingService $listingService, + private readonly NewsMainNewsService $mainNewsService, + private readonly NewsSearchService $searchService, + ) {} + + #[Route('/', name: 'news', methods: ['GET'])] + public function news(NewsListingRequest $request): JsonResponse + { + return (new Handle($this->listingService))->handle($request); + } + + #[Route('/mainNews', name: 'mainNews', methods: ['GET'])] + public function mainNews(EmptyRequest $request): JsonResponse + { + return (new Handle($this->mainNewsService))->handle($request); + } + + #[Route('/search', name: 'searchNews', methods: ['GET'])] + public function search(EmptyRequest $request): JsonResponse { - parent::__construct($service); + return (new Handle($this->searchService))->handle($request); } - #[Route('/', name: 'news')] - public function index(NewsListingRequest $request): JsonResponse + #[Route('/{detailId}', name: 'oneNews', methods: ['GET'])] + public function oneNews(DetailRequest $request): JsonResponse { - return $this->build($request); + return (new Handle($this->detailService))->handle($request); } } diff --git a/app/src/Controller/NewsDetailController.php b/app/src/Controller/NewsDetailController.php deleted file mode 100644 index e236d8c..0000000 --- a/app/src/Controller/NewsDetailController.php +++ /dev/null @@ -1,23 +0,0 @@ -build($request); - } -} diff --git a/app/src/Controller/NewsMainNewsController.php b/app/src/Controller/NewsMainNewsController.php deleted file mode 100644 index 2595dfe..0000000 --- a/app/src/Controller/NewsMainNewsController.php +++ /dev/null @@ -1,23 +0,0 @@ -build($request); - } -} \ No newline at end of file diff --git a/app/src/Controller/NewsSearchController.php b/app/src/Controller/NewsSearchController.php deleted file mode 100644 index a6b0fa6..0000000 --- a/app/src/Controller/NewsSearchController.php +++ /dev/null @@ -1,23 +0,0 @@ -build($request); - } -} \ No newline at end of file diff --git a/app/src/Controller/RestaurantDetailController.php b/app/src/Controller/RestaurantDetailController.php deleted file mode 100644 index 8b547ae..0000000 --- a/app/src/Controller/RestaurantDetailController.php +++ /dev/null @@ -1,23 +0,0 @@ -build($request); - } -} diff --git a/app/src/Controller/RestaurantsController.php b/app/src/Controller/RestaurantsController.php index 3be1890..b268f83 100644 --- a/app/src/Controller/RestaurantsController.php +++ b/app/src/Controller/RestaurantsController.php @@ -2,23 +2,31 @@ namespace App\Controller; +use App\Request\DetailRequest; use App\Request\RestaurantListingRequest; +use App\Service\RestaurantDetailService; use App\Service\RestaurantListingService; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as BundleController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Attribute\Route; -#[Route('/api/v1/restaurants/')] -class RestaurantsController extends AbstractController +#[Route('/api/v1/restaurants')] +class RestaurantsController extends BundleController { - public function __construct(RestaurantListingService $service) + public function __construct( + private readonly RestaurantListingService $listingService, + private readonly RestaurantDetailService $detailService, + ) {} + + #[Route('/', name: 'restaurants', methods: ['GET'])] + public function restaurants(RestaurantListingRequest $request): JsonResponse { - parent::__construct($service); + return (new Handle($this->listingService))->handle($request); } - /** Листинг ресторанов */ - #[Route(name: 'restaurants')] - public function index(RestaurantListingRequest $request): JsonResponse + #[Route('/{detailId}', name: 'restaurant', methods: ['GET'])] + public function restaurant(DetailRequest $request): JsonResponse { - return $this->build($request); + return (new Handle($this->detailService))->handle($request); } } diff --git a/app/src/Request/EmptyRequest.php b/app/src/Request/EmptyRequest.php index 9ea7ad0..28809e1 100644 --- a/app/src/Request/EmptyRequest.php +++ b/app/src/Request/EmptyRequest.php @@ -5,4 +5,6 @@ namespace App\Request; class EmptyRequest extends AbstractRequest { protected const AUTO_VALIDATE = false; + + protected function populate(): void {} } \ No newline at end of file -- GitLab From f19133255d13a35a8523bf1ad42233be4d1fd64d Mon Sep 17 00:00:00 2001 From: AlexP Date: Mon, 13 May 2024 00:10:37 +0500 Subject: [PATCH 09/12] STA-950 | hotfix restaurants tags --- app/src/Dto/TagDto.php | 12 +++++++++--- app/src/Entity/Restaurants.php | 22 ++++++++-------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/app/src/Dto/TagDto.php b/app/src/Dto/TagDto.php index 42dee2b..58733a0 100644 --- a/app/src/Dto/TagDto.php +++ b/app/src/Dto/TagDto.php @@ -4,8 +4,14 @@ namespace App\Dto; class TagDto implements DtoInterface { - public string $name; + /** + * @param string $name + * @param DtoCollection $list + */ + public function __construct( + public string $name, - /** @var DtoCollection */ - public DtoCollection $list; + /** @var DtoCollection */ + public DtoCollection $list, + ) {} } diff --git a/app/src/Entity/Restaurants.php b/app/src/Entity/Restaurants.php index a6208fe..69e614c 100644 --- a/app/src/Entity/Restaurants.php +++ b/app/src/Entity/Restaurants.php @@ -495,19 +495,13 @@ class Restaurants implements PrototypeElementDto ) ); - return new DtoCollection( - TagDto::class, - $jsonCollection - ->map(function(array $tag) { - $tagDto = new TagDto(); - $tagDto->name = key($tag); - $tagDto->list = new DtoCollection( - 'string', - $tag - ); - return $tagDto; - }) - ->toArray() - ); + $tagCollection = new DtoCollection(TagDto::class); + foreach ($jsonCollection as $name => $jsonItem) { + $tagCollection->add( + new TagDto($name, new DtoCollection('string', $jsonItem)) + ); + } + + return $tagCollection; } } -- GitLab From ccd9c148295a681cd0e7a1ba31fd49c1961fef96 Mon Sep 17 00:00:00 2001 From: AlexP Date: Tue, 14 May 2024 02:49:42 +0500 Subject: [PATCH 10/12] STA-960 | fix some issues --- app/composer.json | 2 +- app/config/packages/doctrine.yaml | 4 +- app/config/routes.yaml | 12 +- app/config/services.yaml | 18 +-- app/src/Controller/Handle.php | 32 ----- app/src/Dto/DtoInterface.php | 6 - app/src/Dto/ErrorDto.php | 12 -- app/src/Dto/FileDto.php | 18 --- app/src/Dto/KitchenTypeDto.php | 12 -- app/src/Dto/NewsCategoryDto.php | 12 -- app/src/Dto/NewsDetailElementDto.php | 19 --- app/src/Dto/NewsListDto.php | 20 --- app/src/Dto/NewsListingElementDto.php | 19 --- app/src/Dto/PaginationDto.php | 21 --- app/src/Dto/RestaurantDetailElementDto.php | 45 ------ app/src/Dto/RestaurantListingElementDto.php | 20 --- app/src/Dto/RestaurantTypeDto.php | 12 -- app/src/Dto/ValidateErrorDto.php | 16 --- app/src/Entity/PrototypeDto.php | 11 -- app/src/Entity/PrototypeElementDto.php | 14 -- app/src/Error/AbstractError.php | 10 -- app/src/Error/NotFoundError.php | 16 --- .../{ => News}/Controller/NewsController.php | 37 ++--- app/src/News/Dto/NewsCategoryDto.php | 16 +++ app/src/News/Dto/NewsDetailElementDto.php | 24 ++++ .../Dto/NewsFilterVariantsDto.php} | 8 +- app/src/News/Dto/NewsListDto.php | 23 ++++ app/src/News/Dto/NewsListingElementDto.php | 31 +++++ .../DtoFactory/NewsCategoryDtoFactory.php | 36 +++++ .../NewsDetailElementDtoFactory.php | 28 ++++ .../NewsFilterVariantsDtoFactory.php | 21 +++ .../News/DtoFactory/NewsListDtoFactory.php | 24 ++++ .../NewsListingElementDtoFactory.php | 45 ++++++ .../{ => News}/Request/NewsListingRequest.php | 7 +- app/src/News/Service/NewsDetailService.php | 31 +++++ app/src/News/Service/NewsListingService.php | 57 ++++++++ app/src/News/Service/NewsMainNewsService.php | 22 +++ app/src/News/Service/NewsSearchService.php | 22 +++ app/src/Repository/.gitignore | 0 .../KitchensRepositoryInterface.php | 11 -- .../NewsCategoriesRepositoryInterface.php | 12 -- .../Repository/NewsRepositoryInterface.php | 20 --- .../RestaurantTypeRepositoryInterface.php | 12 -- .../RestaurantsRepositoryInterface.php | 20 --- .../Controller/RestaurantsController.php | 25 ++-- app/src/Restaurants/Dto/KitchenTypeDto.php | 16 +++ .../Dto/RestaurantDetailElementDto.php | 59 ++++++++ .../Dto/RestaurantFilterVariantsDto.php | 7 +- .../Dto/RestaurantListDto.php | 7 +- .../Dto/RestaurantListingElementDto.php | 25 ++++ app/src/Restaurants/Dto/RestaurantTypeDto.php | 16 +++ app/src/{ => Restaurants}/Dto/TagDto.php | 6 +- .../DtoFactory/KitchenTypeDtoFactory.php | 37 +++++ .../RestaurantDetailElementDtoFactory.php | 56 ++++++++ .../RestaurantFilterVariantsDtoFactory.php | 19 +++ .../DtoFactory/RestaurantListDtoFactory.php | 30 ++++ .../RestaurantListingElementDtoFactory.php | 45 ++++++ .../DtoFactory/RestaurantTypeDtoFactory.php | 36 +++++ .../Restaurants/DtoFactory/TagDtoFactory.php | 39 ++++++ .../Request/RestaurantListingRequest.php | 3 +- .../Service/RestaurantDetailService.php | 34 +++++ .../Service/RestaurantListingService.php | 71 ++++++++++ app/src/Service/NewsDetailService.php | 26 ---- app/src/Service/NewsListingService.php | 71 ---------- app/src/Service/NewsMainNewsService.php | 19 --- app/src/Service/NewsSearchService.php | 18 --- app/src/Service/RestaurantDetailService.php | 30 ---- app/src/Service/RestaurantListingService.php | 88 ------------ .../Shared/Abstraction/AbstractController.php | 33 +++++ .../Abstraction}/AbstractRequest.php | 9 +- app/src/Shared/Abstraction/DtoInterface.php | 5 + .../Shared/Abstraction/EntityInterface.php | 5 + .../Abstraction}/ServiceInterface.php | 5 +- app/src/{ => Shared}/Dto/DtoCollection.php | 4 +- app/src/Shared/Dto/ErrorDto.php | 16 +++ app/src/Shared/Dto/FileDto.php | 22 +++ app/src/Shared/Dto/PaginationDto.php | 14 ++ app/src/Shared/Dto/ValidateErrorDto.php | 16 +++ app/src/Shared/DtoFactory/ErrorDtoFactory.php | 18 +++ app/src/Shared/DtoFactory/FileDtoFactory.php | 39 ++++++ .../DtoFactory/PaginationDtoFactory.php | 17 +++ .../DtoFactory/ValidateErrorDtoFactory.php | 20 +++ .../{Controller => Shared/Entity}/.gitignore | 0 app/src/{ => Shared}/Entity/File.php | 24 +--- app/src/{ => Shared}/Entity/Kitchens.php | 21 +-- app/src/{ => Shared}/Entity/News.php | 43 +----- .../{ => Shared}/Entity/NewsCategories.php | 23 +--- app/src/{ => Shared}/Entity/NewsType.php | 5 +- .../{ => Shared}/Entity/RestaurantTypes.php | 21 +-- app/src/{ => Shared}/Entity/Restaurants.php | 129 ++---------------- app/src/{ => Shared}/Entity/Settlements.php | 4 +- app/src/{ => Shared}/Entity/Users.php | 4 +- app/src/Shared/Error/BaseError.php | 20 +++ app/src/Shared/Error/ErrorCode.php | 10 ++ app/src/Shared/Error/NotFoundError.php | 14 ++ .../{Entity => Shared/Repository}/.gitignore | 0 .../Repository/FileRepository.php | 4 +- .../Repository/KitchensRepository.php | 6 +- .../Repository/NewsCategoriesRepository.php | 7 +- .../Repository/NewsRepository.php | 26 ++-- .../Repository/NewsTypeRepository.php | 4 +- .../Repository/RestaurantTypesRepository.php | 6 +- .../Repository/RestaurantsRepository.php | 10 +- .../Repository/SettlementsRepository.php | 5 +- .../Repository/UsersRepository.php | 4 +- .../{ => Shared}/Request/DetailRequest.php | 3 +- app/src/{ => Shared}/Request/EmptyRequest.php | 4 +- 107 files changed, 1279 insertions(+), 982 deletions(-) delete mode 100644 app/src/Controller/Handle.php delete mode 100644 app/src/Dto/DtoInterface.php delete mode 100644 app/src/Dto/ErrorDto.php delete mode 100644 app/src/Dto/FileDto.php delete mode 100644 app/src/Dto/KitchenTypeDto.php delete mode 100644 app/src/Dto/NewsCategoryDto.php delete mode 100644 app/src/Dto/NewsDetailElementDto.php delete mode 100644 app/src/Dto/NewsListDto.php delete mode 100644 app/src/Dto/NewsListingElementDto.php delete mode 100644 app/src/Dto/PaginationDto.php delete mode 100644 app/src/Dto/RestaurantDetailElementDto.php delete mode 100644 app/src/Dto/RestaurantListingElementDto.php delete mode 100644 app/src/Dto/RestaurantTypeDto.php delete mode 100644 app/src/Dto/ValidateErrorDto.php delete mode 100644 app/src/Entity/PrototypeDto.php delete mode 100644 app/src/Entity/PrototypeElementDto.php delete mode 100644 app/src/Error/AbstractError.php delete mode 100644 app/src/Error/NotFoundError.php rename app/src/{ => News}/Controller/NewsController.php (54%) create mode 100644 app/src/News/Dto/NewsCategoryDto.php create mode 100644 app/src/News/Dto/NewsDetailElementDto.php rename app/src/{Dto/NewsFilterVariants.php => News/Dto/NewsFilterVariantsDto.php} (52%) create mode 100644 app/src/News/Dto/NewsListDto.php create mode 100644 app/src/News/Dto/NewsListingElementDto.php create mode 100644 app/src/News/DtoFactory/NewsCategoryDtoFactory.php create mode 100644 app/src/News/DtoFactory/NewsDetailElementDtoFactory.php create mode 100644 app/src/News/DtoFactory/NewsFilterVariantsDtoFactory.php create mode 100644 app/src/News/DtoFactory/NewsListDtoFactory.php create mode 100644 app/src/News/DtoFactory/NewsListingElementDtoFactory.php rename app/src/{ => News}/Request/NewsListingRequest.php (89%) create mode 100644 app/src/News/Service/NewsDetailService.php create mode 100644 app/src/News/Service/NewsListingService.php create mode 100644 app/src/News/Service/NewsMainNewsService.php create mode 100644 app/src/News/Service/NewsSearchService.php delete mode 100644 app/src/Repository/.gitignore delete mode 100644 app/src/Repository/KitchensRepositoryInterface.php delete mode 100644 app/src/Repository/NewsCategoriesRepositoryInterface.php delete mode 100644 app/src/Repository/NewsRepositoryInterface.php delete mode 100644 app/src/Repository/RestaurantTypeRepositoryInterface.php delete mode 100644 app/src/Repository/RestaurantsRepositoryInterface.php rename app/src/{ => Restaurants}/Controller/RestaurantsController.php (50%) create mode 100644 app/src/Restaurants/Dto/KitchenTypeDto.php create mode 100644 app/src/Restaurants/Dto/RestaurantDetailElementDto.php rename app/src/{ => Restaurants}/Dto/RestaurantFilterVariantsDto.php (66%) rename app/src/{ => Restaurants}/Dto/RestaurantListDto.php (74%) create mode 100644 app/src/Restaurants/Dto/RestaurantListingElementDto.php create mode 100644 app/src/Restaurants/Dto/RestaurantTypeDto.php rename app/src/{ => Restaurants}/Dto/TagDto.php (69%) create mode 100644 app/src/Restaurants/DtoFactory/KitchenTypeDtoFactory.php create mode 100644 app/src/Restaurants/DtoFactory/RestaurantDetailElementDtoFactory.php create mode 100644 app/src/Restaurants/DtoFactory/RestaurantFilterVariantsDtoFactory.php create mode 100644 app/src/Restaurants/DtoFactory/RestaurantListDtoFactory.php create mode 100644 app/src/Restaurants/DtoFactory/RestaurantListingElementDtoFactory.php create mode 100644 app/src/Restaurants/DtoFactory/RestaurantTypeDtoFactory.php create mode 100644 app/src/Restaurants/DtoFactory/TagDtoFactory.php rename app/src/{ => Restaurants}/Request/RestaurantListingRequest.php (90%) create mode 100644 app/src/Restaurants/Service/RestaurantDetailService.php create mode 100644 app/src/Restaurants/Service/RestaurantListingService.php delete mode 100644 app/src/Service/NewsDetailService.php delete mode 100644 app/src/Service/NewsListingService.php delete mode 100644 app/src/Service/NewsMainNewsService.php delete mode 100644 app/src/Service/NewsSearchService.php delete mode 100644 app/src/Service/RestaurantDetailService.php delete mode 100644 app/src/Service/RestaurantListingService.php create mode 100644 app/src/Shared/Abstraction/AbstractController.php rename app/src/{Request => Shared/Abstraction}/AbstractRequest.php (88%) create mode 100644 app/src/Shared/Abstraction/DtoInterface.php create mode 100644 app/src/Shared/Abstraction/EntityInterface.php rename app/src/{Service => Shared/Abstraction}/ServiceInterface.php (56%) rename app/src/{ => Shared}/Dto/DtoCollection.php (68%) create mode 100644 app/src/Shared/Dto/ErrorDto.php create mode 100644 app/src/Shared/Dto/FileDto.php create mode 100644 app/src/Shared/Dto/PaginationDto.php create mode 100644 app/src/Shared/Dto/ValidateErrorDto.php create mode 100644 app/src/Shared/DtoFactory/ErrorDtoFactory.php create mode 100644 app/src/Shared/DtoFactory/FileDtoFactory.php create mode 100644 app/src/Shared/DtoFactory/PaginationDtoFactory.php create mode 100644 app/src/Shared/DtoFactory/ValidateErrorDtoFactory.php rename app/src/{Controller => Shared/Entity}/.gitignore (100%) rename app/src/{ => Shared}/Entity/File.php (93%) rename app/src/{ => Shared}/Entity/Kitchens.php (82%) rename app/src/{ => Shared}/Entity/News.php (80%) rename app/src/{ => Shared}/Entity/NewsCategories.php (81%) rename app/src/{ => Shared}/Entity/NewsType.php (95%) rename app/src/{ => Shared}/Entity/RestaurantTypes.php (82%) rename app/src/{ => Shared}/Entity/Restaurants.php (69%) rename app/src/{ => Shared}/Entity/Settlements.php (97%) rename app/src/{ => Shared}/Entity/Users.php (96%) create mode 100644 app/src/Shared/Error/BaseError.php create mode 100644 app/src/Shared/Error/ErrorCode.php create mode 100644 app/src/Shared/Error/NotFoundError.php rename app/src/{Entity => Shared/Repository}/.gitignore (100%) rename app/src/{ => Shared}/Repository/FileRepository.php (91%) rename app/src/{ => Shared}/Repository/KitchensRepository.php (84%) rename app/src/{ => Shared}/Repository/NewsCategoriesRepository.php (84%) rename app/src/{ => Shared}/Repository/NewsRepository.php (73%) rename app/src/{ => Shared}/Repository/NewsTypeRepository.php (92%) rename app/src/{ => Shared}/Repository/RestaurantTypesRepository.php (83%) rename app/src/{ => Shared}/Repository/RestaurantsRepository.php (88%) rename app/src/{ => Shared}/Repository/SettlementsRepository.php (90%) rename app/src/{ => Shared}/Repository/UsersRepository.php (91%) rename app/src/{ => Shared}/Request/DetailRequest.php (87%) rename app/src/{ => Shared}/Request/EmptyRequest.php (65%) diff --git a/app/composer.json b/app/composer.json index 564d77e..be399e9 100644 --- a/app/composer.json +++ b/app/composer.json @@ -4,7 +4,7 @@ "minimum-stability": "stable", "prefer-stable": true, "require": { - "php": ">=8.1", + "php": ">=8.2", "ext-ctype": "*", "ext-iconv": "*", "doctrine/dbal": "^3", diff --git a/app/config/packages/doctrine.yaml b/app/config/packages/doctrine.yaml index bf5aa40..b67e855 100644 --- a/app/config/packages/doctrine.yaml +++ b/app/config/packages/doctrine.yaml @@ -21,8 +21,8 @@ doctrine: App: type: attribute is_bundle: false - dir: '%kernel.project_dir%/src/Entity' - prefix: 'App\Entity' + dir: '%kernel.project_dir%/src/Shared/Entity' + prefix: 'App\Shared\Entity' alias: App controller_resolver: auto_mapping: true diff --git a/app/config/routes.yaml b/app/config/routes.yaml index 41ef814..0370c9f 100644 --- a/app/config/routes.yaml +++ b/app/config/routes.yaml @@ -1,5 +1,11 @@ -controllers: +newsControllers: resource: - path: ../src/Controller/ - namespace: App\Controller + path: ../src/News/Controller/ + namespace: App\News\Controller + type: attribute + +restaurantsControllers: + resource: + path: ../src/Restaurants/Controller/ + namespace: App\Restaurants\Controller type: attribute diff --git a/app/config/services.yaml b/app/config/services.yaml index 2d6a76f..55758d4 100644 --- a/app/config/services.yaml +++ b/app/config/services.yaml @@ -11,14 +11,14 @@ services: autowire: true # Automatically injects dependencies in your services. autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. - # makes classes in src/ available to be used as services - # this creates a service per class whose id is the fully-qualified class name - App\: - resource: '../src/' - exclude: - - '../src/DependencyInjection/' - - '../src/Entity/' - - '../src/Kernel.php' - # add more service definitions when explicit configuration is needed # please note that last definitions always *replace* previous ones + + App\Restaurants\: + resource: '../src/Restaurants/' + + App\News\: + resource: '../src/News/' + + App\Shared\: + resource: '../src/Shared/' \ No newline at end of file diff --git a/app/src/Controller/Handle.php b/app/src/Controller/Handle.php deleted file mode 100644 index 97f6715..0000000 --- a/app/src/Controller/Handle.php +++ /dev/null @@ -1,32 +0,0 @@ -service->serve($request)); -// -// } catch (AbstractError $error) { -// $errorDto = new ErrorDto(); -// -// $errorDto->message = $error->message; -// $errorDto->code = $error->code; -// $errorDto->status = $error->status; -// -// return new JsonResponse($errorDto, $error->status); -// -// } catch (Throwable $exception) { -// $error = new ErrorDto(); -// return new JsonResponse($error, $error->status); -// } - } -} diff --git a/app/src/Dto/DtoInterface.php b/app/src/Dto/DtoInterface.php deleted file mode 100644 index fc79608..0000000 --- a/app/src/Dto/DtoInterface.php +++ /dev/null @@ -1,6 +0,0 @@ - $list - * @param NewsFilterVariants $filterVariants - */ - public function __construct( - public PaginationDto $pagination, - - /** @var DtoCollection */ - public DtoCollection $list, - - public NewsFilterVariants $filterVariants, - ) {} -} diff --git a/app/src/Dto/NewsListingElementDto.php b/app/src/Dto/NewsListingElementDto.php deleted file mode 100644 index ef41fea..0000000 --- a/app/src/Dto/NewsListingElementDto.php +++ /dev/null @@ -1,19 +0,0 @@ -page_size = $limit > 0 ? $limit : 12; - - $this->pages = ceil($total / $this->page_size); - - if (($page > 1) && ($page <= $this->pages)) { - $this->current_page = $page; - } - } -} diff --git a/app/src/Dto/RestaurantDetailElementDto.php b/app/src/Dto/RestaurantDetailElementDto.php deleted file mode 100644 index 13f29c9..0000000 --- a/app/src/Dto/RestaurantDetailElementDto.php +++ /dev/null @@ -1,45 +0,0 @@ -|null */ - public ?DtoCollection $kitchen; - - /** @var DtoCollection|null */ - public ?DtoCollection $phone; - - /** @var DtoCollection|null */ - public ?DtoCollection $email; - - /** @var DtoCollection|null */ - public ?DtoCollection $address; - - /** @var DtoCollection|null */ - public ?DtoCollection $tags; - - public ?string $site; - - /** @var FileDto|null Превью фото */ - public ?FileDto $image; - - /** @var DtoCollection|null */ - public ?DtoCollection $gallery; -} diff --git a/app/src/Dto/RestaurantListingElementDto.php b/app/src/Dto/RestaurantListingElementDto.php deleted file mode 100644 index 3b575da..0000000 --- a/app/src/Dto/RestaurantListingElementDto.php +++ /dev/null @@ -1,20 +0,0 @@ -message = $violation->getPropertyPath() . ':' . $violation->getMessage(); - $this->code = $violation->getCode(); - } -} diff --git a/app/src/Entity/PrototypeDto.php b/app/src/Entity/PrototypeDto.php deleted file mode 100644 index 19c8822..0000000 --- a/app/src/Entity/PrototypeDto.php +++ /dev/null @@ -1,11 +0,0 @@ -message = $message . ' ' . $this->message; - parent::__construct($this->message); - } -} diff --git a/app/src/Controller/NewsController.php b/app/src/News/Controller/NewsController.php similarity index 54% rename from app/src/Controller/NewsController.php rename to app/src/News/Controller/NewsController.php index 90c6a8c..286ff07 100644 --- a/app/src/Controller/NewsController.php +++ b/app/src/News/Controller/NewsController.php @@ -1,49 +1,54 @@ listingService))->handle($request); + return $this->handle($this->listingService, $request); } #[Route('/mainNews', name: 'mainNews', methods: ['GET'])] public function mainNews(EmptyRequest $request): JsonResponse { - return (new Handle($this->mainNewsService))->handle($request); + return $this->handle($this->mainNewsService, $request); } #[Route('/search', name: 'searchNews', methods: ['GET'])] public function search(EmptyRequest $request): JsonResponse { - return (new Handle($this->searchService))->handle($request); + return $this->handle($this->searchService, $request); } #[Route('/{detailId}', name: 'oneNews', methods: ['GET'])] public function oneNews(DetailRequest $request): JsonResponse { - return (new Handle($this->detailService))->handle($request); + return $this->handle($this->detailService, $request); } } diff --git a/app/src/News/Dto/NewsCategoryDto.php b/app/src/News/Dto/NewsCategoryDto.php new file mode 100644 index 0000000..21917d9 --- /dev/null +++ b/app/src/News/Dto/NewsCategoryDto.php @@ -0,0 +1,16 @@ + $category */ public function __construct( - /** @var DtoCollection */ public DtoCollection $category, ) {} } diff --git a/app/src/News/Dto/NewsListDto.php b/app/src/News/Dto/NewsListDto.php new file mode 100644 index 0000000..d4ffffd --- /dev/null +++ b/app/src/News/Dto/NewsListDto.php @@ -0,0 +1,23 @@ + $list + * @param NewsFilterVariantsDto $filterVariants + */ + public function __construct( + public PaginationDto $pagination, + + public DtoCollection $list, + + public NewsFilterVariantsDto $filterVariants, + ) {} +} diff --git a/app/src/News/Dto/NewsListingElementDto.php b/app/src/News/Dto/NewsListingElementDto.php new file mode 100644 index 0000000..dd6c610 --- /dev/null +++ b/app/src/News/Dto/NewsListingElementDto.php @@ -0,0 +1,31 @@ +getId(), + name: $category->getName(), + code: $category->getCode(), + ); + } + + /** + * @param Collection $categories + * @return DtoCollection + */ + public function createCollection(Collection $categories): DtoCollection + { + $categoriesDto = $categories->map(function(NewsCategories $category) { + return $this->create($category); + }); + + return new DtoCollection( + NewsCategoryDto::class, + $categoriesDto->toArray() + ); + } +} diff --git a/app/src/News/DtoFactory/NewsDetailElementDtoFactory.php b/app/src/News/DtoFactory/NewsDetailElementDtoFactory.php new file mode 100644 index 0000000..c4a82b0 --- /dev/null +++ b/app/src/News/DtoFactory/NewsDetailElementDtoFactory.php @@ -0,0 +1,28 @@ +getId(), + name: $news->getName(), + description: $news->getPreviewText(), + createAt: $news->getCreatedAt()->format('Y-m-d H:i:s'), + text: $news->getDetailText(), + image: $news->getPreviewImage() !== null + ? $this->fileFactory->create($news->getPreviewImage()) + : null, + ); + } +} diff --git a/app/src/News/DtoFactory/NewsFilterVariantsDtoFactory.php b/app/src/News/DtoFactory/NewsFilterVariantsDtoFactory.php new file mode 100644 index 0000000..80f54fe --- /dev/null +++ b/app/src/News/DtoFactory/NewsFilterVariantsDtoFactory.php @@ -0,0 +1,21 @@ + $categories + * @return NewsFilterVariantsDto + */ + public function create(DtoCollection $categories): NewsFilterVariantsDto + { + return new NewsFilterVariantsDto( + $categories + ); + } +} diff --git a/app/src/News/DtoFactory/NewsListDtoFactory.php b/app/src/News/DtoFactory/NewsListDtoFactory.php new file mode 100644 index 0000000..40f714f --- /dev/null +++ b/app/src/News/DtoFactory/NewsListDtoFactory.php @@ -0,0 +1,24 @@ +getId(), + name: $news->getName(), + createAt: $news->getCreatedAt()->format('Y-m-d H:i:s'), + detailLink: "api/v1/news/" . $news->getId(), + description: $news->getPreviewText(), + image: $news->getPreviewImage() !== null + ? $this->fileFactory->create($news->getPreviewImage()) + :null, + ); + } + + /** + * @param Collection $news + * @return DtoCollection + */ + public function createCollection(Collection $news): DtoCollection + { + return new DtoCollection( + NewsListingElementDto::class, + $news->map(function(News $oneNews) { + return $this->create($oneNews); + }) + ->toArray() + ); + } +} diff --git a/app/src/Request/NewsListingRequest.php b/app/src/News/Request/NewsListingRequest.php similarity index 89% rename from app/src/Request/NewsListingRequest.php rename to app/src/News/Request/NewsListingRequest.php index fd570e4..31d99f6 100644 --- a/app/src/Request/NewsListingRequest.php +++ b/app/src/News/Request/NewsListingRequest.php @@ -1,10 +1,11 @@ news->find($request->detailId); + + return $news !== null + ? $this->dtoFactory->create($news) + : throw new NotFoundError('News not found'); + } +} diff --git a/app/src/News/Service/NewsListingService.php b/app/src/News/Service/NewsListingService.php new file mode 100644 index 0000000..fd32d9f --- /dev/null +++ b/app/src/News/Service/NewsListingService.php @@ -0,0 +1,57 @@ +news->getCountWithFilters($request->news_category); + + $pagination = $this->paginationFactory->create( + $request->page, + $request->limit, + $countOfNews + ); + + $offset = min($pagination->pageSize, $countOfNews) * ($pagination->currentPage - 1); + + $list = $this->listFactory->createCollection( + $this->news->getWithFilters($request->news_category, $request->limit, $offset) + ); + + $categoriesDto = $this->categoryFactory->createCollection( + $this->newsCategories->getAll() + ); + + $filters = $this->filterFactory->create($categoriesDto); + + return $this->listingFactory->create( + $pagination, + $list, + $filters + ); + } +} diff --git a/app/src/News/Service/NewsMainNewsService.php b/app/src/News/Service/NewsMainNewsService.php new file mode 100644 index 0000000..784633d --- /dev/null +++ b/app/src/News/Service/NewsMainNewsService.php @@ -0,0 +1,22 @@ +dtoFactory->create($this->news->getMainNews()); + } +} diff --git a/app/src/News/Service/NewsSearchService.php b/app/src/News/Service/NewsSearchService.php new file mode 100644 index 0000000..391d3c9 --- /dev/null +++ b/app/src/News/Service/NewsSearchService.php @@ -0,0 +1,22 @@ +dtoFactory->create($this->news->getMainNews()); + } +} diff --git a/app/src/Repository/.gitignore b/app/src/Repository/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/Repository/KitchensRepositoryInterface.php b/app/src/Repository/KitchensRepositoryInterface.php deleted file mode 100644 index afba82d..0000000 --- a/app/src/Repository/KitchensRepositoryInterface.php +++ /dev/null @@ -1,11 +0,0 @@ - */ - public function getAll(): Collection; -} diff --git a/app/src/Repository/NewsRepositoryInterface.php b/app/src/Repository/NewsRepositoryInterface.php deleted file mode 100644 index b67c875..0000000 --- a/app/src/Repository/NewsRepositoryInterface.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * @method News|null find($id, $lockMode = null, $lockVersion = null) - */ -interface NewsRepositoryInterface -{ - public function getMainNews(): News; - public function getCountWithFilters(?string $categoryId): int; - - /** @return Collection */ - public function findByFilters(?string $categoryId, int $limit, int $offset): Collection; -} diff --git a/app/src/Repository/RestaurantTypeRepositoryInterface.php b/app/src/Repository/RestaurantTypeRepositoryInterface.php deleted file mode 100644 index 6198943..0000000 --- a/app/src/Repository/RestaurantTypeRepositoryInterface.php +++ /dev/null @@ -1,12 +0,0 @@ - */ - public function getAll(): Collection; -} diff --git a/app/src/Repository/RestaurantsRepositoryInterface.php b/app/src/Repository/RestaurantsRepositoryInterface.php deleted file mode 100644 index e5e2f2f..0000000 --- a/app/src/Repository/RestaurantsRepositoryInterface.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * @method Restaurants|null find($id, $lockMode = null, $lockVersion = null) - */ -interface RestaurantsRepositoryInterface -{ - public function getCountWithFilters(?string $kitchenId, string $typeId): int; - - /** @return Collection */ - public function findByFilters(?string $kitchenId, ?string $typeId, int $limit, int $offset): Collection; -} diff --git a/app/src/Controller/RestaurantsController.php b/app/src/Restaurants/Controller/RestaurantsController.php similarity index 50% rename from app/src/Controller/RestaurantsController.php rename to app/src/Restaurants/Controller/RestaurantsController.php index b268f83..5893ecb 100644 --- a/app/src/Controller/RestaurantsController.php +++ b/app/src/Restaurants/Controller/RestaurantsController.php @@ -1,32 +1,37 @@ listingService))->handle($request); + return $this->handle($this->listingService, $request); } #[Route('/{detailId}', name: 'restaurant', methods: ['GET'])] public function restaurant(DetailRequest $request): JsonResponse { - return (new Handle($this->detailService))->handle($request); + return $this->handle($this->detailService, $request); } } diff --git a/app/src/Restaurants/Dto/KitchenTypeDto.php b/app/src/Restaurants/Dto/KitchenTypeDto.php new file mode 100644 index 0000000..e326132 --- /dev/null +++ b/app/src/Restaurants/Dto/KitchenTypeDto.php @@ -0,0 +1,16 @@ +|null $kitchen + * @param DtoCollection|null $phone + * @param DtoCollection|null $email + * @param DtoCollection|null $address + * @param DtoCollection|null $tags + * @param string|null $site + * @param FileDto|null $image Превью + * @param DtoCollection|null $gallery + */ + public function __construct( + public string $id, + + public string $name, + + public string $code, + + public string $coordinates, + + public RestaurantTypeDto $type, + + public ?string $check = null, + + public ?string $check_info = null, + + public ?DtoCollection $kitchen = null, + + public ?DtoCollection $phone = null, + + public ?DtoCollection $email = null, + + public ?DtoCollection $address = null, + + public ?DtoCollection $tags = null, + + public ?string $site = null, + + public ?FileDto $image = null, + + public ?DtoCollection $gallery = null, + ) {} +} diff --git a/app/src/Dto/RestaurantFilterVariantsDto.php b/app/src/Restaurants/Dto/RestaurantFilterVariantsDto.php similarity index 66% rename from app/src/Dto/RestaurantFilterVariantsDto.php rename to app/src/Restaurants/Dto/RestaurantFilterVariantsDto.php index 8fd5a95..e4a15c1 100644 --- a/app/src/Dto/RestaurantFilterVariantsDto.php +++ b/app/src/Restaurants/Dto/RestaurantFilterVariantsDto.php @@ -1,8 +1,9 @@ $kitchen */ public function __construct( - /** @var DtoCollection */ public DtoCollection $type, - /** @var DtoCollection */ public DtoCollection $kitchen, ) {} } diff --git a/app/src/Dto/RestaurantListDto.php b/app/src/Restaurants/Dto/RestaurantListDto.php similarity index 74% rename from app/src/Dto/RestaurantListDto.php rename to app/src/Restaurants/Dto/RestaurantListDto.php index fd500cb..9d7f022 100644 --- a/app/src/Dto/RestaurantListDto.php +++ b/app/src/Restaurants/Dto/RestaurantListDto.php @@ -1,6 +1,10 @@ */ public DtoCollection $list, public RestaurantFilterVariantsDto $filterVariants, diff --git a/app/src/Restaurants/Dto/RestaurantListingElementDto.php b/app/src/Restaurants/Dto/RestaurantListingElementDto.php new file mode 100644 index 0000000..b9b212e --- /dev/null +++ b/app/src/Restaurants/Dto/RestaurantListingElementDto.php @@ -0,0 +1,25 @@ + */ public DtoCollection $list, ) {} } diff --git a/app/src/Restaurants/DtoFactory/KitchenTypeDtoFactory.php b/app/src/Restaurants/DtoFactory/KitchenTypeDtoFactory.php new file mode 100644 index 0000000..04c7260 --- /dev/null +++ b/app/src/Restaurants/DtoFactory/KitchenTypeDtoFactory.php @@ -0,0 +1,37 @@ +getId(), + name: $kitchen->getName(), + code: $kitchen->getCode(), + ); + } + + /** + * @param DoctrineCollection|RamseyCollection $kitchens + * @return DtoCollection + */ + public function createCollection(DoctrineCollection|RamseyCollection $kitchens): DtoCollection + { + $kitchenCollection = $kitchens->map(function(Kitchens $kitchen) { + return $this->create($kitchen); + }); + + return new DtoCollection( + KitchenTypeDto::class, + $kitchenCollection->toArray() + ); + } +} diff --git a/app/src/Restaurants/DtoFactory/RestaurantDetailElementDtoFactory.php b/app/src/Restaurants/DtoFactory/RestaurantDetailElementDtoFactory.php new file mode 100644 index 0000000..343b892 --- /dev/null +++ b/app/src/Restaurants/DtoFactory/RestaurantDetailElementDtoFactory.php @@ -0,0 +1,56 @@ +getId(), + name: $restaurant->getName(), + code: $restaurant->getCode(), + coordinates: $restaurant->getCoordinates(), + type: $this->typeFactory->create($restaurant->getType()), + check: $restaurant->getReceipt(), + check_info: $restaurant->getReceiptInfo(), + kitchen: $this->kitchenFactory->createCollection($restaurant->getKitchens()), + phone: $this->decodeJson($restaurant->getPhone()), + email: $this->decodeJson($restaurant->getEmail()), + address: $this->decodeJson($restaurant->getAddress()), + tags: $this->tagFactory->createCollection($restaurant->getTags()), + site: $restaurant->getSite(), + image: $this->fileFactory->create($restaurant->getPreviewImage()), + gallery: $this->fileFactory->createCollection($restaurant->getGallery()), + ); + } + + /** + * @throws \JsonException + */ + private function decodeJson(string $json) + { + return $json === null + ? null + : new DtoCollection( + 'string', + json_decode( + $json, + true, + 512, + JSON_THROW_ON_ERROR + ), + ); + } +} \ No newline at end of file diff --git a/app/src/Restaurants/DtoFactory/RestaurantFilterVariantsDtoFactory.php b/app/src/Restaurants/DtoFactory/RestaurantFilterVariantsDtoFactory.php new file mode 100644 index 0000000..91624eb --- /dev/null +++ b/app/src/Restaurants/DtoFactory/RestaurantFilterVariantsDtoFactory.php @@ -0,0 +1,19 @@ + $list + * @param RestaurantFilterVariantsDto $filters + * @return RestaurantListDto + */ + public function create( + PaginationDto $pagination, + DtoCollection $list, + RestaurantFilterVariantsDto $filters + ): RestaurantListDto { + return new RestaurantListDto( + $pagination, + $list, + $filters + ); + } +} diff --git a/app/src/Restaurants/DtoFactory/RestaurantListingElementDtoFactory.php b/app/src/Restaurants/DtoFactory/RestaurantListingElementDtoFactory.php new file mode 100644 index 0000000..d46d87b --- /dev/null +++ b/app/src/Restaurants/DtoFactory/RestaurantListingElementDtoFactory.php @@ -0,0 +1,45 @@ +getId(), + name: $restaurant->getName(), + code: $restaurant->getCode(), + type: $this->typeFactory->create($restaurant->getType()), + detailLink: 'api/v1/restaurants/' . $restaurant->getId(), + check: $restaurant->getReceipt(), + image: $this->fileFactory->create($restaurant->getPreviewImage()) + ); + } + + /** + * @param Collection $restaurants + * @return DtoCollection + */ + public function createCollection(Collection $restaurants): DtoCollection + { + $restaurantsDto = $restaurants->map(function(Restaurants $restaurant) { + return $this->create($restaurant); + }); + + return new DtoCollection( + RestaurantListingElementDto::class, + $restaurantsDto->toArray(), + ); + } +} diff --git a/app/src/Restaurants/DtoFactory/RestaurantTypeDtoFactory.php b/app/src/Restaurants/DtoFactory/RestaurantTypeDtoFactory.php new file mode 100644 index 0000000..30b6ebc --- /dev/null +++ b/app/src/Restaurants/DtoFactory/RestaurantTypeDtoFactory.php @@ -0,0 +1,36 @@ +getId(), + name: $type->getName(), + code: $type->getCode(), + ); + } + + /** + * @param Collection $types + * @return DtoCollection + */ + public function createCollection(Collection $types): DtoCollection + { + $typesDto = $types->map(function(RestaurantTypes $type) { + return $this->create($type); + }); + + return new DtoCollection( + RestaurantTypeDto::class, + $typesDto->toArray() + ); + } +} diff --git a/app/src/Restaurants/DtoFactory/TagDtoFactory.php b/app/src/Restaurants/DtoFactory/TagDtoFactory.php new file mode 100644 index 0000000..174e26e --- /dev/null +++ b/app/src/Restaurants/DtoFactory/TagDtoFactory.php @@ -0,0 +1,39 @@ + + * @throws JsonException + */ + public function createCollection(string $json): DtoCollection + { + $jsonCollection = new RamseyCollection( + 'array', + json_decode( + $json, + true, + 512, + JSON_THROW_ON_ERROR + ) + ); + + $tagCollection = new DtoCollection(TagDto::class); + + foreach ($jsonCollection as $name => $jsonItem) { + $tagCollection->add( + new TagDto($name, new DtoCollection('string', $jsonItem)) + ); + } + + return $tagCollection; + } +} diff --git a/app/src/Request/RestaurantListingRequest.php b/app/src/Restaurants/Request/RestaurantListingRequest.php similarity index 90% rename from app/src/Request/RestaurantListingRequest.php rename to app/src/Restaurants/Request/RestaurantListingRequest.php index 403a3a9..b85da7f 100644 --- a/app/src/Request/RestaurantListingRequest.php +++ b/app/src/Restaurants/Request/RestaurantListingRequest.php @@ -1,7 +1,8 @@ restaurants->find($request->detailId); + + if ($restaurant === null) { + throw new NotFoundError('Restaurant not found'); + } + + return $this->dtoFactory->create($restaurant); + } +} diff --git a/app/src/Restaurants/Service/RestaurantListingService.php b/app/src/Restaurants/Service/RestaurantListingService.php new file mode 100644 index 0000000..a56b29f --- /dev/null +++ b/app/src/Restaurants/Service/RestaurantListingService.php @@ -0,0 +1,71 @@ +restaurants + ->getCountWithFilters( + $request->restaurant_type_id, + $request->kitchen_id + ); + + $pagination = $this->paginationFactory->create( + $request->page, + $request->limit, + $countOfRestaurants, + ); + + $offset = min($pagination->pageSize, $countOfRestaurants) * ($pagination->currentPage - 1); + + $list = $this->listFactory->createCollection( + $this->restaurants->getWithFilters( + $request->kitchen_id, + $request->restaurant_type_id, + $pagination->pageSize, + $offset, + ), + ); + + + $filters = $this->filterFactory->create( + $this->typeFactory->createCollection($this->types->getAll()), + $this->kitchenFactory->createCollection($this->kitchens->getAll()) + ); + + return $this->listingFactory->create( + $pagination, + $list, + $filters + ); + } +} diff --git a/app/src/Service/NewsDetailService.php b/app/src/Service/NewsDetailService.php deleted file mode 100644 index 19c394d..0000000 --- a/app/src/Service/NewsDetailService.php +++ /dev/null @@ -1,26 +0,0 @@ -news->find($request->detailId); - - if ($news === null) { - throw new NotFoundError('News'); - } - - return $news->getExtendedDto(); - } -} diff --git a/app/src/Service/NewsListingService.php b/app/src/Service/NewsListingService.php deleted file mode 100644 index 6d75636..0000000 --- a/app/src/Service/NewsListingService.php +++ /dev/null @@ -1,71 +0,0 @@ -news-> - getCountWithFilters($request->news_category); - - $pagination = new PaginationDto( - $request->page, - $request->limit, - $countOfRestaurants - ); - - $offset = min($pagination->page_size, $countOfRestaurants) * ($pagination->current_page - 1); - - $list = new DtoCollection( - NewsListingElementDto::class, - $this - ->news - ->findByFilters( - $request->news_category, - $request->limit, $offset - ) - ->map(function(News $news) { - return $news->getDto(); - }) - ->toArray() - ); - - $filters = new NewsFilterVariants( - new DtoCollection( - NewsCategoryDto::class, - $this->newsCategories->getAll() - ->map(function(NewsCategories $category) { - return $category->getDto(); - }) - ->toArray() - ), - ); - - return new NewsListDto( - $pagination, - $list, - $filters - ); - } -} diff --git a/app/src/Service/NewsMainNewsService.php b/app/src/Service/NewsMainNewsService.php deleted file mode 100644 index 16037d3..0000000 --- a/app/src/Service/NewsMainNewsService.php +++ /dev/null @@ -1,19 +0,0 @@ -news->getMainNews()->getDto(); - } -} diff --git a/app/src/Service/NewsSearchService.php b/app/src/Service/NewsSearchService.php deleted file mode 100644 index ff9713e..0000000 --- a/app/src/Service/NewsSearchService.php +++ /dev/null @@ -1,18 +0,0 @@ -news->getMainNews()->getExtendedDto(); - } -} diff --git a/app/src/Service/RestaurantDetailService.php b/app/src/Service/RestaurantDetailService.php deleted file mode 100644 index 2547cfa..0000000 --- a/app/src/Service/RestaurantDetailService.php +++ /dev/null @@ -1,30 +0,0 @@ -restaurants->find($request->detailId); - - if ($restaurant === null) { - throw new NotFoundError('Restaurant'); - } - - return $restaurant->getExtendedDto(); - } -} diff --git a/app/src/Service/RestaurantListingService.php b/app/src/Service/RestaurantListingService.php deleted file mode 100644 index d24741a..0000000 --- a/app/src/Service/RestaurantListingService.php +++ /dev/null @@ -1,88 +0,0 @@ -restaurants - ->getCountWithFilters( - $request->restaurant_type_id, - $request->kitchen_id - ); - - $pagination = new PaginationDto( - $request->page, - $request->limit, - $countOfRestaurants, - ); - - $offset = min($pagination->page_size, $countOfRestaurants) * ($pagination->current_page - 1); - - $list = new DtoCollection( - RestaurantListingElementDto::class, - $this - ->restaurants - ->findByFilters( - $request - ->restaurant_type_id, - $request->kitchen_id, - $request->limit, - $offset, - ) - ->map(function (Restaurants $restaurant) { - return $restaurant->getDto(); - }) - ->toArray() - ); - - $filters = new RestaurantFilterVariantsDto( - new DtoCollection( - RestaurantTypeDto::class, - $this->types->getAll() - ->map(function(RestaurantTypes $types) { - return $types->getDto(); - }) - ->toArray() - ), - new DtoCollection( - KitchenTypeDto::class, - $this->kitchens->getAll() - ->map(function(Kitchens $kitchen) { - return $kitchen->getDto(); - }) - ->toArray() - ), - ); - - return new RestaurantListDto( - $pagination, - $list, - $filters, - ); - } -} diff --git a/app/src/Shared/Abstraction/AbstractController.php b/app/src/Shared/Abstraction/AbstractController.php new file mode 100644 index 0000000..3d40cc8 --- /dev/null +++ b/app/src/Shared/Abstraction/AbstractController.php @@ -0,0 +1,33 @@ +serve($request)); +// +// } catch (BaseError $error) { +// $errorDto = $this->errorFactory->create($error); +// +// return new JsonResponse($errorDto, $errorDto->status); +// +// } catch (Throwable $exception) { +// $error = new ErrorDto(); +// return new JsonResponse($error, $error->status); +// } + } +} diff --git a/app/src/Request/AbstractRequest.php b/app/src/Shared/Abstraction/AbstractRequest.php similarity index 88% rename from app/src/Request/AbstractRequest.php rename to app/src/Shared/Abstraction/AbstractRequest.php index 9ddccd5..a7be59c 100644 --- a/app/src/Request/AbstractRequest.php +++ b/app/src/Shared/Abstraction/AbstractRequest.php @@ -1,9 +1,10 @@ add(new ValidateErrorDto($error)); + $messages->add((new ValidateErrorDtoFactory($error))->create()); } if ($messages->count() > 0) { diff --git a/app/src/Shared/Abstraction/DtoInterface.php b/app/src/Shared/Abstraction/DtoInterface.php new file mode 100644 index 0000000..60a39cd --- /dev/null +++ b/app/src/Shared/Abstraction/DtoInterface.php @@ -0,0 +1,5 @@ +collectionType; } - /** Метод для сериализации коллекции в JSON */ public function jsonSerialize(): array { return $this->data; diff --git a/app/src/Shared/Dto/ErrorDto.php b/app/src/Shared/Dto/ErrorDto.php new file mode 100644 index 0000000..fe14352 --- /dev/null +++ b/app/src/Shared/Dto/ErrorDto.php @@ -0,0 +1,16 @@ +getStatusCode(), + message: $error->getMessage(), + code: $error->getCode(), + ); + } +} diff --git a/app/src/Shared/DtoFactory/FileDtoFactory.php b/app/src/Shared/DtoFactory/FileDtoFactory.php new file mode 100644 index 0000000..6fbc5c9 --- /dev/null +++ b/app/src/Shared/DtoFactory/FileDtoFactory.php @@ -0,0 +1,39 @@ +getId(), + name: $file->getName(), + description: $file->getDescription(), + size: $file->getSize(), + type: $file->getType(), + url: $file->getUrl(), + ); + } + + /** + * @param Collection $files + * @return DtoCollection + */ + public function createCollection(Collection $files): DtoCollection + { + $filesDto = $files->map(function(File $file) { + return $this->create($file); + }); + + return new DtoCollection( + FileDto::class, + $filesDto->toArray() + ); + } +} diff --git a/app/src/Shared/DtoFactory/PaginationDtoFactory.php b/app/src/Shared/DtoFactory/PaginationDtoFactory.php new file mode 100644 index 0000000..933de0c --- /dev/null +++ b/app/src/Shared/DtoFactory/PaginationDtoFactory.php @@ -0,0 +1,17 @@ + 0 ? $limit : 12; + $pages = ceil($total / $pageSize); + $page = ($page > 1) && ($page <= $pages) ? $page : 1; + + return new PaginationDto($page, $pages, $pageSize); + } +} diff --git a/app/src/Shared/DtoFactory/ValidateErrorDtoFactory.php b/app/src/Shared/DtoFactory/ValidateErrorDtoFactory.php new file mode 100644 index 0000000..9cb815a --- /dev/null +++ b/app/src/Shared/DtoFactory/ValidateErrorDtoFactory.php @@ -0,0 +1,20 @@ +getPropertyPath() . ' : ' . $error->getMessage(), + code: ErrorCode::ValidateFailed->value, + status: 422 + ); + } +} diff --git a/app/src/Controller/.gitignore b/app/src/Shared/Entity/.gitignore similarity index 100% rename from app/src/Controller/.gitignore rename to app/src/Shared/Entity/.gitignore diff --git a/app/src/Entity/File.php b/app/src/Shared/Entity/File.php similarity index 93% rename from app/src/Entity/File.php rename to app/src/Shared/Entity/File.php index 751cb27..5c448b7 100644 --- a/app/src/Entity/File.php +++ b/app/src/Shared/Entity/File.php @@ -1,17 +1,16 @@ id = $this->getId(); - $dto->name = $this->getName(); - $dto->description = $this->getDescription(); - $dto->size = $this->getSize(); - $dto->type = $this->getType(); - $dto->url = $this->getUrl(); - - return $dto; - } } diff --git a/app/src/Entity/Kitchens.php b/app/src/Shared/Entity/Kitchens.php similarity index 82% rename from app/src/Entity/Kitchens.php rename to app/src/Shared/Entity/Kitchens.php index d45bf0a..b6eb7b1 100644 --- a/app/src/Entity/Kitchens.php +++ b/app/src/Shared/Entity/Kitchens.php @@ -1,17 +1,16 @@ id = $this->getId(); - $dto->name = $this->getName(); - $dto->code = $this->getCode(); - - return $dto; - } } diff --git a/app/src/Entity/News.php b/app/src/Shared/Entity/News.php similarity index 80% rename from app/src/Entity/News.php rename to app/src/Shared/Entity/News.php index 53a1595..9640253 100644 --- a/app/src/Entity/News.php +++ b/app/src/Shared/Entity/News.php @@ -1,18 +1,19 @@ id = $this->getId(); - $entity->name = $this->getName(); - $entity->description = $this->getDetailText(); - $entity->image = $this->getPreviewImage()?->getDto(); - $entity->create_at = $this->getCreatedAt()->format('Y-m-d H:i:s'); - $entity->detail_link = "api/v1/restaurants/" . $this->getId(); - - return $entity; - } - - /** @inheritDoc */ - public function getExtendedDto(): DtoInterface - { - $entity = new NewsDetailElementDto(); - - $entity->id = $this->getId(); - $entity->name = $this->getName(); - $entity->description = $this->getPreviewText(); - $entity->text = $this->getDetailText(); - $entity->image = $this->getPreviewImage()?->getDto(); - $entity->create_at = $this->getCreatedAt()->format('Y-m-d H:i:s'); - - return $entity; - } } diff --git a/app/src/Entity/NewsCategories.php b/app/src/Shared/Entity/NewsCategories.php similarity index 81% rename from app/src/Entity/NewsCategories.php rename to app/src/Shared/Entity/NewsCategories.php index 0f77fd1..f4b30cb 100644 --- a/app/src/Entity/NewsCategories.php +++ b/app/src/Shared/Entity/NewsCategories.php @@ -1,17 +1,18 @@ id = $this->getId(); - $dto->name = $this->getName(); - $dto->code = $this->getCode(); - - return $dto; - } } diff --git a/app/src/Entity/NewsType.php b/app/src/Shared/Entity/NewsType.php similarity index 95% rename from app/src/Entity/NewsType.php rename to app/src/Shared/Entity/NewsType.php index 8331456..d7d724e 100644 --- a/app/src/Entity/NewsType.php +++ b/app/src/Shared/Entity/NewsType.php @@ -1,9 +1,8 @@ id = $this->getId(); - $dto->name = $this->getName(); - $dto->code = $this->getCode(); - - return $dto; - } } diff --git a/app/src/Entity/Restaurants.php b/app/src/Shared/Entity/Restaurants.php similarity index 69% rename from app/src/Entity/Restaurants.php rename to app/src/Shared/Entity/Restaurants.php index 69e614c..a88eba4 100644 --- a/app/src/Entity/Restaurants.php +++ b/app/src/Shared/Entity/Restaurants.php @@ -1,23 +1,24 @@ id = $this->getId(); - $dto->name = $this->getName(); - $dto->code = $this->getCode(); - $dto->type = $this->getType()->getDto(); - $dto->check = $this->getReceipt(); - $dto->image = $this->getPreviewImage()?->getDto(); - $dto->detail_link = 'api/v1/restaurants/' . $this->getId(); - - return $dto; - } - - /** @inheritDoc - * @throws \JsonException Если получен неправильный json с бд - */ - public function getExtendedDto(): DtoInterface - { - $dto = new RestaurantDetailElementDto(); - - $dto->id = $this->getId(); - $dto->name = $this->getName(); - $dto->code = $this->getCode(); - $dto->coordinates = $this->getCoordinates(); - $dto->type = $this->getType()->getDto(); - $dto->check = $this->getReceipt(); - $dto->check_info = $this->getReceiptInfo(); - - $dto->kitchen = new DtoCollection( - KitchenTypeDto::class, - $this->getKitchens() - ->map(function(Kitchens $kitchen) { - return $kitchen->getDto(); - }) - ->toArray() - ); - - $dto->phone = $this->decode($this->getPhone()); - $dto->email = $this->decode($this->getEmail()); - $dto->address = $this->decode($this->getAddress()); - $dto->tags = $this->decodeTags($this->getTags()); - $dto->site = $this->getSite(); - $dto->image = $this->getPreviewImage()?->getDto(); - $dto->gallery = new DtoCollection( - FileDto::class, - $this->getGallery() - ->map(function(File $file) { - return $file->getDto(); - }) - ->toArray() - ); - - return $dto; - } - - /** - * @throws \JsonException Если получен неправильный json с бд - * @return ?DtoCollection - */ - private function decode(?string $jsonString): ?DtoCollection - { - if ($jsonString === null) { - return null; - } - return new DtoCollection( - 'string', - json_decode( - $jsonString, - true, - 512, - JSON_THROW_ON_ERROR - ) - ); - } - - private function decodeTags(?string $jsonString): ?DtoCollection - { - if ($jsonString === null) { - return null; - } - - $jsonCollection = new RamseyCollection( - 'array', - json_decode( - $jsonString, - true, - 512, - JSON_THROW_ON_ERROR - ) - ); - - $tagCollection = new DtoCollection(TagDto::class); - foreach ($jsonCollection as $name => $jsonItem) { - $tagCollection->add( - new TagDto($name, new DtoCollection('string', $jsonItem)) - ); - } - - return $tagCollection; - } } diff --git a/app/src/Entity/Settlements.php b/app/src/Shared/Entity/Settlements.php similarity index 97% rename from app/src/Entity/Settlements.php rename to app/src/Shared/Entity/Settlements.php index 6f6dc92..3c26eb1 100644 --- a/app/src/Entity/Settlements.php +++ b/app/src/Shared/Entity/Settlements.php @@ -1,8 +1,8 @@ value + ); + } +} diff --git a/app/src/Shared/Error/ErrorCode.php b/app/src/Shared/Error/ErrorCode.php new file mode 100644 index 0000000..a9495f4 --- /dev/null +++ b/app/src/Shared/Error/ErrorCode.php @@ -0,0 +1,10 @@ +createQueryBuilder('n'); - $query = $this->getByFilters($categoryId, $query); + $query = $this->findByFilters($categoryId, $query); return $query->select('COUNT(n.id)')->getQuery()->getSingleScalarResult(); } /** @return Collection */ - public function findByFilters(?string $categoryId, int $limit, int $offset): Collection + public function getWithFilters(?string $categoryId, int $limit, int $offset): Collection { $query = $this->createQueryBuilder('n'); - $query = $this->getByFilters($categoryId, $query); + $query = $this->findByFilters($categoryId, $query); $query = $query->setMaxResults($limit); $query = $query->setFirstResult($offset); return $this->toCollection($query); } - /** @return Collection */ + /** @return Collection */ public function getAll(): Collection { return $this->toCollection($this->createQueryBuilder('n')); } - public function getMain(): News - { - return $this->createQueryBuilder('n') - ->andWhere('n.mainPageRender = true') - ->setMaxResults(1) - ->getQuery() - ->getResult()[0]; - } - /** * @param QueryBuilder $query * @return Collection @@ -81,7 +71,7 @@ class NewsRepository extends ServiceEntityRepository implements NewsRepositoryIn ); } - protected function getByFilters(?string $categoryId, QueryBuilder $query): QueryBuilder + protected function findByFilters(?string $categoryId, QueryBuilder $query): QueryBuilder { if ($categoryId !== null) { $query = $query diff --git a/app/src/Repository/NewsTypeRepository.php b/app/src/Shared/Repository/NewsTypeRepository.php similarity index 92% rename from app/src/Repository/NewsTypeRepository.php rename to app/src/Shared/Repository/NewsTypeRepository.php index e2acd17..e3decdf 100644 --- a/app/src/Repository/NewsTypeRepository.php +++ b/app/src/Shared/Repository/NewsTypeRepository.php @@ -1,8 +1,8 @@ where('r.type.id = :typeId') + ->where('r.type = :typeId') ->setParameter('typeId', $typeId); } return $query; @@ -65,7 +65,7 @@ class RestaurantsRepository extends ServiceEntityRepository implements Restauran } /** @return Collection */ - public function findByFilters(?string $kitchenId, ?string $typeId, int $limit, int $offset): Collection + public function getWithFilters(?string $kitchenId, ?string $typeId, int $limit, int $offset): Collection { $query = $this->createQueryBuilder('r'); $query = $this->filterByKitchen($kitchenId, $query); diff --git a/app/src/Repository/SettlementsRepository.php b/app/src/Shared/Repository/SettlementsRepository.php similarity index 90% rename from app/src/Repository/SettlementsRepository.php rename to app/src/Shared/Repository/SettlementsRepository.php index 66a2f2d..e83866a 100644 --- a/app/src/Repository/SettlementsRepository.php +++ b/app/src/Shared/Repository/SettlementsRepository.php @@ -1,8 +1,9 @@ Date: Fri, 17 May 2024 04:36:10 +0500 Subject: [PATCH 11/12] STA-960 | small fixes --- app/config/services.yaml | 14 +- .../Collection/NewsCategoryCollection.php | 16 +++ app/src/News/Controller/NewsController.php | 49 +++---- app/src/News/Dto/NewsCategoryDto.php | 9 +- app/src/News/Dto/NewsDetailElementDto.php | 21 +-- app/src/News/Dto/NewsFilterVariantsDto.php | 12 +- app/src/News/Dto/NewsListDto.php | 17 ++- app/src/News/Dto/NewsListingElementDto.php | 16 +-- .../DtoFactory/NewsCategoryDtoFactory.php | 9 +- .../NewsDetailElementDtoFactory.php | 5 +- .../NewsFilterVariantsDtoFactory.php | 6 +- .../News/DtoFactory/NewsListDtoFactory.php | 7 +- .../NewsListingElementDtoFactory.php | 20 +-- app/src/News/Request/NewsListingRequest.php | 31 ----- app/src/News/Service/NewsDetailService.php | 31 ----- app/src/News/Service/NewsListingService.php | 57 -------- app/src/News/Service/NewsMainNewsService.php | 22 ---- .../Service/NewsPrepareResponseService.php | 114 ++++++++++++++++ app/src/News/Service/NewsSearchService.php | 22 ---- .../Collection/KitchenCollection.php | 16 +++ .../Collection/RestaurantTypeCollection.php | 16 +++ .../Restaurants/Collection/TagCollection.php | 16 +++ .../Controller/RestaurantsController.php | 35 +++-- app/src/Restaurants/Dto/KitchenTypeDto.php | 6 +- .../Dto/RestaurantDetailElementDto.php | 47 +++---- .../Dto/RestaurantFilterVariantsDto.php | 15 +-- app/src/Restaurants/Dto/RestaurantListDto.php | 12 +- .../Dto/RestaurantListingElementDto.php | 10 +- app/src/Restaurants/Dto/RestaurantTypeDto.php | 6 +- app/src/Restaurants/Dto/TagDto.php | 10 +- .../DtoFactory/KitchenTypeDtoFactory.php | 18 ++- .../RestaurantDetailElementDtoFactory.php | 27 ++-- .../RestaurantFilterVariantsDtoFactory.php | 7 +- .../DtoFactory/RestaurantListDtoFactory.php | 6 +- .../RestaurantListingElementDtoFactory.php | 11 +- .../DtoFactory/RestaurantTypeDtoFactory.php | 9 +- .../Restaurants/DtoFactory/TagDtoFactory.php | 11 +- .../Request/RestaurantListingRequest.php | 36 ------ .../Service/RestaurantDetailService.php | 34 ----- .../Service/RestaurantListingService.php | 71 ---------- .../RestaurantPrepareRequestService.php | 122 ++++++++++++++++++ .../Shared/Abstraction/AbstractController.php | 52 +++++--- .../Abstraction/AbstractDetailElement.php | 9 ++ .../Shared/Abstraction/AbstractListDto.php | 14 ++ .../Abstraction/AbstractListingElementDto.php | 10 ++ .../Shared/Abstraction/AbstractRequest.php | 75 ----------- app/src/Shared/Abstraction/DtoInterface.php | 5 - .../Shared/Abstraction/EntityInterface.php | 5 - .../Shared/Abstraction/ServiceInterface.php | 15 ++- .../{Dto => Collection}/DtoCollection.php | 4 +- app/src/Shared/Collection/FileCollection.php | 15 +++ .../Shared/Collection/ListingCollection.php | 15 +++ .../Shared/Collection/StringCollection.php | 13 ++ app/src/Shared/Dto/ErrorDto.php | 9 +- app/src/Shared/Dto/FileDto.php | 12 +- app/src/Shared/Dto/PaginationDto.php | 7 +- app/src/Shared/Dto/ValidateErrorDto.php | 9 +- app/src/Shared/DtoFactory/ErrorDtoFactory.php | 10 +- app/src/Shared/DtoFactory/FileDtoFactory.php | 11 +- .../DtoFactory/PaginationDtoFactory.php | 2 +- .../DtoFactory/ValidateErrorDtoFactory.php | 5 +- app/src/Shared/Entity/File.php | 24 ++-- app/src/Shared/Entity/Kitchens.php | 3 +- app/src/Shared/Entity/News.php | 4 - app/src/Shared/Entity/NewsCategories.php | 5 +- app/src/Shared/Entity/RestaurantTypes.php | 3 +- app/src/Shared/Entity/Restaurants.php | 24 ++-- app/src/Shared/Error/BaseError.php | 3 +- app/src/Shared/Error/ErrorCode.php | 2 + app/src/Shared/Error/NonValidUuidError.php | 16 +++ app/src/Shared/Error/NotFoundError.php | 7 +- app/src/Shared/Request/DetailRequest.php | 26 ---- app/src/Shared/Request/EmptyRequest.php | 12 -- app/src/Shared/Service/ValidateService.php | 25 ++++ docker-compose.yml => compose.yaml | 0 75 files changed, 723 insertions(+), 747 deletions(-) create mode 100644 app/src/News/Collection/NewsCategoryCollection.php delete mode 100644 app/src/News/Request/NewsListingRequest.php delete mode 100644 app/src/News/Service/NewsDetailService.php delete mode 100644 app/src/News/Service/NewsListingService.php delete mode 100644 app/src/News/Service/NewsMainNewsService.php create mode 100644 app/src/News/Service/NewsPrepareResponseService.php delete mode 100644 app/src/News/Service/NewsSearchService.php create mode 100644 app/src/Restaurants/Collection/KitchenCollection.php create mode 100644 app/src/Restaurants/Collection/RestaurantTypeCollection.php create mode 100644 app/src/Restaurants/Collection/TagCollection.php delete mode 100644 app/src/Restaurants/Request/RestaurantListingRequest.php delete mode 100644 app/src/Restaurants/Service/RestaurantDetailService.php delete mode 100644 app/src/Restaurants/Service/RestaurantListingService.php create mode 100644 app/src/Restaurants/Service/RestaurantPrepareRequestService.php create mode 100644 app/src/Shared/Abstraction/AbstractDetailElement.php create mode 100644 app/src/Shared/Abstraction/AbstractListDto.php create mode 100644 app/src/Shared/Abstraction/AbstractListingElementDto.php delete mode 100644 app/src/Shared/Abstraction/AbstractRequest.php delete mode 100644 app/src/Shared/Abstraction/DtoInterface.php delete mode 100644 app/src/Shared/Abstraction/EntityInterface.php rename app/src/Shared/{Dto => Collection}/DtoCollection.php (87%) create mode 100644 app/src/Shared/Collection/FileCollection.php create mode 100644 app/src/Shared/Collection/ListingCollection.php create mode 100644 app/src/Shared/Collection/StringCollection.php create mode 100644 app/src/Shared/Error/NonValidUuidError.php delete mode 100644 app/src/Shared/Request/DetailRequest.php delete mode 100644 app/src/Shared/Request/EmptyRequest.php create mode 100644 app/src/Shared/Service/ValidateService.php rename docker-compose.yml => compose.yaml (100%) diff --git a/app/config/services.yaml b/app/config/services.yaml index 55758d4..851a662 100644 --- a/app/config/services.yaml +++ b/app/config/services.yaml @@ -14,11 +14,9 @@ services: # add more service definitions when explicit configuration is needed # please note that last definitions always *replace* previous ones - App\Restaurants\: - resource: '../src/Restaurants/' - - App\News\: - resource: '../src/News/' - - App\Shared\: - resource: '../src/Shared/' \ No newline at end of file + App\: + resource: '../src/' + exclude: + - '../src/DependencyInjection/' + - '../src/Entity/' + - '../src/Kernel.php' diff --git a/app/src/News/Collection/NewsCategoryCollection.php b/app/src/News/Collection/NewsCategoryCollection.php new file mode 100644 index 0000000..cd3b77d --- /dev/null +++ b/app/src/News/Collection/NewsCategoryCollection.php @@ -0,0 +1,16 @@ +collectionType, $data); + } +} diff --git a/app/src/News/Controller/NewsController.php b/app/src/News/Controller/NewsController.php index 286ff07..98694b5 100644 --- a/app/src/News/Controller/NewsController.php +++ b/app/src/News/Controller/NewsController.php @@ -2,16 +2,11 @@ namespace App\News\Controller; -use App\News\Request\NewsListingRequest; -use App\News\Service\NewsDetailService; -use App\News\Service\NewsListingService; -use App\News\Service\NewsMainNewsService; -use App\News\Service\NewsSearchService; +use App\News\Service\NewsPrepareResponseService; use App\Shared\Abstraction\AbstractController; use App\Shared\DtoFactory\ErrorDtoFactory; -use App\Shared\Request\DetailRequest; -use App\Shared\Request\EmptyRequest; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpKernel\Attribute\MapQueryParameter; use Symfony\Component\Routing\Attribute\Route; #[Route('/api/v1/news')] @@ -19,36 +14,46 @@ class NewsController extends AbstractController { public function __construct( ErrorDtoFactory $errorFactory, - - private readonly NewsDetailService $detailService, - private readonly NewsListingService $listingService, - private readonly NewsMainNewsService $mainNewsService, - private readonly NewsSearchService $searchService, + private readonly NewsPrepareResponseService $responsePrepareService, ) { parent::__construct($errorFactory); } #[Route('/', name: 'news', methods: ['GET'])] - public function news(NewsListingRequest $request): JsonResponse - { - return $this->handle($this->listingService, $request); + public function news( + #[MapQueryParameter] int $page = 1, + #[MapQueryParameter] int $limit = 12, + #[MapQueryParameter] string $news_category = null + ): JsonResponse { + return $this->handleListing( + $this->responsePrepareService, + $page, + $limit, + $news_category, + ); } #[Route('/mainNews', name: 'mainNews', methods: ['GET'])] - public function mainNews(EmptyRequest $request): JsonResponse + public function mainNews(): JsonResponse { - return $this->handle($this->mainNewsService, $request); + return new JsonResponse($this->responsePrepareService->bornMainNews()); } #[Route('/search', name: 'searchNews', methods: ['GET'])] - public function search(EmptyRequest $request): JsonResponse + public function search(): JsonResponse { - return $this->handle($this->searchService, $request); + return new JsonResponse( + $this->responsePrepareService->bornDetailMainNews() + ); } #[Route('/{detailId}', name: 'oneNews', methods: ['GET'])] - public function oneNews(DetailRequest $request): JsonResponse - { - return $this->handle($this->detailService, $request); + public function oneNews( + #[MapQueryParameter] string $detailId = null + ): JsonResponse { + return $this->handleDetailElement( + $this->responsePrepareService, + $detailId, + ); } } diff --git a/app/src/News/Dto/NewsCategoryDto.php b/app/src/News/Dto/NewsCategoryDto.php index 21917d9..010a7e7 100644 --- a/app/src/News/Dto/NewsCategoryDto.php +++ b/app/src/News/Dto/NewsCategoryDto.php @@ -2,15 +2,12 @@ namespace App\News\Dto; -use App\Shared\Abstraction\DtoInterface; - -class NewsCategoryDto implements DtoInterface +class NewsCategoryDto { public function __construct( public string $id, - public string $name, - public string $code, - ) {} + ) { + } } diff --git a/app/src/News/Dto/NewsDetailElementDto.php b/app/src/News/Dto/NewsDetailElementDto.php index 634effa..530f5e0 100644 --- a/app/src/News/Dto/NewsDetailElementDto.php +++ b/app/src/News/Dto/NewsDetailElementDto.php @@ -2,23 +2,26 @@ namespace App\News\Dto; -use App\Shared\Abstraction\DtoInterface; +use App\Shared\Abstraction\AbstractDetailElement; use App\Shared\Dto\FileDto; -class NewsDetailElementDto implements DtoInterface +class NewsDetailElementDto extends AbstractDetailElement { + /** + * @param string $id + * @param string $name + * @param string $description + * @param string $createAt + * @param string|null $text + * @param FileDto|null $image Преаью + */ public function __construct( public string $id, - public string $name, - public string $description, - public string $createAt, - public ?string $text = null, - - /** @var FileDto Преаью */ public ?FileDto $image = null, - ) {} + ) { + } } diff --git a/app/src/News/Dto/NewsFilterVariantsDto.php b/app/src/News/Dto/NewsFilterVariantsDto.php index b3f9f5c..0544560 100644 --- a/app/src/News/Dto/NewsFilterVariantsDto.php +++ b/app/src/News/Dto/NewsFilterVariantsDto.php @@ -2,16 +2,16 @@ namespace App\News\Dto; -use App\Shared\Abstraction\DtoInterface; -use App\Shared\Dto\DtoCollection; +use App\News\Collection\NewsCategoryCollection; -class NewsFilterVariantsDto implements DtoInterface +class NewsFilterVariantsDto { /** - * @param DtoCollection $category + * @param NewsCategoryCollection $category */ public function __construct( - public DtoCollection $category, - ) {} + public NewsCategoryCollection $category, + ) { + } } diff --git a/app/src/News/Dto/NewsListDto.php b/app/src/News/Dto/NewsListDto.php index d4ffffd..63da8fa 100644 --- a/app/src/News/Dto/NewsListDto.php +++ b/app/src/News/Dto/NewsListDto.php @@ -2,22 +2,21 @@ namespace App\News\Dto; -use App\Shared\Abstraction\DtoInterface; -use App\Shared\Dto\DtoCollection; +use App\Shared\Abstraction\AbstractListDto; +use App\Shared\Collection\ListingCollection; use App\Shared\Dto\PaginationDto; -class NewsListDto implements DtoInterface +class NewsListDto extends AbstractListDto { /** * @param PaginationDto $pagination - * @param DtoCollection $list + * @param ListingCollection $list * @param NewsFilterVariantsDto $filterVariants */ public function __construct( - public PaginationDto $pagination, - - public DtoCollection $list, - + public PaginationDto $pagination, + public ListingCollection $list, public NewsFilterVariantsDto $filterVariants, - ) {} + ) { + } } diff --git a/app/src/News/Dto/NewsListingElementDto.php b/app/src/News/Dto/NewsListingElementDto.php index dd6c610..a291ea1 100644 --- a/app/src/News/Dto/NewsListingElementDto.php +++ b/app/src/News/Dto/NewsListingElementDto.php @@ -2,30 +2,26 @@ namespace App\News\Dto; -use App\Shared\Abstraction\DtoInterface; +use App\Shared\Abstraction\AbstractListingElementDto; use App\Shared\Dto\FileDto; -class NewsListingElementDto implements DtoInterface +class NewsListingElementDto extends AbstractListingElementDto { /** * @param string $id * @param string $name - * @param string $create_at - * @param string $detail_link + * @param string $createAt + * @param string $detailLink * @param string|null $description * @param FileDto|null $image Превью */ public function __construct( public string $id, - public string $name, - public string $createAt, - public string $detailLink, - public ?string $description = null, - public ?FileDto $image = null, - ) {} + ) { + } } diff --git a/app/src/News/DtoFactory/NewsCategoryDtoFactory.php b/app/src/News/DtoFactory/NewsCategoryDtoFactory.php index f5726a8..b9388fc 100644 --- a/app/src/News/DtoFactory/NewsCategoryDtoFactory.php +++ b/app/src/News/DtoFactory/NewsCategoryDtoFactory.php @@ -2,8 +2,8 @@ namespace App\News\DtoFactory; +use App\News\Collection\NewsCategoryCollection; use App\News\Dto\NewsCategoryDto; -use App\Shared\Dto\DtoCollection; use App\Shared\Entity\NewsCategories; use Ramsey\Collection\Collection; @@ -20,16 +20,15 @@ class NewsCategoryDtoFactory /** * @param Collection $categories - * @return DtoCollection + * @return NewsCategoryCollection */ - public function createCollection(Collection $categories): DtoCollection + public function createCollection(Collection $categories): NewsCategoryCollection { $categoriesDto = $categories->map(function(NewsCategories $category) { return $this->create($category); }); - return new DtoCollection( - NewsCategoryDto::class, + return new NewsCategoryCollection( $categoriesDto->toArray() ); } diff --git a/app/src/News/DtoFactory/NewsDetailElementDtoFactory.php b/app/src/News/DtoFactory/NewsDetailElementDtoFactory.php index c4a82b0..ad29868 100644 --- a/app/src/News/DtoFactory/NewsDetailElementDtoFactory.php +++ b/app/src/News/DtoFactory/NewsDetailElementDtoFactory.php @@ -10,7 +10,8 @@ class NewsDetailElementDtoFactory { public function __construct( private readonly FileDtoFactory $fileFactory - ) {} + ) { + } public function create(News $news): NewsDetailElementDto { @@ -18,7 +19,7 @@ class NewsDetailElementDtoFactory id: $news->getId(), name: $news->getName(), description: $news->getPreviewText(), - createAt: $news->getCreatedAt()->format('Y-m-d H:i:s'), + createAt: $news->getCreatedAt()?->format('d.m.Y'), text: $news->getDetailText(), image: $news->getPreviewImage() !== null ? $this->fileFactory->create($news->getPreviewImage()) diff --git a/app/src/News/DtoFactory/NewsFilterVariantsDtoFactory.php b/app/src/News/DtoFactory/NewsFilterVariantsDtoFactory.php index 80f54fe..ab0c5ff 100644 --- a/app/src/News/DtoFactory/NewsFilterVariantsDtoFactory.php +++ b/app/src/News/DtoFactory/NewsFilterVariantsDtoFactory.php @@ -2,17 +2,17 @@ namespace App\News\DtoFactory; +use App\News\Collection\NewsCategoryCollection; use App\News\Dto\NewsCategoryDto; use App\News\Dto\NewsFilterVariantsDto; -use App\Shared\Dto\DtoCollection; class NewsFilterVariantsDtoFactory { /** - * @param DtoCollection $categories + * @param NewsCategoryCollection $categories * @return NewsFilterVariantsDto */ - public function create(DtoCollection $categories): NewsFilterVariantsDto + public function create(NewsCategoryCollection $categories): NewsFilterVariantsDto { return new NewsFilterVariantsDto( $categories diff --git a/app/src/News/DtoFactory/NewsListDtoFactory.php b/app/src/News/DtoFactory/NewsListDtoFactory.php index 40f714f..25613a7 100644 --- a/app/src/News/DtoFactory/NewsListDtoFactory.php +++ b/app/src/News/DtoFactory/NewsListDtoFactory.php @@ -4,17 +4,16 @@ namespace App\News\DtoFactory; use App\News\Dto\NewsFilterVariantsDto; use App\News\Dto\NewsListDto; -use App\Shared\Dto\DtoCollection; +use App\Shared\Collection\ListingCollection; use App\Shared\Dto\PaginationDto; class NewsListDtoFactory { public function create( PaginationDto $pagination, - DtoCollection $list, + ListingCollection $list, NewsFilterVariantsDto $filters, - ): NewsListDto - { + ): NewsListDto { return new NewsListDto( pagination: $pagination, list: $list, diff --git a/app/src/News/DtoFactory/NewsListingElementDtoFactory.php b/app/src/News/DtoFactory/NewsListingElementDtoFactory.php index 668b6ac..11d4412 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\Dto\DtoCollection; +use App\Shared\Collection\ListingCollection; use App\Shared\DtoFactory\FileDtoFactory; use App\Shared\Entity\News; use Ramsey\Collection\Collection; @@ -12,34 +12,34 @@ class NewsListingElementDtoFactory { public function __construct( private readonly FileDtoFactory $fileFactory, - ) {} + ) { + } public function create(News $news): NewsListingElementDto { return new NewsListingElementDto( id: $news->getId(), name: $news->getName(), - createAt: $news->getCreatedAt()->format('Y-m-d H:i:s'), + createAt: $news->getCreatedAt()?->format('d.m.Y'), detailLink: "api/v1/news/" . $news->getId(), description: $news->getPreviewText(), image: $news->getPreviewImage() !== null ? $this->fileFactory->create($news->getPreviewImage()) - :null, + : null, ); } /** * @param Collection $news - * @return DtoCollection + * @return ListingCollection */ - public function createCollection(Collection $news): DtoCollection + public function createCollection(Collection $news): ListingCollection { - return new DtoCollection( - NewsListingElementDto::class, - $news->map(function(News $oneNews) { + return new ListingCollection( + $news->map(function (News $oneNews) { return $this->create($oneNews); }) - ->toArray() + ->toArray() ); } } diff --git a/app/src/News/Request/NewsListingRequest.php b/app/src/News/Request/NewsListingRequest.php deleted file mode 100644 index 31d99f6..0000000 --- a/app/src/News/Request/NewsListingRequest.php +++ /dev/null @@ -1,31 +0,0 @@ -getRequest(); - foreach ($request->query->getIterator() as $property => $value) { - if (property_exists($this, $property)) { - $this->{$property} = $value; - } - } - } -} diff --git a/app/src/News/Service/NewsDetailService.php b/app/src/News/Service/NewsDetailService.php deleted file mode 100644 index 8397215..0000000 --- a/app/src/News/Service/NewsDetailService.php +++ /dev/null @@ -1,31 +0,0 @@ -news->find($request->detailId); - - return $news !== null - ? $this->dtoFactory->create($news) - : throw new NotFoundError('News not found'); - } -} diff --git a/app/src/News/Service/NewsListingService.php b/app/src/News/Service/NewsListingService.php deleted file mode 100644 index fd32d9f..0000000 --- a/app/src/News/Service/NewsListingService.php +++ /dev/null @@ -1,57 +0,0 @@ -news->getCountWithFilters($request->news_category); - - $pagination = $this->paginationFactory->create( - $request->page, - $request->limit, - $countOfNews - ); - - $offset = min($pagination->pageSize, $countOfNews) * ($pagination->currentPage - 1); - - $list = $this->listFactory->createCollection( - $this->news->getWithFilters($request->news_category, $request->limit, $offset) - ); - - $categoriesDto = $this->categoryFactory->createCollection( - $this->newsCategories->getAll() - ); - - $filters = $this->filterFactory->create($categoriesDto); - - return $this->listingFactory->create( - $pagination, - $list, - $filters - ); - } -} diff --git a/app/src/News/Service/NewsMainNewsService.php b/app/src/News/Service/NewsMainNewsService.php deleted file mode 100644 index 784633d..0000000 --- a/app/src/News/Service/NewsMainNewsService.php +++ /dev/null @@ -1,22 +0,0 @@ -dtoFactory->create($this->news->getMainNews()); - } -} diff --git a/app/src/News/Service/NewsPrepareResponseService.php b/app/src/News/Service/NewsPrepareResponseService.php new file mode 100644 index 0000000..dbdd17c --- /dev/null +++ b/app/src/News/Service/NewsPrepareResponseService.php @@ -0,0 +1,114 @@ +|null ...$filters + * @return AbstractListDto + */ + public function bornListDto( + int $page, + int $limit, + ?array $filters + ): AbstractListDto { + $filters['news_category'] = $filters[0]; + if (!$this->validate->isValidUuid($filters['news_category'])) { + $filters['news_category'] = null; + } + + $this->validate->correctPagination($page, $limit); + + $countOfNews = $this->news->getCountWithFilters( + $filters['news_category'] + ); + + $pagination = $this->paginationFactory->create( + $page, + $limit, + $countOfNews + ); + + $offset = min( + $pagination->pageSize, + $countOfNews + ) * ($pagination->currentPage - 1); + + $list = $this->listFactory->createCollection( + $this->news->getWithFilters( + $filters['news_category'], + $limit, + $offset + ) + ); + + $filters = $this->filterFactory->create( + $this->categoryFactory->createCollection( + $this->newsCategories->getAll() + ) + ); + + return $this->listingFactory->create( + $pagination, + $list, + $filters + ); + } + + public function bornMainNews(): NewsListingElementDto + { + return $this->listFactory->create($this->news->getMainNews()); + } + + public function bornDetailMainNews(): NewsDetailElementDto + { + return $this->detailElementFactory->create($this->news->getMainNews()); + } + + public function bornDetailElement(string $detailId): NewsDetailElementDto + { + if (!$this->validate->isValidUuid($detailId)) { + throw new NonValidUuidError(); + } + + $news = $this->news->find($detailId); + + if ($news === null) { + throw new NotFoundError('News not found'); + } + + return $this->detailElementFactory->create($news); + } +} diff --git a/app/src/News/Service/NewsSearchService.php b/app/src/News/Service/NewsSearchService.php deleted file mode 100644 index 391d3c9..0000000 --- a/app/src/News/Service/NewsSearchService.php +++ /dev/null @@ -1,22 +0,0 @@ -dtoFactory->create($this->news->getMainNews()); - } -} diff --git a/app/src/Restaurants/Collection/KitchenCollection.php b/app/src/Restaurants/Collection/KitchenCollection.php new file mode 100644 index 0000000..a2eb60a --- /dev/null +++ b/app/src/Restaurants/Collection/KitchenCollection.php @@ -0,0 +1,16 @@ +collectionType, $data); + } +} diff --git a/app/src/Restaurants/Collection/RestaurantTypeCollection.php b/app/src/Restaurants/Collection/RestaurantTypeCollection.php new file mode 100644 index 0000000..8f4091f --- /dev/null +++ b/app/src/Restaurants/Collection/RestaurantTypeCollection.php @@ -0,0 +1,16 @@ +collectionType, $data); + } +} diff --git a/app/src/Restaurants/Collection/TagCollection.php b/app/src/Restaurants/Collection/TagCollection.php new file mode 100644 index 0000000..dec7c1c --- /dev/null +++ b/app/src/Restaurants/Collection/TagCollection.php @@ -0,0 +1,16 @@ +collectionType, $data); + } +} diff --git a/app/src/Restaurants/Controller/RestaurantsController.php b/app/src/Restaurants/Controller/RestaurantsController.php index 5893ecb..eea4f2d 100644 --- a/app/src/Restaurants/Controller/RestaurantsController.php +++ b/app/src/Restaurants/Controller/RestaurantsController.php @@ -2,13 +2,11 @@ namespace App\Restaurants\Controller; -use App\Restaurants\Request\RestaurantListingRequest; -use App\Restaurants\Service\RestaurantDetailService; -use App\Restaurants\Service\RestaurantListingService; +use App\Restaurants\Service\RestaurantPrepareRequestService; use App\Shared\Abstraction\AbstractController; use App\Shared\DtoFactory\ErrorDtoFactory; -use App\Shared\Request\DetailRequest; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpKernel\Attribute\MapQueryParameter; use Symfony\Component\Routing\Attribute\Route; #[Route('/api/v1/restaurants')] @@ -16,22 +14,33 @@ class RestaurantsController extends AbstractController { public function __construct( ErrorDtoFactory $errorFactory, - - private readonly RestaurantListingService $listingService, - private readonly RestaurantDetailService $detailService, + private readonly RestaurantPrepareRequestService $responsePrepareService, ) { parent::__construct($errorFactory); } #[Route('/', name: 'restaurants', methods: ['GET'])] - public function restaurants(RestaurantListingRequest $request): JsonResponse - { - return $this->handle($this->listingService, $request); + public function restaurants( + #[MapQueryParameter] int $page = 1, + #[MapQueryParameter] int $limit = 12, + #[MapQueryParameter] string $restaurant_type_id = null, + #[MapQueryParameter] string $kitchen_id = null, + ): JsonResponse { + return $this->handleListing( + $this->responsePrepareService, + $page, + $limit, + $restaurant_type_id, + $kitchen_id, + ); } #[Route('/{detailId}', name: 'restaurant', methods: ['GET'])] - public function restaurant(DetailRequest $request): JsonResponse - { - return $this->handle($this->detailService, $request); + public function restaurant(#[MapQueryParameter] string $detailId = null + ): JsonResponse { + return $this->handleDetailElement( + $this->responsePrepareService, + $detailId, + ); } } diff --git a/app/src/Restaurants/Dto/KitchenTypeDto.php b/app/src/Restaurants/Dto/KitchenTypeDto.php index e326132..da4c576 100644 --- a/app/src/Restaurants/Dto/KitchenTypeDto.php +++ b/app/src/Restaurants/Dto/KitchenTypeDto.php @@ -2,15 +2,11 @@ namespace App\Restaurants\Dto; -use App\Shared\Abstraction\DtoInterface; - -class KitchenTypeDto implements DtoInterface +class KitchenTypeDto { public function __construct( public string $id, - public string $name, - public string $code, ) {} } diff --git a/app/src/Restaurants/Dto/RestaurantDetailElementDto.php b/app/src/Restaurants/Dto/RestaurantDetailElementDto.php index 41139b8..bf4d83f 100644 --- a/app/src/Restaurants/Dto/RestaurantDetailElementDto.php +++ b/app/src/Restaurants/Dto/RestaurantDetailElementDto.php @@ -2,11 +2,14 @@ namespace App\Restaurants\Dto; -use App\Shared\Abstraction\DtoInterface; -use App\Shared\Dto\DtoCollection; +use App\Restaurants\Collection\KitchenCollection; +use App\Restaurants\Collection\TagCollection; +use App\Shared\Abstraction\AbstractDetailElement; +use App\Shared\Collection\FileCollection; +use App\Shared\Collection\StringCollection; use App\Shared\Dto\FileDto; -class RestaurantDetailElementDto implements DtoInterface +class RestaurantDetailElementDto extends AbstractDetailElement { /** * @param string $id @@ -16,44 +19,30 @@ class RestaurantDetailElementDto implements DtoInterface * @param RestaurantTypeDto $type * @param string|null $check * @param string|null $check_info - * @param DtoCollection|null $kitchen - * @param DtoCollection|null $phone - * @param DtoCollection|null $email - * @param DtoCollection|null $address - * @param DtoCollection|null $tags + * @param KitchenCollection|null $kitchen + * @param StringCollection|null $phone + * @param StringCollection|null $email + * @param StringCollection|null $address + * @param TagCollection|null $tags * @param string|null $site * @param FileDto|null $image Превью - * @param DtoCollection|null $gallery + * @param FileCollection|null $gallery */ public function __construct( public string $id, - public string $name, - public string $code, - public string $coordinates, - public RestaurantTypeDto $type, - public ?string $check = null, - public ?string $check_info = null, - - public ?DtoCollection $kitchen = null, - - public ?DtoCollection $phone = null, - - public ?DtoCollection $email = null, - - public ?DtoCollection $address = null, - - public ?DtoCollection $tags = null, - + public ?KitchenCollection $kitchen = null, + public ?StringCollection $phone = null, + public ?StringCollection $email = null, + public ?StringCollection $address = null, + public ?TagCollection $tags = null, public ?string $site = null, - public ?FileDto $image = null, - - public ?DtoCollection $gallery = null, + public ?FileCollection $gallery = null, ) {} } diff --git a/app/src/Restaurants/Dto/RestaurantFilterVariantsDto.php b/app/src/Restaurants/Dto/RestaurantFilterVariantsDto.php index e4a15c1..d0e0e65 100644 --- a/app/src/Restaurants/Dto/RestaurantFilterVariantsDto.php +++ b/app/src/Restaurants/Dto/RestaurantFilterVariantsDto.php @@ -2,18 +2,17 @@ namespace App\Restaurants\Dto; -use App\Shared\Abstraction\DtoInterface; -use App\Shared\Dto\DtoCollection; +use App\Restaurants\Collection\KitchenCollection; +use App\Restaurants\Collection\RestaurantTypeCollection; -class RestaurantFilterVariantsDto implements DtoInterface +class RestaurantFilterVariantsDto { /** - * @param DtoCollection $type - * @param DtoCollection $kitchen + * @param RestaurantTypeCollection $type + * @param KitchenCollection $kitchen */ public function __construct( - public DtoCollection $type, - - public DtoCollection $kitchen, + public RestaurantTypeCollection $type, + public KitchenCollection $kitchen, ) {} } diff --git a/app/src/Restaurants/Dto/RestaurantListDto.php b/app/src/Restaurants/Dto/RestaurantListDto.php index 9d7f022..79354d8 100644 --- a/app/src/Restaurants/Dto/RestaurantListDto.php +++ b/app/src/Restaurants/Dto/RestaurantListDto.php @@ -2,22 +2,20 @@ namespace App\Restaurants\Dto; -use App\Shared\Abstraction\DtoInterface; -use App\Shared\Dto\DtoCollection; +use App\Shared\Abstraction\AbstractListDto; +use App\Shared\Collection\ListingCollection; use App\Shared\Dto\PaginationDto; -class RestaurantListDto implements DtoInterface +class RestaurantListDto extends AbstractListDto { /** * @param PaginationDto $pagination - * @param DtoCollection $list + * @param ListingCollection $list * @param RestaurantFilterVariantsDto $filterVariants */ public function __construct( public PaginationDto $pagination, - - public DtoCollection $list, - + public ListingCollection $list, public RestaurantFilterVariantsDto $filterVariants, ) {} } diff --git a/app/src/Restaurants/Dto/RestaurantListingElementDto.php b/app/src/Restaurants/Dto/RestaurantListingElementDto.php index b9b212e..4d7f3dc 100644 --- a/app/src/Restaurants/Dto/RestaurantListingElementDto.php +++ b/app/src/Restaurants/Dto/RestaurantListingElementDto.php @@ -2,24 +2,18 @@ namespace App\Restaurants\Dto; -use App\Shared\Abstraction\DtoInterface; +use App\Shared\Abstraction\AbstractListingElementDto; use App\Shared\Dto\FileDto; -class RestaurantListingElementDto implements DtoInterface +class RestaurantListingElementDto extends AbstractListingElementDto { public function __construct( public string $id, - public string $name, - public string $code, - public RestaurantTypeDto $type, - public string $detailLink, - public ?string $check = null, - public ?FileDto $image = null, ) {} } diff --git a/app/src/Restaurants/Dto/RestaurantTypeDto.php b/app/src/Restaurants/Dto/RestaurantTypeDto.php index c6747da..c8a2b95 100644 --- a/app/src/Restaurants/Dto/RestaurantTypeDto.php +++ b/app/src/Restaurants/Dto/RestaurantTypeDto.php @@ -2,15 +2,11 @@ namespace App\Restaurants\Dto; -use App\Shared\Abstraction\DtoInterface; - -class RestaurantTypeDto implements DtoInterface +class RestaurantTypeDto { public function __construct( public string $id, - public string $name, - public string $code, ) {} } diff --git a/app/src/Restaurants/Dto/TagDto.php b/app/src/Restaurants/Dto/TagDto.php index eb8d11c..2a1369c 100644 --- a/app/src/Restaurants/Dto/TagDto.php +++ b/app/src/Restaurants/Dto/TagDto.php @@ -2,18 +2,16 @@ namespace App\Restaurants\Dto; -use App\Shared\Abstraction\DtoInterface; -use App\Shared\Dto\DtoCollection; +use App\Shared\Collection\StringCollection; -class TagDto implements DtoInterface +class TagDto { /** * @param string $name - * @param DtoCollection $list + * @param StringCollection $list */ public function __construct( public string $name, - - public DtoCollection $list, + public StringCollection $list, ) {} } diff --git a/app/src/Restaurants/DtoFactory/KitchenTypeDtoFactory.php b/app/src/Restaurants/DtoFactory/KitchenTypeDtoFactory.php index 04c7260..7b0d391 100644 --- a/app/src/Restaurants/DtoFactory/KitchenTypeDtoFactory.php +++ b/app/src/Restaurants/DtoFactory/KitchenTypeDtoFactory.php @@ -2,11 +2,11 @@ namespace App\Restaurants\DtoFactory; +use App\Restaurants\Collection\KitchenCollection; use App\Restaurants\Dto\KitchenTypeDto; -use App\Shared\Dto\DtoCollection; use App\Shared\Entity\Kitchens; -use Ramsey\Collection\Collection as RamseyCollection; use Doctrine\Common\Collections\Collection as DoctrineCollection; +use Ramsey\Collection\Collection as RamseyCollection; class KitchenTypeDtoFactory { @@ -21,17 +21,15 @@ class KitchenTypeDtoFactory /** * @param DoctrineCollection|RamseyCollection $kitchens - * @return DtoCollection + * @return KitchenCollection */ - public function createCollection(DoctrineCollection|RamseyCollection $kitchens): DtoCollection - { - $kitchenCollection = $kitchens->map(function(Kitchens $kitchen) { + public function createCollection( + DoctrineCollection|RamseyCollection $kitchens + ): KitchenCollection { + $kitchenCollection = $kitchens->map(function (Kitchens $kitchen) { return $this->create($kitchen); }); - return new DtoCollection( - KitchenTypeDto::class, - $kitchenCollection->toArray() - ); + return new KitchenCollection($kitchenCollection->toArray()); } } diff --git a/app/src/Restaurants/DtoFactory/RestaurantDetailElementDtoFactory.php b/app/src/Restaurants/DtoFactory/RestaurantDetailElementDtoFactory.php index 343b892..39e8d67 100644 --- a/app/src/Restaurants/DtoFactory/RestaurantDetailElementDtoFactory.php +++ b/app/src/Restaurants/DtoFactory/RestaurantDetailElementDtoFactory.php @@ -3,9 +3,10 @@ namespace App\Restaurants\DtoFactory; use App\Restaurants\Dto\RestaurantDetailElementDto; -use App\Shared\Dto\DtoCollection; +use App\Shared\Collection\StringCollection; use App\Shared\DtoFactory\FileDtoFactory; use App\Shared\Entity\Restaurants; +use JsonException; class RestaurantDetailElementDtoFactory { @@ -14,7 +15,12 @@ class RestaurantDetailElementDtoFactory private readonly KitchenTypeDtoFactory $kitchenFactory, private readonly TagDtoFactory $tagFactory, private readonly FileDtoFactory $fileFactory, - ) {} + ) { + } + + /** + * @throws JsonException + */ public function create(Restaurants $restaurant): RestaurantDetailElementDto { return new RestaurantDetailElementDto( @@ -25,26 +31,29 @@ class RestaurantDetailElementDtoFactory type: $this->typeFactory->create($restaurant->getType()), check: $restaurant->getReceipt(), check_info: $restaurant->getReceiptInfo(), - kitchen: $this->kitchenFactory->createCollection($restaurant->getKitchens()), + kitchen: $this->kitchenFactory->createCollection( + $restaurant->getKitchens() + ), phone: $this->decodeJson($restaurant->getPhone()), email: $this->decodeJson($restaurant->getEmail()), address: $this->decodeJson($restaurant->getAddress()), tags: $this->tagFactory->createCollection($restaurant->getTags()), site: $restaurant->getSite(), image: $this->fileFactory->create($restaurant->getPreviewImage()), - gallery: $this->fileFactory->createCollection($restaurant->getGallery()), + gallery: $this->fileFactory->createCollection( + $restaurant->getGallery() + ), ); } /** - * @throws \JsonException + * @throws JsonException */ - private function decodeJson(string $json) + private function decodeJson(?string $json): ?StringCollection { return $json === null ? null - : new DtoCollection( - 'string', + : new StringCollection( json_decode( $json, true, @@ -53,4 +62,4 @@ class RestaurantDetailElementDtoFactory ), ); } -} \ No newline at end of file +} diff --git a/app/src/Restaurants/DtoFactory/RestaurantFilterVariantsDtoFactory.php b/app/src/Restaurants/DtoFactory/RestaurantFilterVariantsDtoFactory.php index 91624eb..74cabf7 100644 --- a/app/src/Restaurants/DtoFactory/RestaurantFilterVariantsDtoFactory.php +++ b/app/src/Restaurants/DtoFactory/RestaurantFilterVariantsDtoFactory.php @@ -2,14 +2,15 @@ namespace App\Restaurants\DtoFactory; +use App\Restaurants\Collection\KitchenCollection; +use App\Restaurants\Collection\RestaurantTypeCollection; use App\Restaurants\Dto\RestaurantFilterVariantsDto; -use App\Shared\Dto\DtoCollection; class RestaurantFilterVariantsDtoFactory { public function create( - DtoCollection $types, - DtoCollection $kitchens + RestaurantTypeCollection $types, + KitchenCollection $kitchens ): RestaurantFilterVariantsDto { return new RestaurantFilterVariantsDto( $types, diff --git a/app/src/Restaurants/DtoFactory/RestaurantListDtoFactory.php b/app/src/Restaurants/DtoFactory/RestaurantListDtoFactory.php index 3a372b9..66ca9e8 100644 --- a/app/src/Restaurants/DtoFactory/RestaurantListDtoFactory.php +++ b/app/src/Restaurants/DtoFactory/RestaurantListDtoFactory.php @@ -5,20 +5,20 @@ namespace App\Restaurants\DtoFactory; use App\Restaurants\Dto\RestaurantFilterVariantsDto; use App\Restaurants\Dto\RestaurantListDto; use App\Restaurants\Dto\RestaurantListingElementDto; -use App\Shared\Dto\DtoCollection; +use App\Shared\Collection\ListingCollection; use App\Shared\Dto\PaginationDto; class RestaurantListDtoFactory { /** * @param PaginationDto $pagination - * @param DtoCollection $list + * @param ListingCollection $list * @param RestaurantFilterVariantsDto $filters * @return RestaurantListDto */ public function create( PaginationDto $pagination, - DtoCollection $list, + ListingCollection $list, RestaurantFilterVariantsDto $filters ): RestaurantListDto { return new RestaurantListDto( diff --git a/app/src/Restaurants/DtoFactory/RestaurantListingElementDtoFactory.php b/app/src/Restaurants/DtoFactory/RestaurantListingElementDtoFactory.php index d46d87b..6fa858d 100644 --- a/app/src/Restaurants/DtoFactory/RestaurantListingElementDtoFactory.php +++ b/app/src/Restaurants/DtoFactory/RestaurantListingElementDtoFactory.php @@ -3,7 +3,7 @@ namespace App\Restaurants\DtoFactory; use App\Restaurants\Dto\RestaurantListingElementDto; -use App\Shared\Dto\DtoCollection; +use App\Shared\Collection\ListingCollection; use App\Shared\DtoFactory\FileDtoFactory; use App\Shared\Entity\Restaurants; use Ramsey\Collection\Collection; @@ -29,17 +29,14 @@ class RestaurantListingElementDtoFactory /** * @param Collection $restaurants - * @return DtoCollection + * @return ListingCollection */ - public function createCollection(Collection $restaurants): DtoCollection + public function createCollection(Collection $restaurants): ListingCollection { $restaurantsDto = $restaurants->map(function(Restaurants $restaurant) { return $this->create($restaurant); }); - return new DtoCollection( - RestaurantListingElementDto::class, - $restaurantsDto->toArray(), - ); + return new ListingCollection($restaurantsDto->toArray()); } } diff --git a/app/src/Restaurants/DtoFactory/RestaurantTypeDtoFactory.php b/app/src/Restaurants/DtoFactory/RestaurantTypeDtoFactory.php index 30b6ebc..b0578d1 100644 --- a/app/src/Restaurants/DtoFactory/RestaurantTypeDtoFactory.php +++ b/app/src/Restaurants/DtoFactory/RestaurantTypeDtoFactory.php @@ -2,8 +2,8 @@ namespace App\Restaurants\DtoFactory; +use App\Restaurants\Collection\RestaurantTypeCollection; use App\Restaurants\Dto\RestaurantTypeDto; -use App\Shared\Dto\DtoCollection; use App\Shared\Entity\RestaurantTypes; use Ramsey\Collection\Collection; @@ -20,16 +20,15 @@ class RestaurantTypeDtoFactory /** * @param Collection $types - * @return DtoCollection + * @return RestaurantTypeCollection */ - public function createCollection(Collection $types): DtoCollection + public function createCollection(Collection $types): RestaurantTypeCollection { $typesDto = $types->map(function(RestaurantTypes $type) { return $this->create($type); }); - return new DtoCollection( - RestaurantTypeDto::class, + return new RestaurantTypeCollection( $typesDto->toArray() ); } diff --git a/app/src/Restaurants/DtoFactory/TagDtoFactory.php b/app/src/Restaurants/DtoFactory/TagDtoFactory.php index 174e26e..d0f1fae 100644 --- a/app/src/Restaurants/DtoFactory/TagDtoFactory.php +++ b/app/src/Restaurants/DtoFactory/TagDtoFactory.php @@ -2,8 +2,9 @@ namespace App\Restaurants\DtoFactory; +use App\Restaurants\Collection\TagCollection; use App\Restaurants\Dto\TagDto; -use App\Shared\Dto\DtoCollection; +use App\Shared\Collection\StringCollection; use JsonException; use Ramsey\Collection\Collection as RamseyCollection; @@ -11,10 +12,10 @@ class TagDtoFactory { /** * @param string $json - * @return DtoCollection + * @return TagCollection * @throws JsonException */ - public function createCollection(string $json): DtoCollection + public function createCollection(string $json): TagCollection { $jsonCollection = new RamseyCollection( 'array', @@ -26,11 +27,11 @@ class TagDtoFactory ) ); - $tagCollection = new DtoCollection(TagDto::class); + $tagCollection = new TagCollection(); foreach ($jsonCollection as $name => $jsonItem) { $tagCollection->add( - new TagDto($name, new DtoCollection('string', $jsonItem)) + new TagDto($name, new StringCollection($jsonItem)) ); } diff --git a/app/src/Restaurants/Request/RestaurantListingRequest.php b/app/src/Restaurants/Request/RestaurantListingRequest.php deleted file mode 100644 index b85da7f..0000000 --- a/app/src/Restaurants/Request/RestaurantListingRequest.php +++ /dev/null @@ -1,36 +0,0 @@ -getRequest(); - foreach ($request->query->getIterator() as $property => $value) { - if (property_exists($this, $property)) { - $this->{$property} = $value; - } - } - } -} diff --git a/app/src/Restaurants/Service/RestaurantDetailService.php b/app/src/Restaurants/Service/RestaurantDetailService.php deleted file mode 100644 index b8dda37..0000000 --- a/app/src/Restaurants/Service/RestaurantDetailService.php +++ /dev/null @@ -1,34 +0,0 @@ -restaurants->find($request->detailId); - - if ($restaurant === null) { - throw new NotFoundError('Restaurant not found'); - } - - return $this->dtoFactory->create($restaurant); - } -} diff --git a/app/src/Restaurants/Service/RestaurantListingService.php b/app/src/Restaurants/Service/RestaurantListingService.php deleted file mode 100644 index a56b29f..0000000 --- a/app/src/Restaurants/Service/RestaurantListingService.php +++ /dev/null @@ -1,71 +0,0 @@ -restaurants - ->getCountWithFilters( - $request->restaurant_type_id, - $request->kitchen_id - ); - - $pagination = $this->paginationFactory->create( - $request->page, - $request->limit, - $countOfRestaurants, - ); - - $offset = min($pagination->pageSize, $countOfRestaurants) * ($pagination->currentPage - 1); - - $list = $this->listFactory->createCollection( - $this->restaurants->getWithFilters( - $request->kitchen_id, - $request->restaurant_type_id, - $pagination->pageSize, - $offset, - ), - ); - - - $filters = $this->filterFactory->create( - $this->typeFactory->createCollection($this->types->getAll()), - $this->kitchenFactory->createCollection($this->kitchens->getAll()) - ); - - return $this->listingFactory->create( - $pagination, - $list, - $filters - ); - } -} diff --git a/app/src/Restaurants/Service/RestaurantPrepareRequestService.php b/app/src/Restaurants/Service/RestaurantPrepareRequestService.php new file mode 100644 index 0000000..742d4c4 --- /dev/null +++ b/app/src/Restaurants/Service/RestaurantPrepareRequestService.php @@ -0,0 +1,122 @@ +validate->isValidUuid($filters['restaurant_type_id'])) { + $filters['news_category'] = null; + } + if (!$this->validate->isValidUuid($filters['kitchen_id'])) { + $filters['news_category'] = null; + } + $this->validate->correctPagination($page, $limit); + + $countOfRestaurants = $this + ->restaurants + ->getCountWithFilters( + $filters['restaurant_type_id'], + $filters['kitchen_id'] + ); + + $pagination = $this->paginationFactory->create( + $page, + $limit, + $countOfRestaurants, + ); + + $offset = min( + $pagination->pageSize, + $countOfRestaurants + ) * ($pagination->currentPage - 1); + + $list = $this->listFactory->createCollection( + $this->restaurants->getWithFilters( + $filters['kitchen_id'], + $filters['restaurant_type_id'], + $pagination->pageSize, + $offset, + ), + ); + + + $filters = $this->filterFactory->create( + $this->typeFactory->createCollection($this->types->getAll()), + $this->kitchenFactory->createCollection($this->kitchens->getAll()) + ); + + return $this->listingFactory->create( + $pagination, + $list, + $filters + ); + } + + /** + * @param string $detailId + * @return AbstractDetailElement + * @throws JsonException + */ + public + function bornDetailElement( + string $detailId + ): AbstractDetailElement { + if (!$this->validate->isValidUuid($detailId)) { + throw new NonValidUuidError(); + } + + $restaurant = $this->restaurants->find($detailId); + + if ($restaurant === null) { + throw new NotFoundError('Restaurant not found'); + } + + return $this->detailFactory->create($restaurant); + } +} diff --git a/app/src/Shared/Abstraction/AbstractController.php b/app/src/Shared/Abstraction/AbstractController.php index 3d40cc8..cfd97b4 100644 --- a/app/src/Shared/Abstraction/AbstractController.php +++ b/app/src/Shared/Abstraction/AbstractController.php @@ -2,32 +2,52 @@ namespace App\Shared\Abstraction; -use App\Shared\Dto\ErrorDto; use App\Shared\DtoFactory\ErrorDtoFactory; use App\Shared\Error\BaseError; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as BundleController; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Response; use Throwable; abstract class AbstractController extends BundleController { public function __construct( protected readonly ErrorDtoFactory $errorFactory, - ) {} + ) { + } + + /** + * @param ServiceInterface $service + * @param int $page + * @param int $limit + * @param array|null $filters + * @return JsonResponse + */ + protected function handleListing( + ServiceInterface $service, + int $page = 1, + int $limit = 12, + ?string ...$filters, + ): JsonResponse { + try { + return new JsonResponse($service->bornListDto($page, $limit, $filters)); + } catch (Throwable) { + return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); + } + } + + protected function handleDetailElement( + ServiceInterface $service, + string $detailId, + ): JsonResponse { + try { + return new JsonResponse($service->bornDetailElement($detailId)); + } catch (BaseError $error) { + $errorDto = $this->errorFactory->create($error); - protected function handle(ServiceInterface $service, AbstractRequest $request): JsonResponse - { -// try { - return new JsonResponse($service->serve($request)); -// -// } catch (BaseError $error) { -// $errorDto = $this->errorFactory->create($error); -// -// return new JsonResponse($errorDto, $errorDto->status); -// -// } catch (Throwable $exception) { -// $error = new ErrorDto(); -// return new JsonResponse($error, $error->status); -// } + return new JsonResponse($errorDto, $errorDto->status); + } catch (Throwable) { + return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); + } } } diff --git a/app/src/Shared/Abstraction/AbstractDetailElement.php b/app/src/Shared/Abstraction/AbstractDetailElement.php new file mode 100644 index 0000000..6386d81 --- /dev/null +++ b/app/src/Shared/Abstraction/AbstractDetailElement.php @@ -0,0 +1,9 @@ + */ + public ListingCollection $list; +} diff --git a/app/src/Shared/Abstraction/AbstractListingElementDto.php b/app/src/Shared/Abstraction/AbstractListingElementDto.php new file mode 100644 index 0000000..9c676fd --- /dev/null +++ b/app/src/Shared/Abstraction/AbstractListingElementDto.php @@ -0,0 +1,10 @@ +populate(); - - if (self::AUTO_VALIDATE) { - $this->validate(); - } - } - - /** - * Маппинг реквеста - * @return void - */ - protected function populate(): void - { - foreach ($this->getRequest()->toArray() as $property => $value) { - if (property_exists($this, $property)) { - $this->{$property} = $value; - } - } - } - - /** - * Валидация и выброкса ошибки при валидации - * @return void - */ - public function validate(): void - { - $errors = $this->validator->validate($this); - - - $messages = new DtoCollection(ValidateErrorDto::class); - - foreach ($errors as $error) { - $messages->add((new ValidateErrorDtoFactory($error))->create()); - } - - if ($messages->count() > 0) { - $response = new JsonResponse($messages, 422); - $response->send(); - - throw new ValidatorException('Validation failed', $messages); - } - } - - /** - * Возвращает HttpFoundation реквест - * @return Request - */ - public function getRequest(): Request - { - return Request::createFromGlobals(); - } -} diff --git a/app/src/Shared/Abstraction/DtoInterface.php b/app/src/Shared/Abstraction/DtoInterface.php deleted file mode 100644 index 60a39cd..0000000 --- a/app/src/Shared/Abstraction/DtoInterface.php +++ /dev/null @@ -1,5 +0,0 @@ -|null $filters + * @return AbstractListDto + */ + public function bornListDto( + int $page, + int $limit, + ?array $filters + ): AbstractListDto; + + public function bornDetailElement(string $detailId): AbstractDetailElement; } + diff --git a/app/src/Shared/Dto/DtoCollection.php b/app/src/Shared/Collection/DtoCollection.php similarity index 87% rename from app/src/Shared/Dto/DtoCollection.php rename to app/src/Shared/Collection/DtoCollection.php index 1e27e88..c8fcf69 100644 --- a/app/src/Shared/Dto/DtoCollection.php +++ b/app/src/Shared/Collection/DtoCollection.php @@ -1,13 +1,13 @@ collectionType, $data); + } +} diff --git a/app/src/Shared/Collection/ListingCollection.php b/app/src/Shared/Collection/ListingCollection.php new file mode 100644 index 0000000..9234de7 --- /dev/null +++ b/app/src/Shared/Collection/ListingCollection.php @@ -0,0 +1,15 @@ +collectionType, $data); + } +} diff --git a/app/src/Shared/Collection/StringCollection.php b/app/src/Shared/Collection/StringCollection.php new file mode 100644 index 0000000..0efaec1 --- /dev/null +++ b/app/src/Shared/Collection/StringCollection.php @@ -0,0 +1,13 @@ +collectionType, $data); + } +} diff --git a/app/src/Shared/Dto/ErrorDto.php b/app/src/Shared/Dto/ErrorDto.php index fe14352..31b8ccb 100644 --- a/app/src/Shared/Dto/ErrorDto.php +++ b/app/src/Shared/Dto/ErrorDto.php @@ -2,15 +2,12 @@ namespace App\Shared\Dto; -use App\Shared\Abstraction\DtoInterface; - -class ErrorDto implements DtoInterface +class ErrorDto { public function __construct( public string $status = '500', - public string $message = 'Something went wrong', - public string $code = '100', - ) {} + ) { + } } diff --git a/app/src/Shared/Dto/FileDto.php b/app/src/Shared/Dto/FileDto.php index 1cff98b..b232359 100644 --- a/app/src/Shared/Dto/FileDto.php +++ b/app/src/Shared/Dto/FileDto.php @@ -2,21 +2,15 @@ namespace App\Shared\Dto; -use App\Shared\Abstraction\DtoInterface; - -class FileDto implements DtoInterface +class FileDto { public function __construct( public string $id, - public string $name, - public string $description, - public int $size, - public string $type, - public string $url, - ) {} + ) { + } } diff --git a/app/src/Shared/Dto/PaginationDto.php b/app/src/Shared/Dto/PaginationDto.php index 8433d9b..a68ad9d 100644 --- a/app/src/Shared/Dto/PaginationDto.php +++ b/app/src/Shared/Dto/PaginationDto.php @@ -2,13 +2,12 @@ namespace App\Shared\Dto; -use App\Shared\Abstraction\DtoInterface; - -class PaginationDto implements DtoInterface +class PaginationDto { public function __construct( public int $currentPage, public int $pages, public int $pageSize, - ) {} + ) { + } } diff --git a/app/src/Shared/Dto/ValidateErrorDto.php b/app/src/Shared/Dto/ValidateErrorDto.php index 02a6766..f3d31a1 100644 --- a/app/src/Shared/Dto/ValidateErrorDto.php +++ b/app/src/Shared/Dto/ValidateErrorDto.php @@ -2,15 +2,12 @@ namespace App\Shared\Dto; -use App\Shared\Abstraction\DtoInterface; - -class ValidateErrorDto implements DtoInterface +class ValidateErrorDto { public function __construct( public string $message, - public string $code, - public string $status, - ) {} + ) { + } } diff --git a/app/src/Shared/DtoFactory/ErrorDtoFactory.php b/app/src/Shared/DtoFactory/ErrorDtoFactory.php index f2bc249..f917e26 100644 --- a/app/src/Shared/DtoFactory/ErrorDtoFactory.php +++ b/app/src/Shared/DtoFactory/ErrorDtoFactory.php @@ -9,10 +9,10 @@ class ErrorDtoFactory { public function create(BaseError $error): ErrorDto { - return new ErrorDto( - status: $error->getStatusCode(), - message: $error->getMessage(), - code: $error->getCode(), - ); + return new ErrorDto( + status: $error->getStatusCode(), + message: $error->getMessage(), + code: $error->getCode(), + ); } } diff --git a/app/src/Shared/DtoFactory/FileDtoFactory.php b/app/src/Shared/DtoFactory/FileDtoFactory.php index 6fbc5c9..7aa47a0 100644 --- a/app/src/Shared/DtoFactory/FileDtoFactory.php +++ b/app/src/Shared/DtoFactory/FileDtoFactory.php @@ -2,7 +2,7 @@ namespace App\Shared\DtoFactory; -use App\Shared\Dto\DtoCollection; +use App\Shared\Collection\FileCollection; use App\Shared\Dto\FileDto; use App\Shared\Entity\File; use Doctrine\Common\Collections\Collection; @@ -23,16 +23,15 @@ class FileDtoFactory /** * @param Collection $files - * @return DtoCollection + * @return FileCollection */ - public function createCollection(Collection $files): DtoCollection + public function createCollection(Collection $files): FileCollection { - $filesDto = $files->map(function(File $file) { + $filesDto = $files->map(function (File $file) { return $this->create($file); }); - return new DtoCollection( - FileDto::class, + return new FileCollection( $filesDto->toArray() ); } diff --git a/app/src/Shared/DtoFactory/PaginationDtoFactory.php b/app/src/Shared/DtoFactory/PaginationDtoFactory.php index 933de0c..7973036 100644 --- a/app/src/Shared/DtoFactory/PaginationDtoFactory.php +++ b/app/src/Shared/DtoFactory/PaginationDtoFactory.php @@ -12,6 +12,6 @@ class PaginationDtoFactory $pages = ceil($total / $pageSize); $page = ($page > 1) && ($page <= $pages) ? $page : 1; - return new PaginationDto($page, $pages, $pageSize); + return new PaginationDto($page, $pages, $pageSize); } } diff --git a/app/src/Shared/DtoFactory/ValidateErrorDtoFactory.php b/app/src/Shared/DtoFactory/ValidateErrorDtoFactory.php index 9cb815a..8947518 100644 --- a/app/src/Shared/DtoFactory/ValidateErrorDtoFactory.php +++ b/app/src/Shared/DtoFactory/ValidateErrorDtoFactory.php @@ -4,13 +4,12 @@ namespace App\Shared\DtoFactory; use App\Shared\Dto\ValidateErrorDto; use App\Shared\Error\ErrorCode; -use http\Message; use Symfony\Component\Validator\ConstraintViolationInterface; class ValidateErrorDtoFactory { - public function create(ConstraintViolationInterface $error): ValidateErrorDto - { + public function create(ConstraintViolationInterface $error + ): ValidateErrorDto { return new ValidateErrorDto( message: $error->getPropertyPath() . ' : ' . $error->getMessage(), code: ErrorCode::ValidateFailed->value, diff --git a/app/src/Shared/Entity/File.php b/app/src/Shared/Entity/File.php index 5c448b7..0063008 100644 --- a/app/src/Shared/Entity/File.php +++ b/app/src/Shared/Entity/File.php @@ -2,7 +2,6 @@ namespace App\Shared\Entity; -use App\Shared\Abstraction\EntityInterface; use App\Shared\Repository\FileRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -10,7 +9,7 @@ use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: FileRepository::class)] -class File implements EntityInterface +class File { #[ORM\Id] #[ORM\Column(type: Types::GUID)] @@ -53,7 +52,6 @@ class File implements EntityInterface * @var Collection */ #[ORM\OneToMany(targetEntity: News::class, mappedBy: 'detailImage')] - private Collection $newsDetail; /** @@ -151,8 +149,8 @@ class File implements EntityInterface return $this->restaurantsPreview; } - public function addRestaurantsPreview(Restaurants $restaurantsPreview): static - { + public function addRestaurantsPreview(Restaurants $restaurantsPreview + ): static { if (!$this->restaurantsPreview->contains($restaurantsPreview)) { $this->restaurantsPreview->add($restaurantsPreview); $restaurantsPreview->setPreviewImage($this); @@ -161,8 +159,8 @@ class File implements EntityInterface return $this; } - public function removeRestaurantsPreview(Restaurants $restaurantsPreview): static - { + public function removeRestaurantsPreview(Restaurants $restaurantsPreview + ): static { if ($this->restaurantsPreview->removeElement($restaurantsPreview)) { // set the owning side to null (unless already changed) if ($restaurantsPreview->getPreviewImage() === $this) { @@ -191,8 +189,8 @@ class File implements EntityInterface return $this; } - public function removeRestaurantsDetail(Restaurants $restaurantsDetail): static - { + public function removeRestaurantsDetail(Restaurants $restaurantsDetail + ): static { if ($this->restaurantsDetail->removeElement($restaurantsDetail)) { // set the owning side to null (unless already changed) if ($restaurantsDetail->getDetailImage() === $this) { @@ -211,8 +209,8 @@ class File implements EntityInterface return $this->restaurantsGallery; } - public function addRestaurantsGallery(Restaurants $restaurantsGallery): static - { + public function addRestaurantsGallery(Restaurants $restaurantsGallery + ): static { if (!$this->restaurantsGallery->contains($restaurantsGallery)) { $this->restaurantsGallery->add($restaurantsGallery); $restaurantsGallery->addGallery($this); @@ -221,8 +219,8 @@ class File implements EntityInterface return $this; } - public function removeRestaurantsGallery(Restaurants $restaurantsGallery): static - { + public function removeRestaurantsGallery(Restaurants $restaurantsGallery + ): static { if ($this->restaurantsGallery->removeElement($restaurantsGallery)) { $restaurantsGallery->removeGallery($this); } diff --git a/app/src/Shared/Entity/Kitchens.php b/app/src/Shared/Entity/Kitchens.php index b6eb7b1..b10ba1c 100644 --- a/app/src/Shared/Entity/Kitchens.php +++ b/app/src/Shared/Entity/Kitchens.php @@ -2,7 +2,6 @@ namespace App\Shared\Entity; -use App\Shared\Abstraction\EntityInterface; use App\Shared\Repository\KitchensRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -10,7 +9,7 @@ use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: KitchensRepository::class)] -class Kitchens implements EntityInterface +class Kitchens { #[ORM\Id] #[ORM\Column(type: Types::GUID)] diff --git a/app/src/Shared/Entity/News.php b/app/src/Shared/Entity/News.php index 9640253..d88a733 100644 --- a/app/src/Shared/Entity/News.php +++ b/app/src/Shared/Entity/News.php @@ -2,10 +2,6 @@ namespace App\Shared\Entity; -use App\News\Dto\NewsDetailElementDto; -use App\News\Dto\NewsListingElementDto; -use App\Shared\Abstraction\DtoInterface; -use App\Shared\Abstraction\EntityInterface; use App\Shared\Repository\NewsRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; diff --git a/app/src/Shared/Entity/NewsCategories.php b/app/src/Shared/Entity/NewsCategories.php index f4b30cb..e22e0cf 100644 --- a/app/src/Shared/Entity/NewsCategories.php +++ b/app/src/Shared/Entity/NewsCategories.php @@ -2,9 +2,6 @@ namespace App\Shared\Entity; -use App\News\Dto\NewsCategoryDto; -use App\Shared\Abstraction\DtoInterface; -use App\Shared\Abstraction\EntityInterface; use App\Shared\Repository\NewsCategoriesRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -12,7 +9,7 @@ use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: NewsCategoriesRepository::class)] -class NewsCategories implements EntityInterface +class NewsCategories { #[ORM\Id] #[ORM\Column(type: Types::GUID)] diff --git a/app/src/Shared/Entity/RestaurantTypes.php b/app/src/Shared/Entity/RestaurantTypes.php index 8081330..49043fc 100644 --- a/app/src/Shared/Entity/RestaurantTypes.php +++ b/app/src/Shared/Entity/RestaurantTypes.php @@ -2,7 +2,6 @@ namespace App\Shared\Entity; -use App\Shared\Abstraction\EntityInterface; use App\Shared\Repository\RestaurantTypesRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -10,7 +9,7 @@ use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: RestaurantTypesRepository::class)] -class RestaurantTypes implements EntityInterface +class RestaurantTypes { #[ORM\Id] #[ORM\Column(type: Types::GUID)] diff --git a/app/src/Shared/Entity/Restaurants.php b/app/src/Shared/Entity/Restaurants.php index a88eba4..11033eb 100644 --- a/app/src/Shared/Entity/Restaurants.php +++ b/app/src/Shared/Entity/Restaurants.php @@ -2,23 +2,15 @@ namespace App\Shared\Entity; -use App\Restaurants\Dto\KitchenTypeDto; -use App\Restaurants\Dto\RestaurantDetailElementDto; -use App\Restaurants\Dto\RestaurantListingElementDto; -use App\Restaurants\Dto\TagDto; -use App\Shared\Abstraction\DtoInterface; -use App\Shared\Abstraction\EntityInterface; -use App\Shared\Dto\DtoCollection; -use App\Shared\Dto\FileDto; use App\Shared\Repository\RestaurantsRepository; +use DateTimeImmutable; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; -use Ramsey\Collection\Collection as RamseyCollection; #[ORM\Entity(repositoryClass: RestaurantsRepository::class)] -class Restaurants implements EntityInterface +class Restaurants { #[ORM\Id] #[ORM\Column(type: Types::GUID)] @@ -31,10 +23,10 @@ class Restaurants implements EntityInterface private ?int $sort = null; #[ORM\Column] - private ?\DateTimeImmutable $createdAt = null; + private ?DateTimeImmutable $createdAt = null; #[ORM\Column] - private ?\DateTimeImmutable $updateAt = null; + private ?DateTimeImmutable $updateAt = null; #[ORM\ManyToOne(inversedBy: 'restaurantsTypes')] private ?RestaurantTypes $type = null; @@ -138,24 +130,24 @@ class Restaurants implements EntityInterface return $this; } - public function getCreatedAt(): ?\DateTimeImmutable + public function getCreatedAt(): ?DateTimeImmutable { return $this->createdAt; } - public function setCreatedAt(\DateTimeImmutable $createdAt): static + public function setCreatedAt(DateTimeImmutable $createdAt): static { $this->createdAt = $createdAt; return $this; } - public function getUpdateAt(): ?\DateTimeImmutable + public function getUpdateAt(): ?DateTimeImmutable { return $this->updateAt; } - public function setUpdateAt(\DateTimeImmutable $updateAt): static + public function setUpdateAt(DateTimeImmutable $updateAt): static { $this->updateAt = $updateAt; diff --git a/app/src/Shared/Error/BaseError.php b/app/src/Shared/Error/BaseError.php index 7a297f7..62eb87c 100644 --- a/app/src/Shared/Error/BaseError.php +++ b/app/src/Shared/Error/BaseError.php @@ -2,12 +2,13 @@ namespace App\Shared\Error; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\HttpException; class BaseError extends HttpException { public function __construct( - int $statusCode = 500, + int $statusCode = Response::HTTP_INTERNAL_SERVER_ERROR, string $message = 'Something bad happening', ErrorCode $code = ErrorCode::NotExcepted ) { diff --git a/app/src/Shared/Error/ErrorCode.php b/app/src/Shared/Error/ErrorCode.php index a9495f4..9217c1f 100644 --- a/app/src/Shared/Error/ErrorCode.php +++ b/app/src/Shared/Error/ErrorCode.php @@ -7,4 +7,6 @@ enum ErrorCode: int case EntityNotFound = 10; case ValidateFailed = 20; case NotExcepted = 50; + + case UuidInvalid = 60; } diff --git a/app/src/Shared/Error/NonValidUuidError.php b/app/src/Shared/Error/NonValidUuidError.php new file mode 100644 index 0000000..9e5b6b8 --- /dev/null +++ b/app/src/Shared/Error/NonValidUuidError.php @@ -0,0 +1,16 @@ +getRequest()->getUri(); - $index = strrpos($requestUrl, "/") + 1; - - $detailId = substr($requestUrl, $index); - - if (property_exists($this, "detailId")) { - $this->{"detailId"} = $detailId; - } - } -} diff --git a/app/src/Shared/Request/EmptyRequest.php b/app/src/Shared/Request/EmptyRequest.php deleted file mode 100644 index 2f2ab8e..0000000 --- a/app/src/Shared/Request/EmptyRequest.php +++ /dev/null @@ -1,12 +0,0 @@ - Date: Fri, 17 May 2024 13:32:24 +0500 Subject: [PATCH 12/12] STA-960 | fixes --- app/src/News/Controller/NewsController.php | 50 ++++++-------- app/src/News/Dto/NewsDetailElementDto.php | 3 +- app/src/News/Dto/NewsListDto.php | 3 +- app/src/News/Dto/NewsListingElementDto.php | 3 +- app/src/News/Request/NewsDetailRequest.php | 43 ++++++++++++ app/src/News/Request/NewsListingRequest.php | 51 ++++++++++++++ .../Service/NewsPrepareResponseService.php | 66 +++++++------------ .../News/UseCase/NewsGetDetailMainUseCase.php | 27 ++++++++ app/src/News/UseCase/NewsGetDetailUseCase.php | 34 ++++++++++ .../News/UseCase/NewsGetListingUseUseCase.php | 27 ++++++++ app/src/News/UseCase/NewsGetMainUseCase.php | 26 ++++++++ .../Controller/RestaurantsController.php | 39 ++++------- .../Dto/RestaurantDetailElementDto.php | 3 +- app/src/Restaurants/Dto/RestaurantListDto.php | 3 +- .../Dto/RestaurantListingElementDto.php | 3 +- .../Request/RestaurantDetailRequest.php | 43 ++++++++++++ .../Request/RestaurantListingRequest.php | 56 ++++++++++++++++ .../RestaurantPrepareRequestService.php | 60 +++++------------ .../UseCase/RestaurantGetDetailUseCase.php | 34 ++++++++++ .../UseCase/RestaurantGetListingUseCase.php | 27 ++++++++ .../Shared/Abstraction/AbstractController.php | 53 --------------- .../Abstraction/AbstractDetailElement.php | 9 --- .../Shared/Abstraction/AbstractListDto.php | 14 ---- .../Abstraction/AbstractListingElementDto.php | 10 --- .../Shared/Abstraction/ServiceInterface.php | 21 ------ .../DtoFactory/PaginationDtoFactory.php | 5 +- app/src/Shared/Service/ValidateService.php | 25 ------- app/src/Shared/Service/ValidationService.php | 29 ++++++++ 28 files changed, 478 insertions(+), 289 deletions(-) create mode 100644 app/src/News/Request/NewsDetailRequest.php create mode 100644 app/src/News/Request/NewsListingRequest.php create mode 100644 app/src/News/UseCase/NewsGetDetailMainUseCase.php create mode 100644 app/src/News/UseCase/NewsGetDetailUseCase.php create mode 100644 app/src/News/UseCase/NewsGetListingUseUseCase.php create mode 100644 app/src/News/UseCase/NewsGetMainUseCase.php create mode 100644 app/src/Restaurants/Request/RestaurantDetailRequest.php create mode 100644 app/src/Restaurants/Request/RestaurantListingRequest.php create mode 100644 app/src/Restaurants/UseCase/RestaurantGetDetailUseCase.php create mode 100644 app/src/Restaurants/UseCase/RestaurantGetListingUseCase.php delete mode 100644 app/src/Shared/Abstraction/AbstractController.php delete mode 100644 app/src/Shared/Abstraction/AbstractDetailElement.php delete mode 100644 app/src/Shared/Abstraction/AbstractListDto.php delete mode 100644 app/src/Shared/Abstraction/AbstractListingElementDto.php delete mode 100644 app/src/Shared/Abstraction/ServiceInterface.php delete mode 100644 app/src/Shared/Service/ValidateService.php create mode 100644 app/src/Shared/Service/ValidationService.php diff --git a/app/src/News/Controller/NewsController.php b/app/src/News/Controller/NewsController.php index 98694b5..34e1dbb 100644 --- a/app/src/News/Controller/NewsController.php +++ b/app/src/News/Controller/NewsController.php @@ -2,58 +2,48 @@ namespace App\News\Controller; -use App\News\Service\NewsPrepareResponseService; -use App\Shared\Abstraction\AbstractController; -use App\Shared\DtoFactory\ErrorDtoFactory; +use App\News\Request\NewsDetailRequest; +use App\News\Request\NewsListingRequest; +use App\News\UseCase\NewsGetDetailMainUseCase; +use App\News\UseCase\NewsGetDetailUseCase; +use App\News\UseCase\NewsGetListingUseUseCase; +use App\News\UseCase\NewsGetMainUseCase; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpKernel\Attribute\MapQueryParameter; use Symfony\Component\Routing\Attribute\Route; #[Route('/api/v1/news')] class NewsController extends AbstractController { public function __construct( - ErrorDtoFactory $errorFactory, - private readonly NewsPrepareResponseService $responsePrepareService, + private readonly NewsGetListingUseUseCase $getListingUseCase, + private readonly NewsGetDetailUseCase $getDetailNews, + private readonly NewsGetMainUseCase $getMainNews, + private readonly NewsGetDetailMainUseCase $getDetailMainNews, ) { - parent::__construct($errorFactory); } #[Route('/', name: 'news', methods: ['GET'])] - public function news( - #[MapQueryParameter] int $page = 1, - #[MapQueryParameter] int $limit = 12, - #[MapQueryParameter] string $news_category = null - ): JsonResponse { - return $this->handleListing( - $this->responsePrepareService, - $page, - $limit, - $news_category, - ); + public function news(NewsListingRequest $request): JsonResponse + { + return $this->getListingUseCase->execute($request); } #[Route('/mainNews', name: 'mainNews', methods: ['GET'])] public function mainNews(): JsonResponse { - return new JsonResponse($this->responsePrepareService->bornMainNews()); + return $this->getMainNews->execute(); } #[Route('/search', name: 'searchNews', methods: ['GET'])] - public function search(): JsonResponse + public function detailMainNews(): JsonResponse { - return new JsonResponse( - $this->responsePrepareService->bornDetailMainNews() - ); + return $this->getDetailMainNews->execute(); } #[Route('/{detailId}', name: 'oneNews', methods: ['GET'])] - public function oneNews( - #[MapQueryParameter] string $detailId = null - ): JsonResponse { - return $this->handleDetailElement( - $this->responsePrepareService, - $detailId, - ); + public function oneNews(NewsDetailRequest $request): JsonResponse + { + return $this->getDetailNews->execute($request); } } diff --git a/app/src/News/Dto/NewsDetailElementDto.php b/app/src/News/Dto/NewsDetailElementDto.php index 530f5e0..e715dda 100644 --- a/app/src/News/Dto/NewsDetailElementDto.php +++ b/app/src/News/Dto/NewsDetailElementDto.php @@ -2,10 +2,9 @@ namespace App\News\Dto; -use App\Shared\Abstraction\AbstractDetailElement; use App\Shared\Dto\FileDto; -class NewsDetailElementDto extends AbstractDetailElement +class NewsDetailElementDto { /** * @param string $id diff --git a/app/src/News/Dto/NewsListDto.php b/app/src/News/Dto/NewsListDto.php index 63da8fa..833a93c 100644 --- a/app/src/News/Dto/NewsListDto.php +++ b/app/src/News/Dto/NewsListDto.php @@ -2,11 +2,10 @@ namespace App\News\Dto; -use App\Shared\Abstraction\AbstractListDto; use App\Shared\Collection\ListingCollection; use App\Shared\Dto\PaginationDto; -class NewsListDto extends AbstractListDto +class NewsListDto { /** * @param PaginationDto $pagination diff --git a/app/src/News/Dto/NewsListingElementDto.php b/app/src/News/Dto/NewsListingElementDto.php index a291ea1..0ff49bb 100644 --- a/app/src/News/Dto/NewsListingElementDto.php +++ b/app/src/News/Dto/NewsListingElementDto.php @@ -2,10 +2,9 @@ namespace App\News\Dto; -use App\Shared\Abstraction\AbstractListingElementDto; use App\Shared\Dto\FileDto; -class NewsListingElementDto extends AbstractListingElementDto +class NewsListingElementDto { /** * @param string $id diff --git a/app/src/News/Request/NewsDetailRequest.php b/app/src/News/Request/NewsDetailRequest.php new file mode 100644 index 0000000..8fdcf65 --- /dev/null +++ b/app/src/News/Request/NewsDetailRequest.php @@ -0,0 +1,43 @@ +populate(); + $this->checkAndCorrectParams(); + } + + private function checkAndCorrectParams(): void + { + if (!$this->validation->isUuidValid($this->detailId)) { + throw new NotFoundError('News not found'); + } + } + + private function populate(): void + { + $requestUrl = $this->getRequest()->getUri(); + $index = strrpos($requestUrl, "/") + 1; + + $restaurantId = substr($requestUrl, $index); + + if (property_exists($this, "detailId")) { + $this->{"detailId"} = $restaurantId; + } + } + + public function getRequest(): Request + { + return Request::createFromGlobals(); + } +} \ No newline at end of file diff --git a/app/src/News/Request/NewsListingRequest.php b/app/src/News/Request/NewsListingRequest.php new file mode 100644 index 0000000..fc80383 --- /dev/null +++ b/app/src/News/Request/NewsListingRequest.php @@ -0,0 +1,51 @@ +populate(); + $this->checkAndCorrectParams(); + } + + private function checkAndCorrectParams(): void + { + if (!$this->validation->isPageValid($this->page)) { + $this->page = 1; + } + + if (!$this->validation->isLimitValid($this->limit)) { + $this->limit = 12; + } + + if (!$this->validation->isUuidValid($this->news_category)) { + $this->news_category = null; + } + } + + private function populate(): void + { + foreach ( + $this->getRequest()->query->getIterator() as $property => $value + ) { + if (property_exists($this, $property)) { + $this->{$property} = $value; + } + } + } + + public function getRequest(): Request + { + return Request::createFromGlobals(); + } +} \ No newline at end of file diff --git a/app/src/News/Service/NewsPrepareResponseService.php b/app/src/News/Service/NewsPrepareResponseService.php index dbdd17c..b652b1d 100644 --- a/app/src/News/Service/NewsPrepareResponseService.php +++ b/app/src/News/Service/NewsPrepareResponseService.php @@ -3,61 +3,43 @@ namespace App\News\Service; use App\News\Dto\NewsDetailElementDto; +use App\News\Dto\NewsListDto; use App\News\Dto\NewsListingElementDto; use App\News\DtoFactory\NewsCategoryDtoFactory; use App\News\DtoFactory\NewsDetailElementDtoFactory; use App\News\DtoFactory\NewsFilterVariantsDtoFactory; use App\News\DtoFactory\NewsListDtoFactory; use App\News\DtoFactory\NewsListingElementDtoFactory; -use App\Shared\Abstraction\AbstractListDto; -use App\Shared\Abstraction\ServiceInterface; +use App\News\Request\NewsDetailRequest; +use App\News\Request\NewsListingRequest; use App\Shared\DtoFactory\PaginationDtoFactory; -use App\Shared\Error\NonValidUuidError; use App\Shared\Error\NotFoundError; use App\Shared\Repository\NewsCategoriesRepository; use App\Shared\Repository\NewsRepository; -use App\Shared\Service\ValidateService; -readonly class NewsPrepareResponseService implements ServiceInterface +class NewsPrepareResponseService { public function __construct( - private NewsRepository $news, - private NewsCategoriesRepository $newsCategories, - private PaginationDtoFactory $paginationFactory, - private NewsListingElementDtoFactory $listFactory, - private NewsFilterVariantsDtoFactory $filterFactory, - private NewsListDtoFactory $listingFactory, - private NewsCategoryDtoFactory $categoryFactory, - private ValidateService $validate, - private NewsDetailElementDtoFactory $detailElementFactory + private readonly NewsRepository $news, + private readonly NewsCategoriesRepository $newsCategories, + private readonly PaginationDtoFactory $paginationFactory, + private readonly NewsListingElementDtoFactory $listFactory, + private readonly NewsFilterVariantsDtoFactory $filterFactory, + private readonly NewsListDtoFactory $listingFactory, + private readonly NewsCategoryDtoFactory $categoryFactory, + private readonly NewsDetailElementDtoFactory $detailElementFactory ) { } - /** - * @param int $page - * @param int $limit - * @param array|null ...$filters - * @return AbstractListDto - */ - public function bornListDto( - int $page, - int $limit, - ?array $filters - ): AbstractListDto { - $filters['news_category'] = $filters[0]; - if (!$this->validate->isValidUuid($filters['news_category'])) { - $filters['news_category'] = null; - } - - $this->validate->correctPagination($page, $limit); - + public function bornListDto(NewsListingRequest $request): NewsListDto + { $countOfNews = $this->news->getCountWithFilters( - $filters['news_category'] + $request->news_category ); $pagination = $this->paginationFactory->create( - $page, - $limit, + $request->page, + $request->limit, $countOfNews ); @@ -68,8 +50,8 @@ readonly class NewsPrepareResponseService implements ServiceInterface $list = $this->listFactory->createCollection( $this->news->getWithFilters( - $filters['news_category'], - $limit, + $request->news_category, + $request->limit, $offset ) ); @@ -97,13 +79,9 @@ readonly class NewsPrepareResponseService implements ServiceInterface return $this->detailElementFactory->create($this->news->getMainNews()); } - public function bornDetailElement(string $detailId): NewsDetailElementDto - { - if (!$this->validate->isValidUuid($detailId)) { - throw new NonValidUuidError(); - } - - $news = $this->news->find($detailId); + public function bornDetailElement(NewsDetailRequest $request + ): NewsDetailElementDto { + $news = $this->news->find($request->detailId); if ($news === null) { throw new NotFoundError('News not found'); diff --git a/app/src/News/UseCase/NewsGetDetailMainUseCase.php b/app/src/News/UseCase/NewsGetDetailMainUseCase.php new file mode 100644 index 0000000..92725a1 --- /dev/null +++ b/app/src/News/UseCase/NewsGetDetailMainUseCase.php @@ -0,0 +1,27 @@ +prepareRequestService->bornDetailMainNews() + ); + } catch (Throwable) { + 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 new file mode 100644 index 0000000..2605bd9 --- /dev/null +++ b/app/src/News/UseCase/NewsGetDetailUseCase.php @@ -0,0 +1,34 @@ +responsePrepareService->bornDetailElement($request) + ); + } catch (NotFoundError $error) { + $errorDto = $this->errorFactory->create($error); + return new JsonResponse($errorDto, $errorDto->status); + } catch (Throwable) { + return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); + } + } +} \ No newline at end of file diff --git a/app/src/News/UseCase/NewsGetListingUseUseCase.php b/app/src/News/UseCase/NewsGetListingUseUseCase.php new file mode 100644 index 0000000..736c1f9 --- /dev/null +++ b/app/src/News/UseCase/NewsGetListingUseUseCase.php @@ -0,0 +1,27 @@ +prepareRequestService->bornListDto($request) + ); + } catch (Throwable) { + return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); + } + } +} diff --git a/app/src/News/UseCase/NewsGetMainUseCase.php b/app/src/News/UseCase/NewsGetMainUseCase.php new file mode 100644 index 0000000..9516d18 --- /dev/null +++ b/app/src/News/UseCase/NewsGetMainUseCase.php @@ -0,0 +1,26 @@ +responsePrepareService->bornMainNews() + ); + } catch (Throwable) { + return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); + } + } +} \ No newline at end of file diff --git a/app/src/Restaurants/Controller/RestaurantsController.php b/app/src/Restaurants/Controller/RestaurantsController.php index eea4f2d..c589e3a 100644 --- a/app/src/Restaurants/Controller/RestaurantsController.php +++ b/app/src/Restaurants/Controller/RestaurantsController.php @@ -2,45 +2,32 @@ namespace App\Restaurants\Controller; -use App\Restaurants\Service\RestaurantPrepareRequestService; -use App\Shared\Abstraction\AbstractController; -use App\Shared\DtoFactory\ErrorDtoFactory; +use App\Restaurants\UseCase\RestaurantGetListingUseCase; +use App\Restaurants\Request\RestaurantDetailRequest; +use App\Restaurants\Request\RestaurantListingRequest; +use App\Restaurants\UseCase\RestaurantGetDetailUseCase; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpKernel\Attribute\MapQueryParameter; use Symfony\Component\Routing\Attribute\Route; #[Route('/api/v1/restaurants')] class RestaurantsController extends AbstractController { public function __construct( - ErrorDtoFactory $errorFactory, - private readonly RestaurantPrepareRequestService $responsePrepareService, + private readonly RestaurantGetListingUseCase $getListingUseCase, + private readonly RestaurantGetDetailUseCase $getDetailUseCase, ) { - parent::__construct($errorFactory); } #[Route('/', name: 'restaurants', methods: ['GET'])] - public function restaurants( - #[MapQueryParameter] int $page = 1, - #[MapQueryParameter] int $limit = 12, - #[MapQueryParameter] string $restaurant_type_id = null, - #[MapQueryParameter] string $kitchen_id = null, - ): JsonResponse { - return $this->handleListing( - $this->responsePrepareService, - $page, - $limit, - $restaurant_type_id, - $kitchen_id, - ); + public function restaurants(RestaurantListingRequest $request): JsonResponse + { + return $this->getListingUseCase->execute($request); } #[Route('/{detailId}', name: 'restaurant', methods: ['GET'])] - public function restaurant(#[MapQueryParameter] string $detailId = null - ): JsonResponse { - return $this->handleDetailElement( - $this->responsePrepareService, - $detailId, - ); + public function restaurant(RestaurantDetailRequest $request): JsonResponse + { + return $this->getDetailUseCase->execute($request); } } diff --git a/app/src/Restaurants/Dto/RestaurantDetailElementDto.php b/app/src/Restaurants/Dto/RestaurantDetailElementDto.php index bf4d83f..75eaa59 100644 --- a/app/src/Restaurants/Dto/RestaurantDetailElementDto.php +++ b/app/src/Restaurants/Dto/RestaurantDetailElementDto.php @@ -4,12 +4,11 @@ namespace App\Restaurants\Dto; use App\Restaurants\Collection\KitchenCollection; use App\Restaurants\Collection\TagCollection; -use App\Shared\Abstraction\AbstractDetailElement; use App\Shared\Collection\FileCollection; use App\Shared\Collection\StringCollection; use App\Shared\Dto\FileDto; -class RestaurantDetailElementDto extends AbstractDetailElement +class RestaurantDetailElementDto { /** * @param string $id diff --git a/app/src/Restaurants/Dto/RestaurantListDto.php b/app/src/Restaurants/Dto/RestaurantListDto.php index 79354d8..1e6ac5d 100644 --- a/app/src/Restaurants/Dto/RestaurantListDto.php +++ b/app/src/Restaurants/Dto/RestaurantListDto.php @@ -2,11 +2,10 @@ namespace App\Restaurants\Dto; -use App\Shared\Abstraction\AbstractListDto; use App\Shared\Collection\ListingCollection; use App\Shared\Dto\PaginationDto; -class RestaurantListDto extends AbstractListDto +class RestaurantListDto { /** * @param PaginationDto $pagination diff --git a/app/src/Restaurants/Dto/RestaurantListingElementDto.php b/app/src/Restaurants/Dto/RestaurantListingElementDto.php index 4d7f3dc..2ffed45 100644 --- a/app/src/Restaurants/Dto/RestaurantListingElementDto.php +++ b/app/src/Restaurants/Dto/RestaurantListingElementDto.php @@ -2,10 +2,9 @@ namespace App\Restaurants\Dto; -use App\Shared\Abstraction\AbstractListingElementDto; use App\Shared\Dto\FileDto; -class RestaurantListingElementDto extends AbstractListingElementDto +class RestaurantListingElementDto { public function __construct( public string $id, diff --git a/app/src/Restaurants/Request/RestaurantDetailRequest.php b/app/src/Restaurants/Request/RestaurantDetailRequest.php new file mode 100644 index 0000000..fbc0acb --- /dev/null +++ b/app/src/Restaurants/Request/RestaurantDetailRequest.php @@ -0,0 +1,43 @@ +populate(); + $this->checkAndCorrectParams(); + } + + private function checkAndCorrectParams(): void + { + if (!$this->validation->isUuidValid($this->detailId)) { + throw new NotFoundError('Restaurant not found'); + } + } + + private function populate(): void + { + $requestUrl = $this->getRequest()->getUri(); + $index = strrpos($requestUrl, "/") + 1; + + $restaurantId = substr($requestUrl, $index); + + if (property_exists($this, "detailId")) { + $this->{"detailId"} = $restaurantId; + } + } + + public function getRequest(): Request + { + return Request::createFromGlobals(); + } +} diff --git a/app/src/Restaurants/Request/RestaurantListingRequest.php b/app/src/Restaurants/Request/RestaurantListingRequest.php new file mode 100644 index 0000000..a198fa0 --- /dev/null +++ b/app/src/Restaurants/Request/RestaurantListingRequest.php @@ -0,0 +1,56 @@ +populate(); + $this->checkAndCorrectParams(); + } + + private function checkAndCorrectParams(): void + { + if (!$this->validation->isPageValid($this->page)) { + $this->page = 1; + } + + if (!$this->validation->isLimitValid($this->limit)) { + $this->limit = 12; + } + + if (!$this->validation->isUuidValid($this->restaurant_type_id)) { + $this->restaurant_type_id = null; + } + + if (!$this->validation->isUuidValid($this->kitchen_id)) { + $this->kitchen_id = null; + } + } + + private function populate(): void + { + foreach ( + $this->getRequest()->query->getIterator() as $property => $value + ) { + if (property_exists($this, $property)) { + $this->{$property} = $value; + } + } + } + + public function getRequest(): Request + { + return Request::createFromGlobals(); + } +} \ No newline at end of file diff --git a/app/src/Restaurants/Service/RestaurantPrepareRequestService.php b/app/src/Restaurants/Service/RestaurantPrepareRequestService.php index 742d4c4..9d24a6a 100644 --- a/app/src/Restaurants/Service/RestaurantPrepareRequestService.php +++ b/app/src/Restaurants/Service/RestaurantPrepareRequestService.php @@ -2,25 +2,24 @@ namespace App\Restaurants\Service; +use App\Restaurants\Dto\RestaurantDetailElementDto; +use App\Restaurants\Dto\RestaurantListDto; use App\Restaurants\DtoFactory\KitchenTypeDtoFactory; use App\Restaurants\DtoFactory\RestaurantDetailElementDtoFactory; use App\Restaurants\DtoFactory\RestaurantFilterVariantsDtoFactory; use App\Restaurants\DtoFactory\RestaurantListDtoFactory; use App\Restaurants\DtoFactory\RestaurantListingElementDtoFactory; use App\Restaurants\DtoFactory\RestaurantTypeDtoFactory; -use App\Shared\Abstraction\AbstractDetailElement; -use App\Shared\Abstraction\AbstractListDto; -use App\Shared\Abstraction\ServiceInterface; +use App\Restaurants\Request\RestaurantDetailRequest; +use App\Restaurants\Request\RestaurantListingRequest; use App\Shared\DtoFactory\PaginationDtoFactory; -use App\Shared\Error\NonValidUuidError; use App\Shared\Error\NotFoundError; use App\Shared\Repository\KitchensRepository; use App\Shared\Repository\RestaurantsRepository; use App\Shared\Repository\RestaurantTypesRepository; -use App\Shared\Service\ValidateService; use JsonException; -class RestaurantPrepareRequestService implements ServiceInterface +class RestaurantPrepareRequestService { public function __construct( private readonly RestaurantsRepository $restaurants, @@ -33,41 +32,24 @@ class RestaurantPrepareRequestService implements ServiceInterface private readonly KitchenTypeDtoFactory $kitchenFactory, private readonly RestaurantListDtoFactory $listingFactory, private readonly RestaurantDetailElementDtoFactory $detailFactory, - private readonly ValidateService $validate, ) { } /** - * @param int $page - * @param int $limit - * @param array|null $filters - * @return AbstractListDto + * @param RestaurantListingRequest $request + * @return RestaurantListDto */ - public function bornListDto( - int $page, - int $limit, - ?array $filters - ): AbstractListDto { - $filters['restaurant_type_id'] = $filters[0]; - $filters['kitchen_id'] = $filters[1]; - if (!$this->validate->isValidUuid($filters['restaurant_type_id'])) { - $filters['news_category'] = null; - } - if (!$this->validate->isValidUuid($filters['kitchen_id'])) { - $filters['news_category'] = null; - } - $this->validate->correctPagination($page, $limit); - + public function bornListDto(RestaurantListingRequest $request): RestaurantListDto { $countOfRestaurants = $this ->restaurants ->getCountWithFilters( - $filters['restaurant_type_id'], - $filters['kitchen_id'] + $request->restaurant_type_id, + $request->kitchen_id, ); $pagination = $this->paginationFactory->create( - $page, - $limit, + $request->page, + $request->limit, $countOfRestaurants, ); @@ -78,8 +60,8 @@ class RestaurantPrepareRequestService implements ServiceInterface $list = $this->listFactory->createCollection( $this->restaurants->getWithFilters( - $filters['kitchen_id'], - $filters['restaurant_type_id'], + $request->kitchen_id, + $request->restaurant_type_id, $pagination->pageSize, $offset, ), @@ -99,19 +81,13 @@ class RestaurantPrepareRequestService implements ServiceInterface } /** - * @param string $detailId - * @return AbstractDetailElement + * @param RestaurantDetailRequest $request + * @return RestaurantDetailElementDto * @throws JsonException */ public - function bornDetailElement( - string $detailId - ): AbstractDetailElement { - if (!$this->validate->isValidUuid($detailId)) { - throw new NonValidUuidError(); - } - - $restaurant = $this->restaurants->find($detailId); + function bornDetailElement(RestaurantDetailRequest $request): RestaurantDetailElementDto { + $restaurant = $this->restaurants->find($request->detailId); if ($restaurant === null) { throw new NotFoundError('Restaurant not found'); diff --git a/app/src/Restaurants/UseCase/RestaurantGetDetailUseCase.php b/app/src/Restaurants/UseCase/RestaurantGetDetailUseCase.php new file mode 100644 index 0000000..e369415 --- /dev/null +++ b/app/src/Restaurants/UseCase/RestaurantGetDetailUseCase.php @@ -0,0 +1,34 @@ +responsePrepareService->bornDetailElement($request) + ); + } catch (NotFoundError $error) { + $errorDto = $this->errorFactory->create($error); + return new JsonResponse($errorDto, $errorDto->status); + } catch (Throwable) { + return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); + } + } +} \ No newline at end of file diff --git a/app/src/Restaurants/UseCase/RestaurantGetListingUseCase.php b/app/src/Restaurants/UseCase/RestaurantGetListingUseCase.php new file mode 100644 index 0000000..2b34a03 --- /dev/null +++ b/app/src/Restaurants/UseCase/RestaurantGetListingUseCase.php @@ -0,0 +1,27 @@ +prepareRequestService->bornListDto($request) + ); + } catch (Throwable) { + return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); + } + } +} diff --git a/app/src/Shared/Abstraction/AbstractController.php b/app/src/Shared/Abstraction/AbstractController.php deleted file mode 100644 index cfd97b4..0000000 --- a/app/src/Shared/Abstraction/AbstractController.php +++ /dev/null @@ -1,53 +0,0 @@ -|null $filters - * @return JsonResponse - */ - protected function handleListing( - ServiceInterface $service, - int $page = 1, - int $limit = 12, - ?string ...$filters, - ): JsonResponse { - try { - return new JsonResponse($service->bornListDto($page, $limit, $filters)); - } catch (Throwable) { - return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); - } - } - - protected function handleDetailElement( - ServiceInterface $service, - string $detailId, - ): JsonResponse { - try { - return new JsonResponse($service->bornDetailElement($detailId)); - } catch (BaseError $error) { - $errorDto = $this->errorFactory->create($error); - - return new JsonResponse($errorDto, $errorDto->status); - } catch (Throwable) { - return new JsonResponse([], Response::HTTP_INTERNAL_SERVER_ERROR); - } - } -} diff --git a/app/src/Shared/Abstraction/AbstractDetailElement.php b/app/src/Shared/Abstraction/AbstractDetailElement.php deleted file mode 100644 index 6386d81..0000000 --- a/app/src/Shared/Abstraction/AbstractDetailElement.php +++ /dev/null @@ -1,9 +0,0 @@ - */ - public ListingCollection $list; -} diff --git a/app/src/Shared/Abstraction/AbstractListingElementDto.php b/app/src/Shared/Abstraction/AbstractListingElementDto.php deleted file mode 100644 index 9c676fd..0000000 --- a/app/src/Shared/Abstraction/AbstractListingElementDto.php +++ /dev/null @@ -1,10 +0,0 @@ -|null $filters - * @return AbstractListDto - */ - public function bornListDto( - int $page, - int $limit, - ?array $filters - ): AbstractListDto; - - public function bornDetailElement(string $detailId): AbstractDetailElement; -} - diff --git a/app/src/Shared/DtoFactory/PaginationDtoFactory.php b/app/src/Shared/DtoFactory/PaginationDtoFactory.php index 7973036..f3787bd 100644 --- a/app/src/Shared/DtoFactory/PaginationDtoFactory.php +++ b/app/src/Shared/DtoFactory/PaginationDtoFactory.php @@ -8,10 +8,9 @@ class PaginationDtoFactory { public function create(int $page, int $limit, int $total): PaginationDto { - $pageSize = $limit > 0 ? $limit : 12; - $pages = ceil($total / $pageSize); + $pages = ceil($total / $limit); $page = ($page > 1) && ($page <= $pages) ? $page : 1; - return new PaginationDto($page, $pages, $pageSize); + return new PaginationDto($page, $pages, $limit); } } diff --git a/app/src/Shared/Service/ValidateService.php b/app/src/Shared/Service/ValidateService.php deleted file mode 100644 index d424d6f..0000000 --- a/app/src/Shared/Service/ValidateService.php +++ /dev/null @@ -1,25 +0,0 @@ -= 1; + } + + public function isLimitValid(int $limit): bool + { + return $limit >= 1; + } +} -- GitLab