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

api-platform / core / 18089937549

29 Sep 2025 07:56AM UTC coverage: 21.764% (-0.3%) from 22.093%
18089937549

Pull #7416

github

web-flow
Merge 061bcc790 into abe0438be
Pull Request #7416: fix(laravel): serializer attributes on Eloquent methods

0 of 151 new or added lines in 11 files covered. (0.0%)

5028 existing lines in 173 files now uncovered.

11889 of 54626 relevant lines covered (21.76%)

25.32 hits per line

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

0.0
/src/Laravel/Controller/ApiPlatformController.php
1
<?php
2

3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <dunglas@gmail.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11

12
declare(strict_types=1);
13

14
namespace ApiPlatform\Laravel\Controller;
15

16
use ApiPlatform\HttpCache\PurgerInterface;
17
use ApiPlatform\Laravel\Eloquent\Listener\PurgeHttpCacheListener;
18
use ApiPlatform\Metadata\HttpOperation;
19
use ApiPlatform\Metadata\Operation\Factory\OperationMetadataFactoryInterface;
20
use ApiPlatform\State\ProcessorInterface;
21
use ApiPlatform\State\ProviderInterface;
22
use Illuminate\Http\Request;
23
use Illuminate\Routing\Controller;
24
use Illuminate\Support\Facades\Event;
25
use Symfony\Component\HttpFoundation\Response;
26

27
class ApiPlatformController extends Controller
28
{
29
    /**
30
     * @param ProviderInterface<object>                                  $provider
31
     * @param ProcessorInterface<iterable<object>|object|null, Response> $processor
32
     */
33
    public function __construct(
34
        protected OperationMetadataFactoryInterface $operationMetadataFactory,
35
        protected ProviderInterface $provider,
36
        protected ProcessorInterface $processor,
37
    ) {
38
    }
×
39

40
    /**
41
     * Display a listing of the resource.
42
     */
43
    public function __invoke(Request $request): Response
44
    {
45
        $operation = $request->attributes->get('_api_operation');
×
46
        if (!$operation) {
×
47
            throw new \RuntimeException('Operation not found.');
×
48
        }
49

50
        if (!$operation instanceof HttpOperation) {
×
51
            throw new \LogicException('Operation is not an HttpOperation.');
×
52
        }
53

54
        $uriVariables = $this->getUriVariables($request, $operation);
×
55
        $request->attributes->set('_api_uri_variables', $uriVariables);
×
56
        // at some point we could introduce that back
57
        // if ($this->uriVariablesConverter) {
58
        //     $context = ['operation' => $operation, 'uri_variables_map' => $uriVariablesMap];
59
        //     $identifiers = $this->uriVariablesConverter->convert($identifiers, $operation->getClass() ?? $resourceClass, $context);
60
        // }
61

62
        $context = [
×
63
            'request' => $request,
×
64
            'uri_variables' => $uriVariables,
×
65
            'resource_class' => $operation->getClass(),
×
66
        ];
×
67

68
        if (null === $operation->canValidate()) {
×
69
            $operation = $operation->withValidate(!$request->isMethodSafe() && !$request->isMethod('DELETE'));
×
70
        }
71

72
        if (null === $operation->canRead()) {
×
73
            $operation = $operation->withRead($operation->getUriVariables() || $request->isMethodSafe());
×
74
        }
75

76
        if (null === $operation->canDeserialize()) {
×
77
            $operation = $operation->withDeserialize(\in_array($operation->getMethod(), ['POST', 'PUT', 'PATCH'], true));
×
78
        }
79

80
        $body = $this->provider->provide($operation, $uriVariables, $context);
×
81

82
        // The provider can change the Operation, extract it again from the Request attributes
83
        if ($request->attributes->get('_api_operation') !== $operation) {
×
84
            $operation = $request->attributes->get('_api_operation');
×
85
            $uriVariables = $this->getUriVariables($request, $operation);
×
86
        }
87

88
        $context['previous_data'] = $request->attributes->get('previous_data');
×
89
        $context['data'] = $request->attributes->get('data');
×
90

91
        if (null === $operation->canWrite()) {
×
92
            $operation = $operation->withWrite(!$request->isMethodSafe());
×
93
        }
94

95
        if (null === $operation->canSerialize()) {
×
96
            $operation = $operation->withSerialize(true);
×
97
        }
98

99
        if (interface_exists(PurgerInterface::class)) {
×
100
            Event::listen('eloquent.saved: *', [PurgeHttpCacheListener::class, 'handleModelSaved']);
×
101
            Event::listen('eloquent.deleted: *', [PurgeHttpCacheListener::class, 'handleModelDeleted']);
×
102
        }
103

104
        return $this->processor->process($body, $operation, $uriVariables, $context);
×
105
    }
106

107
    /**
108
     * @return array<string, mixed>
109
     */
110
    private function getUriVariables(Request $request, HttpOperation $operation): array
111
    {
112
        $uriVariables = [];
×
113
        foreach ($operation->getUriVariables() ?? [] as $parameterName => $_) {
×
114
            // TODO: use $link->getParameterName() instead but be sure it is filled correctly in metadata fist
115
            $parameter = $request->route((string) $parameterName);
×
116
            if (\is_string($parameter) && ($format = $request->attributes->get('_format')) && str_contains($parameter, $format)) {
×
UNCOV
117
                $parameter = substr($parameter, 0, \strlen($parameter) - (\strlen($format) + 1));
×
118
            }
119

UNCOV
120
            $uriVariables[(string) $parameterName] = $parameter;
×
121
        }
122

UNCOV
123
        return $uriVariables;
×
124
    }
125
}
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