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

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

20 May 2026 10:28AM UTC coverage: 98.466% (-0.09%) from 98.554%
26158351968

Pull #128

github

wol-soft
Fix if/then/else branch conflict detection for null-typed and per-branch checks

IfValidatorFactory previously required both then and else branches to conflict
with the parent before throwing, and stripped null from parent type names — so a
null-typed branch against a non-null parent was silently accepted. Now each branch
is checked independently and null from isNullable() is included in the parent set.
getBranchTypeNames() distinguishes null-typed branches ({type: null}) from truly
untyped branches via getTypeHint(), so null-typed branches correctly intersect (or
conflict) with the parent type. CLAUDE.md extended with review-learning policy and
line-number-in-docblock rule. New test coverage for all affected edge cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pull Request #128: Filter composition ordering

772 of 792 new or added lines in 22 files covered. (97.47%)

5 existing lines in 3 files now uncovered.

5455 of 5540 relevant lines covered (98.47%)

592.57 hits per line

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

57.14
/src/Model/Property/PropertyProxy.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace PHPModelGenerator\Model\Property;
6

7
use PHPModelGenerator\Exception\SchemaException;
8
use PHPModelGenerator\Model\Attributes\PhpAttribute;
9
use PHPModelGenerator\Model\GeneratorConfiguration;
10
use PHPModelGenerator\Model\Schema;
11
use PHPModelGenerator\Model\SchemaDefinition\JsonSchema;
12
use PHPModelGenerator\Model\SchemaDefinition\ResolvedDefinitionsCollection;
13
use PHPModelGenerator\Model\Validator\PropertyValidatorInterface;
14
use PHPModelGenerator\PropertyProcessor\Decorator\Property\PropertyDecoratorInterface;
15
use PHPModelGenerator\PropertyProcessor\Decorator\TypeHint\TypeHintDecoratorInterface;
16

17
/**
18
 * Class PropertyProxy
19
 *
20
 * @package PHPModelGenerator\Model
21
 */
