Skip to content
Snippets Groups Projects
Commit 85ecf8b0 authored by Адлан Шамавов's avatar Адлан Шамавов
Browse files

STA-1047 | Добавлены POST, PUT, PATCH, DELETE для контроллеров

parent ddafca3f
No related branches found
No related tags found
1 merge request!16STA 1047
Showing
with 389 additions and 43 deletions
<?php
namespace App\ArgumentResolver;
use App\Exception\RequestBodyConvertException;
use App\Exception\ValidationException;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use App\Attribute\RequestBody;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\SerializerInterface;
class RequestBodyArgumentResolver implements ValueResolverInterface
{
public function __construct(
private SerializerInterface $serializer,
private ValidatorInterface $validator,
) {}
public function resolve(Request $request, ArgumentMetadata $argument): iterable
{
if (!$argument->getAttributesOfType(RequestBody::class, ArgumentMetadata::IS_INSTANCEOF)) {
return [];
}
try {
$model = $this->serializer->deserialize(
$request->getContent(),
$argument->getType(),
JsonEncoder::FORMAT
);
} catch (\Throwable $throwable) {
throw new RequestBodyConvertException($throwable->getMessage());
}
$errors = $this->validator->validate($model);
if (count($errors) > 0) {
throw new ValidationException($errors);
}
return [$model];
}
}
\ No newline at end of file
<?php
namespace App\Attribute;
use Attribute;
#[Attribute(Attribute::TARGET_PARAMETER)]
class RequestBody
{
}
\ No newline at end of file
......@@ -4,7 +4,10 @@ declare(strict_types=1);
namespace App\Controller;
use App\Attribute\RequestBody;
use App\Exception\NewsNotFoundException;
use App\Requests\CreateNewsRequest;
use App\Requests\EditNewsRequest;
use App\Requests\NewsListRequest;
use App\Service\NewsService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
......@@ -55,4 +58,34 @@ class NewsController extends AbstractController
], $e->getCode());
}
}
#[Route('/news', name: 'addNews', methods: ['POST'])]
public function addNews(
#[RequestBody] CreateNewsRequest $request
): Response {
return $this->json($this->newsService->addNewsByRequest($request));
}
#[Route('/news/{id}', name: 'putNews', methods: ['PUT'])]
public function putNews(
string $id,
#[RequestBody] EditNewsRequest $request
): Response {
return $this->json($this->newsService->putNewsByRequest($id, $request));
}
#[Route('/news/{id}', name: 'patchNews', methods: ['PATCH'])]
public function patchNews(
string $id,
#[RequestBody] EditNewsRequest $request
): Response {
return $this->json($this->newsService->patchNewsByRequest($id, $request));
}
#[Route('/news/{id}', name: 'deleteNews', methods: ['DELETE'])]
public function deleteNews(string $id): Response
{
$this->newsService->deleteNews($id);
return $this->json(null);
}
}
......@@ -4,7 +4,10 @@ declare(strict_types=1);
namespace App\Controller;
use App\Attribute\RequestBody;
use App\Exception\RestaurantNotFoundException;
use App\Requests\CreateRestaurantRequest;
use App\Requests\EditRestaurantRequest;
use App\Requests\RestaurantListRequest;
use App\Service\RestaurantService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
......@@ -39,4 +42,34 @@ class RestaurantController extends AbstractController
], $e->getCode());
}
}
#[Route('/restaurant', name: 'addRestaurant', methods: ['POST'])]
public function addRestaurant(
#[RequestBody] CreateRestaurantRequest $request
): Response {
return $this->json($this->restaurantService->addRestaurantByRequest($request));
}
#[Route('/restaurant/{id}', name: 'putRestaurant', methods: ['PUT'])]
public function putRestaurant(
string $id,
#[RequestBody] EditRestaurantRequest $request
): Response {
return $this->json($this->restaurantService->putRestaurantByRequest($id, $request));
}
#[Route('/restaurant/{id}', name: 'patchRestaurant', methods: ['PATCH'])]
public function patchRestaurant(
string $id,
#[RequestBody] EditRestaurantRequest $request
): Response {
return $this->json($this->restaurantService->patchRestaurantByRequest($id, $request));
}
#[Route('/restaurant/{id}', name: 'deleteRestaurant', methods: ['DELETE'])]
public function deleteRestaurant(string $id): Response
{
$this->restaurantService->deleteRestaurant($id);
return $this->json(null);
}
}
......@@ -63,7 +63,7 @@ class News
#[ORM\JoinColumn(nullable: false)]
private ?Seo $seo = null;
#[ORM\OneToOne(cascade: ['persist', 'remove'])]
#[ORM\OneToOne]
#[ORM\JoinColumn(nullable: false)]
private ?File $file = null;
......
......@@ -94,7 +94,7 @@ class Restaurant
#[ORM\JoinColumn(nullable: false)]
private ?Seo $seo = null;
#[ORM\OneToOne(cascade: ['persist', 'remove'], fetch: 'EAGER')]
#[ORM\OneToOne(fetch: 'EAGER')]
#[ORM\JoinColumn(nullable: false)]
private ?File $file = null;
......@@ -109,6 +109,12 @@ class Restaurant
return $this->id;
}
public function setId(Uuid $id): self
{
$this->id = $id;
return $this;
}
public function getName(): ?string
{
return $this->name;
......
......@@ -4,7 +4,9 @@ namespace App\Exception;
use Symfony\Component\HttpFoundation\Response;
enum NewsExceptionEnum: int
enum ErrorCodeEnum: int
{
case NotFound = Response::HTTP_NOT_FOUND;
case BadRequest = Response::HTTP_BAD_REQUEST;
case UnprocessableEntity = Response::HTTP_UNPROCESSABLE_ENTITY;
}
<?php
namespace App\Exception;
use RuntimeException;
class FileNotFoundException extends RuntimeException
{
public function __construct()
{
parent::__construct("File not found", ErrorCodeEnum::NotFound->value);
}
}
\ No newline at end of file
......@@ -2,10 +2,12 @@
namespace App\Exception;
class NewsNotFoundException extends \RuntimeException
use RuntimeException;
class NewsNotFoundException extends RuntimeException
{
public function __construct()
{
parent::__construct("News not found", NewsExceptionEnum::NotFound->value);
parent::__construct("News not found", ErrorCodeEnum::NotFound->value);
}
}
\ No newline at end of file
<?php
namespace App\Exception;
use RuntimeException;
class NewsTypeNotFoundException extends RuntimeException
{
public function __construct()
{
parent::__construct("News type not found", ErrorCodeEnum::NotFound->value);
}
}
\ No newline at end of file
<?php
namespace App\Exception;
use RuntimeException;
class RequestBodyConvertException extends RuntimeException
{
public function __construct($message)
{
parent::__construct("Error converting request body" . $message, ErrorCodeEnum::BadRequest->value);
}
}
\ No newline at end of file
<?php
namespace App\Exception;
use Symfony\Component\HttpFoundation\Response;
enum RestaurantExceptionEnum: int
{
case NotFound = Response::HTTP_NOT_FOUND;
}
......@@ -6,6 +6,6 @@ class RestaurantNotFoundException extends \RuntimeException
{
public function __construct()
{
parent::__construct("Restaurant not found", RestaurantExceptionEnum::NotFound->value);
parent::__construct("Restaurant not found", ErrorCodeEnum::NotFound->value);
}
}
\ No newline at end of file
<?php
namespace App\Exception;
use RuntimeException;
class RestaurantTypeNotFoundException extends RuntimeException
{
public function __construct()
{
parent::__construct("Restaurant type not found", ErrorCodeEnum::NotFound->value);
}
}
\ No newline at end of file
<?php
namespace App\Exception;
use RuntimeException;
class SeoNotFoundException extends RuntimeException
{
public function __construct()
{
parent::__construct("Seo not found", ErrorCodeEnum::NotFound->value);
}
}
\ No newline at end of file
<?php
namespace App\Exception;
use RuntimeException;
class SettlementNotFoundException extends RuntimeException
{
public function __construct()
{
parent::__construct("Settlement not found", ErrorCodeEnum::NotFound->value);
}
}
\ No newline at end of file
<?php
namespace App\Exception;
use RuntimeException;
class ValidationException extends RuntimeException
{
public function __construct($message)
{
parent::__construct('Validation failed' . $message, ErrorCodeEnum::UnprocessableEntity->value);
}
}
\ No newline at end of file
......@@ -2,15 +2,22 @@
namespace App\Mapper;
use App\Entity\File;
use App\Entity\News;
use App\Entity\NewsCategory;
use App\Entity\NewsType;
use App\Entity\Seo;
use App\Model\NewsDetailElement;
use App\Model\NewsFilterVariants;
use App\Model\NewsList;
use App\Model\NewsListingElement;
use App\Model\NewsCategory as NewsCategoryModel;
use App\Model\Pagination;
use App\Requests\CreateNewsRequest;
use App\Requests\EditNewsRequest;
use Ramsey\Collection\Collection;
use DateTimeImmutable;
use Symfony\Component\Uid\Uuid;
class NewsMapper
{
......@@ -74,4 +81,58 @@ class NewsMapper
$newsCategory->getCode(),
);
}
public static function createNewsEntity(
CreateNewsRequest|EditNewsRequest $request,
NewsType $newsType,
Seo $seo,
File $file,
string $id = null
): News {
$news = (new News())
->setCode($request->getCode())
->setActive($request->isActive())
->setCreateAt(new DateTimeImmutable())
->setUpdateAt(new DateTimeImmutable())
->setSort($request->getSort())
->setPreviewImage($request->getPreviewImage())
->setDetailImage($request->getDetailImage())
->setPreviewText($request->getPreviewText())
->setDetailText($request->getDetailText())
->setType($newsType)
->setMainPageRender($request->isMainPageRender())
->setSeo($seo)
->setFile($file);
if ($id !== null) {
$news->setId(new Uuid($id));
}
return $news;
}
public static function updateNewsEntity(
CreateNewsRequest|EditNewsRequest $request,
NewsType $newsType,
Seo $seo,
File $file,
News $news
): News
{
$news->setCode($request->getCode());
$news->setActive($request->isActive());
$news->setCreateAt($news->getCreateAt());
$news->setUpdateAt(new DateTimeImmutable());
$news->setSort($request->getSort());
$news->setPreviewText($request->getPreviewText());
$news->setDetailText($request->getDetailText());
$news->setPreviewImage($request->getPreviewImage());
$news->setDetailImage($request->getDetailImage());
$news->setType($newsType);
$news->setMainPageRender($request->isMainPageRender());
$news->setSeo($seo);
$news->setFile($file);
return $news;
}
}
\ No newline at end of file
......@@ -6,7 +6,10 @@ use App\Entity\Gallery;
use App\Entity\Kitchen;
use App\Entity\Restaurant;
use App\Entity\RestaurantType;
use App\Entity\Seo;
use App\Entity\Settlement;
use App\Entity\Tags;
use App\Entity\File;
use App\Model\KitchenType;
use App\Model\Pagination;
use App\Model\RestaurantDetailElement;
......@@ -15,8 +18,12 @@ use App\Model\RestaurantList;
use App\Model\RestaurantListingElement;
use App\Model\RestaurantType as RestaurantTypeModel;
use App\Model\Tag;
use App\Model\File;
use App\Model\File as FileModel;
use App\Requests\CreateRestaurantRequest;
use App\Requests\EditRestaurantRequest;
use Ramsey\Collection\Collection;
use DateTimeImmutable;
use Symfony\Component\Uid\Uuid;
class RestaurantMapper
{
......@@ -69,7 +76,7 @@ class RestaurantMapper
public static function mapToDetailElement(
Restaurant $restaurant,
Collection $gallery
Collection|null $gallery
): RestaurantDetailElement {
return new RestaurantDetailElement(
$restaurant->getId(),
......@@ -96,7 +103,9 @@ class RestaurantMapper
),
$restaurant->getSite(),
FileMapper::mapToFile($restaurant->getFile()),
self::mapToGallery($gallery),
$gallery
? self::mapToGallery($gallery)
: new Collection(FileModel::class),
$restaurant->getSeo()?->getTitle(),
$restaurant->getSeo()?->getDescription(),
$restaurant->getSeo()?->getKeywords()
......@@ -135,10 +144,81 @@ class RestaurantMapper
public static function mapToGallery(Collection $gallery): Collection
{
return new Collection(File::class, array_map(
return new Collection(FileModel::class, array_map(
function (Gallery $galleryOne) {
return FileMapper::mapToFile($galleryOne->getFile());
}, $gallery->toArray())
);
}
public static function createRestaurantEntity(
CreateRestaurantRequest|EditRestaurantRequest $request,
RestaurantType $restaurantType,
Settlement $settlement,
Seo $seo,
File $file,
string $id = null
): Restaurant {
$restaurant = (new Restaurant())
->setName($request->getName())
->setCode($request->getCode())
->setActive($request->isActive())
->setSort($request->getSort())
->setCreateAt(new DateTimeImmutable())
->setUpdateAt(new DateTimeImmutable())
->setCoordinates($request->getCoordinates())
->setTypeId($restaurantType)
->setSettlementId($settlement)
->setDescription($request->getDescription())
->setCheckPrice($request->getCheck())
->setCheckInfo($request->getCheckInfo())
->setPhone($request->getPhone())
->setEmail($request->getEmail())
->setAddress($request->getAddress())
->setSite($request->getSite())
->setPreviewImage($request->getPreviewImage())
->setDetailImage($request->getDetailImage())
->setSeo($seo)
->setFile($file)
->setHowToFind($request->getHowToFind());
if ($id !== null) {
$restaurant->setId(new Uuid($id));
}
return $restaurant;
}
public static function updateRestaurantEntity(
EditRestaurantRequest $request,
RestaurantType $restaurantType,
Settlement $settlement,
Seo $seo,
File $file,
Restaurant $restaurant
): Restaurant
{
$restaurant->setName($request->getName());
$restaurant->setCode($request->getCode());
$restaurant->setActive($request->isActive());
$restaurant->setSort($request->getSort());
$restaurant->setCreateAt($restaurant->getCreateAt());
$restaurant->setUpdateAt(new DateTimeImmutable());
$restaurant->setCoordinates($request->getCoordinates());
$restaurant->setTypeId($restaurantType);
$restaurant->setSettlementId($settlement);
$restaurant->setDescription($request->getDescription());
$restaurant->setCheckPrice($request->getCheck());
$restaurant->setCheckInfo($request->getCheckInfo());
$restaurant->setPhone($request->getPhone());
$restaurant->setEmail($request->getEmail());
$restaurant->setAddress($request->getAddress());
$restaurant->setSite($request->getSite());
$restaurant->setPreviewImage($request->getPreviewImage());
$restaurant->setHowToFind($request->getHowToFind());
$restaurant->setDetailImage($request->getDetailImage());
$restaurant->setSeo($seo);
$restaurant->setFile($file);
return $restaurant;
}
}
\ No newline at end of file
......@@ -5,6 +5,7 @@ namespace App\Repository;
use App\Entity\File;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Uid\Uuid;
/**
* @extends ServiceEntityRepository<File>
......@@ -21,28 +22,8 @@ class FileRepository extends ServiceEntityRepository
parent::__construct($registry, File::class);
}
// /**
// * @return File[] Returns an array of File objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('f')
// ->andWhere('f.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('f.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?File
// {
// return $this->createQueryBuilder('f')
// ->andWhere('f.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
public function getById(Uuid $id): ?File
{
return $this->find($id);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment