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

JsonBehavior::encodeAttributes()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.3554
c 0
b 0
f 0
cc 5
nc 6
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
            if ($this->owner instanceof BaseActiveRecord) {
85
                if (!isset($this->owner->getDirtyAttributes()[$name])) {
86
                    continue;
87
                }
88
            }
89
            
90
            
91
            $value = $this->owner->{$name};
92
            
93
            if (is_array($value)) {
94
                $this->owner->{$name} = $this->jsonEncode($value);
95
            }
96
        }
97
    }
98
    
99
    /**
100
     * Decode all attributes from php to json.
101
     */
102
    public function decodeAttributes()
103
    {
104
        foreach ($this->attributes as $name) {
105
            $value = $this->owner->{$name};
106
            
107
            $this->owner->{$name} = $this->jsonDecode($value);
108
        }
109
    }
110
    /**
111
     * Encodes the given value into a JSON string.
112
     *
113
     * @param mixed $value This is commonly an array.
114
     * @return string
115
     */
116
    public function jsonEncode($value)
117
    {
118
        return Json::encode($value);
119
    }
120
    
121
    /**
122
     * Decodes the given JSON string into a PHP data structure.
123
     *
124
     * @param string $value
125
     * @return array
126
     */
127
    public function jsonDecode($value)
128
    {
129
        // data is already passed by array
130
        if (is_array($value)) {
131
            return $value;
132
        }
133
134
        return Json::decode($value);
135
    }
136
}
137