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

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

14 Apr 2025 03:57PM UTC coverage: 98.564% (-0.2%) from 98.813%
14450158551

push

github

web-flow
Merge pull request #90 from szepeviktor/patch-1

Make use of GHA features

3295 of 3343 relevant lines covered (98.56%)

569.28 hits per line

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

94.74
/src/Model/Schema.php
1
<?php
2

3
declare(strict_types = 1);
4

5
namespace PHPModelGenerator\Model;
6

7
use PHPModelGenerator\Interfaces\JSONModelInterface;
8
use PHPModelGenerator\Model\Property\PropertyInterface;
9
use PHPModelGenerator\Model\SchemaDefinition\JsonSchema;
10
use PHPModelGenerator\Model\SchemaDefinition\JsonSchemaTrait;
11
use PHPModelGenerator\Model\SchemaDefinition\SchemaDefinitionDictionary;
12
use PHPModelGenerator\Model\Validator\AbstractComposedPropertyValidator;
13
use PHPModelGenerator\Model\Validator\PropertyValidatorInterface;
14
use PHPModelGenerator\Model\Validator\SchemaDependencyValidator;
15
use PHPModelGenerator\PropertyProcessor\Decorator\SchemaNamespaceTransferDecorator;
16
use PHPModelGenerator\SchemaProcessor\Hook\SchemaHookInterface;
17

18
/**
19
 * Class Schema
20
 *
21
 * @package PHPModelGenerator\Model
22
 */
