Passed
Push — master ( 618096...f2b69a )
by Thomas
02:57
created

EncryptedDBJson::pretty()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 1
c 1
b 0
f 1
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace LeKoala\Encrypt;
4
5
use SilverStripe\Forms\HiddenField;
6
use ParagonIE\CipherSweet\JsonFieldMap;
7
use ParagonIE\CipherSweet\EncryptedJsonField;
8
9
/**
10
 * A simple extension over EncryptedDBText that supports json
11
 * as a datastructure
12
 * The data is stored in a text field
13
 *
14
 * If you want to access array stuff, you need to use
15
 * $model->dbObject('myField')->toArray() or any other method
16
 *
17
 * This field is a great way to store serialized encrypted data
18
 */
19
class EncryptedDBJson extends EncryptedDBText
20
{
21
22
    /**
23
     * @return string
24
     */
25
    public function getJsonMap()
26
    {
27
        if (array_key_exists('map', $this->options)) {
28
            return $this->options['map'];
29
        }
30
        return null;
31
    }
32
33
    /**
34
     * We cannot search on json fields
35
     *
36
     * @param string $title
37
     * @return HiddenField
38
     */
39
    public function scaffoldSearchField($title = null)
40
    {
41
        return HiddenField::create($this->getName());
42
    }
43
44
    /**
45
     * Json data is not easily displayed
46
     *
47
     * @param string $title
48
     * @param string $params
49
     * @return HiddenField
50
     */
51
    public function scaffoldFormField($title = null, $params = null)
52
    {
53
        return HiddenField::create($this->getName());
54
    }
55
56
    /**
57
     * @return mixed
58
     */
59
    public function decode()
60
    {
61
        if (!$this->value) {
62
            return false;
63
        }
64
        return json_decode($this->value);
65
    }
66
67
    /**
68
     * @return array
69
     */
70
    public function decodeArray()
71
    {
72
        if (!$this->value) {
73
            return [];
74
        }
75
        return json_decode($this->value, JSON_OBJECT_AS_ARRAY);
0 ignored issues
show
Bug introduced by
LeKoala\Encrypt\JSON_OBJECT_AS_ARRAY of type integer is incompatible with the type boolean|null expected by parameter $associative of json_decode(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

75
        return json_decode($this->value, /** @scrutinizer ignore-type */ JSON_OBJECT_AS_ARRAY);
Loading history...
76
    }
77
78
    /**
79
     * @return array
80
     */
81
    public function toArray()
82
    {
83
        return $this->decodeArray();
84
    }
85
86
    /**
87
     * @return string
88
     */
89
    public function pretty()
90
    {
91
        return json_encode(json_decode($this->value), JSON_PRETTY_PRINT);
92
    }
93
94
    /**
95
     * @inheritDoc
96
     */
97
    public function saveInto($dataObject)
98
    {
99
        if ($this->value && is_array($this->value)) {
100
            $this->value = json_encode($this->value);
101
        }
102
        parent::saveInto($dataObject);
103
    }
104
105
    /**
106
     * Add a value
107
     *
108
     * @link https://stackoverflow.com/questions/7851590/array-set-value-using-dot-notation
109
     * @param string|array $key
110
     * @param string $value
111
     * @return $this
112
     */
113
    public function addValue($key, $value)
114
    {
115
        $currentValue = $this->decodeArray();
116
117
        if (!is_array($key)) {
118
            $key = [$key];
119
        }
120
        $arr = &$currentValue;
121
        foreach ($key as $idx) {
122
            if (!isset($arr[$idx])) {
123
                $arr[$idx] = [];
124
            }
125
            $arr = &$arr[$idx];
126
        }
127
        $arr = $value;
128
        return $this->setValue($currentValue);
129
    }
130
131
    /**
132
     * Internally, the value is always a json string
133
     *
134
     * @param mixed $value
135
     * @param DataObject $record
0 ignored issues
show
Bug introduced by
The type LeKoala\Encrypt\DataObject was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
136
     * @param boolean $markChanged
137
     * @return $this
138
     */
139
    public function setValue($value, $record = null, $markChanged = true)
140
    {
141
        $this->setEncryptionAad($record);
142
143
        // Not supported, we need decrypted values for methods to work properly
144
        // Return early if we keep encrypted value in memory
145
        // if (!EncryptHelper::getAutomaticDecryption()) {
146
        //     $this->value = $value;
147
        //     return $this;
148
        // }
149
150
        // Decrypt first if needed
151
        if ($this->getJsonMap() && $value && is_string($value)) {
152
            if (EncryptHelper::isJsonEncrypted($value)) {
153
                $aad = $this->encryptionAad;
154
                $value = json_encode($this->getEncryptedJsonField()->decryptJson($value, $aad));
155
            }
156
        }
157
        // Internally, we use a string
158
        if (is_array($value)) {
159
            $value = json_encode($value);
160
        }
161
162
        return parent::setValue($value, $record, $markChanged);
163
    }
164
165
    /**
166
     * @inheritDoc
167
     */
168
    public function prepValueForDB($value)
169
    {
170
        // We need an array to encrypt
171
        if ($this->getJsonMap() && $value && is_string($value)) {
172
            $value = $this->toArray();
173
        }
174
        if (is_array($value)) {
175
            if ($this->getJsonMap()) {
176
                $aad = $this->encryptionAad;
177
                $value = $this->getEncryptedJsonField()->encryptJson($value, $aad);
178
                return $value; // return early
179
            } else {
180
                $value = json_encode($value);
181
            }
182
        }
183
        return parent::prepValueForDB($value);
184
    }
185
186
    /**
187
     * We return false because we can accept array and convert it to string
188
     * @return boolean
189
     */
190
    public function scalarValueOnly()
191
    {
192
        return false;
193
    }
194
195
    /**
196
     * @param CipherSweet $engine
0 ignored issues
show
Bug introduced by
The type LeKoala\Encrypt\CipherSweet was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
197
     * @param JsonFieldMap $map
198
     * @return EncryptedJsonField
199
     */
200
    public function getEncryptedJsonField($engine = null, $map = null)
201
    {
202
        if ($engine === null) {
203
            $engine = EncryptHelper::getCipherSweet();
204
        }
205
        if ($map === null) {
206
            $mapString = $this->getJsonMap();
207
            $map = JsonFieldMap::fromString($mapString);
208
        }
209
        $encryptedField = EncryptedJsonField::create($engine, $map, $this->tableName, $this->name);
210
        return $encryptedField;
211
    }
212
}
213