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

api-platform / core / 17054099799

18 Aug 2025 10:28PM UTC coverage: 22.386% (-0.2%) from 22.612%
17054099799

Pull #7150

github

web-flow
Merge 973c71211 into 2d501b315
Pull Request #7150: fix: array shape in ProviderInterface

11062 of 49414 relevant lines covered (22.39%)

11.75 hits per line

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

0.0
/src/Laravel/ApiPlatformProvider.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\GraphQl\Error\ErrorHandler as GraphQlErrorHandler;
17
use ApiPlatform\GraphQl\Error\ErrorHandlerInterface;
18
use ApiPlatform\GraphQl\Executor;
19
use ApiPlatform\GraphQl\ExecutorInterface;
20
use ApiPlatform\GraphQl\Metadata\RuntimeOperationMetadataFactory;
21
use ApiPlatform\GraphQl\Resolver\Factory\ResolverFactory;
22
use ApiPlatform\GraphQl\Resolver\Factory\ResolverFactoryInterface;
23
use ApiPlatform\GraphQl\Resolver\QueryCollectionResolverInterface;
24
use ApiPlatform\GraphQl\Resolver\QueryItemResolverInterface;
25
use ApiPlatform\GraphQl\Resolver\ResourceFieldResolver;
26
use ApiPlatform\GraphQl\Serializer\Exception\ErrorNormalizer as GraphQlErrorNormalizer;
27
use ApiPlatform\GraphQl\Serializer\Exception\HttpExceptionNormalizer as GraphQlHttpExceptionNormalizer;
28
use ApiPlatform\GraphQl\Serializer\Exception\RuntimeExceptionNormalizer as GraphQlRuntimeExceptionNormalizer;
29
use ApiPlatform\GraphQl\Serializer\Exception\ValidationExceptionNormalizer as GraphQlValidationExceptionNormalizer;
30
use ApiPlatform\GraphQl\Serializer\ItemNormalizer as GraphQlItemNormalizer;
31
use ApiPlatform\GraphQl\Serializer\ObjectNormalizer as GraphQlObjectNormalizer;
32
use ApiPlatform\GraphQl\Serializer\SerializerContextBuilder as GraphQlSerializerContextBuilder;
33
use ApiPlatform\GraphQl\State\Processor\NormalizeProcessor;
34
use ApiPlatform\GraphQl\State\Provider\DenormalizeProvider as GraphQlDenormalizeProvider;
35
use ApiPlatform\GraphQl\State\Provider\ReadProvider as GraphQlReadProvider;
36
use ApiPlatform\GraphQl\State\Provider\ResolverProvider;
37
use ApiPlatform\GraphQl\Type\ContextAwareTypeBuilderInterface;
38
use ApiPlatform\GraphQl\Type\FieldsBuilderEnumInterface;
39
use ApiPlatform\GraphQl\Type\SchemaBuilder;
40
use ApiPlatform\GraphQl\Type\SchemaBuilderInterface;
41
use ApiPlatform\GraphQl\Type\TypeBuilder;
42
use ApiPlatform\GraphQl\Type\TypeConverter;
43
use ApiPlatform\GraphQl\Type\TypeConverterInterface;
44
use ApiPlatform\GraphQl\Type\TypesContainer;
45
use ApiPlatform\GraphQl\Type\TypesContainerInterface;
46
use ApiPlatform\GraphQl\Type\TypesFactory;
47
use ApiPlatform\GraphQl\Type\TypesFactoryInterface;
48
use ApiPlatform\Hal\Serializer\CollectionNormalizer as HalCollectionNormalizer;
49
use ApiPlatform\Hal\Serializer\EntrypointNormalizer as HalEntrypointNormalizer;
50
use ApiPlatform\Hal\Serializer\ItemNormalizer as HalItemNormalizer;
51
use ApiPlatform\Hal\Serializer\ObjectNormalizer as HalObjectNormalizer;
52
use ApiPlatform\Hydra\JsonSchema\SchemaFactory as HydraSchemaFactory;
53
use ApiPlatform\Hydra\Serializer\CollectionFiltersNormalizer as HydraCollectionFiltersNormalizer;
54
use ApiPlatform\Hydra\Serializer\CollectionNormalizer as HydraCollectionNormalizer;
55
use ApiPlatform\Hydra\Serializer\DocumentationNormalizer as HydraDocumentationNormalizer;
56
use ApiPlatform\Hydra\Serializer\EntrypointNormalizer as HydraEntrypointNormalizer;
57
use ApiPlatform\Hydra\Serializer\HydraPrefixNameConverter;
58
use ApiPlatform\Hydra\Serializer\PartialCollectionViewNormalizer as HydraPartialCollectionViewNormalizer;
59
use ApiPlatform\Hydra\State\HydraLinkProcessor;
60
use ApiPlatform\JsonApi\JsonSchema\SchemaFactory as JsonApiSchemaFactory;
61
use ApiPlatform\JsonApi\Serializer\CollectionNormalizer as JsonApiCollectionNormalizer;
62
use ApiPlatform\JsonApi\Serializer\EntrypointNormalizer as JsonApiEntrypointNormalizer;
63
use ApiPlatform\JsonApi\Serializer\ErrorNormalizer as JsonApiErrorNormalizer;
64
use ApiPlatform\JsonApi\Serializer\ItemNormalizer as JsonApiItemNormalizer;
65
use ApiPlatform\JsonApi\Serializer\ObjectNormalizer as JsonApiObjectNormalizer;
66
use ApiPlatform\JsonApi\Serializer\ReservedAttributeNameConverter;
67
use ApiPlatform\JsonLd\AnonymousContextBuilderInterface;
68
use ApiPlatform\JsonLd\ContextBuilder as JsonLdContextBuilder;
69
use ApiPlatform\JsonLd\ContextBuilderInterface;
70
use ApiPlatform\JsonLd\Serializer\ItemNormalizer as JsonLdItemNormalizer;
71
use ApiPlatform\JsonLd\Serializer\ObjectNormalizer as JsonLdObjectNormalizer;
72
use ApiPlatform\JsonSchema\DefinitionNameFactory;
73
use ApiPlatform\JsonSchema\DefinitionNameFactoryInterface;
74
use ApiPlatform\JsonSchema\Metadata\Property\Factory\SchemaPropertyMetadataFactory;
75
use ApiPlatform\JsonSchema\SchemaFactory;
76
use ApiPlatform\JsonSchema\SchemaFactoryInterface;
77
use ApiPlatform\Laravel\ApiResource\Error;
78
use ApiPlatform\Laravel\ApiResource\ValidationError;
79
use ApiPlatform\Laravel\Controller\DocumentationController;
80
use ApiPlatform\Laravel\Controller\EntrypointController;
81
use ApiPlatform\Laravel\Eloquent\Filter\JsonApi\SortFilterParameterProvider;
82
use ApiPlatform\Laravel\Eloquent\Metadata\Factory\Property\EloquentAttributePropertyMetadataFactory;
83
use ApiPlatform\Laravel\Eloquent\Metadata\Factory\Property\EloquentPropertyMetadataFactory;
84
use ApiPlatform\Laravel\Eloquent\Metadata\Factory\Property\EloquentPropertyNameCollectionMetadataFactory;
85
use ApiPlatform\Laravel\Eloquent\Metadata\IdentifiersExtractor as EloquentIdentifiersExtractor;
86
use ApiPlatform\Laravel\Eloquent\Metadata\ModelMetadata;
87
use ApiPlatform\Laravel\Eloquent\Metadata\ResourceClassResolver as EloquentResourceClassResolver;
88
use ApiPlatform\Laravel\Eloquent\PropertyAccess\PropertyAccessor as EloquentPropertyAccessor;
89
use ApiPlatform\Laravel\Eloquent\PropertyInfo\EloquentExtractor;
90
use ApiPlatform\Laravel\Eloquent\Serializer\EloquentNameConverter;
91
use ApiPlatform\Laravel\Eloquent\Serializer\SerializerContextBuilder as EloquentSerializerContextBuilder;
92
use ApiPlatform\Laravel\GraphQl\Controller\EntrypointController as GraphQlEntrypointController;
93
use ApiPlatform\Laravel\GraphQl\Controller\GraphiQlController;
94
use ApiPlatform\Laravel\JsonApi\State\JsonApiProvider;
95
use ApiPlatform\Laravel\Metadata\CachePropertyMetadataFactory;
96
use ApiPlatform\Laravel\Metadata\CachePropertyNameCollectionMetadataFactory;
97
use ApiPlatform\Laravel\Routing\IriConverter;
98
use ApiPlatform\Laravel\Routing\Router as UrlGeneratorRouter;
99
use ApiPlatform\Laravel\Routing\SkolemIriConverter;
100
use ApiPlatform\Laravel\Security\ResourceAccessChecker;
101
use ApiPlatform\Laravel\State\AccessCheckerProvider;
102
use ApiPlatform\Laravel\State\SwaggerUiProcessor;
103
use ApiPlatform\Laravel\State\SwaggerUiProvider;
104
use ApiPlatform\Laravel\State\ValidateProvider;
105
use ApiPlatform\Metadata\IdentifiersExtractor;
106
use ApiPlatform\Metadata\IdentifiersExtractorInterface;
107
use ApiPlatform\Metadata\InflectorInterface;
108
use ApiPlatform\Metadata\IriConverterInterface;
109
use ApiPlatform\Metadata\Operation\Factory\OperationMetadataFactory;
110
use ApiPlatform\Metadata\Operation\Factory\OperationMetadataFactoryInterface;
111
use ApiPlatform\Metadata\Operation\PathSegmentNameGeneratorInterface;
112
use ApiPlatform\Metadata\Operation\UnderscorePathSegmentNameGenerator;
113
use ApiPlatform\Metadata\Property\Factory\AttributePropertyMetadataFactory;
114
use ApiPlatform\Metadata\Property\Factory\ClassLevelAttributePropertyNameCollectionFactory;
115
use ApiPlatform\Metadata\Property\Factory\ConcernsPropertyNameCollectionMetadataFactory;
116
use ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyMetadataFactory;
117
use ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyNameCollectionFactory;
118
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
119
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
120
use ApiPlatform\Metadata\Property\Factory\SerializerPropertyMetadataFactory;
121
use ApiPlatform\Metadata\Resource\Factory\AttributesResourceNameCollectionFactory;
122
use ApiPlatform\Metadata\Resource\Factory\ConcernsResourceNameCollectionFactory;
123
use ApiPlatform\Metadata\Resource\Factory\LinkFactory;
124
use ApiPlatform\Metadata\Resource\Factory\LinkFactoryInterface;
125
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
126
use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface;
127
use ApiPlatform\Metadata\ResourceAccessCheckerInterface;
128
use ApiPlatform\Metadata\ResourceClassResolver;
129
use ApiPlatform\Metadata\ResourceClassResolverInterface;
130
use ApiPlatform\Metadata\UrlGeneratorInterface;
131
use ApiPlatform\Metadata\Util\Inflector;
132
use ApiPlatform\OpenApi\Command\OpenApiCommand;
133
use ApiPlatform\OpenApi\Factory\OpenApiFactory;
134
use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface;
135
use ApiPlatform\OpenApi\Options;
136
use ApiPlatform\OpenApi\Serializer\OpenApiNormalizer;
137
use ApiPlatform\Serializer\ItemNormalizer;
138
use ApiPlatform\Serializer\JsonEncoder;
139
use ApiPlatform\Serializer\Mapping\Factory\ClassMetadataFactory as SerializerClassMetadataFactory;
140
use ApiPlatform\Serializer\Mapping\Loader\PropertyMetadataLoader;
141
use ApiPlatform\Serializer\SerializerContextBuilder;
142
use ApiPlatform\State\CallableProcessor;
143
use ApiPlatform\State\CallableProvider;
144
use ApiPlatform\State\ErrorProvider;
145
use ApiPlatform\State\Pagination\Pagination;
146
use ApiPlatform\State\Pagination\PaginationOptions;
147
use ApiPlatform\State\Processor\AddLinkHeaderProcessor;
148
use ApiPlatform\State\Processor\RespondProcessor;
149
use ApiPlatform\State\Processor\SerializeProcessor;
150
use ApiPlatform\State\Processor\WriteProcessor;
151
use ApiPlatform\State\ProcessorInterface;
152
use ApiPlatform\State\Provider\ContentNegotiationProvider;
153
use ApiPlatform\State\Provider\DeserializeProvider;
154
use ApiPlatform\State\Provider\ParameterProvider;
155
use ApiPlatform\State\Provider\ReadProvider;
156
use ApiPlatform\State\ProviderInterface;
157
use ApiPlatform\State\SerializerContextBuilderInterface;
158
use Illuminate\Config\Repository as ConfigRepository;
159
use Illuminate\Contracts\Foundation\Application;
160
use Illuminate\Routing\Router;
161
use Illuminate\Support\ServiceProvider;
162
use Negotiation\Negotiator;
163
use PHPStan\PhpDocParser\Parser\PhpDocParser;
164
use Psr\Log\LoggerInterface;
165
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
166
use Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor;
167
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
168
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
169
use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
170
use Symfony\Component\Routing\RequestContext;
171
use Symfony\Component\Serializer\Encoder\CsvEncoder;
172
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
173
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
174
use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader;
175
use Symfony\Component\Serializer\Mapping\Loader\LoaderChain;
176
use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface;
177
use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter;
178
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
179
use Symfony\Component\Serializer\NameConverter\SnakeCaseToCamelCaseNameConverter;
180
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
181
use Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer;
182
use Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer;
183
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
184
use Symfony\Component\Serializer\Normalizer\DateTimeZoneNormalizer;
185
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
186
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
187
use Symfony\Component\Serializer\Serializer;
188
use Symfony\Component\Serializer\SerializerInterface;
189
use Symfony\Component\WebLink\HttpHeaderSerializer;
190

