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

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

09 Dec 2025 11:52AM UTC coverage: 98.624% (-0.01%) from 98.636%
20062523725

Pull #95

github

Enno Woortmann
Update docs, add test cases
Pull Request #95: Improve the resolving of references

65 of 66 new or added lines in 7 files covered. (98.48%)

1 existing line in 1 file now uncovered.

3440 of 3488 relevant lines covered (98.62%)

559.67 hits per line

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

97.67
/src/SchemaProvider/RefResolverTrait.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace PHPModelGenerator\SchemaProvider;
6

7
use PHPModelGenerator\Exception\SchemaException;
8
use PHPModelGenerator\Model\SchemaDefinition\JsonSchema;
9

10
trait RefResolverTrait
11
{
12
    public function getRef(string $currentFile, ?string $id, string $ref): JsonSchema
192✔
13
    {
14
        $jsonSchemaFilePath = $this->getFullRefURL($id ?? $currentFile, $ref)
192✔
15
            ?: $this->getLocalRefPath($currentFile, $ref);
186✔
16

17
        if ($jsonSchemaFilePath === null || !($jsonSchema = file_get_contents($jsonSchemaFilePath))) {
192✔
18
            throw new SchemaException("Reference to non existing JSON-Schema file $ref");
4✔
19
        }
20

21
        if (!($decodedJsonSchema = json_decode($jsonSchema, true))) {
185✔
NEW
22
            throw new SchemaException("Invalid JSON-Schema file $jsonSchemaFilePath");
×
23
        }
24

25
        return new JsonSchema($jsonSchemaFilePath, $decodedJsonSchema);
185✔
26
    }
27

28
    /**
29
     * Try to build a full URL to fetch the schema from utilizing the $id field of the schema
30
     */
31
    private function getFullRefURL(string $id, string $ref): ?string
192✔
32
    {
33
        if (filter_var($ref, FILTER_VALIDATE_URL)) {
192✔
34
            return $ref;
2✔
35
        }
36

37
        if (!filter_var($id, FILTER_VALIDATE_URL) || ($idURL = parse_url($id)) === false) {
191✔
38
            return null;
186✔
39
        }
40

41
        $baseURL = $idURL['scheme'] . '://' . $idURL['host'] . (isset($idURL['port']) ? ':' . $idURL['port'] : '');
5✔
42

43
        // root relative $ref
44
        if (str_starts_with($ref, '/')) {
5✔
45
            return $baseURL . $ref;
2✔
46
        }
47

48
        // relative $ref against the path of $id
49
        $segments = explode('/', rtrim(dirname($idURL['path'] ?? '/'), '/') . '/' . $ref);
4✔
50
        $output = [];
4✔
51

52
        foreach ($segments as $seg) {
4✔
53
            if ($seg === '' || $seg === '.') {
4✔
54
                continue;
4✔
55
            }
56
            if ($seg === '..') {
4✔
57
                array_pop($output);
2✔
58
                continue;
2✔
59
            }
60
            $output[] = $seg;
4✔
61
        }
62

63
        return $baseURL . '/' . implode('/', $output);
4✔
64
    }
65

66
    private function getLocalRefPath(string $currentFile, string $ref): ?string
186✔
67
    {
68
        $currentDir = dirname($currentFile);
186✔
69
        // windows compatibility
70
        $jsonSchemaFile = str_replace('\\', '/', $ref);
186✔
71

72
        // relative paths to the current location
73
        if (!str_starts_with($jsonSchemaFile, '/')) {
186✔
74
            $candidate = $currentDir . '/' . $jsonSchemaFile;
185✔
75

76
            return file_exists($candidate) ? $candidate : null;
185✔
77
        }
78

79
        // absolute paths: traverse up to find the context root directory
80
        $relative = ltrim($jsonSchemaFile, '/');
2✔
81

82
        $dir = $currentDir;
2✔
83
        while (true) {
2✔
84
            $candidate = $dir . '/' . $relative;
2✔
85
            if (file_exists($candidate)) {
2✔
86
                return $candidate;
1✔
87
            }
88

89
            $parent = dirname($dir);
2✔
90
            if ($parent === $dir) {
2✔
91
                break;
1✔
92
            }
93
            $dir = $parent;
2✔
94
        }
95

96
        return null;
1✔
97
    }
98
}
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