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

api-platform / core / 7142557150

08 Dec 2023 02:28PM UTC coverage: 36.003% (-1.4%) from 37.36%
7142557150

push

github

web-flow
fix(jsonld): remove link to ApiDocumentation when doc is disabled (#6029)

0 of 1 new or added line in 1 file covered. (0.0%)

2297 existing lines in 182 files now uncovered.

9992 of 27753 relevant lines covered (36.0%)

147.09 hits per line

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

95.65
/src/JsonLd/ContextBuilder.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\JsonLd;
15

16
use ApiPlatform\Metadata\Get;
17
use ApiPlatform\Metadata\HttpOperation;
18
use ApiPlatform\Metadata\IriConverterInterface;
19
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
20
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
21
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
22
use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface;
23
use ApiPlatform\Metadata\UrlGeneratorInterface;
24
use ApiPlatform\Metadata\Util\ClassInfoTrait;
25
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
26

27
/**
28
 * {@inheritdoc}
29
 *
30
 * @author Kévin Dunglas <dunglas@gmail.com>
31
 */
32
final class ContextBuilder implements AnonymousContextBuilderInterface
33
{
34
    use ClassInfoTrait;
35

36
    public const FORMAT = 'jsonld';
37

38
    public function __construct(private readonly ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, private readonly ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, private readonly PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, private readonly PropertyMetadataFactoryInterface $propertyMetadataFactory, private readonly UrlGeneratorInterface $urlGenerator, private readonly ?IriConverterInterface $iriConverter = null, private readonly ?NameConverterInterface $nameConverter = null)
39
    {
40
    }
2,499✔
41

42
    /**
43
     * {@inheritdoc}
44
     */
45
    public function getBaseContext(int $referenceType = UrlGeneratorInterface::ABS_URL): array
46
    {
47
        return [
129✔
48
            '@vocab' => $this->urlGenerator->generate('api_doc', ['_format' => self::FORMAT], UrlGeneratorInterface::ABS_URL).'#',
129✔
49
            'hydra' => self::HYDRA_NS,
129✔
50
        ];
129✔
51
    }
52

53
    /**
54
     * {@inheritdoc}
55
     */
56
    public function getEntrypointContext(int $referenceType = UrlGeneratorInterface::ABS_PATH): array
57
    {
58
        $context = $this->getBaseContext($referenceType);
3✔
59

60
        foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) {
3✔
61
            $shortName = $this->resourceMetadataFactory->create($resourceClass)[0]->getShortName();
3✔
62
            $resourceName = lcfirst($shortName);
3✔
63

64
            $context[$resourceName] = [
3✔
65
                '@id' => 'Entrypoint/'.$resourceName,
3✔
66
                '@type' => '@id',
3✔
67
            ];
3✔
68
        }
69

70
        return $context;
3✔
71
    }
72

73
    /**
74
     * {@inheritdoc}
75
     */
76
    public function getResourceContext(string $resourceClass, int $referenceType = UrlGeneratorInterface::ABS_PATH): array
77
    {
78
        /** @var HttpOperation $operation */
79
        $operation = $this->resourceMetadataFactory->create($resourceClass)->getOperation(null, false, true);
18✔
80
        if (null === $shortName = $operation->getShortName()) {
18✔
81
            return [];
×
82
        }
83

84
        if ($operation->getNormalizationContext()['iri_only'] ?? false) {
18✔
85
            $context = $this->getBaseContext($referenceType);
9✔
86
            $context['hydra:member']['@type'] = '@id';
9✔
87

88
            return $context;
9✔
89
        }
90

91
        return $this->getResourceContextWithShortname($resourceClass, $referenceType, $shortName, $operation);
9✔
92
    }
93

94
    /**
95
     * {@inheritdoc}
96
     */
97
    public function getResourceContextUri(string $resourceClass, int $referenceType = null): string
98
    {
99
        $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass)[0];
1,260✔
100
        if (null === $referenceType) {
1,260✔
101
            $referenceType = $resourceMetadata->getUrlGenerationStrategy();
1,260✔
102
        }
103

104
        return $this->urlGenerator->generate('api_jsonld_context', ['shortName' => $resourceMetadata->getShortName()], $referenceType ?? UrlGeneratorInterface::ABS_PATH);
1,260✔
105
    }
