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

api-platform / core / 15128667204

20 May 2025 04:09AM UTC coverage: 26.35% (-0.001%) from 26.351%
15128667204

Pull #7159

github

web-flow
Merge 99f86c570 into a742dbe13
Pull Request #7159: feat(laravel): add name_converter option

0 of 3 new or added lines in 2 files covered. (0.0%)

1 existing line in 1 file now uncovered.

13582 of 51544 relevant lines covered (26.35%)

72.03 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\ApiPlatformController;
80
use ApiPlatform\Laravel\Controller\DocumentationController;
81
use ApiPlatform\Laravel\Controller\EntrypointController;
82
use ApiPlatform\Laravel\Eloquent\Filter\JsonApi\SortFilterParameterProvider;
83
use ApiPlatform\Laravel\Eloquent\Metadata\Factory\Property\EloquentAttributePropertyMetadataFactory;
84
use ApiPlatform\Laravel\Eloquent\Metadata\Factory\Property\EloquentPropertyMetadataFactory;
85
use ApiPlatform\Laravel\Eloquent\Metadata\Factory\Property\EloquentPropertyNameCollectionMetadataFactory;
86
use ApiPlatform\Laravel\Eloquent\Metadata\IdentifiersExtractor as EloquentIdentifiersExtractor;
87
use ApiPlatform\Laravel\Eloquent\Metadata\ModelMetadata;
88
use ApiPlatform\Laravel\Eloquent\Metadata\ResourceClassResolver as EloquentResourceClassResolver;
89
use ApiPlatform\Laravel\Eloquent\PropertyAccess\PropertyAccessor as EloquentPropertyAccessor;
90
use ApiPlatform\Laravel\Eloquent\Serializer\SerializerContextBuilder as EloquentSerializerContextBuilder;
91
use ApiPlatform\Laravel\Eloquent\Serializer\SnakeCaseToCamelCaseNameConverter;
92
use ApiPlatform\Laravel\Exception\ErrorHandler;
93
use ApiPlatform\Laravel\GraphQl\Controller\EntrypointController as GraphQlEntrypointController;
94
use ApiPlatform\Laravel\GraphQl\Controller\GraphiQlController;
95
use ApiPlatform\Laravel\JsonApi\State\JsonApiProvider;
96
use ApiPlatform\Laravel\Metadata\CachePropertyMetadataFactory;
97
use ApiPlatform\Laravel\Metadata\CachePropertyNameCollectionMetadataFactory;
98
use ApiPlatform\Laravel\Routing\IriConverter;
99
use ApiPlatform\Laravel\Routing\Router as UrlGeneratorRouter;
100
use ApiPlatform\Laravel\Routing\SkolemIriConverter;
101
use ApiPlatform\Laravel\Security\ResourceAccessChecker;
102
use ApiPlatform\Laravel\State\AccessCheckerProvider;
103
use ApiPlatform\Laravel\State\SwaggerUiProcessor;
104
use ApiPlatform\Laravel\State\SwaggerUiProvider;
105
use ApiPlatform\Laravel\State\ValidateProvider;
106
use ApiPlatform\Metadata\IdentifiersExtractor;
107
use ApiPlatform\Metadata\IdentifiersExtractorInterface;
108
use ApiPlatform\Metadata\InflectorInterface;
109
use ApiPlatform\Metadata\IriConverterInterface;
110
use ApiPlatform\Metadata\Operation\Factory\OperationMetadataFactory;
111
use ApiPlatform\Metadata\Operation\Factory\OperationMetadataFactoryInterface;
112
use ApiPlatform\Metadata\Operation\PathSegmentNameGeneratorInterface;
113
use ApiPlatform\Metadata\Operation\UnderscorePathSegmentNameGenerator;
114
use ApiPlatform\Metadata\Property\Factory\AttributePropertyMetadataFactory;
115
use ApiPlatform\Metadata\Property\Factory\ClassLevelAttributePropertyNameCollectionFactory;
116
use ApiPlatform\Metadata\Property\Factory\ConcernsPropertyNameCollectionMetadataFactory;
117
use ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyMetadataFactory;
118
use ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyNameCollectionFactory;
119
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
120
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
121
use ApiPlatform\Metadata\Property\Factory\SerializerPropertyMetadataFactory;
122
use ApiPlatform\Metadata\Resource\Factory\AttributesResourceNameCollectionFactory;
123
use ApiPlatform\Metadata\Resource\Factory\ConcernsResourceNameCollectionFactory;
124
use ApiPlatform\Metadata\Resource\Factory\LinkFactory;
125
use ApiPlatform\Metadata\Resource\Factory\LinkFactoryInterface;
126
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
127
use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface;
128
use ApiPlatform\Metadata\ResourceAccessCheckerInterface;
129
use ApiPlatform\Metadata\ResourceClassResolver;
130
use ApiPlatform\Metadata\ResourceClassResolverInterface;
131
use ApiPlatform\Metadata\UrlGeneratorInterface;
132
use ApiPlatform\Metadata\Util\Inflector;
133
use ApiPlatform\OpenApi\Command\OpenApiCommand;
134
use ApiPlatform\OpenApi\Factory\OpenApiFactory;
135
use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface;
136
use ApiPlatform\OpenApi\Options;
137
use ApiPlatform\OpenApi\Serializer\OpenApiNormalizer;
138
use ApiPlatform\Serializer\ItemNormalizer;
139
use ApiPlatform\Serializer\JsonEncoder;
140
use ApiPlatform\Serializer\Mapping\Factory\ClassMetadataFactory as SerializerClassMetadataFactory;
141
use ApiPlatform\Serializer\Mapping\Loader\PropertyMetadataLoader;
142
use ApiPlatform\Serializer\SerializerContextBuilder;
143
use ApiPlatform\State\CallableProcessor;
144
use ApiPlatform\State\CallableProvider;
145
use ApiPlatform\State\ErrorProvider;
146
use ApiPlatform\State\Pagination\Pagination;
147
use ApiPlatform\State\Pagination\PaginationOptions;
148
use ApiPlatform\State\Processor\AddLinkHeaderProcessor;
149
use ApiPlatform\State\Processor\RespondProcessor;
150
use ApiPlatform\State\Processor\SerializeProcessor;
151
use ApiPlatform\State\Processor\WriteProcessor;
152
use ApiPlatform\State\ProcessorInterface;
153
use ApiPlatform\State\Provider\ContentNegotiationProvider;
154
use ApiPlatform\State\Provider\DeserializeProvider;
155
use ApiPlatform\State\Provider\ParameterProvider;
156
use ApiPlatform\State\Provider\ReadProvider;
157
use ApiPlatform\State\ProviderInterface;
158
use ApiPlatform\State\SerializerContextBuilderInterface;
159
use Illuminate\Config\Repository as ConfigRepository;
160
use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandlerInterface;
161
use Illuminate\Contracts\Foundation\Application;
162
use Illuminate\Routing\Router;
163
use Illuminate\Support\ServiceProvider;
164
use Negotiation\Negotiator;
165
use phpDocumentor\Reflection\DocBlockFactory;
166
use Psr\Log\LoggerInterface;
167
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
168
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
169
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
170
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
171
use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
172
use Symfony\Component\Routing\RequestContext;
173
use Symfony\Component\Serializer\Encoder\CsvEncoder;
174
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
175
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
176
use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader;
177
use Symfony\Component\Serializer\Mapping\Loader\LoaderChain;
178
use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface;
179
use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter;
180
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
181
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
182
use Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer;
183
use Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer;
184
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
185
use Symfony\Component\Serializer\Normalizer\DateTimeZoneNormalizer;
186
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
187
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
188
use Symfony\Component\Serializer\Serializer;
189
use Symfony\Component\Serializer\SerializerInterface;
190
use Symfony\Component\WebLink\HttpHeaderSerializer;
191

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

