1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* DB backend for use with a Postgres RDBMS like JSON querying syntax. |
5
|
|
|
* |
6
|
|
|
* @package silverstripe-jsontext |
7
|
|
|
* @subpackage models |
8
|
|
|
* @author Russell Michell <[email protected]> |
9
|
|
|
* @see {@link JSONBackend} |
10
|
|
|
* @see https://github.com/Peekmo/JsonPath/blob/master/tests/JsonStoreTest.php |
11
|
|
|
* @see http://goessner.net/articles/JsonPath/ |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
namespace JSONText\Backends; |
15
|
|
|
|
16
|
|
|
use JSONText\Exceptions\JSONTextException; |
17
|
|
|
use JSONText\Fields\JSONText; |
18
|
|
|
|
19
|
|
|
class PostgresJSONBackend extends JSONBackend |
20
|
|
|
{ |
21
|
|
|
/** |
22
|
|
|
* @inheritdoc |
23
|
|
|
*/ |
24
|
|
View Code Duplication |
public function matchOnInt() |
|
|
|
|
25
|
|
|
{ |
26
|
|
|
if (!is_int($this->operand)) { |
27
|
|
|
$msg = 'Non-integer passed to: ' . __FUNCTION__; |
28
|
|
|
throw new JSONTextException($msg); |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
$expr = '$.[' . $this->operand . ']'; |
32
|
|
|
$fetch = $this->jsonText->getJSONStore()->get($expr); |
33
|
|
|
$vals = array_values($fetch); |
34
|
|
|
|
35
|
|
|
if (isset($vals[0])) { |
36
|
|
|
return [$this->operand => $vals[0]]; |
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
return []; |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* @inheritdoc |
44
|
|
|
*/ |
45
|
|
View Code Duplication |
public function matchOnStr() |
|
|
|
|
46
|
|
|
{ |
47
|
|
|
if (!is_string($this->operand)) { |
48
|
|
|
$msg = 'Non-string passed to: ' . __FUNCTION__; |
49
|
|
|
throw new JSONTextException($msg); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
$expr = '$..' . $this->operand; |
53
|
|
|
$fetch = $this->jsonText->getJSONStore()->get($expr); |
54
|
|
|
$vals = array_values($fetch); |
55
|
|
|
|
56
|
|
|
if (isset($vals[0])) { |
57
|
|
|
return [$this->operand => $vals[0]]; |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
return []; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* @inheritdoc |
65
|
|
|
*/ |
66
|
|
|
public function matchOnPath() |
67
|
|
|
{ |
68
|
|
|
if (!is_string($this->operand) || !$this->jsonText->isJson($this->operand)) { |
69
|
|
|
$msg = 'Invalid JSON passed as operand on RHS.'; |
70
|
|
|
throw new JSONTextException($msg); |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
$operandAsArray = $this->jsonText->toArray($this->operand); |
74
|
|
|
|
75
|
|
|
// Empty is OK..could've been accidental... |
76
|
|
|
if (!count($operandAsArray)) { |
77
|
|
|
return []; |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
$keys = array_keys($operandAsArray); |
81
|
|
|
$vals = array_values($operandAsArray); |
82
|
|
|
if (count($keys) >1 || count($vals) >1) { |
83
|
|
|
$msg = 'Sorry. I can\'t handle complex operands.'; |
84
|
|
|
throw new JSONTextException($msg); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
$source = $this->jsonText->getStoreAsArray(); |
88
|
|
|
$sourceAsIterator = new \RecursiveIteratorIterator( |
89
|
|
|
new \RecursiveArrayIterator($source), |
90
|
|
|
\RecursiveIteratorIterator::SELF_FIRST |
91
|
|
|
); |
92
|
|
|
|
93
|
|
|
$data = []; |
94
|
|
|
foreach ($sourceAsIterator as $sourceKey => $sourceVal) { |
95
|
|
|
if ($keys[0] === $sourceKey && is_array($sourceVal) && !empty($sourceVal[$vals[0]])) { |
96
|
|
|
$data[] = $sourceVal[$vals[0]]; |
97
|
|
|
} |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
return $data; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
} |
104
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.