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

api-platform / core / 14375359694

10 Apr 2025 08:01AM UTC coverage: 8.491% (+0.07%) from 8.425%
14375359694

push

github

web-flow
fix(hydra): use correctly enable_docs (#7062)

18 of 118 new or added lines in 5 files covered. (15.25%)

508 existing lines in 190 files now uncovered.

13401 of 157825 relevant lines covered (8.49%)

22.87 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'];
×
320
            $defaultContext = $config->get('api-platform.serializer', []);
×
321

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1189
        $this->loadRoutesFrom(__DIR__.'/routes/api.php');
×
1190
    }
1191
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc