Use the new mapper component

This commit is contained in:
Tim
2025-08-18 12:30:30 +02:00
parent 2152468bdc
commit 0dc7555ed1
5 changed files with 98 additions and 15 deletions

View File

@ -21,6 +21,7 @@
"symfony/form": "*", "symfony/form": "*",
"symfony/framework-bundle": "*", "symfony/framework-bundle": "*",
"symfony/monolog-bundle": "^3.0", "symfony/monolog-bundle": "^3.0",
"symfony/object-mapper": "7.3.*",
"symfony/property-access": "*", "symfony/property-access": "*",
"symfony/property-info": "*", "symfony/property-info": "*",
"symfony/runtime": "*", "symfony/runtime": "*",

75
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "b4276957397352833f33cac4f3316f34", "content-hash": "405d2a2709cb499d92b64659d2f59b2e",
"packages": [ "packages": [
{ {
"name": "dflydev/dot-access-data", "name": "dflydev/dot-access-data",
@ -4018,6 +4018,79 @@
], ],
"time": "2023-11-06T17:08:13+00:00" "time": "2023-11-06T17:08:13+00:00"
}, },
{
"name": "symfony/object-mapper",
"version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/object-mapper.git",
"reference": "782ee28ec5b1d3f6dbcf93a6b60288df68d774eb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/object-mapper/zipball/782ee28ec5b1d3f6dbcf93a6b60288df68d774eb",
"reference": "782ee28ec5b1d3f6dbcf93a6b60288df68d774eb",
"shasum": ""
},
"require": {
"php": ">=8.2",
"psr/container": "^2.0"
},
"conflict": {
"symfony/property-access": "<7.2"
},
"require-dev": {
"symfony/property-access": "^7.2",
"symfony/var-exporter": "^7.2"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\ObjectMapper\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides a way to map an object to another object",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/object-mapper/tree/v7.3.2"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-07-25T06:21:40+00:00"
},
{ {
"name": "symfony/options-resolver", "name": "symfony/options-resolver",
"version": "v7.3.0", "version": "v7.3.0",

View File

@ -10,6 +10,7 @@ use App\Security\Voter\SnipVoter;
use App\Service\SnipContent\SnipContentService; use App\Service\SnipContent\SnipContentService;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload; use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\ObjectMapper\ObjectMapperInterface;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
class ApiController extends AbstractApiController class ApiController extends AbstractApiController
@ -49,6 +50,7 @@ class ApiController extends AbstractApiController
#[MapRequestPayload] SnipPostRequest $request, #[MapRequestPayload] SnipPostRequest $request,
SnipContentService $cs, SnipContentService $cs,
SnipRepository $repo, SnipRepository $repo,
ObjectMapperInterface $mapper,
): Response ): Response
{ {
$this->denyAccessUnlessGranted(SnipVoter::EDIT, $snip); $this->denyAccessUnlessGranted(SnipVoter::EDIT, $snip);
@ -57,7 +59,7 @@ class ApiController extends AbstractApiController
return $this->errorResponse('Snip is not the latest version'); return $this->errorResponse('Snip is not the latest version');
} }
$request->pushToSnip($snip); $mapper->map($request, $snip);
$repo->save($snip); $repo->save($snip);
if ($request->content !== null) { if ($request->content !== null) {
$cs->update($snip, $request->content, $request->contentName); $cs->update($snip, $request->content, $request->contentName);

View File

@ -0,0 +1,14 @@
<?php
namespace App\Dto\Condition;
use Symfony\Component\ObjectMapper\ConditionCallableInterface;
class ConditionNotNull implements ConditionCallableInterface
{
public function __invoke(mixed $value, object $source, ?object $target): bool
{
return null !== $value;
}
}

View File

@ -2,28 +2,21 @@
namespace App\Dto; namespace App\Dto;
use App\Dto\Condition\ConditionNotNull;
use App\Entity\Snip; use App\Entity\Snip;
use Symfony\Component\ObjectMapper\Attribute\Map;
#[Map(target: Snip::class)]
class SnipPostRequest class SnipPostRequest
{ {
public function __construct( public function __construct(
#[Map(if: new ConditionNotNull())]
public ?string $name = null, public ?string $name = null,
public ?string $content = null, public ?string $content = null,
#[Map(if: new ConditionNotNull())]
public ?bool $public = null, public ?bool $public = null,
#[Map(if: new ConditionNotNull())]
public ?bool $visible = null, public ?bool $visible = null,
public ?string $contentName = null, public ?string $contentName = null,
) {} ) {}
public function pushToSnip(Snip $snip): void
{
if ($this->name !== null) {
$snip->name = $this->name;
}
if ($this->public !== null) {
$snip->public = $this->public;
}
if ($this->visible !== null) {
$snip->visible = $this->visible;
}
}
} }