Completed
Pull Request — master (#84)
by
unknown
13:04
created

Reference::getIterator()   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 0
dl 0
loc 4
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace League\JsonGuard;
4
5
use Closure;
6
7
/**
8
 * A Reference object represents an internal $ref in a JSON object.
9
 * Because JSON references can be circular, in-lining the reference is
10
 * impossible.  This object can be substituted for the $ref instead,
11
 * allowing lazy resolution of the $ref when needed.
12
 */
13
class Reference implements \JsonSerializable, \IteratorAggregate
14
{
15
    /**
16
     * A JSON object resulting from a json_decode call or a Closure.
17
     * If a closure is used it should resolve to a JSON object when called.
18
     *
19
     * @var object|Closure
20
     */
21
    private $schema;
22
23
    private $cached;
24
25
    /**
26
     * A valid JSON reference.  The reference should point to a location in $schema.
27
     * @see https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03
28
     *
29
     * @var string
30
     */
31
    private $ref;
32
33
    /**
34
     * @param object|Closure $schema
35 62
     * @param string         $ref
36
     */
37 62
    public function __construct($schema, $ref)
38 62
    {
39 62
        $this->schema = $schema;
40
        $this->ref    = $ref;
41
    }
42
43
    /**
44
     * Specify data which should be serialized to JSON.
45
     * Because a reference can be circular, references are always
46
     * re-serialized as the reference property instead of attempting
47
     * to inline the data.
48
     *
49
     * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
50
     *
51
     * @return mixed data which can be serialized by <b>json_encode</b>,
52 10
     * which is a value of any type other than a resource.
53
     */
54 10
    public function jsonSerialize()
55
    {
56
        return ['$ref' => $this->ref];
57
    }
58
59
    /**
60
     * Resolve the reference and return the data.
61
     *
62 58
     * @return mixed
63
     */
64 58
    public function resolve()
65 26
    {
66
        if (empty($this->cached)) {
67 44
            if ($this->schema instanceof Closure) {
68
                return $this->resolveExternalReference();
69
            }
70
71
            return $this->resolveInternalReference();
72
        }
73
74
        return $this->cached;
75 26
    }
76
77 26
    /**
78
     * Resolve an external reference and return the resolved schema.
79
     *
80
     * @return mixed The resolved schema
81
     */
82
    private function resolveExternalReference()
83
    {
84
        return call_user_func($this->schema);
85 44
    }
86
87 44
    /**
88 44
     * Resolve an internal reference and return the resolved schema.
89 44
     *
90
     * @return mixed The resolved schema
91
     */
92
    private function resolveInternalReference()
93
    {
94
        $path    = trim($this->ref, '#');
95
        $pointer = new Pointer($this->schema);
96
        return $pointer->get($path);
97
    }
98
99
    /**
100
     * Proxies property access to the underlying schema.
101 16
     *
102
     * @param  string $property
103 16
     *
104 16
     * @return mixed
105 14
     *
106
     * @throws \InvalidArgumentException
107
     */
108 2
    public function __get($property)
109
    {
110
        $schema = $this->resolve();
111
        if (isset($schema->$property)) {
112
            return $schema->$property;
113
        }
114
115
        throw new \InvalidArgumentException(sprintf('Unknown property "%s"', $property));
116
    }
117
118
    public function getIterator()
119
    {
120
        return new \ArrayIterator($this->resolve());
121
    }
122
}
123