201
        $this->app->singleton(PropertyInfoExtractorInterface::class, function () {
×
202
            $phpDocExtractor = class_exists(DocBlockFactory::class) ? new PhpDocExtractor() : null;
×
203
            $reflectionExtractor = new ReflectionExtractor();
×
204

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

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

228
        $this->app->singleton(SerializerClassMetadataFactory::class, function (Application $app) {
×
229
            return new SerializerClassMetadataFactory($app->make(ClassMetadataFactoryInterface::class));
×
230
        });
×
231

232
        $this->app->bind(PathSegmentNameGeneratorInterface::class, UnderscorePathSegmentNameGenerator::class);
×
233

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

241
            $logger = $app->make(LoggerInterface::class);
×
242

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

250
            return new ConcernsResourceNameCollectionFactory($paths, new AttributesResourceNameCollectionFactory($paths));
×
251
        });
×
252

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

258
        $this->app->singleton(PropertyMetadataFactoryInterface::class, function (Application $app) {
×
259
            return new PropertyInfoPropertyMetadataFactory(
×
260
                $app->make(PropertyInfoExtractorInterface::class),
×
261
                new EloquentPropertyMetadataFactory(
×
262
                    $app->make(ModelMetadata::class),
×
263
                )
×
264
            );
×
265
        });
×
266

267
        $this->app->extend(PropertyMetadataFactoryInterface::class, function (PropertyInfoPropertyMetadataFactory $inner, Application $app) {
×
268
            /** @var ConfigRepository $config */
269
            $config = $app['config'];
×
270

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

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

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

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

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

318
        $this->app->bind(NameConverterInterface::class, function (Application $app) {
×
319
            $config = $app['config'];
×
NEW
320
            $nameConverter = $config->get('api-platform.name_converter', SnakeCaseToCamelCaseNameConverter::class);
×
UNCOV
321
            $defaultContext = $config->get('api-platform.serializer', []);
×
322

NEW
323
            return new HydraPrefixNameConverter(new MetadataAwareNameConverter($app->make(ClassMetadataFactoryInterface::class), $app->make($nameConverter)), $defaultContext);
×
324
        });
×
325

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

330
        $this->app->bind(OperationMetadataFactoryInterface::class, OperationMetadataFactory::class);
×
331

332
        $this->app->singleton(ReadProvider::class, function (Application $app) {
×
333
            return new ReadProvider($app->make(CallableProvider::class));
×
334
        });
×
335

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

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

343
        $this->app->singleton(ValidateProvider::class, function (Application $app) {
×
344
            return new ValidateProvider($app->make(SwaggerUiProvider::class), $app);
×
345
        });
×
346

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

351
        if (class_exists(JsonApiProvider::class)) {
×
352
            $this->app->extend(DeserializeProvider::class, function (ProviderInterface $inner, Application $app) {
×
353
                return new JsonApiProvider($inner);
×
354
            });
×
355
        }
356

357
        $this->app->singleton(SortFilterParameterProvider::class, function (Application $app) {
×
358
            return new SortFilterParameterProvider();
×
359
        });
×
360

361
        $this->app->singleton(AccessCheckerProvider::class, function (Application $app) {
×
362
            return new AccessCheckerProvider($app->make(ParameterProvider::class), $app->make(ResourceAccessCheckerInterface::class));
×
363
        });
×
364

365
        $this->app->singleton(Negotiator::class, function (Application $app) {
×
366
            return new Negotiator();
×
367
        });
×
368
        $this->app->singleton(ContentNegotiationProvider::class, function (Application $app) {
×
369
            /** @var ConfigRepository */
370
            $config = $app['config'];
×
371

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

375
        $this->app->bind(ProviderInterface::class, ContentNegotiationProvider::class);
×
376

377
        $this->app->singleton(RespondProcessor::class, function () {
×
378
            return new AddLinkHeaderProcessor(new RespondProcessor(), new HttpHeaderSerializer());
×
379
        });
×
380

381
        $this->app->singleton(SerializeProcessor::class, function (Application $app) {
×
382
            return new SerializeProcessor($app->make(RespondProcessor::class), $app->make(Serializer::class), $app->make(SerializerContextBuilderInterface::class));
×
383
        });
×
384

385
        $this->app->singleton(WriteProcessor::class, function (Application $app) {
×
386
            return new WriteProcessor($app->make(SerializeProcessor::class), $app->make(CallableProcessor::class));
×
387
        });
×
388

389
        $this->app->singleton(SerializerContextBuilder::class, function (Application $app) {
×
390
            /** @var ConfigRepository */
391
            $config = $app['config'];
×
392

393
            return new SerializerContextBuilder($app->make(ResourceMetadataCollectionFactoryInterface::class), $config->get('app.debug'));
×
394
        });
×
395
        $this->app->bind(SerializerContextBuilderInterface::class, EloquentSerializerContextBuilder::class);
×
396
        $this->app->singleton(EloquentSerializerContextBuilder::class, function (Application $app) {
×
397
            return new EloquentSerializerContextBuilder(
×
398
                $app->make(SerializerContextBuilder::class),
×
399
                $app->make(PropertyNameCollectionFactoryInterface::class)
×
400
            );
×
401
        });
×
402

403
        $this->app->singleton(HydraLinkProcessor::class, function (Application $app) {
×
404
            return new HydraLinkProcessor($app->make(WriteProcessor::class), $app->make(UrlGeneratorInterface::class));
×
405
        });
×
406

407
        $this->app->bind(ProcessorInterface::class, function (Application $app) {
×
408
            $config = $app['config'];
×
409
            if ($config->has('api-platform.formats.jsonld')) {
×
410
                return $app->make(HydraLinkProcessor::class);
×
411
            }
412

413
            return $app->make(WriteProcessor::class);
×
414
        });
×
415

416
        $this->app->singleton(ObjectNormalizer::class, function (Application $app) {
×
417
            $config = $app['config'];
×
418
            $defaultContext = $config->get('api-platform.serializer', []);
×
419

420
            return new ObjectNormalizer(defaultContext: $defaultContext);
×
421
        });
×
422

423
        $this->app->singleton(DateTimeNormalizer::class, function (Application $app) {
×
424
            $config = $app['config'];
×
425
            $defaultContext = $config->get('api-platform.serializer', []);
×
426

427
            return new DateTimeNormalizer(defaultContext: $defaultContext);
×
428
        });
×
429

430
        $this->app->singleton(DateTimeZoneNormalizer::class, function () {
×
431
            return new DateTimeZoneNormalizer();
×
432
        });
×
433

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

438
            return new DateIntervalNormalizer(defaultContext: $defaultContext);
×
439
        });
×
440

441
        $this->app->singleton(JsonEncoder::class, function () {
×
442
            return new JsonEncoder('jsonld');
×
443
        });
×
444

445
        $this->app->bind(IriConverterInterface::class, IriConverter::class);
×
446
        $this->app->singleton(IriConverter::class, function (Application $app) {
×
447
            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));
×
448
        });