191
class ApiPlatformProvider extends ServiceProvider
192
{
193
    /**
194
     * Register services.
195
     */
196
    public function register(): void
197
    {
198
        $this->mergeConfigFrom(__DIR__.'/config/api-platform.php', 'api-platform');
×
199

200
        $this->app->singleton(PropertyInfoExtractorInterface::class, function (Application $app) {
×
201
            $phpstanExtractor = class_exists(PhpDocParser::class) ? new PhpStanExtractor() : null;
×
202
            $reflectionExtractor = new ReflectionExtractor();
×
203
            $eloquentExtractor = new EloquentExtractor($app->make(ModelMetadata::class));
×
204

205
            return new PropertyInfoExtractor(
×
206
                [$reflectionExtractor],
×
207
                $phpstanExtractor ? [$phpstanExtractor, $reflectionExtractor] : [$reflectionExtractor],
×
208
                [],
×
209
                [$eloquentExtractor],
×
210
                [$reflectionExtractor]
×
211
            );
×
212
        });
×
213

214
        $this->app->singleton(ModelMetadata::class, function () {
×
215
            return new ModelMetadata();
×
216
        });
×
217

218
        $this->app->bind(LoaderInterface::class, AttributeLoader::class);
×
219
        $this->app->bind(ClassMetadataFactoryInterface::class, ClassMetadataFactory::class);
×
220
        $this->app->singleton(ClassMetadataFactory::class, function (Application $app) {
×
221
            return new ClassMetadataFactory(
×
222
                new LoaderChain([
×
223
                    new PropertyMetadataLoader(
×
224
                        $app->make(PropertyNameCollectionFactoryInterface::class),
×
225
                    ),
×
226
                    new AttributeLoader(),
×
227
                ])
×
228
            );
×
229
        });
×
230

231
        $this->app->singleton(SerializerClassMetadataFactory::class, function (Application $app) {
×
232
            return new SerializerClassMetadataFactory($app->make(ClassMetadataFactoryInterface::class));
×
233
        });
×
234

235
        $this->app->bind(PathSegmentNameGeneratorInterface::class, UnderscorePathSegmentNameGenerator::class);
×
236

237
        $this->app->singleton(ResourceNameCollectionFactoryInterface::class, function (Application $app) {
×
238
            /** @var ConfigRepository */
239
            $config = $app['config'];
×
240
            $paths = $config->get('api-platform.resources') ?? [];
×
241
            $refl = new \ReflectionClass(Error::class);
×
242
            $paths[] = \dirname($refl->getFileName());
×
243

244
            $logger = $app->make(LoggerInterface::class);
×
245

246
            foreach ($paths as $i => $path) {
×
247
                if (!file_exists($path)) {
×
248
                    $logger->warning(\sprintf('We skipped reading resources in "%s" as the path does not exist. Please check the configuration at "api-platform.resources".', $path));
×
249
                    unset($paths[$i]);
×
250
                }
251
            }
252

253
            return new ConcernsResourceNameCollectionFactory($paths, new AttributesResourceNameCollectionFactory($paths));
×
254
        });
×
255

256
        $this->app->bind(ResourceClassResolverInterface::class, ResourceClassResolver::class);
×
257
        $this->app->singleton(ResourceClassResolver::class, function (Application $app) {
×
258
            return new EloquentResourceClassResolver(new ResourceClassResolver($app->make(ResourceNameCollectionFactoryInterface::class)));
×
259
        });
×
260

261
        $this->app->singleton(PropertyMetadataFactoryInterface::class, function (Application $app) {
×
262
            /** @var ConfigRepository $config */
263
            $config = $app['config'];
×
264

265
            return new CachePropertyMetadataFactory(
×
266
                new SchemaPropertyMetadataFactory(
×
267
                    $app->make(ResourceClassResolverInterface::class),
×
268
                    new SerializerPropertyMetadataFactory(
×
269
                        $app->make(SerializerClassMetadataFactory::class),
×
270
                        new PropertyInfoPropertyMetadataFactory(
×
271
                            $app->make(PropertyInfoExtractorInterface::class),
×
272
                            new AttributePropertyMetadataFactory(
×
273
                                new EloquentAttributePropertyMetadataFactory(
×
274
                                    new EloquentPropertyMetadataFactory(
×
275
                                        $app->make(ModelMetadata::class),
×
276
                                    ),
×
277
                                )
×
278
                            ),
×
279
                            $app->make(ResourceClassResolverInterface::class)
×
280
                        ),
×
281
                    )
×
282
                ),
×
283
                true === $config->get('app.debug') ? 'array' : $config->get('api-platform.cache', 'file')
×
284
            );
×
285
        });
×
286

287
        $this->app->singleton(PropertyNameCollectionFactoryInterface::class, function (Application $app) {
×
288
            /** @var ConfigRepository $config */
289
            $config = $app['config'];
×
290

291
            return new CachePropertyNameCollectionMetadataFactory(
×
292
                new ClassLevelAttributePropertyNameCollectionFactory(
×
293
                    new ConcernsPropertyNameCollectionMetadataFactory(
×
294
                        new EloquentPropertyNameCollectionMetadataFactory(
×
295
                            $app->make(ModelMetadata::class),
×
296
                            new PropertyInfoPropertyNameCollectionFactory($app->make(PropertyInfoExtractorInterface::class)),
×
297
                            $app->make(ResourceClassResolverInterface::class)
×
298
                        )
×
299
                    )
×
300
                ),
×
301
                true === $config->get('app.debug') ? 'array' : $config->get('api-platform.cache', 'file')
×
302
            );
×
303
        });
×
304

305
        $this->app->singleton(LinkFactoryInterface::class, function (Application $app) {
×
306
            return new LinkFactory(
×
307
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
308
                $app->make(PropertyMetadataFactoryInterface::class),
×
309
                $app->make(ResourceClassResolverInterface::class),
×
310
            );
×
311
        });
×
312

313
        $this->app->bind(PropertyAccessorInterface::class, function () {
×
314
            return new EloquentPropertyAccessor();
×
315
        });
×
316

317
        $this->app->bind(NameConverterInterface::class, function (Application $app) {
×
318
            $config = $app['config'];
×
319
            $nameConverter = $config->get('api-platform.name_converter', SnakeCaseToCamelCaseNameConverter::class);
×
320
            if ($nameConverter && class_exists($nameConverter)) {
×
321
                $nameConverter = new EloquentNameConverter($app->make($nameConverter));
×
322
            }
323

324
            $defaultContext = $config->get('api-platform.serializer', []);
×
325

326
            return new HydraPrefixNameConverter(new MetadataAwareNameConverter($app->make(ClassMetadataFactoryInterface::class), $nameConverter), $defaultContext);
×
327
        });
×
328

329
        $this->app->singleton(OperationMetadataFactory::class, function (Application $app) {
×
330
            return new OperationMetadataFactory($app->make(ResourceNameCollectionFactoryInterface::class), $app->make(ResourceMetadataCollectionFactoryInterface::class));
×
331
        });
×
332

333
        $this->app->bind(OperationMetadataFactoryInterface::class, OperationMetadataFactory::class);
×
334

335
        $this->app->singleton(ReadProvider::class, function (Application $app) {
×
336
            return new ReadProvider($app->make(CallableProvider::class));
×
337
        });
×
338

339
        $this->app->singleton(SwaggerUiProvider::class, function (Application $app) {
×
340
            /** @var ConfigRepository */
341
            $config = $app['config'];
×
342

343
            return new SwaggerUiProvider($app->make(ReadProvider::class), $app->make(OpenApiFactoryInterface::class), $config->get('api-platform.swagger_ui.enabled', false));
×
344
        });
×
345

346
        $this->app->singleton(DeserializeProvider::class, function (Application $app) {
×
347
            return new DeserializeProvider($app->make(SwaggerUiProvider::class), $app->make(SerializerInterface::class), $app->make(SerializerContextBuilderInterface::class));
×
348
        });
×
349

350
        $this->app->singleton(ValidateProvider::class, function (Application $app) {
×
351
            $config = $app['config'];
×
352
            $nameConverter = $config->get('api-platform.name_converter', SnakeCaseToCamelCaseNameConverter::class);
×
353
            if ($nameConverter && class_exists($nameConverter)) {
×
354
                $nameConverter = $app->make($nameConverter);
×
355
            }
356

357
            return new ValidateProvider($app->make(DeserializeProvider::class), $app, $app->make(ObjectNormalizer::class), $nameConverter);
×
358
        });
×
359

360
        if (class_exists(JsonApiProvider::class)) {
×
361
            $this->app->extend(DeserializeProvider::class, function (ProviderInterface $inner, Application $app) {
×
362
                return new JsonApiProvider($inner);
×
363
            });
×
364
        }
365

366
        $this->app->singleton(SortFilterParameterProvider::class, function (Application $app) {
×
367
            return new SortFilterParameterProvider();
×
368
        });
×
369

370
        $this->app->singleton(AccessCheckerProvider::class, function (Application $app) {
×
371
            return new AccessCheckerProvider($app->make(ParameterProvider::class), $app->make(ResourceAccessCheckerInterface::class));
×
372
        });
×
373

374
        $this->app->singleton(Negotiator::class, function (Application $app) {
×
375
            return new Negotiator();
×
376
        });
×
377
        $this->app->singleton(ContentNegotiationProvider::class, function (Application $app) {
×
378
            /** @var ConfigRepository */
379
            $config = $app['config'];
×
380

381
            return new ContentNegotiationProvider($app->make(AccessCheckerProvider::class), $app->make(Negotiator::class), $config->get('api-platform.formats'), $config->get('api-platform.error_formats'));
×
382
        });
×
383

384
        $this->app->bind(ProviderInterface::class, ContentNegotiationProvider::class);
×
385

386
        $this->app->singleton(RespondProcessor::class, function () {
×
387
            return new AddLinkHeaderProcessor(new RespondProcessor(), new HttpHeaderSerializer());
×
388
        });
×
389

390
        $this->app->singleton(SerializeProcessor::class, function (Application $app) {
×
391
            return new SerializeProcessor($app->make(RespondProcessor::class), $app->make(Serializer::class), $app->make(SerializerContextBuilderInterface::class));
×
392
        });
×
393

394
        $this->app->singleton(WriteProcessor::class, function (Application $app) {
×
395
            return new WriteProcessor($app->make(SerializeProcessor::class), $app->make(CallableProcessor::class));
×
396
        });
×
397

398
        $this->app->singleton(SerializerContextBuilder::class, function (Application $app) {
×
399
            /** @var ConfigRepository */
400
            $config = $app['config'];
×
401

402
            return new SerializerContextBuilder($app->make(ResourceMetadataCollectionFactoryInterface::class), $config->get('app.debug'));
×
403
        });
×
404
        $this->app->bind(SerializerContextBuilderInterface::class, EloquentSerializerContextBuilder::class);
×
405
        $this->app->singleton(EloquentSerializerContextBuilder::class, function (Application $app) {
×
406
            /** @var ConfigRepository */
407
            $config = $app['config'];
×
408

409
            return new EloquentSerializerContextBuilder(
×
410
                $app->make(SerializerContextBuilder::class),
×
411
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
412
                $config->get('api-platform.name_converter', SnakeCaseToCamelCaseNameConverter::class)
×
413
            );
×
414
        });
×
415

416
        $this->app->singleton(HydraLinkProcessor::class, function (Application $app) {
×
417
            return new HydraLinkProcessor($app->make(WriteProcessor::class), $app->make(UrlGeneratorInterface::class));
×
418
        });
×
419

420
        $this->app->bind(ProcessorInterface::class, function (Application $app) {
×
421
            $config = $app['config'];
×
422
            if ($config->has('api-platform.formats.jsonld')) {
×
423
                return $app->make(HydraLinkProcessor::class);
×
424
            }
425

426
            return $app->make(WriteProcessor::class);
×
427
        });
×
428

429
        $this->app->singleton(ObjectNormalizer::class, function (Application $app) {
×
430
            $config = $app['config'];
×
431
            $defaultContext = $config->get('api-platform.serializer', []);
×
432

433
            return new ObjectNormalizer(defaultContext: $defaultContext);
×
434
        });
×
435

436
        $this->app->singleton(DateTimeNormalizer::class, function (Application $app) {
×
437
            $config = $app['config'];
×
438
            $defaultContext = $config->get('api-platform.serializer', []);
×
439

440
            return new DateTimeNormalizer(defaultContext: $defaultContext);
×
441
        });
×
442

443
        $this->app->singleton(DateTimeZoneNormalizer::class, function () {
×
444
            return new DateTimeZoneNormalizer();
×
445
        });
×
446

447
        $this->app->singleton(DateIntervalNormalizer::class, function (Application $app) {
×
448
            $config = $app['config'];
×
449
            $defaultContext = $config->get('api-platform.serializer', []);
×
450

451
            return new DateIntervalNormalizer(defaultContext: $defaultContext);
×
452
        });
×
453

454
        $this->app->singleton(JsonEncoder::class, function () {
×
455
            return new JsonEncoder('jsonld');
×
456
        });
×
457

458
        $this->app->bind(IriConverterInterface::class, IriConverter::class);
×
459
        $this->app->singleton(IriConverter::class, function (Application $app) {
×
460
            return new IriConverter($app->make(CallableProvider::class), $app->make(OperationMetadataFactoryInterface::class), $app->make(UrlGeneratorRouter::class), $app->make(IdentifiersExtractorInterface::class), $app->make(ResourceClassResolverInterface::class), $app->make(ResourceMetadataCollectionFactoryInterface::class), $app->make(SkolemIriConverter::class));
×
461
        });
×
462

463
        $this->app->singleton(SkolemIriConverter::class, function (Application $app) {
×
464
            return new SkolemIriConverter($app->make(UrlGeneratorRouter::class));
×
465
        });
×
466

467
        $this->app->bind(IdentifiersExtractorInterface::class, IdentifiersExtractor::class);
×
468
        $this->app->singleton(IdentifiersExtractor::class, function (Application $app) {
×
469
            return new EloquentIdentifiersExtractor(
×
470
                new IdentifiersExtractor(
×
471
                    $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
472
                    $app->make(ResourceClassResolverInterface::class),
×
473
                    $app->make(PropertyNameCollectionFactoryInterface::class),
×
474
                    $app->make(PropertyMetadataFactoryInterface::class),
×
475
                    $app->make(PropertyAccessorInterface::class)
×
476
                )
×
477
            );
×
478
        });
×
479

480
        $this->app->bind(UrlGeneratorInterface::class, UrlGeneratorRouter::class);
×
481
        $this->app->singleton(UrlGeneratorRouter::class, function (Application $app) {
×
482
            $request = $app->make('request');
×
483
            // https://github.com/laravel/framework/blob/2bfb70bca53e24227a6f921f39d84ba452efd8e0/src/Illuminate/Routing/CompiledRouteCollection.php#L112
484
            $trimmedRequest = $request->duplicate();
×
485
            $parts = explode('?', $request->server->get('REQUEST_URI'), 2);
×
486
            $trimmedRequest->server->set(
×
487
                'REQUEST_URI',
×
488
                rtrim($parts[0], '/').(isset($parts[1]) ? '?'.$parts[1] : '')
×
489
            );
×
490

491
            $urlGenerator = new UrlGeneratorRouter($app->make(Router::class));
×
492
            $urlGenerator->setContext((new RequestContext())->fromRequest($trimmedRequest));
×
493

494
            return $urlGenerator;
×
495
        });
×
496

497
        $this->app->bind(ContextBuilderInterface::class, JsonLdContextBuilder::class);
×
498
        $this->app->singleton(JsonLdContextBuilder::class, function (Application $app) {
×
499
            $config = $app['config'];
×
500
            $defaultContext = $config->get('api-platform.serializer', []);
×
501

502
            return new JsonLdContextBuilder(
×
503
                $app->make(ResourceNameCollectionFactoryInterface::class),
×
504
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
505
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
506
                $app->make(PropertyMetadataFactoryInterface::class),
×
507
                $app->make(UrlGeneratorInterface::class),
×
508
                $app->make(IriConverterInterface::class),
×
509
                $app->make(NameConverterInterface::class),
×
510
                $defaultContext
×
511
            );
×
512
        });
×
513

514
        $this->app->singleton(HydraEntrypointNormalizer::class, function (Application $app) {
×
515
            return new HydraEntrypointNormalizer($app->make(ResourceMetadataCollectionFactoryInterface::class), $app->make(IriConverterInterface::class), $app->make(UrlGeneratorInterface::class));
×
516
        });
×
517

518
        $this->app->singleton(ResourceAccessCheckerInterface::class, function () {
×
519
            return new ResourceAccessChecker();
×
520
        });
×
521

522
        $this->app->singleton(ItemNormalizer::class, function (Application $app) {
×
523
            /** @var ConfigRepository */
524
            $config = $app['config'];
×
525
            $defaultContext = $config->get('api-platform.serializer', []);
×
526

527
            return new ItemNormalizer(
×
528
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
529
                $app->make(PropertyMetadataFactoryInterface::class),
×
530
                $app->make(IriConverterInterface::class),
×
531
                $app->make(ResourceClassResolverInterface::class),
×
532
                $app->make(PropertyAccessorInterface::class),
×
533
                $app->make(NameConverterInterface::class),
×
534
                $app->make(ClassMetadataFactoryInterface::class),
×
535
                $app->make(LoggerInterface::class),
×
536
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
537
                $app->make(ResourceAccessCheckerInterface::class),
×
538
                $defaultContext
×
539
            );
×
540
        });
×
541

542
        $this->app->bind(AnonymousContextBuilderInterface::class, JsonLdContextBuilder::class);
×
543

544
        $this->app->singleton(JsonLdObjectNormalizer::class, function (Application $app) {
×
545
            return new JsonLdObjectNormalizer(
×
546
                $app->make(ObjectNormalizer::class),
×
547
                $app->make(IriConverterInterface::class),
×
548
                $app->make(AnonymousContextBuilderInterface::class)
×
549
            );
×
550
        });
×
551

552
        $this->app->singleton(HalCollectionNormalizer::class, function (Application $app) {
×
553
            /** @var ConfigRepository */
554
            $config = $app['config'];
×
555

556
            return new HalCollectionNormalizer(
×
557
                $app->make(ResourceClassResolverInterface::class),
×
558
                $config->get('api-platform.pagination.page_parameter_name'),
×
559
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
560
            );
×
561
        });
×
562

563
        $this->app->singleton(HalObjectNormalizer::class, function (Application $app) {
×
564
            return new HalObjectNormalizer(
×
565
                $app->make(ObjectNormalizer::class),
×
566
                $app->make(IriConverterInterface::class)
×
567
            );
×
568
        });
×
569

570
        $this->app->singleton(HalItemNormalizer::class, function (Application $app) {
×
571
            /** @var ConfigRepository */
572
            $config = $app['config'];
×
573
            $defaultContext = $config->get('api-platform.serializer', []);
×
574

575
            return new HalItemNormalizer(
×
576
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
577
                $app->make(PropertyMetadataFactoryInterface::class),
×
578
                $app->make(IriConverterInterface::class),
×
579
                $app->make(ResourceClassResolverInterface::class),
×
580
                $app->make(PropertyAccessorInterface::class),
×
581
                $app->make(NameConverterInterface::class),
×
582
                $app->make(ClassMetadataFactoryInterface::class),
×
583
                $defaultContext,
×
584
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
585
                $app->make(ResourceAccessCheckerInterface::class),
×
586
            );
×
587
        });
×
588

589
        $this->app->singleton(Options::class, function (Application $app) {
×
590
            /** @var ConfigRepository */
591
            $config = $app['config'];
×
592

593
            return new Options(
×
594
                title: $config->get('api-platform.title', ''),
×
595
                description: $config->get('api-platform.description', ''),
×
596
                version: $config->get('api-platform.version', ''),
×
597
                oAuthEnabled: $config->get('api-platform.swagger_ui.oauth.enabled', false),
×
598
                oAuthType: $config->get('api-platform.swagger_ui.oauth.type', null),
×
599
                oAuthFlow: $config->get('api-platform.swagger_ui.oauth.flow', null),
×
600
                oAuthTokenUrl: $config->get('api-platform.swagger_ui.oauth.tokenUrl', null),
×
601
                oAuthAuthorizationUrl: $config->get('api-platform.swagger_ui.oauth.authorizationUrl', null),
×
602
                oAuthRefreshUrl: $config->get('api-platform.swagger_ui.oauth.refreshUrl', null),
×
603
                oAuthScopes: $config->get('api-platform.swagger_ui.oauth.scopes', []),
×
604
                apiKeys: $config->get('api-platform.swagger_ui.apiKeys', []),
×
605
                contactName: $config->get('api-platform.swagger_ui.contact.name', ''),
×
606
                contactUrl: $config->get('api-platform.swagger_ui.contact.url', ''),
×
607
                contactEmail: $config->get('api-platform.swagger_ui.contact.email', ''),
×
608
                licenseName: $config->get('api-platform.swagger_ui.license.name', ''),
×
609
                licenseUrl: $config->get('api-platform.swagger_ui.license.url', ''),
×
610
                persistAuthorization: $config->get('api-platform.swagger_ui.persist_authorization', false),
×
611
                httpAuth: $config->get('api-platform.swagger_ui.http_auth', []),
×
612
                tags: $config->get('api-platform.openapi.tags', []),
×
613
                errorResourceClass: Error::class,
×
614
                validationErrorResourceClass: ValidationError::class
×
615
            );
×
616
        });
×
617

618
        $this->app->singleton(SwaggerUiProcessor::class, function (Application $app) {
×
619
            /** @var ConfigRepository */
620
            $config = $app['config'];
×
621

622
            return new SwaggerUiProcessor(
×
623
                urlGenerator: $app->make(UrlGeneratorInterface::class),
×
624
                normalizer: $app->make(NormalizerInterface::class),
×
625
                openApiOptions: $app->make(Options::class),
×
626
                oauthClientId: $config->get('api-platform.swagger_ui.oauth.clientId'),
×
627
                oauthClientSecret: $config->get('api-platform.swagger_ui.oauth.clientSecret'),
×
628
                oauthPkce: $config->get('api-platform.swagger_ui.oauth.pkce', false),
×
629
            );
×
630
        });
×
631

632
        $this->app->singleton(DocumentationController::class, function (Application $app) {
×
633
            /** @var ConfigRepository */
634
            $config = $app['config'];
×
635

636
            return new DocumentationController($app->make(ResourceNameCollectionFactoryInterface::class), $config->get('api-platform.title') ?? '', $config->get('api-platform.description') ?? '', $config->get('api-platform.version') ?? '', $app->make(OpenApiFactoryInterface::class), $app->make(ProviderInterface::class), $app->make(ProcessorInterface::class), $app->make(Negotiator::class), $config->get('api-platform.docs_formats'), $config->get('api-platform.swagger_ui.enabled', false));
×
637
        });
×
638

639
        $this->app->singleton(EntrypointController::class, function (Application $app) {
×
640
            /** @var ConfigRepository */
641
            $config = $app['config'];
×
642

643
            return new EntrypointController($app->make(ResourceNameCollectionFactoryInterface::class), $app->make(ProviderInterface::class), $app->make(ProcessorInterface::class), $config->get('api-platform.docs_formats'));
×
644
        });
×
645

646
        $this->app->singleton(Pagination::class, function (Application $app) {
×
647
            /** @var ConfigRepository */
648
            $config = $app['config'];
×
649

650
            return new Pagination($config->get('api-platform.pagination'), []);
×
651
        });
×
652

653
        $this->app->singleton(PaginationOptions::class, function (Application $app) {
×
654
            /** @var ConfigRepository */
655
            $config = $app['config'];
×
656
            $defaults = $config->get('api-platform.defaults');
×
657
            $pagination = $config->get('api-platform.pagination');
×
658

659
            return new PaginationOptions(
×
660
                $defaults['pagination_enabled'] ?? true,
×
661
                $pagination['page_parameter_name'] ?? 'page',
×
662
                $defaults['pagination_client_items_per_page'] ?? false,
×
663
                $pagination['items_per_page_parameter_name'] ?? 'itemsPerPage',
×
664
                $defaults['pagination_client_enabled'] ?? false,
×
665
                $pagination['enabled_parameter_name'] ?? 'pagination',
×
666
                $defaults['pagination_items_per_page'] ?? 30,
×
667
                $defaults['pagination_maximum_items_per_page'] ?? 30,
×
668
                $defaults['pagination_partial'] ?? false,
×
669
                $defaults['pagination_client_partial'] ?? false,
×
670
                $pagination['partial_parameter_name'] ?? 'partial',
×
671
            );
×
672
        });
×
673

674
        $this->app->bind(OpenApiFactoryInterface::class, OpenApiFactory::class);
×
675
        $this->app->singleton(OpenApiFactory::class, function (Application $app) {
×
676
            /** @var ConfigRepository */
677
            $config = $app['config'];
×
678

679
            return new OpenApiFactory(
×
680
                $app->make(ResourceNameCollectionFactoryInterface::class),
×
681
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
682
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
683
                $app->make(PropertyMetadataFactoryInterface::class),
×
684
                $app->make(SchemaFactoryInterface::class),
×
685
                null,
×
686
                $config->get('api-platform.formats'),
×
687
                $app->make(Options::class),
×
688
                $app->make(PaginationOptions::class),
×
689
                null,
×
690
                $config->get('api-platform.error_formats'),
×
691
                // ?RouterInterface $router = null
×
692
            );
×
693
        });
×
694

695
        $this->app->singleton(OpenApiCommand::class, function (Application $app) {
×
696
            return new OpenApiCommand($app->make(OpenApiFactory::class), $app->make(Serializer::class));
×
697
        });
×
698

699
        $this->app->bind(DefinitionNameFactoryInterface::class, DefinitionNameFactory::class);
×
700
        $this->app->singleton(DefinitionNameFactory::class, function (Application $app) {
×
701
            /** @var ConfigRepository */
702
            $config = $app['config'];
×
703

704
            return new DefinitionNameFactory($config->get('api-platform.formats'));
×
705
        });
×
706

707
        $this->app->singleton(SchemaFactory::class, function (Application $app) {
×
708
            /** @var ConfigRepository */
709
            $config = $app['config'];
×
710

711
            return new SchemaFactory(
×
712
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
713
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
714
                $app->make(PropertyMetadataFactoryInterface::class),
×
715
                $app->make(NameConverterInterface::class),
×
716
                $app->make(ResourceClassResolverInterface::class),
×
717
                $config->get('api-platform.formats'),
×
718
                $app->make(DefinitionNameFactoryInterface::class),
×
719
            );
×
720
        });
×
721
        $this->app->singleton(JsonApiSchemaFactory::class, function (Application $app) {
×
722
            return new JsonApiSchemaFactory(
×
723
                $app->make(SchemaFactory::class),
×
724
                $app->make(PropertyMetadataFactoryInterface::class),
×
725
                $app->make(ResourceClassResolverInterface::class),
×
726
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
727
                $app->make(DefinitionNameFactoryInterface::class),
×
728
            );
×
729
        });
×
730
        $this->app->singleton(HydraSchemaFactory::class, function (Application $app) {
×
731
            $config = $app['config'];
×
732
            $defaultContext = $config->get('api-platform.serializer', []);
×
733

734
            return new HydraSchemaFactory(
×
735
                $app->make(JsonApiSchemaFactory::class),
×
736
                $defaultContext
×
737
            );
×
738
        });
×
739

740
        $this->app->bind(SchemaFactoryInterface::class, HydraSchemaFactory::class);
×
741

742
        $this->app->singleton(OpenApiNormalizer::class, function (Application $app) {
×
743
            return new OpenApiNormalizer($app->make(ObjectNormalizer::class));
×
744
        });
×
745

746
        $this->app->singleton(HydraDocumentationNormalizer::class, function (Application $app) {
×
747
            $config = $app['config'];
×
748
            $defaultContext = $config->get('api-platform.serializer', []);
×
749
            $entrypointEnabled = $config->get('api-platform.enable_entrypoint', true);
×
750

751
            return new HydraDocumentationNormalizer(
×
752
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
753
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
754
                $app->make(PropertyMetadataFactoryInterface::class),
×
755
                $app->make(ResourceClassResolverInterface::class),
×
756
                $app->make(UrlGeneratorInterface::class),
×
757
                $app->make(NameConverterInterface::class),
×
758
                $defaultContext,
×
759
                $entrypointEnabled
×
760
            );
×
761
        });
×
762

763
        $this->app->singleton(HydraPartialCollectionViewNormalizer::class, function (Application $app) {
×
764
            $config = $app['config'];
×
765
            $defaultContext = $config->get('api-platform.serializer', []);
×
766

767
            return new HydraPartialCollectionViewNormalizer(
×
768
                new HydraCollectionFiltersNormalizer(
×
769
                    new HydraCollectionNormalizer(
×
770
                        $app->make(ContextBuilderInterface::class),
×
771
                        $app->make(ResourceClassResolverInterface::class),
×
772
                        $app->make(IriConverterInterface::class),
×
773
                        $defaultContext
×
774
                    ),
×
775
                    $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
776
                    $app->make(ResourceClassResolverInterface::class),
×
777
                    null, // filterLocator, we use only Parameters with Laravel and we don't need to call filters there
×
778
                    $defaultContext
×
779
                ),
×
780
                'page',
×
781
                'pagination',
×
782
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
783
                $app->make(PropertyAccessorInterface::class),
×
784
                $config->get('api-platform.url_generation_strategy', UrlGeneratorInterface::ABS_PATH),
×
785
                $defaultContext,
×
786
            );
×
787
        });
×
788

789
        $this->app->singleton(ReservedAttributeNameConverter::class, function (Application $app) {
×
790
            return new ReservedAttributeNameConverter($app->make(NameConverterInterface::class));
×
791
        });
×
792

793
        if (interface_exists(FieldsBuilderEnumInterface::class)) {
×
794
            $this->registerGraphQl();
×
795
        }
796

797
        $this->app->singleton(JsonApiEntrypointNormalizer::class, function (Application $app) {
×
798
            return new JsonApiEntrypointNormalizer(
×
799
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
800
                $app->make(IriConverterInterface::class),
×
801
                $app->make(UrlGeneratorInterface::class),
×
802
            );
×
803
        });
×
804

805
        $this->app->singleton(JsonApiCollectionNormalizer::class, function (Application $app) {
×
806
            /** @var ConfigRepository */
807
            $config = $app['config'];
×
808

809
            return new JsonApiCollectionNormalizer(
×
810
                $app->make(ResourceClassResolverInterface::class),
×
811
                $config->get('api-platform.pagination.page_parameter_name'),
×
812
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
813
            );
×
814
        });
×
815

816
        $this->app->singleton(JsonApiItemNormalizer::class, function (Application $app) {
×
817
            $config = $app['config'];
×
818
            $defaultContext = $config->get('api-platform.serializer', []);
×
819

820
            return new JsonApiItemNormalizer(
×
821
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
822
                $app->make(PropertyMetadataFactoryInterface::class),
×
823
                $app->make(IriConverterInterface::class),
×
824
                $app->make(ResourceClassResolverInterface::class),
×
825
                $app->make(PropertyAccessorInterface::class),
×
826
                $app->make(NameConverterInterface::class),
×
827
                $app->make(ClassMetadataFactoryInterface::class),
×
828
                $defaultContext,
×
829
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
830
                $app->make(ResourceAccessCheckerInterface::class),
×
831
                null
×
832
                // $app->make(TagCollectorInterface::class),
×
833
            );
×
834
        });
×
835

836
        $this->app->singleton(JsonApiErrorNormalizer::class, function (Application $app) {
×
837
            return new JsonApiErrorNormalizer(
×
838
                $app->make(JsonApiItemNormalizer::class),
×
839
            );
×
840
        });
×
841

842
        $this->app->singleton(JsonApiObjectNormalizer::class, function (Application $app) {
×
843
            return new JsonApiObjectNormalizer(
×
844
                $app->make(ObjectNormalizer::class),
×
845
                $app->make(IriConverterInterface::class),
×
846
                $app->make(ResourceClassResolverInterface::class),
×
847
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
848
            );
×
849
        });
×
850

851
        $this->app->singleton('api_platform_normalizer_list', function (Application $app) {
×
852
            $list = new \SplPriorityQueue();
×
853
            $list->insert($app->make(HydraEntrypointNormalizer::class), -800);
×
854
            $list->insert($app->make(HydraPartialCollectionViewNormalizer::class), -800);
×
855
            $list->insert($app->make(HalCollectionNormalizer::class), -800);
×
856
            $list->insert($app->make(HalEntrypointNormalizer::class), -985);
×
857
            $list->insert($app->make(HalObjectNormalizer::class), -995);
×
858
            $list->insert($app->make(HalItemNormalizer::class), -890);
×
859
            $list->insert($app->make(JsonLdItemNormalizer::class), -890);
×
860
            $list->insert($app->make(JsonLdObjectNormalizer::class), -995);
×
861
            $list->insert($app->make(ArrayDenormalizer::class), -990);
×
862
            $list->insert($app->make(DateTimeZoneNormalizer::class), -915);
×
863
            $list->insert($app->make(DateIntervalNormalizer::class), -915);
×
864
            $list->insert($app->make(DateTimeNormalizer::class), -910);
×
865
            $list->insert($app->make(BackedEnumNormalizer::class), -910);
×
866
            $list->insert($app->make(ObjectNormalizer::class), -1000);
×
867
            $list->insert($app->make(ItemNormalizer::class), -895);
×
868
            $list->insert($app->make(OpenApiNormalizer::class), -780);
×
869
            $list->insert($app->make(HydraDocumentationNormalizer::class), -790);
×
870

871
            $list->insert($app->make(JsonApiEntrypointNormalizer::class), -800);
×
872
            $list->insert($app->make(JsonApiCollectionNormalizer::class), -985);
×
873
            $list->insert($app->make(JsonApiItemNormalizer::class), -890);
×
874
            $list->insert($app->make(JsonApiErrorNormalizer::class), -790);
×
875
            $list->insert($app->make(JsonApiObjectNormalizer::class), -995);
×
876

877
            if (interface_exists(FieldsBuilderEnumInterface::class)) {
×
878
                $list->insert($app->make(GraphQlItemNormalizer::class), -890);
×
879
                $list->insert($app->make(GraphQlObjectNormalizer::class), -995);
×
880
                $list->insert($app->make(GraphQlErrorNormalizer::class), -790);
×
881
                $list->insert($app->make(GraphQlValidationExceptionNormalizer::class), -780);
×
882
                $list->insert($app->make(GraphQlHttpExceptionNormalizer::class), -780);
×
883
                $list->insert($app->make(GraphQlRuntimeExceptionNormalizer::class), -780);
×
884
            }
885

886
            return $list;
×
887
        });
×
888

889
        $this->app->bind(SerializerInterface::class, Serializer::class);
×
890
        $this->app->bind(NormalizerInterface::class, Serializer::class);
×
891
        $this->app->singleton(Serializer::class, function (Application $app) {
×
892
            // TODO: unused + implement hal/jsonapi ?
893
            // $list->insert($dataUriNormalizer, -920);
894
            // $list->insert($unwrappingDenormalizer, 1000);
895
            // $list->insert($jsonserializableNormalizer, -900);
896
            // $list->insert($uuidDenormalizer, -895); //Todo ramsey uuid support ?
897

898
            return new Serializer(
×
899
                iterator_to_array($app->make('api_platform_normalizer_list')),
×
900
                [
×
901
                    new JsonEncoder('json'),
×
902
                    $app->make(JsonEncoder::class),
×
903
                    new JsonEncoder('jsonopenapi'),
×
904
                    new JsonEncoder('jsonapi'),
×
905
                    new JsonEncoder('jsonhal'),
×
906
                    new CsvEncoder(),
×
907
                ]
×
908
            );
×
909
        });
×
910

911
        $this->app->singleton(JsonLdItemNormalizer::class, function (Application $app) {
×
912
            $config = $app['config'];
×
913
            $defaultContext = $config->get('api-platform.serializer', []);
×
914

915
            return new JsonLdItemNormalizer(
×
916
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
917
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
918
                $app->make(PropertyMetadataFactoryInterface::class),
×
919
                $app->make(IriConverterInterface::class),
×
920
                $app->make(ResourceClassResolverInterface::class),
×
921
                $app->make(ContextBuilderInterface::class),
×
922
                $app->make(PropertyAccessorInterface::class),
×
923
                $app->make(NameConverterInterface::class),
×
924
                $app->make(ClassMetadataFactoryInterface::class),
×
925
                $defaultContext,
×
926
                $app->make(ResourceAccessCheckerInterface::class)
×
927
            );
×
928
        });
×
929

930
        $this->app->singleton(InflectorInterface::class, function (Application $app) {
×
931
            return new Inflector();
×
932
        });
×
933

934
        if ($this->app->runningInConsole()) {
×
935
            $this->commands([
×
936
                Console\InstallCommand::class,
×
937
                Console\Maker\MakeStateProcessorCommand::class,
×
938
                Console\Maker\MakeStateProviderCommand::class,
×
939
                OpenApiCommand::class,
×
940
            ]);
×
941
        }
942
    }
943

944
    private function registerGraphQl(): void
945
    {
946
        $this->app->singleton(GraphQlItemNormalizer::class, function (Application $app) {
×
947
            return new GraphQlItemNormalizer(
×
948
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
949
                $app->make(PropertyMetadataFactoryInterface::class),
×
950
                $app->make(IriConverterInterface::class),
×
951
                $app->make(IdentifiersExtractorInterface::class),
×
952
                $app->make(ResourceClassResolverInterface::class),
×
953
                $app->make(PropertyAccessorInterface::class),
×
954
                $app->make(NameConverterInterface::class),
×
955
                $app->make(SerializerClassMetadataFactory::class),
×
956
                null,
×
957
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
958
                $app->make(ResourceAccessCheckerInterface::class)
×
959
            );
×
960
        });
×
961

962
        $this->app->singleton(GraphQlObjectNormalizer::class, function (Application $app) {
×
963
            return new GraphQlObjectNormalizer(
×
964
                $app->make(ObjectNormalizer::class),
×
965
                $app->make(IriConverterInterface::class),
×
966
                $app->make(IdentifiersExtractorInterface::class),
×
967
            );
×
968
        });
×
969

970
        $this->app->singleton(GraphQlErrorNormalizer::class, function () {
×
971
            return new GraphQlErrorNormalizer();
×
972
        });
×
973

974
        $this->app->singleton(GraphQlValidationExceptionNormalizer::class, function (Application $app) {
×
975
            /** @var ConfigRepository */
976
            $config = $app['config'];
×
977

978
            return new GraphQlValidationExceptionNormalizer($config->get('api-platform.exception_to_status'));
×
979
        });
×
980

981
        $this->app->singleton(GraphQlHttpExceptionNormalizer::class, function () {
×
982
            return new GraphQlHttpExceptionNormalizer();
×
983
        });
×
984

985
        $this->app->singleton(GraphQlRuntimeExceptionNormalizer::class, function () {
×
986
            return new GraphQlHttpExceptionNormalizer();
×
987
        });
×
988

989
        $this->app->singleton('api_platform.graphql.type_locator', function (Application $app) {
×
990
            $tagged = iterator_to_array($app->tagged('api_platform.graphql.type'));
×
991
            $services = [];
×
992
            foreach ($tagged as $service) {
×
993
                $services[$service->name] = $service;
×
994
            }
995

996
            return new ServiceLocator($services);
×
997
        });
×
998

999
        $this->app->singleton(TypesFactoryInterface::class, function (Application $app) {
×
1000
            $tagged = iterator_to_array($app->tagged('api_platform.graphql.type'));
×
1001

1002
            return new TypesFactory($app->make('api_platform.graphql.type_locator'), array_column($tagged, 'name'));
×
1003
        });
×
1004

1005
        $this->app->singleton(TypesContainerInterface::class, function () {
×
1006
            return new TypesContainer();
×
1007
        });
×
1008

1009
        $this->app->singleton(ResourceFieldResolver::class, function (Application $app) {
×
1010
            return new ResourceFieldResolver($app->make(IriConverterInterface::class));
×
1011
        });
×
1012

1013
        $this->app->singleton(ContextAwareTypeBuilderInterface::class, function (Application $app) {
×
1014
            return new TypeBuilder(
×
1015
                $app->make(TypesContainerInterface::class),
×
1016
                $app->make(ResourceFieldResolver::class),
×
1017
                null,
×
1018
                $app->make(Pagination::class)
×
1019
            );
×
1020
        });
×
1021

1022
        $this->app->singleton(TypeConverterInterface::class, function (Application $app) {
×
1023
            return new TypeConverter(
×
1024
                $app->make(ContextAwareTypeBuilderInterface::class),
×
1025
                $app->make(TypesContainerInterface::class),
×
1026
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
1027
                $app->make(PropertyMetadataFactoryInterface::class),
×
1028
            );
×
1029
        });
×
1030

1031
        $this->app->singleton(GraphQlSerializerContextBuilder::class, function (Application $app) {
×
1032
            return new GraphQlSerializerContextBuilder($app->make(NameConverterInterface::class));
×
1033
        });
×
1034

1035
        $this->app->singleton(GraphQlReadProvider::class, function (Application $app) {
×
1036
            /** @var ConfigRepository */
1037
            $config = $app['config'];
×
1038

1039
            return new GraphQlReadProvider(
×
1040
                $this->app->make(CallableProvider::class),
×
1041
                $app->make(IriConverterInterface::class),
×
1042
                $app->make(GraphQlSerializerContextBuilder::class),
×
1043
                $config->get('api-platform.graphql.nesting_separator') ?? '__'
×
1044
            );
×
1045
        });
×
1046
        $this->app->alias(GraphQlReadProvider::class, 'api_platform.graphql.state_provider.read');
×
1047

1048
        $this->app->singleton(ErrorProvider::class, function (Application $app) {
×
1049
            /** @var ConfigRepository */
1050
            $config = $app['config'];
×
1051

1052
            return new ErrorProvider(
×
1053
                $config->get('app.debug'),
×
1054
                $app->make(ResourceClassResolver::class),
×
1055
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
1056
            );
×
1057
        });
×
1058

1059
        $this->app->singleton(ResolverProvider::class, function (Application $app) {
×
1060
            $resolvers = iterator_to_array($app->tagged('api_platform.graphql.resolver'));
×
1061
            $taggedItemResolvers = iterator_to_array($app->tagged(QueryItemResolverInterface::class));
×
1062
            $taggedCollectionResolvers = iterator_to_array($app->tagged(QueryCollectionResolverInterface::class));
×
1063

1064
            return new ResolverProvider(
×
1065
                $app->make(GraphQlReadProvider::class),
×
1066
                new ServiceLocator([...$resolvers, ...$taggedItemResolvers, ...$taggedCollectionResolvers]),
×
1067
            );
×
1068
        });
×
1069

1070
        $this->app->alias(ResolverProvider::class, 'api_platform.graphql.state_provider.resolver');
×
1071

1072
        $this->app->singleton(GraphQlDenormalizeProvider::class, function (Application $app) {
×
1073
            return new GraphQlDenormalizeProvider(
×
1074
                $this->app->make(ResolverProvider::class),
×
1075
                $app->make(SerializerInterface::class),
×
1076
                $app->make(GraphQlSerializerContextBuilder::class)
×
1077
            );
×
1078
        });
×
1079

1080
        $this->app->alias(GraphQlDenormalizeProvider::class, 'api_platform.graphql.state_provider.denormalize');
×
1081

1082
        $this->app->singleton('api_platform.graphql.state_provider.access_checker', function (Application $app) {
×
1083
            return new AccessCheckerProvider($app->make('api_platform.graphql.state_provider.parameter'), $app->make(ResourceAccessCheckerInterface::class));
×
1084
        });
×
1085

1086
        $this->app->singleton(NormalizeProcessor::class, function (Application $app) {
×
1087
            return new NormalizeProcessor(
×
1088
                $app->make(SerializerInterface::class),
×
1089
                $app->make(GraphQlSerializerContextBuilder::class),
×
1090
                $app->make(Pagination::class)
×
1091
            );
×
1092
        });
×
1093
        $this->app->alias(NormalizeProcessor::class, 'api_platform.graphql.state_processor.normalize');
×
1094

1095
        $this->app->singleton('api_platform.graphql.state_processor', function (Application $app) {
×
1096
            return new WriteProcessor(
×
1097
                $app->make('api_platform.graphql.state_processor.normalize'),
×
1098
                $app->make(CallableProcessor::class),
×
1099
            );
×
1100
        });
×
1101

1102
        $this->app->singleton(ResolverFactoryInterface::class, function (Application $app) {
×
1103
            return new ResolverFactory(
×
1104
                $app->make('api_platform.graphql.state_provider.access_checker'),
×
1105
                $app->make('api_platform.graphql.state_processor'),
×
1106
                $app->make('api_platform.graphql.runtime_operation_metadata_factory'),
×
1107
            );
×
1108
        });
×
1109

1110
        $this->app->singleton('api_platform.graphql.runtime_operation_metadata_factory', function (Application $app) {
×
1111
            return new RuntimeOperationMetadataFactory(
×
1112
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
1113
                $app->make(UrlGeneratorRouter::class)
×
1114
            );
×
1115
        });
×
1116

1117
        $this->app->singleton(SchemaBuilderInterface::class, function (Application $app) {
×
1118
            return new SchemaBuilder($app->make(ResourceNameCollectionFactoryInterface::class), $app->make(ResourceMetadataCollectionFactoryInterface::class), $app->make(TypesFactoryInterface::class), $app->make(TypesContainerInterface::class), $app->make(FieldsBuilderEnumInterface::class));
×
1119
        });
×
1120

1121
        $this->app->singleton(ErrorHandlerInterface::class, function () {
×
1122
            return new GraphQlErrorHandler();
×
1123
        });
×
1124

1125
        $this->app->singleton(ExecutorInterface::class, function (Application $app) {
×
1126
            /** @var ConfigRepository */
1127
            $config = $app['config'];
×
1128

1129
            return new Executor($config->get('api-platform.graphql.introspection.enabled') ?? false, $config->get('api-platform.graphql.max_query_complexity') ?? 500, $config->get('api-platform.graphql.max_query_depth') ?? 200);
×
1130
        });
×
1131

1132
        $this->app->singleton(GraphiQlController::class, function (Application $app) {
×
1133
            /** @var ConfigRepository */
1134
            $config = $app['config'];
×
1135
            $prefix = $config->get('api-platform.defaults.route_prefix') ?? '';
×
1136

1137
            return new GraphiQlController($prefix);
×
1138
        });
×
1139

1140
        $this->app->singleton(GraphQlEntrypointController::class, function (Application $app) {
×
1141
            /** @var ConfigRepository */
1142
            $config = $app['config'];
×
1143

1144
            return new GraphQlEntrypointController(
×
1145
                $app->make(SchemaBuilderInterface::class),
×
1146
                $app->make(ExecutorInterface::class),
×
1147
                $app->make(GraphiQlController::class),
×
1148
                $app->make(SerializerInterface::class),
×
1149
                $app->make(ErrorHandlerInterface::class),
×
1150
                debug: $config->get('app.debug'),
×
1151
                negotiator: $app->make(Negotiator::class),
×
1152
                formats: $config->get('api-platform.formats')
×
1153
            );
×
1154
        });
×
1155
    }
1156

1157
    /**
1158
     * Bootstrap services.
1159
     */
1160
    public function boot(): void
1161
    {
1162
        if ($this->app->runningInConsole()) {
×
1163
            $this->publishes([
×
1164
                __DIR__.'/config/api-platform.php' => $this->app->configPath('api-platform.php'),
×
1165
            ], 'api-platform-config');
×
1166

1167
            $this->publishes([
×
1168
                __DIR__.'/public' => $this->app->publicPath('vendor/api-platform'),
×
1169
            ], ['api-platform-assets', 'public']);
×
1170
        }
1171

1172
        $this->loadViewsFrom(__DIR__.'/resources/views', 'api-platform');
×
1173

1174
        $config = $this->app['config'];
×
1175

1176
        if ($config->get('api-platform.graphql.enabled')) {
×
1177
            $fieldsBuilder = $this->app->make(FieldsBuilderEnumInterface::class);
×
1178
            $typeBuilder = $this->app->make(ContextAwareTypeBuilderInterface::class);
×
1179
            $typeBuilder->setFieldsBuilderLocator(new ServiceLocator(['api_platform.graphql.fields_builder' => $fieldsBuilder]));
×
1180
        }
1181

1182
        $this->loadRoutesFrom(__DIR__.'/routes/api.php');
×
1183
    }
1184
}
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

© 2025 Coveralls, Inc