diff --git a/app/composer.json b/app/composer.json index 564d77eb4e396930f5f79afd26e5d1388479ff03..be399e99a066e779e3015ba3f581ad72061505b3 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 bf5aa40f261c4b9a45213683c22be84f11c81bc5..b67e855acedb857cef8a56c4aba956f5a175b6ca 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 41ef8140ba811c0da46ce1962ffa50d4c56b9840..0370c9f31ee96143a1f488bc5300b7b92a18d416 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 2d6a76f94dce138741e2d63ae83a11c1879031d9..851a66275ae74e085d470571afbe8687d1c939ac 100644 --- a/app/config/services.yaml +++ b/app/config/services.yaml @@ -11,14 +11,12 @@ 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 + # add more service definitions when explicit configuration is needed + # please note that last definitions always *replace* previous ones + 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 diff --git a/app/src/News/Collection/NewsCategoryCollection.php b/app/src/News/Collection/NewsCategoryCollection.php new file mode 100644 index 0000000000000000000000000000000000000000..cd3b77d5b8d59437427d7abe372259acfb36835a --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..34e1dbba36c09283223134479ddea3d751b61ee3 --- /dev/null +++ b/app/src/News/Controller/NewsController.php @@ -0,0 +1,49 @@ +getListingUseCase->execute($request); + } + + #[Route('/mainNews', name: 'mainNews', methods: ['GET'])] + public function mainNews(): JsonResponse + { + return $this->getMainNews->execute(); + } + + #[Route('/search', name: 'searchNews', methods: ['GET'])] + public function detailMainNews(): JsonResponse + { + return $this->getDetailMainNews->execute(); + } + + #[Route('/{detailId}', name: 'oneNews', methods: ['GET'])] + public function oneNews(NewsDetailRequest $request): JsonResponse + { + return $this->getDetailNews->execute($request); + } +} diff --git a/app/src/News/Dto/NewsCategoryDto.php b/app/src/News/Dto/NewsCategoryDto.php new file mode 100644 index 0000000000000000000000000000000000000000..010a7e7b98a722c4448d469cfbbe9049fabf42a2 --- /dev/null +++ b/app/src/News/Dto/NewsCategoryDto.php @@ -0,0 +1,13 @@ + $category + */ + public function __construct( + public NewsCategoryCollection $category, + ) { + } +} diff --git a/app/src/News/Dto/NewsListDto.php b/app/src/News/Dto/NewsListDto.php new file mode 100644 index 0000000000000000000000000000000000000000..833a93c6a3a508198c9f303d2bab3e082232c2c9 --- /dev/null +++ b/app/src/News/Dto/NewsListDto.php @@ -0,0 +1,21 @@ + $list + * @param NewsFilterVariantsDto $filterVariants + */ + public function __construct( + 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 new file mode 100644 index 0000000000000000000000000000000000000000..0ff49bb2987eadaaa721f80c34184c73fbfb3e64 --- /dev/null +++ b/app/src/News/Dto/NewsListingElementDto.php @@ -0,0 +1,26 @@ +getId(), + name: $category->getName(), + code: $category->getCode(), + ); + } + + /** + * @param Collection $categories + * @return NewsCategoryCollection + */ + public function createCollection(Collection $categories): NewsCategoryCollection + { + $categoriesDto = $categories->map(function(NewsCategories $category) { + return $this->create($category); + }); + + return new NewsCategoryCollection( + $categoriesDto->toArray() + ); + } +} diff --git a/app/src/News/DtoFactory/NewsDetailElementDtoFactory.php b/app/src/News/DtoFactory/NewsDetailElementDtoFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..ad29868c955fd3974902d2a8624d6ede05feb9fd --- /dev/null +++ b/app/src/News/DtoFactory/NewsDetailElementDtoFactory.php @@ -0,0 +1,29 @@ +getId(), + name: $news->getName(), + description: $news->getPreviewText(), + createAt: $news->getCreatedAt()?->format('d.m.Y'), + 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 0000000000000000000000000000000000000000..ab0c5ff15c7c6447fcadb9dc78eeccc5fcc76f41 --- /dev/null +++ b/app/src/News/DtoFactory/NewsFilterVariantsDtoFactory.php @@ -0,0 +1,21 @@ + $categories + * @return 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 new file mode 100644 index 0000000000000000000000000000000000000000..25613a79836d08f7cd125ebfbb0fb34c49b35f6c --- /dev/null +++ b/app/src/News/DtoFactory/NewsListDtoFactory.php @@ -0,0 +1,23 @@ +getId(), + name: $news->getName(), + 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, + ); + } + + /** + * @param Collection $news + * @return ListingCollection + */ + public function createCollection(Collection $news): ListingCollection + { + return new ListingCollection( + $news->map(function (News $oneNews) { + return $this->create($oneNews); + }) + ->toArray() + ); + } +} diff --git a/app/src/News/Request/NewsDetailRequest.php b/app/src/News/Request/NewsDetailRequest.php new file mode 100644 index 0000000000000000000000000000000000000000..8fdcf654405a1161f58e4cee8bb4ead33de4dc28 --- /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 0000000000000000000000000000000000000000..fc803834be8229fb702bf31256b4b8206ada0831 --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..b652b1d9970390c8dfa24409f88614501e67703b --- /dev/null +++ b/app/src/News/Service/NewsPrepareResponseService.php @@ -0,0 +1,92 @@ +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 + ) + ); + + $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(NewsDetailRequest $request + ): NewsDetailElementDto { + $news = $this->news->find($request->detailId); + + if ($news === null) { + throw new NotFoundError('News not found'); + } + + return $this->detailElementFactory->create($news); + } +} diff --git a/app/src/News/UseCase/NewsGetDetailMainUseCase.php b/app/src/News/UseCase/NewsGetDetailMainUseCase.php new file mode 100644 index 0000000000000000000000000000000000000000..92725a121c29184bc53d4071b17c548a4e1ec7c4 --- /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 0000000000000000000000000000000000000000..2605bd94f84d89844e02a0089589e2190969bca5 --- /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 0000000000000000000000000000000000000000..736c1f97850033d4e8cafb8aba35febc9e85bc46 --- /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 0000000000000000000000000000000000000000..9516d1899e9abfc08a4045dcb1ccae54037d0fe2 --- /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/Repository/.gitignore b/app/src/Repository/.gitignore deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/app/src/Repository/KitchensRepository.php b/app/src/Repository/KitchensRepository.php deleted file mode 100644 index b65972f426471d1569a2e884e83c55a6d4c77f12..0000000000000000000000000000000000000000 --- a/app/src/Repository/KitchensRepository.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * @method Kitchens|null find($id, $lockMode = null, $lockVersion = null) - * @method Kitchens|null findOneBy(array $criteria, array $orderBy = null) - * @method Kitchens[] findAll() - * @method Kitchens[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class KitchensRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - 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() - // ; - // } -} diff --git a/app/src/Repository/NewsCategoriesRepository.php b/app/src/Repository/NewsCategoriesRepository.php deleted file mode 100644 index cb2bf88ccea70122feaa335005456ecac54a0c0a..0000000000000000000000000000000000000000 --- a/app/src/Repository/NewsCategoriesRepository.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * @method NewsCategories|null find($id, $lockMode = null, $lockVersion = null) - * @method NewsCategories|null findOneBy(array $criteria, array $orderBy = null) - * @method NewsCategories[] findAll() - * @method NewsCategories[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class NewsCategoriesRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - 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() - // ; - // } -} diff --git a/app/src/Repository/NewsRepository.php b/app/src/Repository/NewsRepository.php deleted file mode 100644 index c74af620cac5a7513b64aadd7b91e4d738102600..0000000000000000000000000000000000000000 --- a/app/src/Repository/NewsRepository.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * @method News|null find($id, $lockMode = null, $lockVersion = null) - * @method News|null findOneBy(array $criteria, array $orderBy = null) - * @method News[] findAll() - * @method News[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class NewsRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - 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() - // ; - // } -} diff --git a/app/src/Repository/NewsTypeRepository.php b/app/src/Repository/NewsTypeRepository.php deleted file mode 100644 index dabf301c391be2c46d86cf26cc184faa0b2ff502..0000000000000000000000000000000000000000 --- a/app/src/Repository/NewsTypeRepository.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * @method NewsType|null find($id, $lockMode = null, $lockVersion = null) - * @method NewsType|null findOneBy(array $criteria, array $orderBy = null) - * @method NewsType[] findAll() - * @method NewsType[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class NewsTypeRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - 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() - // ; - // } -} diff --git a/app/src/Repository/RestaurantTypesRepository.php b/app/src/Repository/RestaurantTypesRepository.php deleted file mode 100644 index 8a2f3c345922d1a9dc3bc24b88e2816f6e3f0060..0000000000000000000000000000000000000000 --- a/app/src/Repository/RestaurantTypesRepository.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * @method RestaurantTypes|null find($id, $lockMode = null, $lockVersion = null) - * @method RestaurantTypes|null findOneBy(array $criteria, array $orderBy = null) - * @method RestaurantTypes[] findAll() - * @method RestaurantTypes[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class RestaurantTypesRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - 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() - // ; - // } -} diff --git a/app/src/Repository/RestaurantsRepository.php b/app/src/Repository/RestaurantsRepository.php deleted file mode 100644 index f540695ade01a46901b408f4fceebfcd4fd52908..0000000000000000000000000000000000000000 --- a/app/src/Repository/RestaurantsRepository.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * @method Restaurants|null find($id, $lockMode = null, $lockVersion = null) - * @method Restaurants|null findOneBy(array $criteria, array $orderBy = null) - * @method Restaurants[] findAll() - * @method Restaurants[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class RestaurantsRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - 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() -// ; -// } -} diff --git a/app/src/Repository/SettlementsRepository.php b/app/src/Repository/SettlementsRepository.php deleted file mode 100644 index 4e84a187b8e9c4715b121045721c12dd994d7b68..0000000000000000000000000000000000000000 --- a/app/src/Repository/SettlementsRepository.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * @method Settlements|null find($id, $lockMode = null, $lockVersion = null) - * @method Settlements|null findOneBy(array $criteria, array $orderBy = null) - * @method Settlements[] findAll() - * @method Settlements[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class SettlementsRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - 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 deleted file mode 100644 index a151d1bf09840a4a040356bc419e97fefa9532bf..0000000000000000000000000000000000000000 --- a/app/src/Repository/UsersRepository.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * @method Users|null find($id, $lockMode = null, $lockVersion = null) - * @method Users|null findOneBy(array $criteria, array $orderBy = null) - * @method Users[] findAll() - * @method Users[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - */ -class UsersRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - 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/app/src/Restaurants/Collection/KitchenCollection.php b/app/src/Restaurants/Collection/KitchenCollection.php new file mode 100644 index 0000000000000000000000000000000000000000..a2eb60a8cd4ff3704ed2f31eb0de2853a5a84f19 --- /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 0000000000000000000000000000000000000000..8f4091f8a0f08ed893f96104b80f22c5c74e7f4c --- /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 0000000000000000000000000000000000000000..dec7c1c0b3a66f92c38dc00f2409c1ff5df3ec52 --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..c589e3acfaba4a340b59a12ea0df51bafde7d192 --- /dev/null +++ b/app/src/Restaurants/Controller/RestaurantsController.php @@ -0,0 +1,33 @@ +getListingUseCase->execute($request); + } + + #[Route('/{detailId}', name: 'restaurant', methods: ['GET'])] + public function restaurant(RestaurantDetailRequest $request): JsonResponse + { + return $this->getDetailUseCase->execute($request); + } +} diff --git a/app/src/Restaurants/Dto/KitchenTypeDto.php b/app/src/Restaurants/Dto/KitchenTypeDto.php new file mode 100644 index 0000000000000000000000000000000000000000..da4c576d2d1739321b2bd24670c415d284674548 --- /dev/null +++ b/app/src/Restaurants/Dto/KitchenTypeDto.php @@ -0,0 +1,12 @@ +|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 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 ?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 ?FileCollection $gallery = null, + ) {} +} diff --git a/app/src/Restaurants/Dto/RestaurantFilterVariantsDto.php b/app/src/Restaurants/Dto/RestaurantFilterVariantsDto.php new file mode 100644 index 0000000000000000000000000000000000000000..d0e0e65b7c241b934ff645a2868ac41c8c2ba31f --- /dev/null +++ b/app/src/Restaurants/Dto/RestaurantFilterVariantsDto.php @@ -0,0 +1,18 @@ + $type + * @param KitchenCollection $kitchen + */ + public function __construct( + public RestaurantTypeCollection $type, + public KitchenCollection $kitchen, + ) {} +} diff --git a/app/src/Restaurants/Dto/RestaurantListDto.php b/app/src/Restaurants/Dto/RestaurantListDto.php new file mode 100644 index 0000000000000000000000000000000000000000..1e6ac5d5b995500610ab768c88fab3344a3d4e0e --- /dev/null +++ b/app/src/Restaurants/Dto/RestaurantListDto.php @@ -0,0 +1,20 @@ + $list + * @param RestaurantFilterVariantsDto $filterVariants + */ + public function __construct( + public PaginationDto $pagination, + public ListingCollection $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 0000000000000000000000000000000000000000..2ffed4543b1f377faad9253c32bd6f9b1590fdde --- /dev/null +++ b/app/src/Restaurants/Dto/RestaurantListingElementDto.php @@ -0,0 +1,18 @@ + $list + */ + public function __construct( + public string $name, + public StringCollection $list, + ) {} +} diff --git a/app/src/Restaurants/DtoFactory/KitchenTypeDtoFactory.php b/app/src/Restaurants/DtoFactory/KitchenTypeDtoFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..7b0d391a1ef93b52bc9a573b395aa2cccf3700de --- /dev/null +++ b/app/src/Restaurants/DtoFactory/KitchenTypeDtoFactory.php @@ -0,0 +1,35 @@ +getId(), + name: $kitchen->getName(), + code: $kitchen->getCode(), + ); + } + + /** + * @param DoctrineCollection|RamseyCollection $kitchens + * @return KitchenCollection + */ + public function createCollection( + DoctrineCollection|RamseyCollection $kitchens + ): KitchenCollection { + $kitchenCollection = $kitchens->map(function (Kitchens $kitchen) { + return $this->create($kitchen); + }); + + return new KitchenCollection($kitchenCollection->toArray()); + } +} diff --git a/app/src/Restaurants/DtoFactory/RestaurantDetailElementDtoFactory.php b/app/src/Restaurants/DtoFactory/RestaurantDetailElementDtoFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..39e8d674a2e68e1f9f1016e2dbd6aad3c7de7e2a --- /dev/null +++ b/app/src/Restaurants/DtoFactory/RestaurantDetailElementDtoFactory.php @@ -0,0 +1,65 @@ +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): ?StringCollection + { + return $json === null + ? null + : new StringCollection( + json_decode( + $json, + true, + 512, + JSON_THROW_ON_ERROR + ), + ); + } +} diff --git a/app/src/Restaurants/DtoFactory/RestaurantFilterVariantsDtoFactory.php b/app/src/Restaurants/DtoFactory/RestaurantFilterVariantsDtoFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..74cabf76534ab850eee1a1fb2997f34a5b9e8485 --- /dev/null +++ b/app/src/Restaurants/DtoFactory/RestaurantFilterVariantsDtoFactory.php @@ -0,0 +1,20 @@ + $list + * @param RestaurantFilterVariantsDto $filters + * @return RestaurantListDto + */ + public function create( + PaginationDto $pagination, + ListingCollection $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 0000000000000000000000000000000000000000..6fa858dd61ae612d50c08cca853daaf06681b4d0 --- /dev/null +++ b/app/src/Restaurants/DtoFactory/RestaurantListingElementDtoFactory.php @@ -0,0 +1,42 @@ +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 ListingCollection + */ + public function createCollection(Collection $restaurants): ListingCollection + { + $restaurantsDto = $restaurants->map(function(Restaurants $restaurant) { + return $this->create($restaurant); + }); + + return new ListingCollection($restaurantsDto->toArray()); + } +} diff --git a/app/src/Restaurants/DtoFactory/RestaurantTypeDtoFactory.php b/app/src/Restaurants/DtoFactory/RestaurantTypeDtoFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..b0578d15bfa4adc1c04b7e93671b46a968d3ddce --- /dev/null +++ b/app/src/Restaurants/DtoFactory/RestaurantTypeDtoFactory.php @@ -0,0 +1,35 @@ +getId(), + name: $type->getName(), + code: $type->getCode(), + ); + } + + /** + * @param Collection $types + * @return RestaurantTypeCollection + */ + public function createCollection(Collection $types): RestaurantTypeCollection + { + $typesDto = $types->map(function(RestaurantTypes $type) { + return $this->create($type); + }); + + return new RestaurantTypeCollection( + $typesDto->toArray() + ); + } +} diff --git a/app/src/Restaurants/DtoFactory/TagDtoFactory.php b/app/src/Restaurants/DtoFactory/TagDtoFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..d0f1fae2414e4966001e469a11fb1047283ebe23 --- /dev/null +++ b/app/src/Restaurants/DtoFactory/TagDtoFactory.php @@ -0,0 +1,40 @@ + + * @throws JsonException + */ + public function createCollection(string $json): TagCollection + { + $jsonCollection = new RamseyCollection( + 'array', + json_decode( + $json, + true, + 512, + JSON_THROW_ON_ERROR + ) + ); + + $tagCollection = new TagCollection(); + + foreach ($jsonCollection as $name => $jsonItem) { + $tagCollection->add( + new TagDto($name, new StringCollection($jsonItem)) + ); + } + + return $tagCollection; + } +} diff --git a/app/src/Restaurants/Request/RestaurantDetailRequest.php b/app/src/Restaurants/Request/RestaurantDetailRequest.php new file mode 100644 index 0000000000000000000000000000000000000000..fbc0acb5cea941c6acfe474f32086d071df1cb7d --- /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 0000000000000000000000000000000000000000..a198fa061beefadc64053ac68fd0998643759a18 --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..9d24a6ad4f53a6050e64f8f80f28dd49c0197b98 --- /dev/null +++ b/app/src/Restaurants/Service/RestaurantPrepareRequestService.php @@ -0,0 +1,98 @@ +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 + ); + } + + /** + * @param RestaurantDetailRequest $request + * @return RestaurantDetailElementDto + * @throws JsonException + */ + public + function bornDetailElement(RestaurantDetailRequest $request): RestaurantDetailElementDto { + $restaurant = $this->restaurants->find($request->detailId); + + if ($restaurant === null) { + throw new NotFoundError('Restaurant not found'); + } + + return $this->detailFactory->create($restaurant); + } +} diff --git a/app/src/Restaurants/UseCase/RestaurantGetDetailUseCase.php b/app/src/Restaurants/UseCase/RestaurantGetDetailUseCase.php new file mode 100644 index 0000000000000000000000000000000000000000..e36941547087cac0b72f8c777f3d35bfce79ebca --- /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 0000000000000000000000000000000000000000..2b34a0318b47383f245b3f8d4b7ee87d584dc6fd --- /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/Collection/DtoCollection.php b/app/src/Shared/Collection/DtoCollection.php new file mode 100644 index 0000000000000000000000000000000000000000..c8fcf698e558dbbb556c1e8b036cb6a4c3af1081 --- /dev/null +++ b/app/src/Shared/Collection/DtoCollection.php @@ -0,0 +1,27 @@ +collectionType; + } + + public function jsonSerialize(): array + { + return $this->data; + } +} diff --git a/app/src/Shared/Collection/FileCollection.php b/app/src/Shared/Collection/FileCollection.php new file mode 100644 index 0000000000000000000000000000000000000000..07ccdf45086887b11c7cec1fd04323ef01202731 --- /dev/null +++ b/app/src/Shared/Collection/FileCollection.php @@ -0,0 +1,15 @@ +collectionType, $data); + } +} diff --git a/app/src/Shared/Collection/ListingCollection.php b/app/src/Shared/Collection/ListingCollection.php new file mode 100644 index 0000000000000000000000000000000000000000..9234de7c7b0f995f6d7451149ce31f361fab1005 --- /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 0000000000000000000000000000000000000000..0efaec1fbe84e7e11946d38536c1aa855d1b3d3c --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..31b8ccbdf4378e0956f3cd62f54e5292683f0da7 --- /dev/null +++ b/app/src/Shared/Dto/ErrorDto.php @@ -0,0 +1,13 @@ +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 0000000000000000000000000000000000000000..7aa47a0e32ef80659ea2dbf3cd98a06240403c28 --- /dev/null +++ b/app/src/Shared/DtoFactory/FileDtoFactory.php @@ -0,0 +1,38 @@ +getId(), + name: $file->getName(), + description: $file->getDescription(), + size: $file->getSize(), + type: $file->getType(), + url: $file->getUrl(), + ); + } + + /** + * @param Collection $files + * @return FileCollection + */ + public function createCollection(Collection $files): FileCollection + { + $filesDto = $files->map(function (File $file) { + return $this->create($file); + }); + + return new FileCollection( + $filesDto->toArray() + ); + } +} diff --git a/app/src/Shared/DtoFactory/PaginationDtoFactory.php b/app/src/Shared/DtoFactory/PaginationDtoFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..f3787bdbf19e38406683ec766d959874759cc9ce --- /dev/null +++ b/app/src/Shared/DtoFactory/PaginationDtoFactory.php @@ -0,0 +1,16 @@ + 1) && ($page <= $pages) ? $page : 1; + + return new PaginationDto($page, $pages, $limit); + } +} diff --git a/app/src/Shared/DtoFactory/ValidateErrorDtoFactory.php b/app/src/Shared/DtoFactory/ValidateErrorDtoFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..894751831a14c6c692c58f60f46a19439bdacd66 --- /dev/null +++ b/app/src/Shared/DtoFactory/ValidateErrorDtoFactory.php @@ -0,0 +1,19 @@ +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/Shared/Entity/File.php b/app/src/Shared/Entity/File.php new file mode 100644 index 0000000000000000000000000000000000000000..00630084dce1e3010df006db60162a3d68fb5bde --- /dev/null +++ b/app/src/Shared/Entity/File.php @@ -0,0 +1,290 @@ + + */ + #[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/Shared/Entity/Kitchens.php similarity index 94% rename from app/src/Entity/Kitchens.php rename to app/src/Shared/Entity/Kitchens.php index 29ac79059c1792e977930b0b44ae1cea82bff9b0..b10ba1c28fc9f4a00b9b68cbcfbcb0aab6bdf1be 100644 --- a/app/src/Entity/Kitchens.php +++ b/app/src/Shared/Entity/Kitchens.php @@ -1,8 +1,8 @@ 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/Shared/Entity/News.php similarity index 89% rename from app/src/Entity/News.php rename to app/src/Shared/Entity/News.php index cd6d609dfaeec5a9ee187daf9684fe3c7bc1bb24..d88a733362e78f0119bb8c0c6f08a167f536367d 100644 --- a/app/src/Entity/News.php +++ b/app/src/Shared/Entity/News.php @@ -1,8 +1,8 @@ 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/Shared/Entity/NewsCategories.php similarity index 93% rename from app/src/Entity/NewsCategories.php rename to app/src/Shared/Entity/NewsCategories.php index aa5bf02acb016cd97b99dae560b01b1abbdb5ac5..e22e0cf7b109ed8b553797689db258892f9d0867 100644 --- a/app/src/Entity/NewsCategories.php +++ b/app/src/Shared/Entity/NewsCategories.php @@ -1,8 +1,8 @@ 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/Shared/Entity/NewsType.php similarity index 94% rename from app/src/Entity/NewsType.php rename to app/src/Shared/Entity/NewsType.php index f5764f28073991d615d358775bd5cc3b9e3e9536..d7d724e70b18aad687fdf58c239e5bed8b303cd5 100644 --- a/app/src/Entity/NewsType.php +++ b/app/src/Shared/Entity/NewsType.php @@ -1,8 +1,8 @@ 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/Shared/Entity/RestaurantTypes.php similarity index 93% rename from app/src/Entity/RestaurantTypes.php rename to app/src/Shared/Entity/RestaurantTypes.php index fc3c1b0f143a85c74a8bf31d42a516f79796b6e7..49043fca0f8a84effd7f1fdfb08f2ef530c85b17 100644 --- a/app/src/Entity/RestaurantTypes.php +++ b/app/src/Shared/Entity/RestaurantTypes.php @@ -1,13 +1,12 @@ 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/Shared/Entity/Restaurants.php similarity index 77% rename from app/src/Entity/Restaurants.php rename to app/src/Shared/Entity/Restaurants.php index 4419b8171b44c73350bdea6b5e9ad96d2cc7d3bb..11033eb315b16404f82679979c1883c6dbafa086 100644 --- a/app/src/Entity/Restaurants.php +++ b/app/src/Shared/Entity/Restaurants.php @@ -1,8 +1,9 @@ + */ + #[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; } @@ -125,24 +130,24 @@ class Restaurants 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; @@ -293,86 +298,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/Shared/Entity/Settlements.php similarity index 96% rename from app/src/Entity/Settlements.php rename to app/src/Shared/Entity/Settlements.php index 304a26ca2f29851adbef4d81650e49ae65032173..3c26eb18a18d49bfdf0b8d6a44cf488f320561ad 100644 --- a/app/src/Entity/Settlements.php +++ b/app/src/Shared/Entity/Settlements.php @@ -1,8 +1,8 @@ restaurants = new ArrayCollection(); } - public function getId(): ?int + public function getId(): ?string { return $this->id; } diff --git a/app/src/Entity/Users.php b/app/src/Shared/Entity/Users.php similarity index 96% rename from app/src/Entity/Users.php rename to app/src/Shared/Entity/Users.php index 6c8ef97fc003dec41cc292d315159475d7c1a79b..bbb1f07df25e5c89d58e74a18260a75a05bd8daa 100644 --- a/app/src/Entity/Users.php +++ b/app/src/Shared/Entity/Users.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 0000000000000000000000000000000000000000..9217c1f06b3fe96995fc14daad6b16e1501f31d3 --- /dev/null +++ b/app/src/Shared/Error/ErrorCode.php @@ -0,0 +1,12 @@ + + * + * @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/Shared/Repository/KitchensRepository.php b/app/src/Shared/Repository/KitchensRepository.php new file mode 100644 index 0000000000000000000000000000000000000000..663104669e6cafbdce67941c8801bea6dd9c703e --- /dev/null +++ b/app/src/Shared/Repository/KitchensRepository.php @@ -0,0 +1,30 @@ + + * + * @method Kitchens|null find($id, $lockMode = null, $lockVersion = null) + * @method Kitchens|null findOneBy(array $criteria, array $orderBy = null) + * @method Kitchens[] findAll() + * @method Kitchens[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class KitchensRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Kitchens::class); + } + + /** @return Collection */ + public function getAll(): Collection + { + return new Collection(Kitchens::class, $this->findAll()); + } +} diff --git a/app/src/Shared/Repository/NewsCategoriesRepository.php b/app/src/Shared/Repository/NewsCategoriesRepository.php new file mode 100644 index 0000000000000000000000000000000000000000..9c346899320b015b47e635e3bd99f2729228ea37 --- /dev/null +++ b/app/src/Shared/Repository/NewsCategoriesRepository.php @@ -0,0 +1,32 @@ + + * + * @method NewsCategories|null find($id, $lockMode = null, $lockVersion = null) + * @method NewsCategories|null findOneBy(array $criteria, array $orderBy = null) + * @method NewsCategories[] findAll() + * @method NewsCategories[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class NewsCategoriesRepository extends ServiceEntityRepository{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, NewsCategories::class); + } + + /** + * Возвращает все сущности + * @return Collection + */ + public function getAll(): Collection + { + return new Collection(NewsCategories::class, $this->findAll()); + } +} diff --git a/app/src/Shared/Repository/NewsRepository.php b/app/src/Shared/Repository/NewsRepository.php new file mode 100644 index 0000000000000000000000000000000000000000..4dfe2295098538879780a447dec6589198550bb4 --- /dev/null +++ b/app/src/Shared/Repository/NewsRepository.php @@ -0,0 +1,83 @@ + + * + * @method News|null find($id, $lockMode = null, $lockVersion = null) + * @method News|null findOneBy(array $criteria, array $orderBy = null) + * @method News[] findAll() + * @method News[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class NewsRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, News::class); + } + + public function getMainNews(): News + { + return $this->createQueryBuilder('n') + ->andWhere('n.mainPageRender = true') + ->setMaxResults(1) + ->getQuery() + ->getResult()[0]; + } + + public function getCountWithFilters(?string $categoryId): int + { + $query = $this->createQueryBuilder('n'); + $query = $this->findByFilters($categoryId, $query); + return $query->select('COUNT(n.id)')->getQuery()->getSingleScalarResult(); + } + + /** @return Collection */ + public function getWithFilters(?string $categoryId, int $limit, int $offset): Collection + { + $query = $this->createQueryBuilder('n'); + $query = $this->findByFilters($categoryId, $query); + $query = $query->setMaxResults($limit); + $query = $query->setFirstResult($offset); + return $this->toCollection($query); + } + + /** @return Collection */ + public function getAll(): Collection + { + return $this->toCollection($this->createQueryBuilder('n')); + } + + /** + * @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 findByFilters(?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/Shared/Repository/NewsTypeRepository.php b/app/src/Shared/Repository/NewsTypeRepository.php new file mode 100644 index 0000000000000000000000000000000000000000..e3decdf1337d92c4d089bb97b72d9e7cf4237c31 --- /dev/null +++ b/app/src/Shared/Repository/NewsTypeRepository.php @@ -0,0 +1,30 @@ + + * + * @method NewsType|null find($id, $lockMode = null, $lockVersion = null) + * @method NewsType|null findOneBy(array $criteria, array $orderBy = null) + * @method NewsType[] findAll() + * @method NewsType[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class NewsTypeRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, NewsType::class); + } + + /** @return Collection */ + public function getAll(): Collection + { + return new Collection(NewsType::class, $this->findAll()); + } +} diff --git a/app/src/Shared/Repository/RestaurantTypesRepository.php b/app/src/Shared/Repository/RestaurantTypesRepository.php new file mode 100644 index 0000000000000000000000000000000000000000..8ba1ec24bc7ad01d36b3818c96fbab4141598453 --- /dev/null +++ b/app/src/Shared/Repository/RestaurantTypesRepository.php @@ -0,0 +1,30 @@ + + * + * @method RestaurantTypes|null find($id, $lockMode = null, $lockVersion = null) + * @method RestaurantTypes|null findOneBy(array $criteria, array $orderBy = null) + * @method RestaurantTypes[] findAll() + * @method RestaurantTypes[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class RestaurantTypesRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, RestaurantTypes::class); + } + + /** @return Collection */ + public function getAll(): Collection + { + return new Collection(RestaurantTypes::class, $this->findAll()); + } +} diff --git a/app/src/Shared/Repository/RestaurantsRepository.php b/app/src/Shared/Repository/RestaurantsRepository.php new file mode 100644 index 0000000000000000000000000000000000000000..48eef29c71b89a3ab453955aaec6e357fc71e6fd --- /dev/null +++ b/app/src/Shared/Repository/RestaurantsRepository.php @@ -0,0 +1,77 @@ + + * + * @method Restaurants|null find($id, $lockMode = null, $lockVersion = null) + * @method Restaurants|null findOneBy(array $criteria, array $orderBy = null) + * @method Restaurants[] findAll() + * @method Restaurants[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class RestaurantsRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Restaurants::class); + } + + /** @return Collection */ + protected function toCollection(QueryBuilder $query): Collection + { + return new Collection( + Restaurants::class, + $query + ->orderBy('r.sort', 'ASC') + ->getQuery() + ->getResult() + ); + } + + protected function filterByKitchen(?string $kitchenId, QueryBuilder $query): QueryBuilder + { + if ($kitchenId !== null) { + $query = $query + ->innerJoin('r.kitchens', '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 = :typeId') + ->setParameter('typeId', $typeId); + } + return $query; + } + + public function getCountWithFilters(?string $kitchenId, ?string $typeId): int + { + $query = $this->createQueryBuilder('r'); + $query = $this->filterByKitchen($kitchenId, $query); + $query = $this->filterByType($typeId, $query); + return $query->select('COUNT(r.id)')->getQuery()->getSingleScalarResult(); + } + + /** @return Collection */ + public function getWithFilters(?string $kitchenId, ?string $typeId, int $limit, int $offset): Collection + { + $query = $this->createQueryBuilder('r'); + $query = $this->filterByKitchen($kitchenId, $query); + $query = $this->filterByType($typeId, $query); + $query = $query->setMaxResults($limit); + $query = $query->setFirstResult($offset); + return $this->toCollection($query); + } +} diff --git a/app/src/Shared/Repository/SettlementsRepository.php b/app/src/Shared/Repository/SettlementsRepository.php new file mode 100644 index 0000000000000000000000000000000000000000..e83866a8195857f8baa510f1f7c5268bed092654 --- /dev/null +++ b/app/src/Shared/Repository/SettlementsRepository.php @@ -0,0 +1,24 @@ + + * + * @method Settlements|null find($id, $lockMode = null, $lockVersion = null) + * @method Settlements|null findOneBy(array $criteria, array $orderBy = null) + * @method Settlements[] findAll() + * @method Settlements[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class SettlementsRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Settlements::class); + } +} diff --git a/app/src/Shared/Repository/UsersRepository.php b/app/src/Shared/Repository/UsersRepository.php new file mode 100644 index 0000000000000000000000000000000000000000..770a961c0ad5bd864c28bfa4b8f41cc02d44e40b --- /dev/null +++ b/app/src/Shared/Repository/UsersRepository.php @@ -0,0 +1,23 @@ + + * + * @method Users|null find($id, $lockMode = null, $lockVersion = null) + * @method Users|null findOneBy(array $criteria, array $orderBy = null) + * @method Users[] findAll() + * @method Users[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class UsersRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Users::class); + } +} diff --git a/app/src/Shared/Service/ValidationService.php b/app/src/Shared/Service/ValidationService.php new file mode 100644 index 0000000000000000000000000000000000000000..9c0139d415f1664e346a42ec1ca24771135e12dc --- /dev/null +++ b/app/src/Shared/Service/ValidationService.php @@ -0,0 +1,29 @@ += 1; + } + + public function isLimitValid(int $limit): bool + { + return $limit >= 1; + } +} diff --git a/docker-compose.yml b/compose.yaml similarity index 95% rename from docker-compose.yml rename to compose.yaml index dcc482eeababe568a506e18c71700413addbbb42..caddeb2596e0711a442abcfdc30ca41916f12f4b 100644 --- a/docker-compose.yml +++ b/compose.yaml @@ -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