×
449

450
        $this->app->singleton(SkolemIriConverter::class, function (Application $app) {
×
451
            return new SkolemIriConverter($app->make(UrlGeneratorRouter::class));
×
452
        });
×
453

454
        $this->app->bind(IdentifiersExtractorInterface::class, IdentifiersExtractor::class);
×
455
        $this->app->singleton(IdentifiersExtractor::class, function (Application $app) {
×
456
            return new EloquentIdentifiersExtractor(
×
457
                new IdentifiersExtractor(
×
458
                    $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
459
                    $app->make(ResourceClassResolverInterface::class),
×
460
                    $app->make(PropertyNameCollectionFactoryInterface::class),
×
461
                    $app->make(PropertyMetadataFactoryInterface::class),
×
462
                    $app->make(PropertyAccessorInterface::class)
×
463
                )
×
464
            );
×
465
        });
×
466

467
        $this->app->bind(UrlGeneratorInterface::class, UrlGeneratorRouter::class);
×
468
        $this->app->singleton(UrlGeneratorRouter::class, function (Application $app) {
×
469
            $request = $app->make('request');
×
470
            // https://github.com/laravel/framework/blob/2bfb70bca53e24227a6f921f39d84ba452efd8e0/src/Illuminate/Routing/CompiledRouteCollection.php#L112
471
            $trimmedRequest = $request->duplicate();
×
472
            $parts = explode('?', $request->server->get('REQUEST_URI'), 2);
×
473
            $trimmedRequest->server->set(
×
474
                'REQUEST_URI',
×
475
                rtrim($parts[0], '/').(isset($parts[1]) ? '?'.$parts[1] : '')
×
476
            );
×
477

478
            $urlGenerator = new UrlGeneratorRouter($app->make(Router::class));
×
479
            $urlGenerator->setContext((new RequestContext())->fromRequest($trimmedRequest));
×
480

481
            return $urlGenerator;
×
482
        });
×
483

484
        $this->app->bind(ContextBuilderInterface::class, JsonLdContextBuilder::class);
×
485
        $this->app->singleton(JsonLdContextBuilder::class, function (Application $app) {
×
486
            $config = $app['config'];
×
487
            $defaultContext = $config->get('api-platform.serializer', []);
×
488

489
            return new JsonLdContextBuilder(
×
490
                $app->make(ResourceNameCollectionFactoryInterface::class),
×
491
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
492
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
493
                $app->make(PropertyMetadataFactoryInterface::class),
×
494
                $app->make(UrlGeneratorInterface::class),
×
495
                $app->make(IriConverterInterface::class),
×
496
                $app->make(NameConverterInterface::class),
×
497
                $defaultContext
×
498
            );
×
499
        });
×
500

501
        $this->app->singleton(HydraEntrypointNormalizer::class, function (Application $app) {
×
502
            return new HydraEntrypointNormalizer($app->make(ResourceMetadataCollectionFactoryInterface::class), $app->make(IriConverterInterface::class), $app->make(UrlGeneratorInterface::class));
×
503
        });
×
504

505
        $this->app->singleton(ResourceAccessCheckerInterface::class, function () {
×
506
            return new ResourceAccessChecker();
×
507
        });
×
508

509
        $this->app->singleton(ItemNormalizer::class, function (Application $app) {
×
510
            /** @var ConfigRepository */
511
            $config = $app['config'];
×
512
            $defaultContext = $config->get('api-platform.serializer', []);
×
513

514
            return new ItemNormalizer(
×
515
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
516
                $app->make(PropertyMetadataFactoryInterface::class),
×
517
                $app->make(IriConverterInterface::class),
×
518
                $app->make(ResourceClassResolverInterface::class),
×
519
                $app->make(PropertyAccessorInterface::class),
×
520
                $app->make(NameConverterInterface::class),
×
521
                $app->make(ClassMetadataFactoryInterface::class),
×
522
                $app->make(LoggerInterface::class),
×
523
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
524
                $app->make(ResourceAccessCheckerInterface::class),
×
525
                $defaultContext
×
526
            );
×
527
        });
