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

wol-soft / php-json-schema-model-generator / 23325740070

20 Mar 2026 01:53AM UTC coverage: 98.567% (-0.1%) from 98.693%
23325740070

Pull #115

github

Enno Woortmann
Document patternProperties type intersection behaviour in object.rst

Add a note to the Pattern Properties section explaining that when a
declared property name matches a pattern, both constraints apply
simultaneously (allOf semantics). Compatible types are narrowed to the
intersection; contradictory types throw SchemaException at generation time.
Pull Request #115: Type system (Type widening for compositions, union types)

360 of 370 new or added lines in 23 files covered. (97.3%)

5 existing lines in 5 files now uncovered.

3783 of 3838 relevant lines covered (98.57%)

546.14 hits per line

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

92.19
/src/Model/SchemaDefinition/SchemaDefinitionDictionary.php
1
<?php
2

3
declare(strict_types = 1);
4

5
namespace PHPModelGenerator\Model\SchemaDefinition;
6

7
use ArrayObject;
8
use PHPModelGenerator\Exception\SchemaException;
9
use PHPModelGenerator\Model\Schema;
10
use PHPModelGenerator\SchemaProcessor\SchemaProcessor;
11

12
/**
13
 * Class SchemaDefinitionDictionary
14
 *
15
 * @package PHPModelGenerator\Model\SchemaDefinition
16
 */
17
class SchemaDefinitionDictionary extends ArrayObject
18
{
19
    /** @var Schema[] */
20
    private array $parsedExternalFileSchemas = [];
21

22
    /**
23
     * SchemaDefinitionDictionary constructor.
24
     */
25
    public function __construct(private JsonSchema $schema)
2,071✔
26
    {
27
        parent::__construct();
2,071✔
28
    }
29

30
    /**
31
     * Set up the definition directory for the schema
32
     */
33
    public function setUpDefinitionDictionary(SchemaProcessor $schemaProcessor, Schema $schema): void {
2,063✔
34
        // attach the root node to the definition dictionary
35
        $this->addDefinition('#', new SchemaDefinition($schema->getJsonSchema(), $schemaProcessor, $schema));
2,063✔
36

37
        foreach ($schema->getJsonSchema()->getJson() as $key => $propertyEntry) {
2,063✔
38
            if (!is_array($propertyEntry)) {
2,063✔
39
                continue;
2,063✔
40
            }
41

42
            // add the root nodes of the schema to resolve path references
43
            $this->addDefinition(
2,048✔
44
                $key,
2,048✔
45
                new SchemaDefinition($schema->getJsonSchema()->withJson($propertyEntry), $schemaProcessor, $schema),
2,048✔
46
            );
2,048✔
47
        }
48

49
        $this->fetchDefinitionsById($schema->getJsonSchema(), $schemaProcessor, $schema);
2,063✔
50
    }
51

52
    /**
53
     * Fetch all schema definitions with an ID for direct references
54
     */
55
    protected function fetchDefinitionsById(
2,063✔
56
        JsonSchema $jsonSchema,
57
        SchemaProcessor $schemaProcessor,
58
        Schema $schema,
59
    ): void {
60
        $json = $jsonSchema->getJson();
2,063✔
61

62
        if (isset($json['$id'])) {
2,063✔
63
            $this->addDefinition(
315✔
64
                str_starts_with($json['$id'], '#') ? $json['$id'] : "#{$json['$id']}",
315✔
65
                new SchemaDefinition($jsonSchema, $schemaProcessor, $schema),
315✔
66
            );
315✔
67
        }
68

69
        foreach ($json as $item) {
2,063✔
70
            if (!is_array($item)) {
2,063✔
71
                continue;
2,063✔
72
            }
73

74
            $this->fetchDefinitionsById($jsonSchema->withJson($item), $schemaProcessor, $schema);
2,048✔
75
        }
76
    }
77

78
    /**
79
     * Add a partial schema definition to the schema
80
     *
81
     * @return $this
82
     */
83
    public function addDefinition(string $key, SchemaDefinition $definition): self
2,063✔
84
    {
85
        if (isset($this[$key])) {
2,063✔
86
            return $this;
869✔
87
        }
88

89
        $this[$key] = $definition;
2,063✔
90

91
        return $this;
2,063✔
92
    }
93

94
    /**
95
     * @throws SchemaException
96
     */
97
    public function getDefinition(string $key, SchemaProcessor $schemaProcessor, array &$path = []): ?SchemaDefinition
529✔
98
    {
99
        if (str_starts_with($key, '#') && strpos($key, '/')) {
529✔
100
            $path = explode('/', $key);
404✔
101
            array_shift($path);
404✔
102
            $key  = array_shift($path);
404✔
103
        }
104

105
        if (!isset($this[$key])) {
529✔
106
            if (strstr($key, '#', true)) {
192✔
107
                [$jsonSchemaFile, $externalKey] = explode('#', $key);
166✔
108
            } else {
109
                $jsonSchemaFile = $key;
26✔
110
                $externalKey = '';
26✔
111
            }
112

113
            if (array_key_exists($jsonSchemaFile, $this->parsedExternalFileSchemas)) {
192✔
UNCOV
114
                return $this->parsedExternalFileSchemas[$jsonSchemaFile]->getSchemaDictionary()->getDefinition(
×
115
                    "#$externalKey",
×
116
                    $schemaProcessor,
×
117
                    $path,
×
118
                );
×
119
            }
120

121
            return $jsonSchemaFile
192✔
122
                ? $this->parseExternalFile($jsonSchemaFile, "#$externalKey", $schemaProcessor, $path)
192✔
123
                : null;
185✔
124
        }
125

126
        return $this[$key] ?? null;
522✔
127
    }
128

129
    /**
130
     * @throws SchemaException
131
     */
132
    private function parseExternalFile(
192✔
133
        string $jsonSchemaFile,
134
        string $externalKey,
135
        SchemaProcessor $schemaProcessor,
136
        array &$path,
137
    ): ?SchemaDefinition {
138
        $jsonSchema = $schemaProcessor->getSchemaProvider()->getRef(
192✔
139
            $this->schema->getFile(),
192✔
140
            $this->schema->getJson()['$id'] ?? null,
192✔
141
            $jsonSchemaFile,
192✔
142
        );
192✔
143

144
        // set up a dummy schema to fetch the definitions from the external file
145
        $schema = new Schema(
185✔
146
            '',
185✔
147
            $schemaProcessor->getCurrentClassPath(),
185✔
148
            'ExternalSchema',
185✔
149
            $jsonSchema,
185✔
150
            new self($jsonSchema),
185✔
151
        );
185✔
152

153
        $schema->getSchemaDictionary()->setUpDefinitionDictionary($schemaProcessor, $schema);
185✔
154
        $this->parsedExternalFileSchemas[$jsonSchemaFile] = $schema;
185✔
155

156
        return $schema->getSchemaDictionary()->getDefinition($externalKey, $schemaProcessor, $path);
185✔
157
    }
158
}
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