106

107
    /**
108
     * {@inheritdoc}
109
     */
110
    public function getAnonymousResourceContext(object $object, array $context = [], int $referenceType = UrlGeneratorInterface::ABS_PATH): array
111
    {
112
        $outputClass = $this->getObjectClass($object);
108✔
113
        $operation = $context['operation'] ?? new Get(shortName: (new \ReflectionClass($outputClass))->getShortName());
108✔
114
        $shortName = $operation->getShortName();
108✔
115

116
        $jsonLdContext = [
108✔
117
            '@context' => $this->getResourceContextWithShortname(
108✔
118
                $outputClass,
108✔
119
                $referenceType,
108✔
120
                $shortName
108✔
121
            ),
108✔
122
            '@type' => $shortName,
108✔
123
        ];
108✔
124

125
        if (isset($context['iri'])) {
108✔
UNCOV
126
            $jsonLdContext['@id'] = $context['iri'];
×
127
        } elseif (true === ($context['gen_id'] ?? true) && $this->iriConverter) {
108✔
128
            $jsonLdContext['@id'] = $this->iriConverter->getIriFromResource($object);
102✔
129
        }
130

131
        if ($context['has_context'] ?? false) {
108✔
132
            unset($jsonLdContext['@context']);
81✔
133
        }
134

135
        // here the object can be different from the resource given by the $context['api_resource'] value
136
        if (isset($context['api_resource'])) {
108✔
UNCOV
137
            $jsonLdContext['@type'] = $this->resourceMetadataFactory->create($this->getObjectClass($context['api_resource']))[0]->getShortName();
×
138
        }
139

140
        return $jsonLdContext;
108✔
141
    }
142

143
    private function getResourceContextWithShortname(string $resourceClass, int $referenceType, string $shortName, HttpOperation $operation = null): array
144
    {
145
        $context = $this->getBaseContext($referenceType);
117✔
146
        $propertyContext = $operation ? ['normalization_groups' => $operation->getNormalizationContext()['groups'] ?? null, 'denormalization_groups' => $operation->getDenormalizationContext()['groups'] ?? null] : ['normalization_groups' => [], 'denormalization_groups' => []];
117✔
147

148
        foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) {
117✔
149
            $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName, $propertyContext);
114✔
150

151
            if ($propertyMetadata->isIdentifier() && true !== $propertyMetadata->isWritable()) {
114✔
152
                continue;
57✔
153
            }
154

155
            $convertedName = $this->nameConverter ? $this->nameConverter->normalize($propertyName, $resourceClass, self::FORMAT) : $propertyName;
114✔
156
            $jsonldContext = $propertyMetadata->getJsonldContext() ?? [];
114✔
157

158
            if ($id = $propertyMetadata->getIris()) {
114✔
159
                $id = 1 === (is_countable($id) ? \count($id) : 0) ? $id[0] : $id;
3✔
160
            }
161

162
            if (!$id) {
114✔
163
                $id = sprintf('%s/%s', $shortName, $convertedName);
114✔
164
            }
165

166
            if (false === $propertyMetadata->isReadableLink()) {
114✔
167
                $jsonldContext += [
3✔
168
                    '@id' => $id,
3✔
169
                    '@type' => '@id',
3✔
170
                ];
3✔
171
            }
172

173
            if (empty($jsonldContext)) {
114✔
174
                $context[$convertedName] = $id;
111✔
175
            } else {
176
                $context[$convertedName] = $jsonldContext + [
6✔
177
                    '@id' => $id,
6✔
178
                ];
6✔
179
            }
180
        }
181

182
        return $context;
117✔
183
    }
184
}
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