×
528

529
        $this->app->bind(AnonymousContextBuilderInterface::class, JsonLdContextBuilder::class);
×
530

531
        $this->app->singleton(JsonLdObjectNormalizer::class, function (Application $app) {
×
532
            return new JsonLdObjectNormalizer(
×
533
                $app->make(ObjectNormalizer::class),
×
534
                $app->make(IriConverterInterface::class),
×
535
                $app->make(AnonymousContextBuilderInterface::class)
×
536
            );
×
537
        });
×
538

539
        $this->app->singleton(HalCollectionNormalizer::class, function (Application $app) {
×
540
            /** @var ConfigRepository */
541
            $config = $app['config'];
×
542

543
            return new HalCollectionNormalizer(
×
544
                $app->make(ResourceClassResolverInterface::class),
×
545
                $config->get('api-platform.pagination.page_parameter_name'),
×
546
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
547
            );
×
548
        });
×
549

550
        $this->app->singleton(HalObjectNormalizer::class, function (Application $app) {
×
551
            return new HalObjectNormalizer(
×
552
                $app->make(ObjectNormalizer::class),
×
553
                $app->make(IriConverterInterface::class)
×
554
            );
×
555
        });
×
556

557
        $this->app->singleton(HalItemNormalizer::class, function (Application $app) {
×
558
            /** @var ConfigRepository */
559
            $config = $app['config'];
×
560
            $defaultContext = $config->get('api-platform.serializer', []);
×
561

562
            return new HalItemNormalizer(
×
563
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
564
                $app->make(PropertyMetadataFactoryInterface::class),
×
565
                $app->make(IriConverterInterface::class),
×
566
                $app->make(ResourceClassResolverInterface::class),
×
567
                $app->make(PropertyAccessorInterface::class),
×
568
                $app->make(NameConverterInterface::class),
×
569
                $app->make(ClassMetadataFactoryInterface::class),
×
570
                $defaultContext,
×
571
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
572
                $app->make(ResourceAccessCheckerInterface::class),
×
573
            );
×
574
        });
×
575

576
        $this->app->singleton(Options::class, function (Application $app) {
×
577
            /** @var ConfigRepository */
578
            $config = $app['config'];
×
579

580
            return new Options(
×
581
                title: $config->get('api-platform.title', ''),
×
582
                description: $config->get('api-platform.description', ''),
×
583
                version: $config->get('api-platform.version', ''),
×
584
                oAuthEnabled: $config->get('api-platform.swagger_ui.oauth.enabled', false),
×
585
                oAuthType: $config->get('api-platform.swagger_ui.oauth.type', null),
×
586
                oAuthFlow: $config->get('api-platform.swagger_ui.oauth.flow', null),
×
587
                oAuthTokenUrl: $config->get('api-platform.swagger_ui.oauth.tokenUrl', null),
×
588
                oAuthAuthorizationUrl: $config->get('api-platform.swagger_ui.oauth.authorizationUrl', null),
×
589
                oAuthRefreshUrl: $config->get('api-platform.swagger_ui.oauth.refreshUrl', null),
×
590
                oAuthScopes: $config->get('api-platform.swagger_ui.oauth.scopes', []),
×
591
                apiKeys: $config->get('api-platform.swagger_ui.apiKeys', []),
×
592
                contactName: $config->get('api-platform.swagger_ui.contact.name', ''),
×
593
                contactUrl: $config->get('api-platform.swagger_ui.contact.url', ''),
×
594
                contactEmail: $config->get('api-platform.swagger_ui.contact.email', ''),
×
595
                licenseName: $config->get('api-platform.swagger_ui.license.name', ''),
×
596
                licenseUrl: $config->get('api-platform.swagger_ui.license.url', ''),
×
597
                persistAuthorization: $config->get('api-platform.swagger_ui.persist_authorization', false),
×
598
                httpAuth: $config->get('api-platform.swagger_ui.http_auth', []),
×
599
                tags: $config->get('api-platform.openapi.tags', []),
×
600
                errorResourceClass: Error::class,
×
601
                validationErrorResourceClass: ValidationError::class
×
602
            );
×
603
        });
×
604

605
        $this->app->singleton(SwaggerUiProcessor::class, function (Application $app) {
×
606
            /** @var ConfigRepository */
607
            $config = $app['config'];
×
608

609
            return new SwaggerUiProcessor(
×
610
                urlGenerator: $app->make(UrlGeneratorInterface::class),
×
611
                normalizer: $app->make(NormalizerInterface::class),
×
612
                openApiOptions: $app->make(Options::class),
×
613
                oauthClientId: $config->get('api-platform.swagger_ui.oauth.clientId'),
×
614
                oauthClientSecret: $config->get('api-platform.swagger_ui.oauth.clientSecret'),
×
615
                oauthPkce: $config->get('api-platform.swagger_ui.oauth.pkce', false),
×
616
            );
×
617
        });
×
618

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

623
            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));
×
624
        });
×
625

626
        $this->app->singleton(EntrypointController::class, function (Application $app) {
×
627
            /** @var ConfigRepository */
628
            $config = $app['config'];
×
629

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

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

637
            return new Pagination($config->get('api-platform.pagination'), []);
×
638
        });
×
639

640
        $this->app->singleton(PaginationOptions::class, function (Application $app) {
×
641
            /** @var ConfigRepository */
642
            $config = $app['config'];
×
643
            $defaults = $config->get('api-platform.defaults');
×
644
            $pagination = $config->get('api-platform.pagination');
×
645

646
            return new PaginationOptions(
×
647
                $defaults['pagination_enabled'] ?? true,
×
648
                $pagination['page_parameter_name'] ?? 'page',
×
649
                $defaults['pagination_client_items_per_page'] ?? false,
×
650
                $pagination['items_per_page_parameter_name'] ?? 'itemsPerPage',
×
651
                $defaults['pagination_client_enabled'] ?? false,
×
652
                $pagination['enabled_parameter_name'] ?? 'pagination',
×
653
                $defaults['pagination_items_per_page'] ?? 30,
×
654
                $defaults['pagination_maximum_items_per_page'] ?? 30,
×
655
                $defaults['pagination_partial'] ?? false,
×
656
                $defaults['pagination_client_partial'] ?? false,
×
657
                $pagination['partial_parameter_name'] ?? 'partial',
×
658
            );
×
659
        });
