• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

GollumSF / rest-bundle / 23707748905

29 Mar 2026 11:09AM UTC coverage: 99.281% (-0.5%) from 99.815%
23707748905

push

github

Smeagolworms4
Fix Post resolver

19 of 21 new or added lines in 2 files covered. (90.48%)

1 existing line in 1 file now uncovered.

552 of 556 relevant lines covered (99.28%)

22.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.15
/src/Request/ValueResolver/PostRestValueResolver.php
1
<?php
2
namespace GollumSF\RestBundle\Request\ValueResolver;
3

4
use Doctrine\Persistence\ManagerRegistry;
5
use GollumSF\ControllerActionExtractorBundle\Extractor\ControllerActionExtractorInterface;
6
use GollumSF\RestBundle\Attribute\Unserialize;
7
use GollumSF\RestBundle\Metadata\Unserialize\MetadataUnserializeManagerInterface;
8
use GollumSF\RestBundle\Traits\ManagerRegistryToManager;
9
use Symfony\Component\HttpFoundation\Request;
10
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
11
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
12
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
13
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
14
use Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException;
15
use Symfony\Component\Serializer\SerializerInterface;
16

17
class PostRestValueResolver implements ValueResolverInterface
18
{
19
        use ManagerRegistryToManager;
20

21
        private ControllerActionExtractorInterface $controllerActionExtractor;
22
        private MetadataUnserializeManagerInterface $metadataUnserializeManager;
23
        private SerializerInterface $serializer;
24
        private ?ManagerRegistry $managerRegistry = null;
25

26
        public function __construct(
27
                ControllerActionExtractorInterface $controllerActionExtractor,
28
                MetadataUnserializeManagerInterface $metadataUnserializeManager,
29
                SerializerInterface $serializer
30
        ) {
31
                $this->controllerActionExtractor = $controllerActionExtractor;
50✔
32
                $this->metadataUnserializeManager = $metadataUnserializeManager;
50✔
33
                $this->serializer = $serializer;
50✔
34
        }
35

36
        public function setManagerRegistry(ManagerRegistry $managerRegistry): void {
37
                $this->managerRegistry = $managerRegistry;
41✔
38
        }
39

40
        public function resolve(Request $request, ArgumentMetadata $argument): iterable
41
        {
42
                // If already resolved by a previous pass (e.g. by the SerializerSubscriber)
43
                if (
44
                        $request->attributes->has(Unserialize::REQUEST_ATTRIBUTE_NAME) &&
49✔
45
                        $request->attributes->get(Unserialize::REQUEST_ATTRIBUTE_NAME) === $argument->getName()
49✔
46
                ) {
47
                        return [ $request->attributes->get($argument->getName()) ];
1✔
48
                }
49

50
                $controllerAction = $this->controllerActionExtractor->extractFromRequest($request);
48✔
51
                if (!$controllerAction) {
48✔
52
                        return [];
1✔
53
                }
54

55
                $metadata = $this->metadataUnserializeManager->getMetadata(
47✔
56
                        $controllerAction->getControllerClass(),
47✔
57
                        $controllerAction->getActionMethod()
47✔
58
                );
47✔
59

60
                if (!$metadata || $metadata->getName() !== $argument->getName()) {
47✔
61
                        return [];
11✔
62
                }
63

64
                $class = $argument->getType();
36✔
65
                if (!$class) {
36✔
66
                        return [];
1✔
67
                }
68

69
                $argumentName = $argument->getName();
35✔
70

71
                // If we have an identifier in the route (PUT/PATCH with {id}), load entity from Doctrine
72
                if ($this->hasIdentifier($request, $argumentName)) {
35✔
73
                        $entity = $this->resolveFromDoctrine($request, $class, $argumentName);
15✔
74
                        if ($entity) {
15✔
75
                                $request->attributes->set($argumentName, $entity);
11✔
76
                        } else {
77
                                throw new NotFoundHttpException(sprintf('"%s" object not found by "%s".', $class, self::class));
4✔
78
                        }
79
                } else {
80
                        // No identifier in route: deserialize the body to create/find the entity
81
                        // This replicates the old PostRestParamConverter behavior
82
                        $content = $request->getContent();
20✔
83
                        if ($content) {
20✔
84
                                try {
85
                                        $entity = $this->serializer->deserialize($content, $class, 'json', [
19✔
86
                                                'groups' => $metadata->getGroups(),
19✔
87
                                        ]);
19✔
88
                                        $request->attributes->set($argumentName, $entity);
13✔
89
                                } catch (MissingConstructorArgumentsException $e) {
6✔
NEW
90
                                        throw new BadRequestHttpException($e->getMessage());
×
91
                                } catch (\UnexpectedValueException $e) {
6✔
92
                                        throw new BadRequestHttpException($e->getMessage());
6✔
93
                                }
94
                        }
95
                }
96

97
                $request->attributes->set(Unserialize::REQUEST_ATTRIBUTE_CLASS, $class);
25✔
98
                $request->attributes->set(Unserialize::REQUEST_ATTRIBUTE_NAME, $argumentName);
25✔
99

100
                return [ $request->attributes->get($argumentName) ];
25✔
101
        }
102

103
        protected function hasIdentifier(Request $request, string $argumentName): bool
104
        {
105
                if ($request->attributes->has($argumentName)) {
35✔
106
                        return $request->attributes->get($argumentName) !== null;
4✔
107
                }
108
                if ($request->attributes->has('id')) {
31✔
109
                        return $request->attributes->get('id') !== null;
11✔
110
                }
111
                return false;
20✔
112
        }
113

114
        private function resolveFromDoctrine(Request $request, string $class, string $argumentName): ?object
115
        {
116
                if (!$this->isEntity($class)) {
16✔
117
                        return null;
2✔
118
                }
119

120
                $em = $this->getEntityManagerForClass($class);
14✔
121
                if (!$em) {
14✔
UNCOV
122
                        return null;
×
123
                }
124

125
                $id = $request->attributes->get($argumentName) ?? $request->attributes->get('id');
14✔
126
                if ($id === null) {
14✔
127
                        return null;
1✔
128
                }
129

130
                return $em->getRepository($class)->find($id);
13✔
131
        }
132
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc