Completed
Pull Request — master (#2007)
by Basil
02:19
created

JsonBehavior::decodeAttributes()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
3
namespace luya\behaviors;
4
5
use luya\helpers\Json;
6
use yii\base\Behavior;
7
use yii\db\ActiveRecord;
8
use yii\db\BaseActiveRecord;
9
10
/**
11
 * Json Behavior.
12
 *
13
 * Provides auto encoding for array values after validation in order to store in the database.
14
 * 
15
 * In order to work only with arrayable json values use:
16
 * 
17
 * ```php
18
 * public function behaviors()
19
 * {
20
 *     return [
21
 *         'json' => [
22
 *             'class' => JsonBehavior:class,
23
 *             'attributes' => ['json_field'],
24
 *             'encodeBeforeValidate' => true,
25
 *             'decodeAfterFind' => true,
26
 *         ]
27
 *     ];
28
 * }
29
 * 
30
 * public function rules()
31
 * {
32
 *     return [
33
 *         [['json_field', 'each', 'rule' => ['safe']]]
34
 *     ]
35
 * }
36
 * ```
37
 *
38
 * @author Basil Suter <[email protected]>
39
 * @since 1.0.9
40
 */
41
class JsonBehavior extends Behavior
42
{
43
    public $attributes = [];
44
45
    /**
46
     * @var boolean If enabled, the data will be encoded before validating, this means the validation rule should be `array` otherwise the validation must be `string`.
47
     * This might also differ based on how the data is passed to the model. Data passed to the model will be encoded from string to array (if not already).
48
     * @since 1.2.0 
49
     */
50
    public $encodeBeforeValidate = true;
51
52
    /**
53
     * @var boolean If enabled the data will be encoded from json to array after populating the active record data.
54
     * @since 1.2.0
55
     */
56
    public $decodeAfterFind = false;
57
    
58
    /**
59
     * @inheritdoc
60
     */
61
    public function events()
62
    {
63
        $events = [];
64
        if ($this->encodeBeforeValidate) {
65
            $events[ActiveRecord::EVENT_BEFORE_VALIDATE] = 'encodeAttributes';
66
        } else {
67
            $events[ActiveRecord::EVENT_AFTER_VALIDATE] = 'encodeAttributes';
68
        }
69
70
        if ($this->decodeAfterFind) {
71
            $events[ActiveRecord::EVENT_AFTER_FIND] = 'decodeAttributes';
72
        }
73
74
        return $events;
75
    }
76
    
77
    /**
78
     * Encode all attributes from json to php.
79
     */
80
    public function encodeAttributes()
81
    {
82
        foreach ($this->attributes as $name) {
83
84
            $value = $this->owner->{$name};
85
            
86
            if (is_array($value)) {
87
                $this->owner->{$name} = $this->jsonEncode($value);
88
            }
89
        }
90
    }
91
    
92
    /**
93
     * Decode all attributes from php to json.
94
     */
95
    public function decodeAttributes()
96
    {
97
        foreach ($this->attributes as $name) {
98
            $value = $this->owner->{$name};
99
            
100
            $this->owner->{$name} = $this->jsonDecode($value);
101
        }
102
    }
103
    /**
104
     * Encodes the given value into a JSON string.
105
     *
106
     * @param mixed $value This is commonly an array.
107
     * @return string
108
     */
109
    public function jsonEncode($value)
110
    {
111
        // if value is already a json, skip encoding and return result
112
        // ensure data is not doulble encoded or throws exception
113
        if (Json::isJson($value)) {
114
            return $value;
115
        }
116
117
        return Json::encode($value);
118
    }
119
    
120
    /**
121
     * Decodes the given JSON string into a PHP data structure.
122
     *
123
     * @param string $value
124
     * @return array
125
     */
126
    public function jsonDecode($value)
127
    {
128
        // data is already passed by array
129
        if (is_array($value)) {
130
            return $value;
131
        }
132
133
        return Json::decode($value);
134
    }
135
}
136