×
660

661
        $this->app->bind(OpenApiFactoryInterface::class, OpenApiFactory::class);
×
662
        $this->app->singleton(OpenApiFactory::class, function (Application $app) {
×
663
            /** @var ConfigRepository */
664
            $config = $app['config'];
×
665

666
            return new OpenApiFactory(
×
667
                $app->make(ResourceNameCollectionFactoryInterface::class),
×
668
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
669
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
670
                $app->make(PropertyMetadataFactoryInterface::class),
×
671
                $app->make(SchemaFactoryInterface::class),
×
672
                null,
×
673
                $config->get('api-platform.formats'),
×
674
                $app->make(Options::class),
×
675
                $app->make(PaginationOptions::class),
×
676
                null,
×
677
                $config->get('api-platform.error_formats'),
×
678
                // ?RouterInterface $router = null
×
679
            );
×
680
        });
×
681

682
        $this->app->singleton(OpenApiCommand::class, function (Application $app) {
×
683
            return new OpenApiCommand($app->make(OpenApiFactory::class), $app->make(Serializer::class));
×
684
        });
×
685

686
        $this->app->bind(DefinitionNameFactoryInterface::class, DefinitionNameFactory::class);
×
687
        $this->app->singleton(DefinitionNameFactory::class, function (Application $app) {
×
688
            /** @var ConfigRepository */
689
            $config = $app['config'];
×
690

691
            return new DefinitionNameFactory($config->get('api-platform.formats'));
×
692
        });
×
693

694
        $this->app->singleton(SchemaFactory::class, function (Application $app) {
×
695
            /** @var ConfigRepository */
696
            $config = $app['config'];
×
697

698
            return new SchemaFactory(
×
699
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
700
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
701
                $app->make(PropertyMetadataFactoryInterface::class),
×
702
                $app->make(NameConverterInterface::class),
×
703
                $app->make(ResourceClassResolverInterface::class),
×
704
                $config->get('api-platform.formats'),
×
705
                $app->make(DefinitionNameFactoryInterface::class),
×
706
            );
×
707
        });
×
708
        $this->app->singleton(JsonApiSchemaFactory::class, function (Application $app) {
×
709
            return new JsonApiSchemaFactory(
×
710
                $app->make(SchemaFactory::class),
×
711
                $app->make(PropertyMetadataFactoryInterface::class),
×
712
                $app->make(ResourceClassResolverInterface::class),
×
713
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
714
                $app->make(DefinitionNameFactoryInterface::class),
×
715
            );
×
716
        });
×
717
        $this->app->singleton(HydraSchemaFactory::class, function (Application $app) {
×
718
            $config = $app['config'];
×
719
            $defaultContext = $config->get('api-platform.serializer', []);
×
720

721
            return new HydraSchemaFactory(
×
722
                $app->make(JsonApiSchemaFactory::class),
×
723
                $defaultContext
×
724
            );
×
725
        });
×
726

727
        $this->app->bind(SchemaFactoryInterface::class, HydraSchemaFactory::class);
×
728

729
        $this->app->singleton(OpenApiNormalizer::class, function (Application $app) {
×
730
            return new OpenApiNormalizer($app->make(ObjectNormalizer::class));
×
731
        });
×
732

733
        $this->app->singleton(HydraDocumentationNormalizer::class, function (Application $app) {
×
734
            $config = $app['config'];
×
735
            $defaultContext = $config->get('api-platform.serializer', []);
×
736
            $entrypointEnabled = $config->get('api-platform.enable_entrypoint', true);
×
737

738
            return new HydraDocumentationNormalizer(
×
739
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
740
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
741
                $app->make(PropertyMetadataFactoryInterface::class),
×
742
                $app->make(ResourceClassResolverInterface::class),
×
743
                $app->make(UrlGeneratorInterface::class),
×
744
                $app->make(NameConverterInterface::class),
×
745
                $defaultContext,
×
746
                $entrypointEnabled
×
747
            );
×
748
        });
×
749

750
        $this->app->singleton(HydraPartialCollectionViewNormalizer::class, function (Application $app) {
×
751
            $config = $app['config'];
×
752
            $defaultContext = $config->get('api-platform.serializer', []);
×
753

754
            return new HydraPartialCollectionViewNormalizer(
×
755
                new HydraCollectionFiltersNormalizer(
×
756
                    new HydraCollectionNormalizer(
×
757
                        $app->make(ContextBuilderInterface::class),
×
758
                        $app->make(ResourceClassResolverInterface::class),
×
759
                        $app->make(IriConverterInterface::class),
×
760
                        $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
761
                        $defaultContext
×
762
                    ),
×
763
                    $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
764
                    $app->make(ResourceClassResolverInterface::class),
×
765
                    null, // filterLocator, we use only Parameters with Laravel and we don't need to call filters there
×
766
                    $defaultContext
×
767
                ),
×
768
                'page',
×
769
                'pagination',
×
770
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
771
                $app->make(PropertyAccessorInterface::class),
×
772
                $config->get('api-platform.url_generation_strategy', UrlGeneratorInterface::ABS_PATH),
×
773
                $defaultContext,
×
774
            );
×
775
        });
×
776

777
        $this->app->singleton(ReservedAttributeNameConverter::class, function (Application $app) {
×
778
            return new ReservedAttributeNameConverter($app->make(NameConverterInterface::class));
×
779
        });
×
780

781
        if (interface_exists(FieldsBuilderEnumInterface::class)) {
×
782
            $this->registerGraphQl();
×
783
        }
784

785
        $this->app->singleton(JsonApiEntrypointNormalizer::class, function (Application $app) {
×
786
            return new JsonApiEntrypointNormalizer(
×
787
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
788
                $app->make(IriConverterInterface::class),
×
789
                $app->make(UrlGeneratorInterface::class),
×
790
            );
×
791
        });
×
792

793
        $this->app->singleton(JsonApiCollectionNormalizer::class, function (Application $app) {
×
794
            /** @var ConfigRepository */
795
            $config = $app['config'];
×
796

797
            return new JsonApiCollectionNormalizer(
×
798
                $app->make(ResourceClassResolverInterface::class),
×
799
                $config->get('api-platform.pagination.page_parameter_name'),
×
800
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
801
            );
×
802
        });
×
803

804
        $this->app->singleton(JsonApiItemNormalizer::class, function (Application $app) {
×
805
            $config = $app['config'];
×
806
            $defaultContext = $config->get('api-platform.serializer', []);
×
807

808
            return new JsonApiItemNormalizer(
×
809
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
810
                $app->make(PropertyMetadataFactoryInterface::class),
×
811
                $app->make(IriConverterInterface::class),
×
812
                $app->make(ResourceClassResolverInterface::class),
×
813
                $app->make(PropertyAccessorInterface::class),
×
814
                $app->make(NameConverterInterface::class),
×
815
                $app->make(ClassMetadataFactoryInterface::class),
×
816
                $defaultContext,
×
817
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
818
                $app->make(ResourceAccessCheckerInterface::class),
×
819
                null
×
820
                // $app->make(TagCollectorInterface::class),
×
821
            );
×
822
        });
×
823

824
        $this->app->singleton(JsonApiErrorNormalizer::class, function (Application $app) {
×
825
            return new JsonApiErrorNormalizer(
×
826
                $app->make(JsonApiItemNormalizer::class),
×
827
            );
×
828
        });
×
829

830
        $this->app->singleton(JsonApiObjectNormalizer::class, function (Application $app) {
×
831
            return new JsonApiObjectNormalizer(
×
832
                $app->make(ObjectNormalizer::class),
×
833
                $app->make(IriConverterInterface::class),
×
834
                $app->make(ResourceClassResolverInterface::class),
×
835
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
836
            );
×
837
        });
×
838

839
        $this->app->singleton('api_platform_normalizer_list', function (Application $app) {
×
840
            $list = new \SplPriorityQueue();
×
841
            $list->insert($app->make(HydraEntrypointNormalizer::class), -800);
×
842
            $list->insert($app->make(HydraPartialCollectionViewNormalizer::class), -800);
×
843
            $list->insert($app->make(HalCollectionNormalizer::class), -800);
×
844
            $list->insert($app->make(HalEntrypointNormalizer::class), -985);
×
845
            $list->insert($app->make(HalObjectNormalizer::class), -995);
×
846
            $list->insert($app->make(HalItemNormalizer::class), -890);
×
847
            $list->insert($app->make(JsonLdItemNormalizer::class), -890);
×
848
            $list->insert($app->make(JsonLdObjectNormalizer::class), -995);
×
849
            $list->insert($app->make(ArrayDenormalizer::class), -990);
×
850
            $list->insert($app->make(DateTimeZoneNormalizer::class), -915);
×
851
            $list->insert($app->make(DateIntervalNormalizer::class), -915);
×
852
            $list->insert($app->make(DateTimeNormalizer::class), -910);
×
853
            $list->insert($app->make(BackedEnumNormalizer::class), -910);
×
854
            $list->insert($app->make(ObjectNormalizer::class), -1000);
×
855
            $list->insert($app->make(ItemNormalizer::class), -895);
×
856
            $list->insert($app->make(OpenApiNormalizer::class), -780);
×
857
            $list->insert($app->make(HydraDocumentationNormalizer::class), -790);
×
858

859
            $list->insert($app->make(JsonApiEntrypointNormalizer::class), -800);
×
860
            $list->insert($app->make(JsonApiCollectionNormalizer::class), -985);
×
861
            $list->insert($app->make(JsonApiItemNormalizer::class), -890);
×
862
            $list->insert($app->make(JsonApiErrorNormalizer::class), -790);
×
863
            $list->insert($app->make(JsonApiObjectNormalizer::class), -995);
×
864

865
            if (interface_exists(FieldsBuilderEnumInterface::class)) {
×
866
                $list->insert($app->make(GraphQlItemNormalizer::class), -890);
×
867
                $list->insert($app->make(GraphQlObjectNormalizer::class), -995);
×
868
                $list->insert($app->make(GraphQlErrorNormalizer::class), -790);
×
869
                $list->insert($app->make(GraphQlValidationExceptionNormalizer::class), -780);
×
870
                $list->insert($app->make(GraphQlHttpExceptionNormalizer::class), -780);
×
871
                $list->insert($app->make(GraphQlRuntimeExceptionNormalizer::class), -780);
×
872
            }
873

874
            return $list;
×
875
        });
×
876

877
        $this->app->bind(SerializerInterface::class, Serializer::class);
×
878
        $this->app->bind(NormalizerInterface::class, Serializer::class);
×
879
        $this->app->singleton(Serializer::class, function (Application $app) {
×
880
            // TODO: unused + implement hal/jsonapi ?
881
            // $list->insert($dataUriNormalizer, -920);
882
            // $list->insert($unwrappingDenormalizer, 1000);
883
            // $list->insert($jsonserializableNormalizer, -900);
884
            // $list->insert($uuidDenormalizer, -895); //Todo ramsey uuid support ?
885

886
            return new Serializer(
×
887
                iterator_to_array($app->make('api_platform_normalizer_list')),
×
888
                [
×
889
                    new JsonEncoder('json'),
×
890
                    $app->make(JsonEncoder::class),
×
891
                    new JsonEncoder('jsonopenapi'),
×
892
                    new JsonEncoder('jsonapi'),
×
893
                    new JsonEncoder('jsonhal'),
×
894
                    new CsvEncoder(),
×
895
                ]
×
896
            );
×
897
        });
×
898

899
        $this->app->singleton(JsonLdItemNormalizer::class, function (Application $app) {
×
900
            $config = $app['config'];
×
901
            $defaultContext = $config->get('api-platform.serializer', []);
×
902

903
            return new JsonLdItemNormalizer(
×
904
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
905
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
906
                $app->make(PropertyMetadataFactoryInterface::class),
×
907
                $app->make(IriConverterInterface::class),
×
908
                $app->make(ResourceClassResolverInterface::class),
×
909
                $app->make(ContextBuilderInterface::class),
×
910
                $app->make(PropertyAccessorInterface::class),
×
911
                $app->make(NameConverterInterface::class),
×
912
                $app->make(ClassMetadataFactoryInterface::class),
×
913
                $defaultContext,
×
914
                $app->make(ResourceAccessCheckerInterface::class)
×
915
            );
×
916
        });
