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

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

07 Jul 2026 09:31AM UTC coverage: 98.076%. First build
28856540538

Pull #157

github

wol-soft
Warn and skip on unevaluatedProperties dead cells + edge-case tests

UnevaluatedPropertiesValidatorFactory now consolidates all four
sibling shapes that leave the unevaluatedProperties bucket
permanently empty into a single deadCodeReason() helper:

- additionalProperties: true — every extra flows to the model but
  the accumulator does not credit it, so the validator would still
  fire and defeat the intent of `additionalProperties: true`.
- additionalProperties: {schema} — every extra is claimed and
  validated by additionalProperties; the unevaluated set is empty.
- additionalProperties: false — every extra is rejected before the
  post-composition phase, so the unevaluated validator never runs.
- denyAdditionalProperties() generator flag with additionalProperties
  absent — synthesises the same false shape at configuration time.

Each cell emits a distinct warning via the existing echo channel
so build-output greps can identify the specific dead shape, and
skips validator emission entirely.

Tests added:

- Object-side dead-code data provider covering all four shapes plus
  the denyAdditionalProperties() variant. Rows pass the
  GeneratorConfiguration directly (setOutputEnabled(true) on the
  base, chained with setDenyAdditionalProperties(true) on the deny
  row) so the test signature drops the closure/fallback boilerplate.
- testAdditionalFalseRejectsExtrasEvenWhenUnevaluatedSchemaWouldAccept
  proves the factory suppressed the validator: an extra that would
  satisfy the unevaluated integer schema is still rejected because
  additionalProperties: false runs first.
- testContradictoryInnerSchemaThrowsSchemaExceptionPointingAtFile
  pins that an unevaluatedProperties schema with contradictory allOf
  types surfaces via the existing "conflicting types" SchemaException
  path, with the file identifier preserved.
- testPropertyNamesRejectionPrecedesUnevaluated data-provider variant
  covering both direct-exception and error-collection modes. The
  re... (continued)
Pull Request #157: Unevaluated properties

712 of 774 new or added lines in 38 files covered. (91.99%)

7237 of 7379 relevant lines covered (98.08%)

563.49 hits per line

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

95.24
/src/Model/Validator/AdditionalPropertiesValidator.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace PHPModelGenerator\Model\Validator;
6

7
use PHPModelGenerator\Exception\Object\InvalidAdditionalPropertiesException;
8
use PHPModelGenerator\Exception\SchemaException;
9
use PHPModelGenerator\Model\Property\Property;
10
use PHPModelGenerator\Model\Property\PropertyInterface;
11
use PHPModelGenerator\Model\Schema;
12
use PHPModelGenerator\Model\SchemaDefinition\JsonSchema;
13
use PHPModelGenerator\PropertyProcessor\PropertyFactory;
14
use PHPModelGenerator\SchemaProcessor\SchemaProcessor;
15
use PHPModelGenerator\Utils\RenderHelper;
16

17
/**
18
 * Class AdditionalPropertiesValidator
19
 *
20
 * @package PHPModelGenerator\Model\Validator
21
 */
22
class AdditionalPropertiesValidator extends PropertyTemplateValidator
23
{
24
    protected const PROPERTY_NAME = 'additional property';
25

26
    protected const PROPERTIES_KEY = 'properties';
27
    protected const ADDITIONAL_PROPERTIES_KEY = 'additionalProperties';
28

29
    protected const EXCEPTION_CLASS = InvalidAdditionalPropertiesException::class;
30

31
    private readonly PropertyInterface $validationProperty;
32
    private bool $collectAdditionalProperties = false;
33

34
    /**
35
     * AdditionalPropertiesValidator constructor.
36
     *
37
     * @throws SchemaException
38
     */
39
    public function __construct(
139✔
40
        SchemaProcessor $schemaProcessor,
41
        Schema $schema,
42
        JsonSchema $propertiesStructure,
43
        ?string $propertyName = null,
44
    ) {
45
        $propertyFactory = new PropertyFactory();
139✔
46

47
        $this->validationProperty = $propertyFactory->create(
139✔
48
            $schemaProcessor,
139✔
49
            $schema,
139✔
50
            static::PROPERTY_NAME,
139✔
51
            $propertiesStructure->navigate(static::ADDITIONAL_PROPERTIES_KEY),
139✔
52
            true,
139✔
53
        );
139✔
54

55
        $this->validationProperty->onResolve(function (): void {
139✔
56
            $this->resolve();
139✔
57
        });
139✔
58

59
        $patternProperties = array_keys($schema->getJsonSchema()->getJson()['patternProperties'] ?? []);
139✔
60

61
        parent::__construct(
139✔
62
            new Property($propertyName ?? $schema->getClassName(), null, $propertiesStructure),
139✔
63
            DIRECTORY_SEPARATOR . 'Validator' . DIRECTORY_SEPARATOR . 'AdditionalProperties.phptpl',
139✔
64
            [
139✔
65
                'schema' => $schema,
139✔
66
                'validationProperty' => $this->validationProperty,
139✔
67
                'additionalProperties' => RenderHelper::varExportArray(
139✔
68
                    array_keys($propertiesStructure->getJson()[static::PROPERTIES_KEY] ?? []),
139✔
69
                ),
139✔
70
                'patternProperties' => $patternProperties
139✔
NEW
71
                    ? RenderHelper::varExportPcrePatterns($patternProperties)
×
NEW
72
                    : null,
×
73
                'generatorConfiguration' => $schemaProcessor->getGeneratorConfiguration(),
139✔
74
                'viewHelper' => new RenderHelper($schemaProcessor->getGeneratorConfiguration()),
139✔
75
                // by default don't collect additional property data
76
                'collectAdditionalProperties' => &$this->collectAdditionalProperties,
139✔
77
            ],
139✔
78
            static::EXCEPTION_CLASS,
139✔
79
            ['&$invalidProperties'],
139✔
80
        );
139✔
81
    }
82

83
    /**
84
     * @inheritDoc
85
     */
86
    public function getCheck(): string
139✔
87
    {
88
        $this->removeRequiredPropertyValidator($this->validationProperty);
139✔
89

90
        return parent::getCheck();
139✔
91
    }
92

93
    public function setCollectAdditionalProperties(bool $collectAdditionalProperties): void
97✔
94
    {
95
        $this->collectAdditionalProperties = $collectAdditionalProperties;
97✔
96
    }
97

98
    public function getValidationProperty(): PropertyInterface
97✔
99
    {
100
        return $this->validationProperty;
97✔
101
    }
102

103
    /**
104
     * Initialize all variables which are required to execute a property names validator
105
     */
106
    public function getValidatorSetUp(): string
139✔
107
    {
108
        return '
139✔
109
            $properties = $value;
110
            $invalidProperties = [];
111
        ';
139✔
112
    }
113
}
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