23
class Schema
24
{
25
    use JsonSchemaTrait;
26

27
    /** @var string */
28
    protected $description;
29

30
    /** @var string[] */
31
    protected $traits = [];
32
    /** @var string[] */
33
    protected $interfaces = [];
34
    /** @var PropertyInterface[] The properties which are part of the class */
35
    protected $properties = [];
36
    /** @var MethodInterface[] */
37
    protected $methods = [];
38

39
    /** @var PropertyValidatorInterface[] A Collection of validators which must be applied
40
     *                                    before adding properties to the model
41
     */
42
    protected $baseValidators = [];
43
    /** @var string[] */
44
    protected $usedClasses = [];
45
    /** @var SchemaNamespaceTransferDecorator[] */
46
    protected $namespaceTransferDecorators = [];
47
    /** @var SchemaHookInterface[] */
48
    protected $schemaHooks = [];
49

50
    protected SchemaDefinitionDictionary $schemaDefinitionDictionary;
51

52
    private int $resolvedProperties = 0;
53
    /** @var callable[] */
54
    private array $onAllPropertiesResolvedCallbacks = [];
55

56
    /**
57
     * Schema constructor.
58
     */
59
    public function __construct(
1,974✔
60
        protected string $classPath,
61
        protected string $className,
62
        JsonSchema $schema,
63
        ?SchemaDefinitionDictionary $dictionary = null,
64
        protected bool $initialClass = false,
65
    ) {
66
        $this->jsonSchema = $schema;
1,974✔
67
        $this->schemaDefinitionDictionary = $dictionary ?? new SchemaDefinitionDictionary('');
1,974✔
68
        $this->description = $schema->getJson()['description'] ?? '';
1,974✔
69

70
        $this->addInterface(JSONModelInterface::class);
1,974✔
71
    }
72

73
    public function getClassName(): string
1,035✔
74
    {
75
        return $this->className;
1,035✔
76
    }
77

78
    public function getClassPath(): string
875✔
79
    {
80
        return $this->classPath;
875✔
81
    }
82

83
    public function getDescription(): string
1,891✔
84
    {
85
        return $this->description;
1,891✔
86
    }
87

88
    public function onAllPropertiesResolved(callable $callback): self
294✔
89
    {
90
        $this->resolvedProperties === count($this->properties)
294✔
91
            ? $callback()
294✔
92
            : $this->onAllPropertiesResolvedCallbacks[] = $callback;
×
93

94
        return $this;
294✔
95
    }
96

97
    /**
98
     * @return PropertyInterface[]
99
     */
100
    public function getProperties(): array
1,906✔
101
    {
102
        $hasSchemaDependencyValidator = static function (PropertyInterface $property): bool {
1,906✔
103
            foreach ($property->getValidators() as $validator) {
999✔
104
                if ($validator->getValidator() instanceof SchemaDependencyValidator) {
820✔
105
                    return true;
63✔
106
                }
107
            }
108

109
            return false;
999✔
110
        };
1,906✔
111

112
        // order the properties to make sure properties with a SchemaDependencyValidator are validated at the beginning
113
        // of the validation process for correct exception order of the messages
114
        usort(
1,906✔
115
            $this->properties,
1,906✔
116
            static function (
1,906✔
117
                PropertyInterface $property,
1,906✔
118
                PropertyInterface $comparedProperty,
1,906✔
119
            ) use ($hasSchemaDependencyValidator): int {
1,906✔
120
                $propertyHasSchemaDependencyValidator = $hasSchemaDependencyValidator($property);
999✔
121
                $comparedPropertyHasSchemaDependencyValidator = $hasSchemaDependencyValidator($comparedProperty);
999✔
122
                return $comparedPropertyHasSchemaDependencyValidator <=> $propertyHasSchemaDependencyValidator;
999✔
123
            },
1,906✔
124
        );
1,906✔
125

126
        return $this->properties;
1,906✔
127
    }
128

129
    public function addProperty(PropertyInterface $property): self
1,877✔
130
    {
131
        if (!isset($this->properties[$property->getName()])) {
1,877✔
132
            $this->properties[$property->getName()] = $property;
1,877✔
133

134
            $property->onResolve(function (): void {
1,877✔
135
                if (++$this->resolvedProperties === count($this->properties)) {
1,833✔
136
                    foreach ($this->onAllPropertiesResolvedCallbacks as $callback) {
1,833✔
137
                        $callback();
×
138

139
                        $this->onAllPropertiesResolvedCallbacks = [];
×
140
                    }
141
                }
142
            });
1,877✔
143
        } else {
144
            // TODO tests:
145
            // testConditionalObjectProperty
146
            // testInvalidConditionalObjectPropertyThrowsAnException
147
            // testInvalidValuesForMultipleValuesInCompositionThrowsAnException
148
          //  throw new SchemaException("Duplicate attribute name {$property->getName()}");
149
        }
150

151
        return $this;
1,877✔
152
    }
153

154
    /**
155
     * @return PropertyValidatorInterface[]
156
     */
157
    public function getBaseValidators(): array
1,906✔
158
    {
159
        return $this->baseValidators;
1,906✔
160
    }
161

162
    /**
163
     * Get the keys of all composition base validators
164
     */
165
    public function getCompositionValidatorKeys(): array
1,891✔
166
    {
167
        $keys = [];
1,891✔
168

169
        foreach ($this->baseValidators as $key => $validator) {
1,891✔
170
            if (is_a($validator, AbstractComposedPropertyValidator::class)) {
513✔
171
                $keys[] = $key;
206✔
172
            }
173
        }
174

175
        return $keys;
1,891✔
176
    }
177

178
    public function addBaseValidator(PropertyValidatorInterface $baseValidator): self
516✔
179
    {
180
        $this->baseValidators[] = $baseValidator;
516✔
181

182
        return $this;
516✔
183
    }
184

185
    public function getSchemaDictionary(): SchemaDefinitionDictionary
1,966✔
186
    {
187
        return $this->schemaDefinitionDictionary;
1,966✔
188
    }
189

190
    /**
191
     * Add a class to the schema which is required
192
     */
193
    public function addUsedClass(string $fqcn): self
1,974✔
194
    {
195
        $this->usedClasses[] = trim($fqcn, '\\');
1,974✔
196

197
        return $this;
1,974✔
198
    }
199

200
    public function addNamespaceTransferDecorator(SchemaNamespaceTransferDecorator $decorator): self
822✔
201
    {
202
        $this->namespaceTransferDecorators[] = $decorator;
822✔
203

204
        return $this;
822✔
205
    }
206

207
    /**
208
     * @param Schema[] $visitedSchema
209
     *
210
     * @return string[]
211
     */
212
    public function getUsedClasses(array $visitedSchema = []): array
1,891✔
213
    {
214
        $usedClasses = $this->usedClasses;
1,891✔
215

216
        foreach ($this->namespaceTransferDecorators as $decorator) {
1,891✔
217
            $usedClasses = array_merge($usedClasses, $decorator->resolve(array_merge($visitedSchema, [$this])));
820✔
218
        }
219

220
        return $usedClasses;
1,891✔
221
    }
222

223
    /**
224
     * @param string $methodKey An unique key in the scope of the schema to identify the method
225
     */
226
    public function addMethod(string $methodKey, MethodInterface $method): self
956✔
227
    {
228
        $this->methods[$methodKey] = $method;
956✔
229

230
        return $this;
956✔
231
    }
232

233
    /**
234
     * @return MethodInterface[]
235
     */
236
    public function getMethods(): array
1,891✔
237
    {
238
        return $this->methods;
1,891✔
239
    }
240

241
    public function hasMethod(string $methodKey): bool
686✔
242
    {
243
        return isset($this->methods[$methodKey]);
686✔
244
    }
245

246
    /**
247
     * @return string[]
248
     */
249
    public function getTraits(): array
1,891✔
250
    {
251
        return $this->traits;
1,891✔
252
    }
253

254
    public function addTrait(string $trait): self
43✔
255
    {
256
        $this->traits[] = $trait;
43✔
257
        $this->addUsedClass($trait);
43✔
258

259
        return $this;
43✔
260
    }
261

262
    /**
263
     * @return string[]
264
     */
265
    public function getInterfaces(): array
1,891✔
266
    {
267
        return $this->interfaces;
1,891✔
268
    }
269

270
    public function addInterface(string $interface): self
1,974✔
271
    {
272
        $this->interfaces[] = $interface;
1,974✔
273
        $this->addUsedClass($interface);
1,974✔
274

275
        return $this;
1,974✔
276
    }
277

278
    /**
279
     * Add an additional schema hook
280
     */
281
    public function addSchemaHook(SchemaHookInterface $schemaHook): self
1,905✔
282
    {
283
        $this->schemaHooks[] = $schemaHook;
1,905✔
284

285
        return $this;
1,905✔
286
    }
287

288
    /**
289
     * @return SchemaHookInterface[]
290
     */
291
    public function getSchemaHooks(): array
1,891✔
292
    {
293
        return $this->schemaHooks;
1,891✔
294
    }
295

296
    public function isInitialClass(): bool
×
297
    {
298
        return $this->initialClass;
×
299
    }
300
}
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