×
917

918
        $this->app->singleton(InflectorInterface::class, function (Application $app) {
×
919
            return new Inflector();
×
920
        });
×
921

922
        if ($this->app->runningInConsole()) {
×
923
            $this->commands([
×
924
                Console\InstallCommand::class,
×
925
                Console\Maker\MakeStateProcessorCommand::class,
×
926
                Console\Maker\MakeStateProviderCommand::class,
×
927
                OpenApiCommand::class,
×
928
            ]);
×
929
        }
930
    }
931

932
    private function registerGraphQl(): void
933
    {
934
        $this->app->singleton(GraphQlItemNormalizer::class, function (Application $app) {
×
935
            return new GraphQlItemNormalizer(
×
936
                $app->make(PropertyNameCollectionFactoryInterface::class),
×
937
                $app->make(PropertyMetadataFactoryInterface::class),
×
938
                $app->make(IriConverterInterface::class),
×
939
                $app->make(IdentifiersExtractorInterface::class),
×
940
                $app->make(ResourceClassResolverInterface::class),
×
941
                $app->make(PropertyAccessorInterface::class),
×
942
                $app->make(NameConverterInterface::class),
×
943
                $app->make(SerializerClassMetadataFactory::class),
×
944
                null,
×
945
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
946
                $app->make(ResourceAccessCheckerInterface::class)
×
947
            );
×
948
        });
×
949

950
        $this->app->singleton(GraphQlObjectNormalizer::class, function (Application $app) {
×
951
            return new GraphQlObjectNormalizer(
×
952
                $app->make(ObjectNormalizer::class),
×
953
                $app->make(IriConverterInterface::class),
×
954
                $app->make(IdentifiersExtractorInterface::class),
×
955
            );
×
956
        });
×
957

958
        $this->app->singleton(GraphQlErrorNormalizer::class, function () {
×
959
            return new GraphQlErrorNormalizer();
×
960
        });
×
961

962
        $this->app->singleton(GraphQlValidationExceptionNormalizer::class, function (Application $app) {
×
963
            /** @var ConfigRepository */
964
            $config = $app['config'];
×
965

966
            return new GraphQlValidationExceptionNormalizer($config->get('api-platform.exception_to_status'));
×
967
        });
×
968

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

973
        $this->app->singleton(GraphQlRuntimeExceptionNormalizer::class, function () {
×
974
            return new GraphQlHttpExceptionNormalizer();
×
975
        });
×
976

977
        $this->app->singleton('api_platform.graphql.type_locator', function (Application $app) {
×
978
            $tagged = iterator_to_array($app->tagged('api_platform.graphql.type'));
×
979
            $services = [];
×
980
            foreach ($tagged as $service) {
×
981
                $services[$service->name] = $service;
×
982
            }
983

984
            return new ServiceLocator($services);
×
985
        });
×
986

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

990
            return new TypesFactory($app->make('api_platform.graphql.type_locator'), array_column($tagged, 'name'));
×
991
        });
×
992

993
        $this->app->singleton(TypesContainerInterface::class, function () {
×
994
            return new TypesContainer();
×
995
        });
×
996

997
        $this->app->singleton(ResourceFieldResolver::class, function (Application $app) {
×
998
            return new ResourceFieldResolver($app->make(IriConverterInterface::class));
×
999
        });
×
1000

1001
        $this->app->singleton(ContextAwareTypeBuilderInterface::class, function (Application $app) {
×
1002
            return new TypeBuilder(
×
1003
                $app->make(TypesContainerInterface::class),
×
1004
                $app->make(ResourceFieldResolver::class),
×
1005
                null,
×
1006
                $app->make(Pagination::class)
×
1007
            );
×
1008
        });
×
1009

1010
        $this->app->singleton(TypeConverterInterface::class, function (Application $app) {
×
1011
            return new TypeConverter(
×
1012
                $app->make(ContextAwareTypeBuilderInterface::class),
×
1013
                $app->make(TypesContainerInterface::class),
×
1014
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
1015
                $app->make(PropertyMetadataFactoryInterface::class),
×
1016
            );
×
1017
        });
×
1018

1019
        $this->app->singleton(GraphQlSerializerContextBuilder::class, function (Application $app) {
×
1020
            return new GraphQlSerializerContextBuilder($app->make(NameConverterInterface::class));
×
1021
        });
×
1022

1023
        $this->app->singleton(GraphQlReadProvider::class, function (Application $app) {
×
1024
            /** @var ConfigRepository */
1025
            $config = $app['config'];
×
1026

1027
            return new GraphQlReadProvider(
×
1028
                $this->app->make(CallableProvider::class),
×
1029
                $app->make(IriConverterInterface::class),
×
1030
                $app->make(GraphQlSerializerContextBuilder::class),
×
1031
                $config->get('api-platform.graphql.nesting_separator') ?? '__'
×
1032
            );
×
1033
        });
×
1034
        $this->app->alias(GraphQlReadProvider::class, 'api_platform.graphql.state_provider.read');
×
1035

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

1040
            return new ErrorProvider(
×
1041
                $config->get('app.debug'),
×
1042
                $app->make(ResourceClassResolver::class),
×
1043
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
1044
            );
×
1045
        });
×
1046

1047
        $this->app->singleton(ResolverProvider::class, function (Application $app) {
×
1048
            $resolvers = iterator_to_array($app->tagged('api_platform.graphql.resolver'));
×
1049
            $taggedItemResolvers = iterator_to_array($app->tagged(QueryItemResolverInterface::class));
×
1050
            $taggedCollectionResolvers = iterator_to_array($app->tagged(QueryCollectionResolverInterface::class));
×
1051

1052
            return new ResolverProvider(
×
1053
                $app->make(GraphQlReadProvider::class),
×
1054
                new ServiceLocator([...$resolvers, ...$taggedItemResolvers, ...$taggedCollectionResolvers]),
×
1055
            );
×
1056
        });
×
1057

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