22
class PropertyProxy extends AbstractProperty
23
{
24
    /**
25
     * PropertyProxy constructor.
26
     *
27
     * @param string $name The name must be provided separately as the name is not bound to the structure of a
28
     * referenced schema. Consequently, two properties with different names can refer an identical schema utilizing the
29
     * PropertyProxy. By providing a name to each of the proxies the resulting properties will get the correct names.
30
     *
31
     * @throws SchemaException
32
     */
33
    public function __construct(
868✔
34
        string $name,
35
        JsonSchema $jsonSchema,
36
        protected ResolvedDefinitionsCollection $definitionsCollection,
37
        protected string $key,
38
    ) {
39
        parent::__construct($name, $jsonSchema);
868✔
40
    }
41

42
    /**
43
     * Get the property out of the resolved definitions collection to proxy function calls
44
     */
45
    protected function getProperty(): PropertyInterface
868✔
46
    {
47
        return $this->definitionsCollection->offsetGet($this->key);
868✔
48
    }
49

50
    /**
51
     * @inheritdoc
52
     */
53
    public function getType(bool $outputType = false): ?PropertyType
189✔
54
    {
55
        return $this->getProperty()->getType($outputType);
189✔
56
    }
57

58
    /**
59
     * @inheritdoc
60
     */
61
    public function setType(
×
62
        ?PropertyType $type = null,
63
        ?PropertyType $outputType = null,
64
        bool $reset = false,
65
    ): PropertyInterface {
66
        return $this->getProperty()->setType($type, $outputType, $reset);
×
67
    }
68

69
    /**
70
     * @inheritdoc
71
     */
72
    public function getTypeHint(bool $outputType = false, array $skipDecorators = []): string
396✔
73
    {
74
        return $this->getProperty()->getTypeHint($outputType, $skipDecorators);
396✔
75
    }
76

77
    /**
78
     * @inheritdoc
79
     */
80
    public function addTypeHintDecorator(TypeHintDecoratorInterface $typeHintDecorator): PropertyInterface
×
81
    {
82
        return $this->getProperty()->addTypeHintDecorator($typeHintDecorator);
×
83
    }
84

85
    /**
86
     * @inheritdoc
87
     */
88
    public function getDescription(): string
13✔
89
    {
90
        return $this->getProperty()->getDescription();
13✔
91
    }
92

93
    public function getComment(): ?string
13✔
94
    {
95
        return $this->getProperty()->getComment();
13✔
96
    }
97

98
    public function setComment(string $comment): PropertyInterface
×
99
    {
100
        $this->getProperty()->setComment($comment);
×
101

102
        return $this;
×
103
    }
104

105
    public function getExamples(): array
13✔
106
    {
107
        return $this->getProperty()->getExamples();
13✔
108
    }
109

110
    public function setExamples(array $examples): PropertyInterface
×
111
    {
112
        $this->getProperty()->setExamples($examples);
×
113

114
        return $this;
×
115
    }
116

117
    /**
118
     * @inheritdoc
119
     */
NEW
120
    public function addValidator(
×
121
        PropertyValidatorInterface $validator,
122
        int $priority = 99,
123
        ?string $sourceKey = null,
124
    ): PropertyInterface {
NEW
125
        return $this->getProperty()->addValidator($validator, $priority, $sourceKey);
×
126
    }
127

128
    /**
129
     * @inheritdoc
130
     */
131
    public function getValidators(): array
15✔
132
    {
133
        return $this->getProperty()->getValidators();
15✔
134
    }
135

136
    /**
137
     * @inheritdoc
138
     */
139
    public function filterValidators(callable $filter): PropertyInterface
856✔
140
    {
141
        return $this->getProperty()->filterValidators($filter);
856✔
142
    }
143

144
    /**
145
     * @inheritdoc
146
     */
147
    public function getOrderedValidators(): array
846✔
148
    {
149
        return array_map(
846✔
150
            fn(PropertyValidatorInterface $propertyValidator): PropertyValidatorInterface =>
846✔
151
                $propertyValidator->withProperty($this),
846✔
152
            $this->getProperty()->getOrderedValidators(),
846✔
153
        );
846✔
154
    }
155

156
    /**
157
     * @inheritdoc
158
     */
159
    public function addDecorator(PropertyDecoratorInterface $decorator): PropertyInterface
×
160
    {
161
        return $this->getProperty()->addDecorator($decorator);
×
162
    }
163

164
    /**
165
     * @inheritdoc
166
     */
167
    public function filterDecorators(callable $filter): PropertyInterface
×
168
    {
169
        return $this->getProperty()->filterDecorators($filter);
×
170
    }
171

172
    /**
173
     * @inheritdoc
174
     */
175
    public function resolveDecorator(string $input, bool $nestedProperty): string
673✔
176
    {
177
        foreach ($this->getProperty()->getDecorators() as $decorator) {
673✔
178
            $input = $decorator->decorate($input, $this, $nestedProperty);
673✔
179
        }
180

181
        return $input;
673✔
182
    }
183

184
    /**
185
     * @inheritdoc
186
     */
187
    public function getDecorators(): array
846✔
188
    {
189
        return $this->getProperty()->getDecorators();
846✔
190
    }
191

192
    /**
193
     * @inheritdoc
194
     */
195
    public function setRequired(bool $isPropertyRequired): PropertyInterface
×
196
    {
197
        return $this->getProperty()->setRequired($isPropertyRequired);
×
198
    }
199

200
    /**
201
     * @inheritdoc
202
     */
203
    public function isRequired(): bool
173✔
204
    {
205
        return $this->getProperty()->isRequired();
173✔
206
    }
207

208
    /**
209
     * @inheritdoc
210
     */
211
    public function setReadOnly(bool $isPropertyReadOnly): PropertyInterface
×
212
    {
213
        return $this->getProperty()->setReadOnly($isPropertyReadOnly);
×
214
    }
215

216
    /**
217
     * @inheritdoc
218
     */
219
    public function isReadOnly(): bool
13✔
220
    {
221
        return $this->getProperty()->isReadOnly();
13✔
222
    }
223

224
    /**
225
     * @inheritdoc
226
     */
227
    public function setWriteOnly(bool $isPropertyWriteOnly): PropertyInterface
×
228
    {
229
        return $this->getProperty()->setWriteOnly($isPropertyWriteOnly);
×
230
    }
231

232
    /**
233
     * @inheritdoc
234
     */
235
    public function isWriteOnly(): bool
13✔
236
    {
237
        return $this->getProperty()->isWriteOnly();
13✔
238
    }
239

240
    /**
241
     * @inheritdoc
242
     */
243
    public function setDefaultValue($defaultValue, bool $raw = false): PropertyInterface
×
244
    {
245
        return $this->getProperty()->setDefaultValue($defaultValue, $raw);
×
246
    }
247

248
    /**
249
     * @inheritdoc
250
     */
251
    public function getDefaultValue(): ?string
13✔
252
    {
253
        return $this->getProperty()->getDefaultValue();
13✔
254
    }
255

256
    /**
257
     * @inheritdoc
258
     */
259
    public function setNestedSchema(Schema $schema): PropertyInterface
×
260
    {
261
        return $this->getProperty()->setNestedSchema($schema);
×
262
    }
263

264
    /**
265
     * @inheritdoc
266
     */
267
    public function getNestedSchema(): ?Schema
780✔
268
    {
269
        return $this->getProperty()->getNestedSchema();
780✔
270
    }
271

272
    /**
273
     * @inheritdoc
274
     */
275
    public function getJsonSchema(): JsonSchema
×
276
    {
277
        return $this->getProperty()->getJsonSchema();
×
278
    }
279

280
    /**
281
     * @inheritdoc
282
     */
283
    public function setInternal(bool $isPropertyInternal): PropertyInterface
×
284
    {
285
        return $this->getProperty()->setInternal($isPropertyInternal);
×
286
    }
287

288
    /**
289
     * @inheritdoc
290
     */
291
    public function isInternal(): bool
13✔
292
    {
293
        return $this->getProperty()->isInternal();
13✔
294
    }
295

296
    /**
297
     * @inheritdoc
298
     */
299
    public function addAttribute(
×
300
        PhpAttribute $attribute,
301
        ?GeneratorConfiguration $generatorConfiguration = null,
302
        ?int $enablementFlag = null,
303
    ): static {
304
        $this->getProperty()->addAttribute($attribute);
×
305

306
        return $this;
×
307
    }
308

309
    /**
310
     * @inheritdoc
311
     */
312
    public function getAttributes(): array
13✔
313
    {
314
        return $this->getProperty()->getAttributes();
13✔
315
    }
316
}
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