Passed
Push — master ( 7ad944...9954d6 )
by Viacheslav
02:21
created

JsonPointer::escapeSegment()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
c 0
b 0
f 0
rs 9.4285
cc 2
eloc 4
nc 2
nop 2
1
<?php
2
3
namespace Swaggest\JsonDiff;
4
5
6
class JsonPointer
7
{
8
    /**
9
     * @param string $key
10
     * @param bool $isURIFragmentId
11
     * @return string
12
     */
13
    public static function escapeSegment($key, $isURIFragmentId = false)
14
    {
15
        if ($isURIFragmentId) {
16
            return str_replace(array('%2F', '%7E'), array('~0', '~1'), urlencode($key));
17
        } else {
18
            return str_replace(array('~', '/'), array('~0', '~1'), $key);
19
        }
20
    }
21
22
    /**
23
     * @param string $path
24
     * @return string[]
25
     * @throws Exception
26
     */
27
    public static function splitPath($path)
28
    {
29
        $pathItems = explode('/', $path);
30
        $first = array_shift($pathItems);
31
        $result = array();
32
        if ($first === '#') {
33
            foreach ($pathItems as $key) {
34
                $key = str_replace(array('~0', '~1'), array('~', '/'), urldecode($key));
35
                $result[] = $key;
36
            }
37
        } else {
38
            if ($first !== '') {
39
                throw new Exception('Path must start with "/": ' . $path);
40
            }
41
            foreach ($pathItems as $key) {
42
                $key = str_replace(array('~0', '~1'), array('~', '/'), $key);
43
                $result[] = $key;
44
            }
45
        }
46
        return $result;
47
    }
48
49
    /**
50
     * @param mixed $holder
51
     * @param string[] $pathItems
52
     * @param mixed $value
53
     */
54
    public static function add(&$holder, $pathItems, $value)
55
    {
56
        $ref = &$holder;
57
        while (null !== $key = array_shift($pathItems)) {
58
            if ($ref instanceof \stdClass) {
59
                $ref = &$ref->$key;
60
            } elseif ($ref === null
61
                && !is_int($key)
62
                && false === filter_var($key, FILTER_VALIDATE_INT)
63
            ) {
64
                $key = (string)$key;
65
                $ref = new \stdClass();
66
                $ref = &$ref->{$key};
67
            } else {
68
                $ref = &$ref[$key];
69
            }
70
        }
71
        $ref = $value;
72
    }
73
74
    private static function arrayKeyExists($key, array $a)
75
    {
76
        if (array_key_exists($key, $a)) {
77
            return true;
78
        }
79
        $key = (string)$key;
80
        foreach ($a as $k => $v) {
81
            if ((string)$k === $key) {
82
                return true;
83
            }
84
        }
85
        return false;
86
    }
87
88
    private static function arrayGet($key, array $a)
89
    {
90
        $key = (string)$key;
91
        foreach ($a as $k => $v) {
92
            if ((string)$k === $key) {
93
                return $v;
94
            }
95
        }
96
        return false;
97
    }
98
99
100
    /**
101
     * @param mixed $holder
102
     * @param string[] $pathItems
103
     * @return bool|mixed
104
     * @throws Exception
105
     */
106
    public static function get($holder, $pathItems)
107
    {
108
        $ref = $holder;
109
        while (null !== $key = array_shift($pathItems)) {
110
            if ($ref instanceof \stdClass) {
111
                $vars = (array)$ref;
112
                if (self::arrayKeyExists($key, $vars)) {
113
                    $ref = self::arrayGet($key, $vars);
114
                } else {
115
                    throw new Exception('Key not found: ' . $key);
116
                }
117
            } elseif (is_array($ref)) {
118
                if (self::arrayKeyExists($key, $ref)) {
119
                    $ref = $ref[$key];
120
                } else {
121
                    throw new Exception('Key not found: ' . $key);
122
                }
123
            } else {
124
                throw new Exception('Key not found: ' . $key);
125
            }
126
        }
127
        return $ref;
128
    }
129
130
    /**
131
     * @param mixed $holder
132
     * @param string[] $pathItems
133
     * @return mixed
134
     * @throws Exception
135
     */
136
    public static function remove(&$holder, $pathItems)
137
    {
138
        $ref = &$holder;
139
        while (null !== $key = array_shift($pathItems)) {
140
            $parent = &$ref;
141
            $refKey = $key;
142
            if ($ref instanceof \stdClass) {
143
                if (property_exists($ref, $key)) {
144
                    $ref = &$ref->$key;
145
                } else {
146
                    throw new Exception('Key not found: ' . $key);
147
                }
148
            } else {
149
                if (array_key_exists($key, $ref)) {
150
                    $ref = &$ref[$key];
151
                } else {
152
                    throw new Exception('Key not found: ' . $key);
153
                }
154
            }
155
        }
156
157
        if (isset($parent) && isset($refKey)) {
158
            if ($parent instanceof \stdClass) {
159
                unset($parent->$refKey);
160
            } else {
161
                unset($parent[$refKey]);
162
            }
163
        }
164
        return $ref;
165
    }
166
}