1060
        $this->app->singleton(GraphQlDenormalizeProvider::class, function (Application $app) {
×
1061
            return new GraphQlDenormalizeProvider(
×
1062
                $this->app->make(ResolverProvider::class),
×
1063
                $app->make(SerializerInterface::class),
×
1064
                $app->make(GraphQlSerializerContextBuilder::class)
×
1065
            );
×
1066
        });
×
1067

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

1070
        $this->app->singleton('api_platform.graphql.state_provider.access_checker', function (Application $app) {
×
1071
            return new AccessCheckerProvider($app->make('api_platform.graphql.state_provider.parameter'), $app->make(ResourceAccessCheckerInterface::class));
×
1072
        });
×
1073

1074
        $this->app->singleton(NormalizeProcessor::class, function (Application $app) {
×
1075
            return new NormalizeProcessor(
×
1076
                $app->make(SerializerInterface::class),
×
1077
                $app->make(GraphQlSerializerContextBuilder::class),
×
1078
                $app->make(Pagination::class)
×
1079
            );
×
1080
        });
×
1081
        $this->app->alias(NormalizeProcessor::class, 'api_platform.graphql.state_processor.normalize');
×
1082

1083
        $this->app->singleton('api_platform.graphql.state_processor', function (Application $app) {
×
1084
            return new WriteProcessor(
×
1085
                $app->make('api_platform.graphql.state_processor.normalize'),
×
1086
                $app->make(CallableProcessor::class),
×
1087
            );
×
1088
        });
×
1089

1090
        $this->app->singleton(ResolverFactoryInterface::class, function (Application $app) {
×
1091
            return new ResolverFactory(
×
1092
                $app->make('api_platform.graphql.state_provider.access_checker'),
×
1093
                $app->make('api_platform.graphql.state_processor'),
×
1094
                $app->make('api_platform.graphql.runtime_operation_metadata_factory'),
×
1095
            );
×
1096
        });
×
1097

1098
        $this->app->singleton('api_platform.graphql.runtime_operation_metadata_factory', function (Application $app) {
×
1099
            return new RuntimeOperationMetadataFactory(
×
1100
                $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
1101
                $app->make(UrlGeneratorRouter::class)
×
1102
            );
×
1103
        });
×
1104

1105
        $this->app->singleton(SchemaBuilderInterface::class, function (Application $app) {
×
1106
            return new SchemaBuilder($app->make(ResourceNameCollectionFactoryInterface::class), $app->make(ResourceMetadataCollectionFactoryInterface::class), $app->make(TypesFactoryInterface::class), $app->make(TypesContainerInterface::class), $app->make(FieldsBuilderEnumInterface::class));
×
1107
        });
×
1108

1109
        $this->app->singleton(ErrorHandlerInterface::class, function () {
×
1110
            return new GraphQlErrorHandler();
×
1111
        });
×
1112

1113
        $this->app->singleton(ExecutorInterface::class, function (Application $app) {
×
1114
            /** @var ConfigRepository */
1115
            $config = $app['config'];
×
1116

1117
            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);
×
1118
        });
×
1119

1120
        $this->app->singleton(GraphiQlController::class, function (Application $app) {
×
1121
            /** @var ConfigRepository */
1122
            $config = $app['config'];
×
1123
            $prefix = $config->get('api-platform.defaults.route_prefix') ?? '';
×
1124

1125
            return new GraphiQlController($prefix);
×
1126
        });
×
1127

1128
        $this->app->singleton(GraphQlEntrypointController::class, function (Application $app) {
×
1129
            /** @var ConfigRepository */
1130
            $config = $app['config'];
×
1131

1132
            return new GraphQlEntrypointController(
×
1133
                $app->make(SchemaBuilderInterface::class),
×
1134
                $app->make(ExecutorInterface::class),
×
1135
                $app->make(GraphiQlController::class),
×
1136
                $app->make(SerializerInterface::class),
×
1137
                $app->make(ErrorHandlerInterface::class),
×
1138
                debug: $config->get('app.debug'),
×
1139
                negotiator: $app->make(Negotiator::class),
×
1140
                formats: $config->get('api-platform.formats')
×
1141
            );
×
1142
        });
×
1143

1144
        $this->app->singleton(
×
1145
            ExceptionHandlerInterface::class,
×
1146
            function (Application $app) {
×
1147
                /** @var ConfigRepository */
1148
                $config = $app['config'];
×
1149

1150
                return new ErrorHandler(
×
1151
                    $app,
×
1152
                    $app->make(ResourceMetadataCollectionFactoryInterface::class),
×
1153
                    $app->make(ApiPlatformController::class),
×
1154
                    $app->make(IdentifiersExtractorInterface::class),
×
1155
                    $app->make(ResourceClassResolverInterface::class),
×
1156
                    $app->make(Negotiator::class),
×
1157
                    $config->get('api-platform.exception_to_status'),
×
1158
                    $config->get('app.debug'),
×
1159
                    $config->get('api-platform.error_formats')
×
1160
                );
×
1161
            }
×
1162
        );
×
1163
    }
1164

1165
    /**
1166
     * Bootstrap services.
1167
     */
1168
    public function boot(): void
1169
    {
1170
        if ($this->app->runningInConsole()) {
×
1171
            $this->publishes([
×
1172
                __DIR__.'/config/api-platform.php' => $this->app->configPath('api-platform.php'),
×
1173
            ], 'api-platform-config');
×
1174

1175
            $this->publishes([
×
1176
                __DIR__.'/public' => $this->app->publicPath('vendor/api-platform'),
×
1177
            ], ['api-platform-assets', 'public']);
×
1178
        }
1179

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

1182
        $config = $this->app['config'];
×
1183

1184
        if ($config->get('api-platform.graphql.enabled')) {
×
1185
            $fieldsBuilder = $this->app->make(FieldsBuilderEnumInterface::class);
×
1186
            $typeBuilder = $this->app->make(ContextAwareTypeBuilderInterface::class);
×
1187
            $typeBuilder->setFieldsBuilderLocator(new ServiceLocator(['api_platform.graphql.fields_builder' => $fieldsBuilder]));
×
1188
        }
1189

1190
        $this->loadRoutesFrom(__DIR__.'/routes/api.php');
×
1191
    }
1192
}
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