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

api-platform / core / 13998954715

21 Mar 2025 06:57PM UTC coverage: 8.514% (+0.07%) from 8.443%
13998954715

push

github

web-flow
fix(laravel): defer autoconfiguration (#7040)

fixes #7033

0 of 106 new or added lines in 6 files covered. (0.0%)

2 existing lines in 2 files now uncovered.

13382 of 157180 relevant lines covered (8.51%)

22.87 hits per line

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

0.0
/src/Laravel/ApiPlatformDeferredProvider.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;
15

16
use ApiPlatform\JsonApi\Filter\SparseFieldset;
17
use ApiPlatform\JsonApi\Filter\SparseFieldsetParameterProvider;
18
use ApiPlatform\Laravel\Eloquent\Extension\FilterQueryExtension;
19
use ApiPlatform\Laravel\Eloquent\Extension\QueryExtensionInterface;
20
use ApiPlatform\Laravel\Eloquent\Filter\BooleanFilter;
21
use ApiPlatform\Laravel\Eloquent\Filter\DateFilter;
22
use ApiPlatform\Laravel\Eloquent\Filter\EqualsFilter;
23
use ApiPlatform\Laravel\Eloquent\Filter\FilterInterface as EloquentFilterInterface;
24
use ApiPlatform\Laravel\Eloquent\Filter\JsonApi\SortFilter;
25
use ApiPlatform\Laravel\Eloquent\Filter\JsonApi\SortFilterParameterProvider;
26
use ApiPlatform\Laravel\Eloquent\Filter\OrderFilter;
27
use ApiPlatform\Laravel\Eloquent\Filter\PartialSearchFilter;
28
use ApiPlatform\Laravel\Eloquent\Filter\RangeFilter;
29
use ApiPlatform\Laravel\Eloquent\State\CollectionProvider;
30
use ApiPlatform\Laravel\Eloquent\State\ItemProvider;
31
use ApiPlatform\Laravel\Eloquent\State\LinksHandler;
32
use ApiPlatform\Laravel\Eloquent\State\LinksHandlerInterface;
33
use ApiPlatform\Laravel\Eloquent\State\PersistProcessor;
34
use ApiPlatform\Laravel\Eloquent\State\RemoveProcessor;
35
use ApiPlatform\Laravel\State\ParameterValidatorProvider;
36
use ApiPlatform\Laravel\State\SwaggerUiProcessor;
37
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
38
use ApiPlatform\Metadata\ResourceAccessCheckerInterface;
39
use ApiPlatform\Metadata\Util\ReflectionClassRecursiveIterator;
40
use ApiPlatform\Serializer\Filter\FilterInterface as SerializerFilterInterface;
41
use ApiPlatform\Serializer\Filter\PropertyFilter;
42
use ApiPlatform\Serializer\Parameter\SerializerFilterParameterProvider;
43
use ApiPlatform\State\CallableProcessor;
44
use ApiPlatform\State\CallableProvider;
45
use ApiPlatform\State\ErrorProvider;
46
use ApiPlatform\State\Pagination\Pagination;
47
use ApiPlatform\State\ParameterProviderInterface;
48
use ApiPlatform\State\ProcessorInterface;
49
use ApiPlatform\State\Provider\DeserializeProvider;
50
use ApiPlatform\State\Provider\ParameterProvider;
51
use ApiPlatform\State\Provider\SecurityParameterProvider;
52
use ApiPlatform\State\ProviderInterface;
53
use Illuminate\Contracts\Foundation\Application;
54
use Illuminate\Contracts\Support\DeferrableProvider;
55
use Illuminate\Support\ServiceProvider;
56

57
class ApiPlatformDeferredProvider extends ServiceProvider implements DeferrableProvider
58
{
59
    /**
60
     * Register any application services.
61
     */
62
    public function register(): void
63
    {
NEW
64
        $directory = app_path();
×
NEW
65
        $classes = ReflectionClassRecursiveIterator::getReflectionClassesFromDirectories([$directory]);
×
66

NEW
67
        $this->autoconfigure($classes, QueryExtensionInterface::class, [FilterQueryExtension::class]);
×
NEW
68
        $this->app->singleton(ItemProvider::class, function (Application $app) {
×
NEW
69
            $tagged = iterator_to_array($app->tagged(LinksHandlerInterface::class));
×
70

NEW
71
            return new ItemProvider(new LinksHandler($app, $app->make(ResourceMetadataCollectionFactoryInterface::class)), new ServiceLocator($tagged), $app->tagged(QueryExtensionInterface::class));
×
NEW
72
        });
×
73

NEW
74
        $this->app->singleton(CollectionProvider::class, function (Application $app) {
×
NEW
75
            $tagged = iterator_to_array($app->tagged(LinksHandlerInterface::class));
×
76

NEW
77
            return new CollectionProvider($app->make(Pagination::class), new LinksHandler($app, $app->make(ResourceMetadataCollectionFactoryInterface::class)), $app->tagged(QueryExtensionInterface::class), new ServiceLocator($tagged));
×
NEW
78
        });
×
79

NEW
80
        $this->app->singleton(SerializerFilterParameterProvider::class, function (Application $app) {
×
NEW
81
            $tagged = iterator_to_array($app->tagged(SerializerFilterInterface::class));
×
82

NEW
83
            return new SerializerFilterParameterProvider(new ServiceLocator($tagged));
×
NEW
84
        });
×
NEW
85
        $this->app->alias(SerializerFilterParameterProvider::class, 'api_platform.serializer.filter_parameter_provider');
×
86

NEW
87
        $this->app->singleton('filters', function (Application $app) {
×
NEW
88
            return new ServiceLocator(array_merge(
×
NEW
89
                iterator_to_array($app->tagged(SerializerFilterInterface::class)),
×
NEW
90
                iterator_to_array($app->tagged(EloquentFilterInterface::class))
×
NEW
91
            ));
×
NEW
92
        });
×
93

NEW
94
        $this->autoconfigure($classes, SerializerFilterInterface::class, [PropertyFilter::class]);
×
95

NEW
96
        $this->app->singleton(ParameterProvider::class, function (Application $app) {
×
NEW
97
            $tagged = iterator_to_array($app->tagged(ParameterProviderInterface::class));
×
NEW
98
            $tagged['api_platform.serializer.filter_parameter_provider'] = $app->make(SerializerFilterParameterProvider::class);
×
99

NEW
100
            return new ParameterProvider(
×
NEW
101
                new ParameterValidatorProvider(
×
NEW
102
                    new SecurityParameterProvider(
×
NEW
103
                        $app->make(DeserializeProvider::class),
×
NEW
104
                        $app->make(ResourceAccessCheckerInterface::class)
×
NEW
105
                    ),
×
NEW
106
                ),
×
NEW
107
                new ServiceLocator($tagged)
×
NEW
108
            );
×
NEW
109
        });
×
110

NEW
111
        $this->autoconfigure($classes, ParameterProviderInterface::class, [SerializerFilterParameterProvider::class, SortFilterParameterProvider::class, SparseFieldsetParameterProvider::class]);
×
112

NEW
113
        $this->app->bind(FilterQueryExtension::class, function (Application $app) {
×
NEW
114
            $tagged = iterator_to_array($app->tagged(EloquentFilterInterface::class));
×
115

NEW
116
            return new FilterQueryExtension(new ServiceLocator($tagged));
×
NEW
117
        });
×
118

NEW
119
        $this->autoconfigure($classes, EloquentFilterInterface::class, [
×
NEW
120
            BooleanFilter::class,
×
NEW
121
            EqualsFilter::class,
×
NEW
122
            PartialSearchFilter::class,
×
NEW
123
            DateFilter::class,
×
NEW
124
            OrderFilter::class,
×
NEW
125
            RangeFilter::class,
×
NEW
126
            SortFilter::class,
×
NEW
127
            SparseFieldset::class,
×
NEW
128
        ]);
×
129

NEW
130
        $this->app->singleton(CallableProcessor::class, function (Application $app) {
×
131
            /** @var ConfigRepository */
NEW
132
            $config = $app['config'];
×
NEW
133
            $tagged = iterator_to_array($app->tagged(ProcessorInterface::class));
×
134

NEW
135
            if ($config->get('api-platform.swagger_ui.enabled', false)) {
×
136
                // TODO: tag SwaggerUiProcessor instead?
NEW
137
                $tagged['api_platform.swagger_ui.processor'] = $app->make(SwaggerUiProcessor::class);
×
138
            }
139

NEW
140
            return new CallableProcessor(new ServiceLocator($tagged));
×
NEW
141
        });
×
142

NEW
143
        $this->autoconfigure($classes, ProcessorInterface::class, [RemoveProcessor::class, PersistProcessor::class]);
×
144

NEW
145
        $this->app->singleton(CallableProvider::class, function (Application $app) {
×
NEW
146
            $tagged = iterator_to_array($app->tagged(ProviderInterface::class));
×
147

NEW
148
            return new CallableProvider(new ServiceLocator($tagged));
×
NEW
149
        });
×
150

NEW
151
        $this->autoconfigure($classes, ProviderInterface::class, [ItemProvider::class, CollectionProvider::class, ErrorProvider::class]);
×
152
    }
153

154
    /**
155
     * @param array<class-string, \ReflectionClass> $classes
156
     * @param class-string                          $interface
157
     * @param array<int, class-string>              $apiPlatformProviders
158
     */
159
    private function autoconfigure(array $classes, string $interface, array $apiPlatformProviders): void
160
    {
NEW
161
        $m = $apiPlatformProviders;
×
NEW
162
        foreach ($classes as $className => $refl) {
×
NEW
163
            if ($refl->implementsInterface($interface)) {
×
NEW
164
                $m[] = $className;
×
165
            }
166
        }
167

NEW
168
        if ($m) {
×
NEW
169
            $this->app->tag($m, $interface);
×
170
        }
171
    }
172

173
    /**
174
     * Get the services provided by the provider.
175
     *
176
     * @return array<int, string>
177
     */
178
    public function provides(): array
179
    {
NEW
180
        return [
×
NEW
181
            CallableProvider::class,
×
NEW
182
            CallableProcessor::class,
×
NEW
183
            ItemProvider::class,
×
NEW
184
            CollectionProvider::class,
×
NEW
185
            SerializerFilterParameterProvider::class,
×
NEW
186
            ParameterProvider::class,
×
NEW
187
            FilterQueryExtension::class,
×
NEW
188
            'filters',
×
NEW
189
        ];
×
190
    }
191
}
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