Completed
Pull Request — master (#11)
by
unknown
10:09 queued 08:38
created

functions.php ➔ is_relative_ref()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 0
cts 1
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace League\JsonReference;
4
5
//use Sabre\Uri;
6
use peterpostmann\uri;
7
8
/**
9
 * @param object|array $json
10
 *
11
 * @return Pointer
12
 */
13
function pointer(&$json)
14
{
15 24
    return new Pointer($json);
16
}
17
18
/**
19
 * Escape a JSON Pointer.
20
 *
21
 * @param  string $pointer
22
 * @return string
23
 */
24
function escape_pointer($pointer)
25
{
26
    return str_replace(['~', '/'], ['~0', '~1'], $pointer);
27
}
28
29
30
/**
31
 * Push a segment onto the given JSON Pointer.
32
 *
33
 * @param string   $pointer
34
 * @param string[] $segments
35
 *
36
 * @return string
37
 *
38
 */
39
function pointer_push($pointer, ...$segments)
40
{
41 50
    $segments = str_replace(['~', '/'], ['~0', '~1'], $segments);
42 50
    return ($pointer !== '/' ? $pointer : '') . '/' . implode('/', $segments);
43
}
44
45
/**
46
 * Removes the fragment from a reference.
47
 *
48
 * @param  string $ref
49
 * @return string
50
 */
51
function strip_fragment($ref)
52
{
53 44
    $fragment = uri\parse_uri($ref)['fragment'];
54
55 44
    return $fragment ? str_replace('#'.$fragment, '#', $ref) : $ref;
56
}
57
58
/**
59
 * Check if the reference contains a fragment and resolve
60
 * the pointer.  Otherwise returns the original schema.
61
 *
62
 * @param  string $ref
63
 * @param  object $schema
64
 *
65
 * @return object
66
 */
67
function resolve_fragment($ref, $schema)
68
{
69 44
    $fragment = uri\parse_uri($ref)['fragment'];
70
71 44
    if (!is_internal_ref($ref) && is_string($fragment)) {
72 8
        return (new Pointer($schema))->get($fragment);
73
    }
74
75 38
    return $schema;
76
}
77
78
/**
79
 * @param string $keyword
80
 * @param mixed  $value
81
 *
82
 * @return bool
83
 */
84
function is_ref($keyword, $value)
85
{
86 50
    return $keyword === '$ref' && is_string($value);
87
}
88
89
/**
90
 * Determine if a reference is relative.
91
 * A reference is relative if it does not being with a prefix.
92
 *
93
 * @param string $ref
94
 *
95
 * @return bool
96
 */
97
function is_relative_ref($ref)
98
{
99
    return !preg_match('#^.+\:\/\/.*#', $ref);
100
}
101
102
/**
103
 * @param string $value
104
 *
105
 * @return bool
106
 */
107
function is_internal_ref($value)
108
{
109 62
    return is_string($value) && substr($value, 0, 1) === '#';
110
}
111
112
/**
113
 * Parse an external reference returning the prefix and path.
114
 *
115
 * @param string $ref
116
 *
117
 * @return array
118
 *
119
 * @throws \InvalidArgumentException
120
 */
121
function parse_external_ref($ref)
122
{
123 48
    $components = uri\parse_uri($ref);
124
125 48
    if (!$components['_protocol']) {
126 2
        throw new \InvalidArgumentException(
127 2
            sprintf(
128
                'The path  "%s" was expected to be an external reference but is missing a prefix.  ' .
129 2
                'The schema path should start with a prefix i.e. "file://".',
130 1
                $ref
131 1
            )
132 1
        );
133
    }
134
135 46
    $prefix = $components['_protocol'] !== true ? $components['_protocol'] : 'file';
136 46
    $path   = $components['_ressource'];
137 46
    $parts  = explode('://', $path, 2);
138 46
    $path   = count($parts) === 2 ? $parts[1] : $path;
139
140 46
    return [$prefix, $path];
141
}
142
143
/**
144
 * Resolve the given id against the parent scope and return the resolved URI.
145
 *
146
 * @param string $id          The id to resolve.  This should be a valid relative or absolute URI.
147
 * @param string $parentScope The parent scope to resolve against.  Should be a valid URI or empty.
148
 *
149
 * @return string
150
 */
151
function resolve_uri($id, $parentScope)
152
{
153
    // If there is no parent scope, there is nothing to resolve against.
154 38
    if ($parentScope === '') {
155 10
        return $id;
156
    }
157
158 30
    return uri\resolve_uri($parentScope, $id);
159
}
160
161
/**
162
 * Recursively iterates over each value in the schema passing them to the callback function.
163
 * If the callback function returns true the value is returned into the result array, keyed by a JSON Pointer.
164
 *
165
 * @param mixed    $schema
166
 * @param callable $callback
167
 * @param string   $pointer
168
 *
169
 * @return array
170
 */
171
function schema_extract($schema, callable $callback, $pointer = '')
172
{
173 52
    $matches = [];
174
175 52
    if ($schema instanceof Reference || (!is_array($schema) && !is_object($schema))) {
176 18
        return $matches;
177
    }
178
179 52
    foreach ($schema as $keyword => $value) {
180 26
        switch (true) {
181 52
            case is_object($value):
182 46
                $matches = array_merge($matches, schema_extract($value, $callback, pointer_push($pointer, $keyword)));
183 46
                break;
184 52
            case is_array($value):
185 22
                foreach ($value as $k => $v) {
186 22
                    if ($callback($k, $v)) {
187
                        $matches[pointer_push($pointer, $keyword)] = $v;
188
                    } else {
189 22
                        $matches = array_merge(
190 22
                            $matches,
191 22
                            schema_extract($v, $callback, pointer_push($pointer, $keyword, $k))
192 11
                        );
193
                    }
194 11
                }
195 22
                break;
196 52
            case $callback($keyword, $value):
197 50
                $matches[$pointer] = $value;
198 51
                break;
199
        }
200 26
    }
201
202 52
    return $matches;
203
}
204
205
/**
206
 * @param object $schema
207
 * @param object $resolvedRef
208
 * @param string $path
209
 *
210
 * @return object
211
 */
212
function merge_ref($schema, $resolvedRef, $path = '')
213
{
214 48
    if ($path === '') {
215 6
        pointer($schema)->remove('$ref');
216 6
        foreach ($resolvedRef as $prop => $value) {
217 4
            pointer($schema)->set($prop, $value);
218 2
        }
219 4
        return $schema;
220
    }
221
222 42
    $pointer = new Pointer($schema);
223 42
    if ($pointer->has($path)) {
224 42
        $pointer->set($path, $resolvedRef);
225 21
    }
226 42
    return $schema;
227
}
228