Skip to content

Commit

Permalink
Add MapRequestPayload
Browse files Browse the repository at this point in the history
  • Loading branch information
TheCadien committed Feb 2, 2024
1 parent cc57a8e commit 62cefde
Show file tree
Hide file tree
Showing 16 changed files with 200 additions and 250 deletions.
17 changes: 9 additions & 8 deletions Api/Factory/NewsApiDtoFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@

final class NewsApiDtoFactory
{
public function generate(NewsEntity $entity): News
public function generate(NewsEntity $entity, string $locale): News
{
return new News(
$entity->getId(),
$entity->getTitle(),
$entity->getTeaser(),
$entity->getContent(),
$entity->isEnabled(),
$entity->getPublishedAt(),
id: $entity->getId(),
title: $entity->getTitle(),

Check failure on line 14 in Api/Factory/NewsApiDtoFactory.php

View workflow job for this annotation

GitHub Actions / phpstan

Parameter $title of class TheCadien\Bundle\SuluNewsBundle\Api\News constructor expects string, string|null given.
teaser: $entity->getTeaser(),
content: $entity->getContent(),
enabled: $entity->isEnabled(),
publishedAt: $entity->getPublishedAt(),
route: $entity->getRoute()?->getPath(),
tags: $entity->getTagNameArray(),
header: [
Expand All @@ -25,7 +25,8 @@ public function generate(NewsEntity $entity): News
created: $entity->getCreated(),
changed: $entity->getChanged(),
author: $entity->getCreator()?->getId(),
ext: $entity->getSeo()
ext: $entity->getSeo(),
locale: $locale
);
}
}
24 changes: 14 additions & 10 deletions Api/News.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,27 @@

namespace TheCadien\Bundle\SuluNewsBundle\Api;

use Symfony\Component\Validator\Constraints as Assert;

final class News
{
public function __construct(
public int $id,
public ?string $title = null,
public ?string $teaser = null,
public ?array $content = null,
public ?bool $enabled = null,
#[Assert\NotBlank(groups: ['edit'])]
public ?int $id,
public string $title,
public ?string $teaser,
public ?array $content,

Check failure on line 25 in Api/News.php

View workflow job for this annotation

GitHub Actions / phpstan

Property TheCadien\Bundle\SuluNewsBundle\Api\News::$content type has no value type specified in iterable type array.
public ?bool $enabled,
public ?\DateTime $publishedAt = null,
public ?string $route = null,
public ?array $tags = null,
public ?array $header = null,
public ?string $route,
public ?array $tags,

Check failure on line 29 in Api/News.php

View workflow job for this annotation

GitHub Actions / phpstan

Property TheCadien\Bundle\SuluNewsBundle\Api\News::$tags type has no value type specified in iterable type array.
public ?array $header,

Check failure on line 30 in Api/News.php

View workflow job for this annotation

GitHub Actions / phpstan

Property TheCadien\Bundle\SuluNewsBundle\Api\News::$header type has no value type specified in iterable type array.
public ?\DateTime $authored = null,
public ?\DateTime $created = null,
public ?\DateTime $changed = null,
public ?int $author = null,
public ?string $ext = null
public ?int $author,
public ?string $ext,
public ?string $locale = null
) {
}
}
79 changes: 28 additions & 51 deletions Controller/Admin/NewsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,23 @@

namespace TheCadien\Bundle\SuluNewsBundle\Controller\Admin;

use Sulu\Component\Rest\Exception\EntityNotFoundException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Annotation\Route;
use TheCadien\Bundle\SuluNewsBundle\Api\Factory\NewsApiDtoFactory;
use TheCadien\Bundle\SuluNewsBundle\Api\News as NewsApi;
use TheCadien\Bundle\SuluNewsBundle\Common\DoctrineListRepresentationFactory;
use TheCadien\Bundle\SuluNewsBundle\Entity\News;
use TheCadien\Bundle\SuluNewsBundle\Repository\NewsRepository;
use TheCadien\Bundle\SuluNewsBundle\Exception\NewsException;
use TheCadien\Bundle\SuluNewsBundle\Service\News\NewsService;

#[AsController]
final class NewsController extends AbstractController
{
public function __construct(
private readonly NewsRepository $repository,
private readonly NewsService $newsService,
private readonly DoctrineListRepresentationFactory $doctrineListRepresentationFactory,
private readonly NewsApiDtoFactory $apiDtoFactory
Expand All @@ -41,87 +39,66 @@ public function __construct(
#[Route('/news', name: 'app.cget_news', methods: ['GET'])]
public function cget(Request $request): Response
{
$locale = $request->query->get('locale');
$listRepresentation = $this->doctrineListRepresentationFactory->createDoctrineListRepresentation(
News::RESOURCE_KEY,
[],
['locale' => $locale]
['locale' => $request->query->get('locale')]
);

return $this->json($listRepresentation->toArray());
}

#[Route('/news/{id}', name: 'app.get_news', methods: ['GET'])]
public function get(int $id, Request $request): Response
public function get(News $news, Request $request): Response
{
if (!($entity = $this->repository->findById($id)) instanceof \TheCadien\Bundle\SuluNewsBundle\Entity\News) {
throw new NotFoundHttpException();
}
$apiEntity = $this->generateApiNewsEntity($entity, $request->query->get('locale'));

return $this->json($apiEntity, 200, []);
return $this->json($this->apiDtoFactory->generate($news, $request->query->get('locale')));
}

#[Route('/news', name: 'app.post_news', methods: ['POST'])]
public function post(Request $request): Response
public function post(#[MapRequestPayload(acceptFormat: 'json')] NewsApi $newsApi, Request $request): Response
{
$news = $this->newsService->saveNewNews($request->request->all(), $request->query->get('locale'));

$apiEntity = $this->generateApiNewsEntity($news, $request->query->get('locale'));
try {
$news = $this->newsService->saveNewNews($newsApi, $request->query->get('locale'));
} catch (NewsException) {
throw new NewsException();
}

return $this->json($apiEntity, 200, [], ['fullNews']);
return $this->json($this->apiDtoFactory->generate($news, $request->query->get('locale')), 200, [], ['fullNews']);
}

#[Route('/news/{id}', name: 'app.post_news_trigger', methods: ['POST'])]
public function postTrigger(int $id, Request $request): Response
public function postTrigger(News $news, Request $request): Response
{
$news = $this->repository->findById($id);
if (!$news instanceof News) {
throw new NotFoundHttpException();
try {
$news = $this->newsService->updateNewsPublish($news, $request->query->all());
} catch (NewsException) {
throw new NewsException();
}

$news = $this->newsService->updateNewsPublish($news, $request->query->all());

$apiEntity = $this->generateApiNewsEntity($news, $request->query->get(
'locale'
));

return $this->json($apiEntity);
return $this->json($this->apiDtoFactory->generate($news, $request->query->get('locale')));
}

#[Route('/news/{id}', name: 'app.put_news', methods: ['PUT'])]
public function put(int $id, Request $request): Response
public function put(News $news, #[MapRequestPayload(acceptFormat: 'json')] NewsApi $newsApi, Request $request): Response
{
$entity = $this->repository->findById($id);
if (!$entity instanceof News) {
throw new NotFoundHttpException();
try {
$updatedEntity = $this->newsService->updateNews($newsApi, $news, $request->query->get('locale'));
} catch (NewsException) {
throw new NewsException();
}

$updatedEntity = $this->newsService->updateNews($request->request->all(), $entity, $request->query->get('locale'));
$apiEntity = $this->generateApiNewsEntity($updatedEntity, $request->query->get('locale'));

return $this->json($apiEntity);
return $this->json($this->apiDtoFactory->generate($updatedEntity, $request->query->get('locale')));
}

#[Route('/news/{id}', name: 'app.delete_news', methods: ['DELETE'])]
public function delete(int $id): Response
public function delete(News $news): Response
{
try {
$this->newsService->removeNews($id);
} catch (\Exception) {
throw new EntityNotFoundException(News::class, $id);
$this->newsService->removeNews($news->getId());
} catch (NewsException) {
throw new NewsException();
}

return $this->json(null, 204);
}

protected function generateApiNewsEntity(News $entity, string $locale): NewsApi
{
return $this->apiDtoFactory->generate($entity);
}

public function getPriority(): int
{
return 0;
}
}
33 changes: 0 additions & 33 deletions Entity/Factory/AbstractFactory.php

This file was deleted.

2 changes: 1 addition & 1 deletion Entity/Factory/MediaFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use Sulu\Bundle\MediaBundle\Entity\MediaRepositoryInterface;
use Sulu\Component\Rest\Exception\EntityNotFoundException;

class MediaFactory extends AbstractFactory implements MediaFactoryInterface
class MediaFactory implements MediaFactoryInterface
{
/**
* NewsFactory constructor.
Expand Down
49 changes: 16 additions & 33 deletions Entity/Factory/NewsFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@

use Sulu\Bundle\ContactBundle\Entity\ContactRepositoryInterface;
use Sulu\Component\Persistence\RelationTrait;
use TheCadien\Bundle\SuluNewsBundle\Api\News as NewsApi;
use TheCadien\Bundle\SuluNewsBundle\Entity\News;

class NewsFactory extends AbstractFactory implements NewsFactoryInterface
class NewsFactory implements NewsFactoryInterface
{
use RelationTrait;

Expand All @@ -33,34 +34,17 @@ public function __construct(private readonly MediaFactoryInterface $mediaFactory
*
* @throws \Exception
*/
public function generateNewsFromRequest(News $news, array $data, string $locale = null, $state = null): News
public function generateNewsFromRequest(News $news, NewsApi $data, string $locale = null, $state = null): News
{
if ($this->getProperty($data, 'title')) {
$news->setTitle($this->getProperty($data, 'title'));
}

if ($this->getProperty($data, 'teaser')) {
$news->setTeaser($this->getProperty($data, 'teaser'));
}

if ($this->getProperty($data, 'header')) {
$news->setHeader($this->mediaFactory->generateMedia($data['header']));
}

if ($this->getProperty($data, 'publishedAt')) {
$news->setPublishedAt(new \DateTime($this->getProperty($data, 'publishedAt')));
}

if ($this->getProperty($data, 'content')) {
$news->setContent($this->getProperty($data, 'content'));
}

if ($this->getProperty($data, 'ext')) {
$news->setSeo($this->getProperty($data['ext'], 'seo'));
}

if ($tags = $this->getProperty($data, 'tags')) {
$this->tagFactory->processTags($news, $tags);
$news->setTitle($data->title);
$news->setTeaser($data->teaser);
$news->setHeader($data->header);
$news->setPublishedAt($data->publishedAt);
$news->setContent($data->content);
$news->setSeo($data->ext);

if ($data->tags) {
$this->tagFactory->processTags($news, $data->tags);
}

if (!$news->getId()) {
Expand All @@ -75,13 +59,12 @@ public function generateNewsFromRequest(News $news, array $data, string $locale
$news->setEnabled($state);
}

if ($authored = $this->getProperty($data, 'authored')) {
$news->setCreated(new \DateTime($authored));
if ($data->authored) {
$news->setCreated($data->authored);
}

if ($author = $this->getProperty($data, 'author')) {
// @var Contact $contact
$news->setCreator($this->contactRepository->find($author));
if ($data->author) {
$news->setCreator($this->contactRepository->find($data->author));
}

return $news;
Expand Down
3 changes: 2 additions & 1 deletion Entity/Factory/NewsFactoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@

namespace TheCadien\Bundle\SuluNewsBundle\Entity\Factory;

use TheCadien\Bundle\SuluNewsBundle\Api\News as NewsApi;
use TheCadien\Bundle\SuluNewsBundle\Entity\News;

interface NewsFactoryInterface
{
public function generateNewsFromRequest(News $news, array $data, string $locale): News;
public function generateNewsFromRequest(News $news, NewsApi $data, string $locale): News;
}
24 changes: 18 additions & 6 deletions Entity/Factory/TagFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use Sulu\Component\Persistence\RelationTrait;
use TheCadien\Bundle\SuluNewsBundle\Entity\News;

class TagFactory extends AbstractFactory implements TagFactoryInterface
class TagFactory implements TagFactoryInterface
{
use RelationTrait;

Expand All @@ -35,24 +35,36 @@ public function __construct(private readonly TagManagerInterface $tagManager)
*/
public function processTags(News $news, $tags)
{
$get = fn ($tag) => $tag->getId();
$get = function ($tag) {
return $tag->getId();
};

$delete = fn ($tag) => $news->removeTag($tag);
$delete = function ($tag) use ($news) {
return $news->removeTag($tag);
};

$update = fn () => true;
$update = function () {
return true;
};

$add = fn ($tag) => $this->addTag($news, $tag);
$add = function ($tag) use ($news) {
return $this->addTag($news, $tag);
};

$entities = $news->getTags();

return $this->processSubEntities(
$result = $this->processSubEntities(
$entities,
$tags,
$get,
$add,
$update,
$delete
);

$this->resetIndexOfSubentites($entities);

return $result;
}

/**
Expand Down
Loading

0 comments on commit 62cefde

Please sign in to comment.