├── .gitignore
├── .scrutinizer.yml
├── .travis.yml
├── LICENSE
├── README.md
├── README.ru.md
├── composer.json
├── composer.lock
├── phpunit.xml.dist
├── src
├── JsonBehavior.php
├── JsonField.php
└── JsonValidator.php
└── tests
├── BehaviorTest.php
├── Item.php
├── ItemMerge.php
├── ItemRequired.php
├── TestMigration.php
└── bootstrap.php
/.gitignore:
--------------------------------------------------------------------------------
1 | # phpstorm project files
2 | .idea
3 |
4 | # windows thumbnail cache
5 | Thumbs.db
6 |
7 | # composer vendor dir
8 | /vendor
9 |
10 | # composer itself is not needed
11 | composer.phar
12 |
13 | # Mac DS_Store Files
14 | .DS_Store
15 |
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | tools:
2 | external_code_coverage:
3 | timeout: 2100
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | dist: trusty
3 |
4 | php:
5 | - 5.4
6 | - 5.5
7 | - 5.6
8 | - 7.1
9 | - 7.2
10 | - 7.3
11 | - 7.4
12 |
13 | sudo: false
14 |
15 | install:
16 | - composer self-update
17 | - composer update --prefer-dist --no-interaction
18 |
19 | before_script:
20 | - |
21 | if [ $TRAVIS_PHP_VERSION = '7.4' ]; then
22 | PHPUNIT_FLAGS="--coverage-clover=coverage.clover"
23 | fi
24 |
25 | script:
26 | - vendor/bin/phpunit $PHPUNIT_FLAGS
27 |
28 | after_script:
29 | - |
30 | if [ $TRAVIS_PHP_VERSION = '7.4' ]; then
31 | wget https://scrutinizer-ci.com/ocular.phar
32 | php ocular.phar code-coverage:upload --format=php-clover coverage.clover
33 | fi
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 PaulZi (pavel.zimakoff@gmail.com)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Yii2 json attribute behavior
2 |
3 | Auto decode/encode attribute value in json, provide array access and json validator.
4 |
5 | **WARNING! From version 2.0.14 Yii has built-in DB JSON-type, and this behavior is no longer required.**
6 |
7 | [Russian readme](https://github.com/paulzi/yii2-json-behavior/blob/master/README.ru.md)
8 |
9 | [](https://packagist.org/packages/paulzi/yii2-json-behavior)
10 | [](https://scrutinizer-ci.com/g/paulzi/yii2-json-behavior/?branch=master)
11 | [](https://scrutinizer-ci.com/g/paulzi/yii2-json-behavior/?branch=master)
12 | [](https://travis-ci.org/paulzi/yii2-json-behavior)
13 | [](https://packagist.org/packages/paulzi/yii2-json-behavior)
14 |
15 | ## Install
16 |
17 | Install via Composer:
18 |
19 | ```bash
20 | composer require paulzi/yii2-json-behavior
21 | ```
22 |
23 | or add
24 |
25 | ```bash
26 | "paulzi/yii2-json-behavior" : "~1.0.0"
27 | ```
28 |
29 | to the `require` section of your `composer.json` file.
30 |
31 | ## Usage
32 |
33 | ### JsonBehavior
34 |
35 | Configure your model:
36 |
37 | ```php
38 | use paulzi\jsonBehavior\JsonBehavior;
39 |
40 | class Item extends \yii\db\ActiveRecord
41 | {
42 | public function behaviors() {
43 | return [
44 | [
45 | 'class' => JsonBehavior::className(),
46 | 'attributes' => ['params'],
47 | ],
48 | ];
49 | }
50 | }
51 | ```
52 |
53 | Now you can access to attribute as array:
54 |
55 | ```php
56 | $item = Item::findOne(1);
57 | $item->params['one'] = 'two';
58 | $item->params['two'] = [];
59 | $item->params['two']['key'] = true;
60 | $item->save();
61 |
62 | $item = Item::findOne(1);
63 | echo $item['two']['key']; // true
64 | ```
65 |
66 | Set attribute via json string:
67 |
68 | ```php
69 | $item = new Item();
70 | $item->params->set('[2, 4, 42]');
71 | echo $item->params[2]; // 42
72 | ```
73 |
74 | Set attribute via array:
75 |
76 | ```php
77 | $item = new Item();
78 | $item->params->set(['test' => ['one' => 1]]);
79 | echo $item->params['test']['one']; // 1
80 | ```
81 |
82 | Convert to json string:
83 |
84 | ```php
85 | $item = new Item();
86 | $item->params['test'] = ['one' => false, 'two' => [1, 2, 3]];
87 | var_dump((string)$item->params); // {"one":false,"two":[1,2,3]}
88 | ```
89 |
90 | Convert to array:
91 |
92 | ```php
93 | $item = new Item();
94 | $item->params->set('{ "one": 1, "two": null, "three": false, "four": "four" }');
95 | var_dump($item->params->toArray());
96 | ```
97 |
98 | Check empty:
99 |
100 | ```php
101 | $item = new Item();
102 | $item->params->set('{}');
103 | var_dump($item->params->isEmpty()); // true
104 | ```
105 |
106 | #### emptyValue
107 |
108 | You can set `emptyValue` option to define an empty JSON value (default `null`). Can be `'{}'`, `'[]''` or `null`.
109 |
110 | ### JsonValidator
111 |
112 | Configure your model (see behavior config upper):
113 |
114 | ```php
115 | use paulzi\jsonBehavior\JsonValidator;
116 |
117 | class Item extends \yii\db\ActiveRecord
118 | {
119 | public function rules() {
120 | return [
121 | [['params'], JsonValidator::className()],
122 | ];
123 | }
124 | }
125 | ```
126 |
127 | Validate:
128 |
129 | ```php
130 | $item = new Item();
131 | $item->attributes = ['params' => '{ test: }'];
132 | var_dump($item->save()); // false
133 | var_dump($item->errors); // ['params' => ['Value is not valid JSON or scalar']]
134 | ```
135 |
136 | You can set `merge = true`, in this case, instead of replacing all field data of the transmitted data, `array_merge()` will be applied with old data in the field (which are taken from `oldAttributes` of ActiveRecord). This option can be apply only with ActiveRecord:
137 |
138 | ```php
139 | use paulzi\jsonBehavior\JsonValidator;
140 |
141 | class Item extends \yii\db\ActiveRecord
142 | {
143 | public function rules() {
144 | return [
145 | [['params'], JsonValidator::className(), 'merge' => true],
146 | ];
147 | }
148 | }
149 | ```
150 |
151 | ### JsonField
152 |
153 | You can use `JsonField` class for other models:
154 |
155 | ```php
156 | class Item
157 | {
158 | public $params;
159 |
160 | public function __constructor()
161 | {
162 | $this->params = new JsonField();
163 | }
164 | }
165 |
166 | // ...
167 |
168 | $item = new Item();
169 | $item->params['one'] = 1;
170 | var_dump((string)$item->params); // {"one":1}
171 | ```
172 |
173 | ## How To
174 |
175 | ### Usage isAttributeChanged() and getDirtyAttributes()
176 |
177 | Yii2 does not provide the ability to inject code to check attribute dirty.
178 |
179 | If you need to use methods `isAttributeChanged()` or `getDirtyAttributes()`, you can override them in model:
180 |
181 | ```php
182 | /**
183 | * @inheritdoc
184 | */
185 | public function isAttributeChanged($name, $identical = true)
186 | {
187 | if ($this->$name instanceof JsonField) {
188 | return (string)$this->$name !== $this->getOldAttribute($name);
189 | } else {
190 | return parent::isAttributeChanged($name, $identical);
191 | }
192 | }
193 |
194 | /**
195 | * @inheritdoc
196 | */
197 | public function getDirtyAttributes($names = null)
198 | {
199 | $result = [];
200 | $data = parent::getDirtyAttributes($names);
201 | foreach ($data as $name => $value) {
202 | if ($value instanceof JsonField) {
203 | if ((string)$value !== $this->getOldAttribute($name)) {
204 | $result[$name] = $value;
205 | }
206 | } else {
207 | $result[$name] = $value;
208 | }
209 | }
210 | return $result;
211 | }
212 | ```
--------------------------------------------------------------------------------
/README.ru.md:
--------------------------------------------------------------------------------
1 | # Yii2 json attribute behavior
2 |
3 | Автоматически призводит кодирование/декодирование атрибутов в формат json, предоставляет доступ как к массиву и валидацию json.
4 |
5 | **ВНИМАНИЕ! Начиная с версии 2.0.14 Yii имеет встроенную поддержку JSON-типов в БД, и данное поведение больше не будет работать с такими полями.**
6 |
7 | [English readme](https://github.com/paulzi/yii2-json-behavior/)
8 |
9 | [](https://packagist.org/packages/paulzi/yii2-json-behavior)
10 | [](https://scrutinizer-ci.com/g/paulzi/yii2-json-behavior/?branch=master)
11 | [](https://scrutinizer-ci.com/g/paulzi/yii2-json-behavior/?branch=master)
12 | [](https://travis-ci.org/paulzi/yii2-json-behavior)
13 | [](https://packagist.org/packages/paulzi/yii2-json-behavior)
14 |
15 | ## Установка
16 |
17 | Установка через Composer:
18 |
19 | ```bash
20 | composer require paulzi/yii2-json-behavior
21 | ```
22 |
23 | или добавьте
24 |
25 | ```bash
26 | "paulzi/yii2-json-behavior" : "~1.0.0"
27 | ```
28 |
29 | в секцию `require` в вашем `composer.json` файле.
30 |
31 | ## Использование
32 |
33 | ### JsonBehavior
34 |
35 | Настройте вашу модель:
36 |
37 | ```php
38 | use paulzi\jsonBehavior\JsonBehavior;
39 |
40 | class Item extends \yii\db\ActiveRecord
41 | {
42 | public function behaviors() {
43 | return [
44 | [
45 | 'class' => JsonBehavior::className(),
46 | 'attributes' => ['params'],
47 | ],
48 | ];
49 | }
50 | }
51 | ```
52 |
53 | Теперь вы можете обращаться к атрибуту как к массиву:
54 |
55 | ```php
56 | $item = Item::findOne(1);
57 | $item->params['one'] = 'two';
58 | $item->params['two'] = [];
59 | $item->params['two']['key'] = true;
60 | $item->save();
61 |
62 | $item = Item::findOne(1);
63 | echo $item['two']['key']; // true
64 | ```
65 |
66 | Установка значения атрибута через JSON-строку:
67 |
68 | ```php
69 | $item = new Item();
70 | $item->params->set('[2, 4, 42]');
71 | echo $item->params[2]; // 42
72 | ```
73 |
74 | Установка значения атрибута через массив:
75 |
76 | ```php
77 | $item = new Item();
78 | $item->params->set(['test' => ['one' => 1]]);
79 | echo $item->params['test']['one']; // 1
80 | ```
81 |
82 | Получение значения в виде JSON-строки:
83 |
84 | ```php
85 | $item = new Item();
86 | $item->params['test'] = ['one' => false, 'two' => [1, 2, 3]];
87 | var_dump((string)$item->params); // {"one":false,"two":[1,2,3]}
88 | ```
89 |
90 | Получение значения в виде массива:
91 |
92 | ```php
93 | $item = new Item();
94 | $item->params->set('{ "one": 1, "two": null, "three": false, "four": "four" }');
95 | var_dump($item->params->toArray());
96 | ```
97 |
98 | Проверка на пустоту:
99 |
100 | ```php
101 | $item = new Item();
102 | $item->params->set('{}');
103 | var_dump($item->params->isEmpty()); // true
104 | ```
105 |
106 | #### emptyValue
107 |
108 | Вы можете задать опцию `emptyValue` для определения значения для пустого JSON (по умолчанию `null`). Может принимать значения `'{}'`, `'[]''` или `null`.
109 |
110 | ### JsonValidator
111 |
112 | Настройте дополнительно модель (подключение поведения описано выше):
113 |
114 | ```php
115 | use paulzi\jsonBehavior\JsonValidator;
116 |
117 | class Item extends \yii\db\ActiveRecord
118 | {
119 | public function rules() {
120 | return [
121 | [['params'], JsonValidator::className()],
122 | ];
123 | }
124 | }
125 | ```
126 |
127 | Валидация:
128 |
129 | ```php
130 | $item = new Item();
131 | $item->attributes = ['params' => '{ test: }'];
132 | var_dump($item->save()); // false
133 | var_dump($item->errors); // ['params' => ['Value is not valid JSON or scalar']]
134 | ```
135 |
136 | В качестве опции можно передать `merge = true`, в этом случае вместо замены всего значения поля переданными данными, будет осуществлен `array_merge()` со старыми данными в поле (которые берутся из `oldAttributes` ActiveRecord). Данный параметр применим только для ActiveRecord:
137 |
138 | ```php
139 | use paulzi\jsonBehavior\JsonValidator;
140 |
141 | class Item extends \yii\db\ActiveRecord
142 | {
143 | public function rules() {
144 | return [
145 | [['params'], JsonValidator::className(), 'merge' => true],
146 | ];
147 | }
148 | }
149 | ```
150 |
151 | ### JsonField
152 |
153 | Вы можете использовать класс `JsonField` для других моделей:
154 |
155 | ```php
156 | class Item
157 | {
158 | public $params;
159 |
160 | public function __constructor()
161 | {
162 | $this->params = new JsonField();
163 | }
164 | }
165 |
166 | // ...
167 |
168 | $item = new Item();
169 | $item->params['one'] = 1;
170 | var_dump((string)$item->params); // {"one":1}
171 | ```
172 |
173 | ## How To
174 |
175 | ### Использование методов isAttributeChanged() and getDirtyAttributes()
176 |
177 | Yii2 не предоставляет возможности для внедрения стороннего кода при выполнении проверки `dirty` атрибута.
178 |
179 | Если вам необходимо использовать методы `isAttributeChanged()` или `getDirtyAttributes()`, вы можете переопределить их в модели:
180 |
181 | ```php
182 | /**
183 | * @inheritdoc
184 | */
185 | public function isAttributeChanged($name, $identical = true)
186 | {
187 | if ($this->$name instanceof JsonField) {
188 | return (string)$this->$name !== $this->getOldAttribute($name);
189 | } else {
190 | return parent::isAttributeChanged($name, $identical);
191 | }
192 | }
193 |
194 | /**
195 | * @inheritdoc
196 | */
197 | public function getDirtyAttributes($names = null)
198 | {
199 | $result = [];
200 | $data = parent::getDirtyAttributes($names);
201 | foreach ($data as $name => $value) {
202 | if ($value instanceof JsonField) {
203 | if ((string)$value !== $this->getOldAttribute($name)) {
204 | $result[$name] = $value;
205 | }
206 | } else {
207 | $result[$name] = $value;
208 | }
209 | }
210 | return $result;
211 | }
212 | ```
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "paulzi/yii2-json-behavior",
3 | "description": "Yii2 json attribute behavior",
4 | "keywords": ["yii2", "json", "behavior", "validator"],
5 | "type": "yii2-extension",
6 | "license": "MIT",
7 | "support": {
8 | "issues": "https://github.com/paulzi/yii2-json-behavior/issues?state=open",
9 | "source": "https://github.com/paulzi/yii2-json-behavior"
10 | },
11 | "authors": [
12 | {
13 | "name": "PaulZi",
14 | "email": "pavel.zimakoff@gmail.com"
15 | }
16 | ],
17 | "minimum-stability": "stable",
18 | "require": {
19 | "php": ">=5.4.0",
20 | "yiisoft/yii2": "~2.0.0"
21 | },
22 | "require-dev": {
23 | "phpunit/phpunit": "~4.0"
24 | },
25 | "repositories": [
26 | {
27 | "type": "composer",
28 | "url": "https://asset-packagist.org"
29 | }
30 | ],
31 | "autoload": {
32 | "psr-4": {
33 | "paulzi\\jsonBehavior\\": "./src"
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "c1bbc962c0fb59d89af3417a5710d157",
8 | "packages": [
9 | {
10 | "name": "bower-asset/inputmask",
11 | "version": "3.3.10",
12 | "source": {
13 | "type": "git",
14 | "url": "https://github.com/RobinHerbots/Inputmask.git",
15 | "reference": "14873e5775964275d13621cbe2b52e4448af3707"
16 | },
17 | "dist": {
18 | "type": "zip",
19 | "url": "https://api.github.com/repos/RobinHerbots/Inputmask/zipball/14873e5775964275d13621cbe2b52e4448af3707",
20 | "reference": "14873e5775964275d13621cbe2b52e4448af3707",
21 | "shasum": null
22 | },
23 | "require": {
24 | "bower-asset/jquery": ">=1.7"
25 | },
26 | "type": "bower-asset",
27 | "license": [
28 | "http://opensource.org/licenses/mit-license.php"
29 | ]
30 | },
31 | {
32 | "name": "bower-asset/jquery",
33 | "version": "3.2.1",
34 | "source": {
35 | "type": "git",
36 | "url": "https://github.com/jquery/jquery-dist.git",
37 | "reference": "77d2a51d0520d2ee44173afdf4e40a9201f5964e"
38 | },
39 | "dist": {
40 | "type": "zip",
41 | "url": "https://api.github.com/repos/jquery/jquery-dist/zipball/77d2a51d0520d2ee44173afdf4e40a9201f5964e",
42 | "reference": "77d2a51d0520d2ee44173afdf4e40a9201f5964e",
43 | "shasum": null
44 | },
45 | "type": "bower-asset",
46 | "license": [
47 | "MIT"
48 | ]
49 | },
50 | {
51 | "name": "bower-asset/punycode",
52 | "version": "v1.3.2",
53 | "source": {
54 | "type": "git",
55 | "url": "https://github.com/bestiejs/punycode.js.git",
56 | "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3"
57 | },
58 | "dist": {
59 | "type": "zip",
60 | "url": "https://api.github.com/repos/bestiejs/punycode.js/zipball/38c8d3131a82567bfef18da09f7f4db68c84f8a3",
61 | "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3",
62 | "shasum": ""
63 | },
64 | "type": "bower-asset-library",
65 | "extra": {
66 | "bower-asset-main": "punycode.js",
67 | "bower-asset-ignore": [
68 | "coverage",
69 | "tests",
70 | ".*",
71 | "component.json",
72 | "Gruntfile.js",
73 | "node_modules",
74 | "package.json"
75 | ]
76 | }
77 | },
78 | {
79 | "name": "bower-asset/yii2-pjax",
80 | "version": "2.0.7.1",
81 | "source": {
82 | "type": "git",
83 | "url": "https://github.com/yiisoft/jquery-pjax.git",
84 | "reference": "aef7b953107264f00234902a3880eb50dafc48be"
85 | },
86 | "dist": {
87 | "type": "zip",
88 | "url": "https://api.github.com/repos/yiisoft/jquery-pjax/zipball/aef7b953107264f00234902a3880eb50dafc48be",
89 | "reference": "aef7b953107264f00234902a3880eb50dafc48be",
90 | "shasum": null
91 | },
92 | "require": {
93 | "bower-asset/jquery": ">=1.8"
94 | },
95 | "type": "bower-asset",
96 | "license": [
97 | "MIT"
98 | ]
99 | },
100 | {
101 | "name": "cebe/markdown",
102 | "version": "1.1.2",
103 | "source": {
104 | "type": "git",
105 | "url": "https://github.com/cebe/markdown.git",
106 | "reference": "25b28bae8a6f185b5030673af77b32e1163d5c6e"
107 | },
108 | "dist": {
109 | "type": "zip",
110 | "url": "https://api.github.com/repos/cebe/markdown/zipball/25b28bae8a6f185b5030673af77b32e1163d5c6e",
111 | "reference": "25b28bae8a6f185b5030673af77b32e1163d5c6e",
112 | "shasum": ""
113 | },
114 | "require": {
115 | "lib-pcre": "*",
116 | "php": ">=5.4.0"
117 | },
118 | "require-dev": {
119 | "cebe/indent": "*",
120 | "facebook/xhprof": "*@dev",
121 | "phpunit/phpunit": "4.1.*"
122 | },
123 | "bin": [
124 | "bin/markdown"
125 | ],
126 | "type": "library",
127 | "extra": {
128 | "branch-alias": {
129 | "dev-master": "1.1.x-dev"
130 | }
131 | },
132 | "autoload": {
133 | "psr-4": {
134 | "cebe\\markdown\\": ""
135 | }
136 | },
137 | "notification-url": "https://packagist.org/downloads/",
138 | "license": [
139 | "MIT"
140 | ],
141 | "authors": [
142 | {
143 | "name": "Carsten Brandt",
144 | "email": "mail@cebe.cc",
145 | "homepage": "http://cebe.cc/",
146 | "role": "Creator"
147 | }
148 | ],
149 | "description": "A super fast, highly extensible markdown parser for PHP",
150 | "homepage": "https://github.com/cebe/markdown#readme",
151 | "keywords": [
152 | "extensible",
153 | "fast",
154 | "gfm",
155 | "markdown",
156 | "markdown-extra"
157 | ],
158 | "time": "2017-07-16T21:13:23+00:00"
159 | },
160 | {
161 | "name": "ezyang/htmlpurifier",
162 | "version": "v4.9.3",
163 | "source": {
164 | "type": "git",
165 | "url": "https://github.com/ezyang/htmlpurifier.git",
166 | "reference": "95e1bae3182efc0f3422896a3236e991049dac69"
167 | },
168 | "dist": {
169 | "type": "zip",
170 | "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/95e1bae3182efc0f3422896a3236e991049dac69",
171 | "reference": "95e1bae3182efc0f3422896a3236e991049dac69",
172 | "shasum": ""
173 | },
174 | "require": {
175 | "php": ">=5.2"
176 | },
177 | "require-dev": {
178 | "simpletest/simpletest": "^1.1"
179 | },
180 | "type": "library",
181 | "autoload": {
182 | "psr-0": {
183 | "HTMLPurifier": "library/"
184 | },
185 | "files": [
186 | "library/HTMLPurifier.composer.php"
187 | ]
188 | },
189 | "notification-url": "https://packagist.org/downloads/",
190 | "license": [
191 | "LGPL"
192 | ],
193 | "authors": [
194 | {
195 | "name": "Edward Z. Yang",
196 | "email": "admin@htmlpurifier.org",
197 | "homepage": "http://ezyang.com"
198 | }
199 | ],
200 | "description": "Standards compliant HTML filter written in PHP",
201 | "homepage": "http://htmlpurifier.org/",
202 | "keywords": [
203 | "html"
204 | ],
205 | "time": "2017-06-03T02:28:16+00:00"
206 | },
207 | {
208 | "name": "yiisoft/yii2",
209 | "version": "2.0.13",
210 | "source": {
211 | "type": "git",
212 | "url": "https://github.com/yiisoft/yii2-framework.git",
213 | "reference": "9f82b8f0df9adb4b8a410be5aaa97818153689d9"
214 | },
215 | "dist": {
216 | "type": "zip",
217 | "url": "https://api.github.com/repos/yiisoft/yii2-framework/zipball/9f82b8f0df9adb4b8a410be5aaa97818153689d9",
218 | "reference": "9f82b8f0df9adb4b8a410be5aaa97818153689d9",
219 | "shasum": ""
220 | },
221 | "require": {
222 | "bower-asset/inputmask": "~3.2.2 | ~3.3.5",
223 | "bower-asset/jquery": "3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable",
224 | "bower-asset/punycode": "1.3.*",
225 | "bower-asset/yii2-pjax": "~2.0.1",
226 | "cebe/markdown": "~1.0.0 | ~1.1.0",
227 | "ext-ctype": "*",
228 | "ext-mbstring": "*",
229 | "ezyang/htmlpurifier": "~4.6",
230 | "lib-pcre": "*",
231 | "php": ">=5.4.0",
232 | "yiisoft/yii2-composer": "~2.0.4"
233 | },
234 | "bin": [
235 | "yii"
236 | ],
237 | "type": "library",
238 | "extra": {
239 | "branch-alias": {
240 | "dev-master": "2.0.x-dev"
241 | }
242 | },
243 | "autoload": {
244 | "psr-4": {
245 | "yii\\": ""
246 | }
247 | },
248 | "notification-url": "https://packagist.org/downloads/",
249 | "license": [
250 | "BSD-3-Clause"
251 | ],
252 | "authors": [
253 | {
254 | "name": "Qiang Xue",
255 | "email": "qiang.xue@gmail.com",
256 | "homepage": "http://www.yiiframework.com/",
257 | "role": "Founder and project lead"
258 | },
259 | {
260 | "name": "Alexander Makarov",
261 | "email": "sam@rmcreative.ru",
262 | "homepage": "http://rmcreative.ru/",
263 | "role": "Core framework development"
264 | },
265 | {
266 | "name": "Maurizio Domba",
267 | "homepage": "http://mdomba.info/",
268 | "role": "Core framework development"
269 | },
270 | {
271 | "name": "Carsten Brandt",
272 | "email": "mail@cebe.cc",
273 | "homepage": "http://cebe.cc/",
274 | "role": "Core framework development"
275 | },
276 | {
277 | "name": "Timur Ruziev",
278 | "email": "resurtm@gmail.com",
279 | "homepage": "http://resurtm.com/",
280 | "role": "Core framework development"
281 | },
282 | {
283 | "name": "Paul Klimov",
284 | "email": "klimov.paul@gmail.com",
285 | "role": "Core framework development"
286 | },
287 | {
288 | "name": "Dmitry Naumenko",
289 | "email": "d.naumenko.a@gmail.com",
290 | "role": "Core framework development"
291 | },
292 | {
293 | "name": "Boudewijn Vahrmeijer",
294 | "email": "info@dynasource.eu",
295 | "homepage": "http://dynasource.eu",
296 | "role": "Core framework development"
297 | }
298 | ],
299 | "description": "Yii PHP Framework Version 2",
300 | "homepage": "http://www.yiiframework.com/",
301 | "keywords": [
302 | "framework",
303 | "yii2"
304 | ],
305 | "time": "2017-11-02T22:09:29+00:00"
306 | },
307 | {
308 | "name": "yiisoft/yii2-composer",
309 | "version": "2.0.5",
310 | "source": {
311 | "type": "git",
312 | "url": "https://github.com/yiisoft/yii2-composer.git",
313 | "reference": "3f4923c2bde6caf3f5b88cc22fdd5770f52f8df2"
314 | },
315 | "dist": {
316 | "type": "zip",
317 | "url": "https://api.github.com/repos/yiisoft/yii2-composer/zipball/3f4923c2bde6caf3f5b88cc22fdd5770f52f8df2",
318 | "reference": "3f4923c2bde6caf3f5b88cc22fdd5770f52f8df2",
319 | "shasum": ""
320 | },
321 | "require": {
322 | "composer-plugin-api": "^1.0"
323 | },
324 | "require-dev": {
325 | "composer/composer": "^1.0"
326 | },
327 | "type": "composer-plugin",
328 | "extra": {
329 | "class": "yii\\composer\\Plugin",
330 | "branch-alias": {
331 | "dev-master": "2.0.x-dev"
332 | }
333 | },
334 | "autoload": {
335 | "psr-4": {
336 | "yii\\composer\\": ""
337 | }
338 | },
339 | "notification-url": "https://packagist.org/downloads/",
340 | "license": [
341 | "BSD-3-Clause"
342 | ],
343 | "authors": [
344 | {
345 | "name": "Qiang Xue",
346 | "email": "qiang.xue@gmail.com"
347 | }
348 | ],
349 | "description": "The composer plugin for Yii extension installer",
350 | "keywords": [
351 | "composer",
352 | "extension installer",
353 | "yii2"
354 | ],
355 | "time": "2016-12-20T13:26:02+00:00"
356 | }
357 | ],
358 | "packages-dev": [
359 | {
360 | "name": "doctrine/instantiator",
361 | "version": "1.0.5",
362 | "source": {
363 | "type": "git",
364 | "url": "https://github.com/doctrine/instantiator.git",
365 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
366 | },
367 | "dist": {
368 | "type": "zip",
369 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
370 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
371 | "shasum": ""
372 | },
373 | "require": {
374 | "php": ">=5.3,<8.0-DEV"
375 | },
376 | "require-dev": {
377 | "athletic/athletic": "~0.1.8",
378 | "ext-pdo": "*",
379 | "ext-phar": "*",
380 | "phpunit/phpunit": "~4.0",
381 | "squizlabs/php_codesniffer": "~2.0"
382 | },
383 | "type": "library",
384 | "extra": {
385 | "branch-alias": {
386 | "dev-master": "1.0.x-dev"
387 | }
388 | },
389 | "autoload": {
390 | "psr-4": {
391 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
392 | }
393 | },
394 | "notification-url": "https://packagist.org/downloads/",
395 | "license": [
396 | "MIT"
397 | ],
398 | "authors": [
399 | {
400 | "name": "Marco Pivetta",
401 | "email": "ocramius@gmail.com",
402 | "homepage": "http://ocramius.github.com/"
403 | }
404 | ],
405 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
406 | "homepage": "https://github.com/doctrine/instantiator",
407 | "keywords": [
408 | "constructor",
409 | "instantiate"
410 | ],
411 | "time": "2015-06-14T21:17:01+00:00"
412 | },
413 | {
414 | "name": "phpdocumentor/reflection-common",
415 | "version": "1.0.1",
416 | "source": {
417 | "type": "git",
418 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
419 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6"
420 | },
421 | "dist": {
422 | "type": "zip",
423 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
424 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
425 | "shasum": ""
426 | },
427 | "require": {
428 | "php": ">=5.5"
429 | },
430 | "require-dev": {
431 | "phpunit/phpunit": "^4.6"
432 | },
433 | "type": "library",
434 | "extra": {
435 | "branch-alias": {
436 | "dev-master": "1.0.x-dev"
437 | }
438 | },
439 | "autoload": {
440 | "psr-4": {
441 | "phpDocumentor\\Reflection\\": [
442 | "src"
443 | ]
444 | }
445 | },
446 | "notification-url": "https://packagist.org/downloads/",
447 | "license": [
448 | "MIT"
449 | ],
450 | "authors": [
451 | {
452 | "name": "Jaap van Otterdijk",
453 | "email": "opensource@ijaap.nl"
454 | }
455 | ],
456 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
457 | "homepage": "http://www.phpdoc.org",
458 | "keywords": [
459 | "FQSEN",
460 | "phpDocumentor",
461 | "phpdoc",
462 | "reflection",
463 | "static analysis"
464 | ],
465 | "time": "2017-09-11T18:02:19+00:00"
466 | },
467 | {
468 | "name": "phpdocumentor/reflection-docblock",
469 | "version": "4.1.1",
470 | "source": {
471 | "type": "git",
472 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
473 | "reference": "2d3d238c433cf69caeb4842e97a3223a116f94b2"
474 | },
475 | "dist": {
476 | "type": "zip",
477 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/2d3d238c433cf69caeb4842e97a3223a116f94b2",
478 | "reference": "2d3d238c433cf69caeb4842e97a3223a116f94b2",
479 | "shasum": ""
480 | },
481 | "require": {
482 | "php": "^7.0",
483 | "phpdocumentor/reflection-common": "^1.0@dev",
484 | "phpdocumentor/type-resolver": "^0.4.0",
485 | "webmozart/assert": "^1.0"
486 | },
487 | "require-dev": {
488 | "mockery/mockery": "^0.9.4",
489 | "phpunit/phpunit": "^4.4"
490 | },
491 | "type": "library",
492 | "autoload": {
493 | "psr-4": {
494 | "phpDocumentor\\Reflection\\": [
495 | "src/"
496 | ]
497 | }
498 | },
499 | "notification-url": "https://packagist.org/downloads/",
500 | "license": [
501 | "MIT"
502 | ],
503 | "authors": [
504 | {
505 | "name": "Mike van Riel",
506 | "email": "me@mikevanriel.com"
507 | }
508 | ],
509 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
510 | "time": "2017-08-30T18:51:59+00:00"
511 | },
512 | {
513 | "name": "phpdocumentor/type-resolver",
514 | "version": "0.4.0",
515 | "source": {
516 | "type": "git",
517 | "url": "https://github.com/phpDocumentor/TypeResolver.git",
518 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7"
519 | },
520 | "dist": {
521 | "type": "zip",
522 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7",
523 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7",
524 | "shasum": ""
525 | },
526 | "require": {
527 | "php": "^5.5 || ^7.0",
528 | "phpdocumentor/reflection-common": "^1.0"
529 | },
530 | "require-dev": {
531 | "mockery/mockery": "^0.9.4",
532 | "phpunit/phpunit": "^5.2||^4.8.24"
533 | },
534 | "type": "library",
535 | "extra": {
536 | "branch-alias": {
537 | "dev-master": "1.0.x-dev"
538 | }
539 | },
540 | "autoload": {
541 | "psr-4": {
542 | "phpDocumentor\\Reflection\\": [
543 | "src/"
544 | ]
545 | }
546 | },
547 | "notification-url": "https://packagist.org/downloads/",
548 | "license": [
549 | "MIT"
550 | ],
551 | "authors": [
552 | {
553 | "name": "Mike van Riel",
554 | "email": "me@mikevanriel.com"
555 | }
556 | ],
557 | "time": "2017-07-14T14:27:02+00:00"
558 | },
559 | {
560 | "name": "phpspec/prophecy",
561 | "version": "v1.7.2",
562 | "source": {
563 | "type": "git",
564 | "url": "https://github.com/phpspec/prophecy.git",
565 | "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6"
566 | },
567 | "dist": {
568 | "type": "zip",
569 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6",
570 | "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6",
571 | "shasum": ""
572 | },
573 | "require": {
574 | "doctrine/instantiator": "^1.0.2",
575 | "php": "^5.3|^7.0",
576 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0",
577 | "sebastian/comparator": "^1.1|^2.0",
578 | "sebastian/recursion-context": "^1.0|^2.0|^3.0"
579 | },
580 | "require-dev": {
581 | "phpspec/phpspec": "^2.5|^3.2",
582 | "phpunit/phpunit": "^4.8 || ^5.6.5"
583 | },
584 | "type": "library",
585 | "extra": {
586 | "branch-alias": {
587 | "dev-master": "1.7.x-dev"
588 | }
589 | },
590 | "autoload": {
591 | "psr-0": {
592 | "Prophecy\\": "src/"
593 | }
594 | },
595 | "notification-url": "https://packagist.org/downloads/",
596 | "license": [
597 | "MIT"
598 | ],
599 | "authors": [
600 | {
601 | "name": "Konstantin Kudryashov",
602 | "email": "ever.zet@gmail.com",
603 | "homepage": "http://everzet.com"
604 | },
605 | {
606 | "name": "Marcello Duarte",
607 | "email": "marcello.duarte@gmail.com"
608 | }
609 | ],
610 | "description": "Highly opinionated mocking framework for PHP 5.3+",
611 | "homepage": "https://github.com/phpspec/prophecy",
612 | "keywords": [
613 | "Double",
614 | "Dummy",
615 | "fake",
616 | "mock",
617 | "spy",
618 | "stub"
619 | ],
620 | "time": "2017-09-04T11:05:03+00:00"
621 | },
622 | {
623 | "name": "phpunit/php-code-coverage",
624 | "version": "2.2.4",
625 | "source": {
626 | "type": "git",
627 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
628 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
629 | },
630 | "dist": {
631 | "type": "zip",
632 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
633 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
634 | "shasum": ""
635 | },
636 | "require": {
637 | "php": ">=5.3.3",
638 | "phpunit/php-file-iterator": "~1.3",
639 | "phpunit/php-text-template": "~1.2",
640 | "phpunit/php-token-stream": "~1.3",
641 | "sebastian/environment": "^1.3.2",
642 | "sebastian/version": "~1.0"
643 | },
644 | "require-dev": {
645 | "ext-xdebug": ">=2.1.4",
646 | "phpunit/phpunit": "~4"
647 | },
648 | "suggest": {
649 | "ext-dom": "*",
650 | "ext-xdebug": ">=2.2.1",
651 | "ext-xmlwriter": "*"
652 | },
653 | "type": "library",
654 | "extra": {
655 | "branch-alias": {
656 | "dev-master": "2.2.x-dev"
657 | }
658 | },
659 | "autoload": {
660 | "classmap": [
661 | "src/"
662 | ]
663 | },
664 | "notification-url": "https://packagist.org/downloads/",
665 | "license": [
666 | "BSD-3-Clause"
667 | ],
668 | "authors": [
669 | {
670 | "name": "Sebastian Bergmann",
671 | "email": "sb@sebastian-bergmann.de",
672 | "role": "lead"
673 | }
674 | ],
675 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
676 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
677 | "keywords": [
678 | "coverage",
679 | "testing",
680 | "xunit"
681 | ],
682 | "time": "2015-10-06T15:47:00+00:00"
683 | },
684 | {
685 | "name": "phpunit/php-file-iterator",
686 | "version": "1.4.2",
687 | "source": {
688 | "type": "git",
689 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
690 | "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5"
691 | },
692 | "dist": {
693 | "type": "zip",
694 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
695 | "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
696 | "shasum": ""
697 | },
698 | "require": {
699 | "php": ">=5.3.3"
700 | },
701 | "type": "library",
702 | "extra": {
703 | "branch-alias": {
704 | "dev-master": "1.4.x-dev"
705 | }
706 | },
707 | "autoload": {
708 | "classmap": [
709 | "src/"
710 | ]
711 | },
712 | "notification-url": "https://packagist.org/downloads/",
713 | "license": [
714 | "BSD-3-Clause"
715 | ],
716 | "authors": [
717 | {
718 | "name": "Sebastian Bergmann",
719 | "email": "sb@sebastian-bergmann.de",
720 | "role": "lead"
721 | }
722 | ],
723 | "description": "FilterIterator implementation that filters files based on a list of suffixes.",
724 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
725 | "keywords": [
726 | "filesystem",
727 | "iterator"
728 | ],
729 | "time": "2016-10-03T07:40:28+00:00"
730 | },
731 | {
732 | "name": "phpunit/php-text-template",
733 | "version": "1.2.1",
734 | "source": {
735 | "type": "git",
736 | "url": "https://github.com/sebastianbergmann/php-text-template.git",
737 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
738 | },
739 | "dist": {
740 | "type": "zip",
741 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
742 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
743 | "shasum": ""
744 | },
745 | "require": {
746 | "php": ">=5.3.3"
747 | },
748 | "type": "library",
749 | "autoload": {
750 | "classmap": [
751 | "src/"
752 | ]
753 | },
754 | "notification-url": "https://packagist.org/downloads/",
755 | "license": [
756 | "BSD-3-Clause"
757 | ],
758 | "authors": [
759 | {
760 | "name": "Sebastian Bergmann",
761 | "email": "sebastian@phpunit.de",
762 | "role": "lead"
763 | }
764 | ],
765 | "description": "Simple template engine.",
766 | "homepage": "https://github.com/sebastianbergmann/php-text-template/",
767 | "keywords": [
768 | "template"
769 | ],
770 | "time": "2015-06-21T13:50:34+00:00"
771 | },
772 | {
773 | "name": "phpunit/php-timer",
774 | "version": "1.0.9",
775 | "source": {
776 | "type": "git",
777 | "url": "https://github.com/sebastianbergmann/php-timer.git",
778 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f"
779 | },
780 | "dist": {
781 | "type": "zip",
782 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
783 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
784 | "shasum": ""
785 | },
786 | "require": {
787 | "php": "^5.3.3 || ^7.0"
788 | },
789 | "require-dev": {
790 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
791 | },
792 | "type": "library",
793 | "extra": {
794 | "branch-alias": {
795 | "dev-master": "1.0-dev"
796 | }
797 | },
798 | "autoload": {
799 | "classmap": [
800 | "src/"
801 | ]
802 | },
803 | "notification-url": "https://packagist.org/downloads/",
804 | "license": [
805 | "BSD-3-Clause"
806 | ],
807 | "authors": [
808 | {
809 | "name": "Sebastian Bergmann",
810 | "email": "sb@sebastian-bergmann.de",
811 | "role": "lead"
812 | }
813 | ],
814 | "description": "Utility class for timing",
815 | "homepage": "https://github.com/sebastianbergmann/php-timer/",
816 | "keywords": [
817 | "timer"
818 | ],
819 | "time": "2017-02-26T11:10:40+00:00"
820 | },
821 | {
822 | "name": "phpunit/php-token-stream",
823 | "version": "1.4.11",
824 | "source": {
825 | "type": "git",
826 | "url": "https://github.com/sebastianbergmann/php-token-stream.git",
827 | "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7"
828 | },
829 | "dist": {
830 | "type": "zip",
831 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7",
832 | "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7",
833 | "shasum": ""
834 | },
835 | "require": {
836 | "ext-tokenizer": "*",
837 | "php": ">=5.3.3"
838 | },
839 | "require-dev": {
840 | "phpunit/phpunit": "~4.2"
841 | },
842 | "type": "library",
843 | "extra": {
844 | "branch-alias": {
845 | "dev-master": "1.4-dev"
846 | }
847 | },
848 | "autoload": {
849 | "classmap": [
850 | "src/"
851 | ]
852 | },
853 | "notification-url": "https://packagist.org/downloads/",
854 | "license": [
855 | "BSD-3-Clause"
856 | ],
857 | "authors": [
858 | {
859 | "name": "Sebastian Bergmann",
860 | "email": "sebastian@phpunit.de"
861 | }
862 | ],
863 | "description": "Wrapper around PHP's tokenizer extension.",
864 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
865 | "keywords": [
866 | "tokenizer"
867 | ],
868 | "time": "2017-02-27T10:12:30+00:00"
869 | },
870 | {
871 | "name": "phpunit/phpunit",
872 | "version": "4.8.36",
873 | "source": {
874 | "type": "git",
875 | "url": "https://github.com/sebastianbergmann/phpunit.git",
876 | "reference": "46023de9a91eec7dfb06cc56cb4e260017298517"
877 | },
878 | "dist": {
879 | "type": "zip",
880 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517",
881 | "reference": "46023de9a91eec7dfb06cc56cb4e260017298517",
882 | "shasum": ""
883 | },
884 | "require": {
885 | "ext-dom": "*",
886 | "ext-json": "*",
887 | "ext-pcre": "*",
888 | "ext-reflection": "*",
889 | "ext-spl": "*",
890 | "php": ">=5.3.3",
891 | "phpspec/prophecy": "^1.3.1",
892 | "phpunit/php-code-coverage": "~2.1",
893 | "phpunit/php-file-iterator": "~1.4",
894 | "phpunit/php-text-template": "~1.2",
895 | "phpunit/php-timer": "^1.0.6",
896 | "phpunit/phpunit-mock-objects": "~2.3",
897 | "sebastian/comparator": "~1.2.2",
898 | "sebastian/diff": "~1.2",
899 | "sebastian/environment": "~1.3",
900 | "sebastian/exporter": "~1.2",
901 | "sebastian/global-state": "~1.0",
902 | "sebastian/version": "~1.0",
903 | "symfony/yaml": "~2.1|~3.0"
904 | },
905 | "suggest": {
906 | "phpunit/php-invoker": "~1.1"
907 | },
908 | "bin": [
909 | "phpunit"
910 | ],
911 | "type": "library",
912 | "extra": {
913 | "branch-alias": {
914 | "dev-master": "4.8.x-dev"
915 | }
916 | },
917 | "autoload": {
918 | "classmap": [
919 | "src/"
920 | ]
921 | },
922 | "notification-url": "https://packagist.org/downloads/",
923 | "license": [
924 | "BSD-3-Clause"
925 | ],
926 | "authors": [
927 | {
928 | "name": "Sebastian Bergmann",
929 | "email": "sebastian@phpunit.de",
930 | "role": "lead"
931 | }
932 | ],
933 | "description": "The PHP Unit Testing framework.",
934 | "homepage": "https://phpunit.de/",
935 | "keywords": [
936 | "phpunit",
937 | "testing",
938 | "xunit"
939 | ],
940 | "time": "2017-06-21T08:07:12+00:00"
941 | },
942 | {
943 | "name": "phpunit/phpunit-mock-objects",
944 | "version": "2.3.8",
945 | "source": {
946 | "type": "git",
947 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
948 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
949 | },
950 | "dist": {
951 | "type": "zip",
952 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
953 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
954 | "shasum": ""
955 | },
956 | "require": {
957 | "doctrine/instantiator": "^1.0.2",
958 | "php": ">=5.3.3",
959 | "phpunit/php-text-template": "~1.2",
960 | "sebastian/exporter": "~1.2"
961 | },
962 | "require-dev": {
963 | "phpunit/phpunit": "~4.4"
964 | },
965 | "suggest": {
966 | "ext-soap": "*"
967 | },
968 | "type": "library",
969 | "extra": {
970 | "branch-alias": {
971 | "dev-master": "2.3.x-dev"
972 | }
973 | },
974 | "autoload": {
975 | "classmap": [
976 | "src/"
977 | ]
978 | },
979 | "notification-url": "https://packagist.org/downloads/",
980 | "license": [
981 | "BSD-3-Clause"
982 | ],
983 | "authors": [
984 | {
985 | "name": "Sebastian Bergmann",
986 | "email": "sb@sebastian-bergmann.de",
987 | "role": "lead"
988 | }
989 | ],
990 | "description": "Mock Object library for PHPUnit",
991 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
992 | "keywords": [
993 | "mock",
994 | "xunit"
995 | ],
996 | "time": "2015-10-02T06:51:40+00:00"
997 | },
998 | {
999 | "name": "sebastian/comparator",
1000 | "version": "1.2.4",
1001 | "source": {
1002 | "type": "git",
1003 | "url": "https://github.com/sebastianbergmann/comparator.git",
1004 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be"
1005 | },
1006 | "dist": {
1007 | "type": "zip",
1008 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
1009 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
1010 | "shasum": ""
1011 | },
1012 | "require": {
1013 | "php": ">=5.3.3",
1014 | "sebastian/diff": "~1.2",
1015 | "sebastian/exporter": "~1.2 || ~2.0"
1016 | },
1017 | "require-dev": {
1018 | "phpunit/phpunit": "~4.4"
1019 | },
1020 | "type": "library",
1021 | "extra": {
1022 | "branch-alias": {
1023 | "dev-master": "1.2.x-dev"
1024 | }
1025 | },
1026 | "autoload": {
1027 | "classmap": [
1028 | "src/"
1029 | ]
1030 | },
1031 | "notification-url": "https://packagist.org/downloads/",
1032 | "license": [
1033 | "BSD-3-Clause"
1034 | ],
1035 | "authors": [
1036 | {
1037 | "name": "Jeff Welch",
1038 | "email": "whatthejeff@gmail.com"
1039 | },
1040 | {
1041 | "name": "Volker Dusch",
1042 | "email": "github@wallbash.com"
1043 | },
1044 | {
1045 | "name": "Bernhard Schussek",
1046 | "email": "bschussek@2bepublished.at"
1047 | },
1048 | {
1049 | "name": "Sebastian Bergmann",
1050 | "email": "sebastian@phpunit.de"
1051 | }
1052 | ],
1053 | "description": "Provides the functionality to compare PHP values for equality",
1054 | "homepage": "http://www.github.com/sebastianbergmann/comparator",
1055 | "keywords": [
1056 | "comparator",
1057 | "compare",
1058 | "equality"
1059 | ],
1060 | "time": "2017-01-29T09:50:25+00:00"
1061 | },
1062 | {
1063 | "name": "sebastian/diff",
1064 | "version": "1.4.3",
1065 | "source": {
1066 | "type": "git",
1067 | "url": "https://github.com/sebastianbergmann/diff.git",
1068 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4"
1069 | },
1070 | "dist": {
1071 | "type": "zip",
1072 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4",
1073 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4",
1074 | "shasum": ""
1075 | },
1076 | "require": {
1077 | "php": "^5.3.3 || ^7.0"
1078 | },
1079 | "require-dev": {
1080 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
1081 | },
1082 | "type": "library",
1083 | "extra": {
1084 | "branch-alias": {
1085 | "dev-master": "1.4-dev"
1086 | }
1087 | },
1088 | "autoload": {
1089 | "classmap": [
1090 | "src/"
1091 | ]
1092 | },
1093 | "notification-url": "https://packagist.org/downloads/",
1094 | "license": [
1095 | "BSD-3-Clause"
1096 | ],
1097 | "authors": [
1098 | {
1099 | "name": "Kore Nordmann",
1100 | "email": "mail@kore-nordmann.de"
1101 | },
1102 | {
1103 | "name": "Sebastian Bergmann",
1104 | "email": "sebastian@phpunit.de"
1105 | }
1106 | ],
1107 | "description": "Diff implementation",
1108 | "homepage": "https://github.com/sebastianbergmann/diff",
1109 | "keywords": [
1110 | "diff"
1111 | ],
1112 | "time": "2017-05-22T07:24:03+00:00"
1113 | },
1114 | {
1115 | "name": "sebastian/environment",
1116 | "version": "1.3.8",
1117 | "source": {
1118 | "type": "git",
1119 | "url": "https://github.com/sebastianbergmann/environment.git",
1120 | "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea"
1121 | },
1122 | "dist": {
1123 | "type": "zip",
1124 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea",
1125 | "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea",
1126 | "shasum": ""
1127 | },
1128 | "require": {
1129 | "php": "^5.3.3 || ^7.0"
1130 | },
1131 | "require-dev": {
1132 | "phpunit/phpunit": "^4.8 || ^5.0"
1133 | },
1134 | "type": "library",
1135 | "extra": {
1136 | "branch-alias": {
1137 | "dev-master": "1.3.x-dev"
1138 | }
1139 | },
1140 | "autoload": {
1141 | "classmap": [
1142 | "src/"
1143 | ]
1144 | },
1145 | "notification-url": "https://packagist.org/downloads/",
1146 | "license": [
1147 | "BSD-3-Clause"
1148 | ],
1149 | "authors": [
1150 | {
1151 | "name": "Sebastian Bergmann",
1152 | "email": "sebastian@phpunit.de"
1153 | }
1154 | ],
1155 | "description": "Provides functionality to handle HHVM/PHP environments",
1156 | "homepage": "http://www.github.com/sebastianbergmann/environment",
1157 | "keywords": [
1158 | "Xdebug",
1159 | "environment",
1160 | "hhvm"
1161 | ],
1162 | "time": "2016-08-18T05:49:44+00:00"
1163 | },
1164 | {
1165 | "name": "sebastian/exporter",
1166 | "version": "1.2.2",
1167 | "source": {
1168 | "type": "git",
1169 | "url": "https://github.com/sebastianbergmann/exporter.git",
1170 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
1171 | },
1172 | "dist": {
1173 | "type": "zip",
1174 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
1175 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
1176 | "shasum": ""
1177 | },
1178 | "require": {
1179 | "php": ">=5.3.3",
1180 | "sebastian/recursion-context": "~1.0"
1181 | },
1182 | "require-dev": {
1183 | "ext-mbstring": "*",
1184 | "phpunit/phpunit": "~4.4"
1185 | },
1186 | "type": "library",
1187 | "extra": {
1188 | "branch-alias": {
1189 | "dev-master": "1.3.x-dev"
1190 | }
1191 | },
1192 | "autoload": {
1193 | "classmap": [
1194 | "src/"
1195 | ]
1196 | },
1197 | "notification-url": "https://packagist.org/downloads/",
1198 | "license": [
1199 | "BSD-3-Clause"
1200 | ],
1201 | "authors": [
1202 | {
1203 | "name": "Jeff Welch",
1204 | "email": "whatthejeff@gmail.com"
1205 | },
1206 | {
1207 | "name": "Volker Dusch",
1208 | "email": "github@wallbash.com"
1209 | },
1210 | {
1211 | "name": "Bernhard Schussek",
1212 | "email": "bschussek@2bepublished.at"
1213 | },
1214 | {
1215 | "name": "Sebastian Bergmann",
1216 | "email": "sebastian@phpunit.de"
1217 | },
1218 | {
1219 | "name": "Adam Harvey",
1220 | "email": "aharvey@php.net"
1221 | }
1222 | ],
1223 | "description": "Provides the functionality to export PHP variables for visualization",
1224 | "homepage": "http://www.github.com/sebastianbergmann/exporter",
1225 | "keywords": [
1226 | "export",
1227 | "exporter"
1228 | ],
1229 | "time": "2016-06-17T09:04:28+00:00"
1230 | },
1231 | {
1232 | "name": "sebastian/global-state",
1233 | "version": "1.1.1",
1234 | "source": {
1235 | "type": "git",
1236 | "url": "https://github.com/sebastianbergmann/global-state.git",
1237 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
1238 | },
1239 | "dist": {
1240 | "type": "zip",
1241 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
1242 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
1243 | "shasum": ""
1244 | },
1245 | "require": {
1246 | "php": ">=5.3.3"
1247 | },
1248 | "require-dev": {
1249 | "phpunit/phpunit": "~4.2"
1250 | },
1251 | "suggest": {
1252 | "ext-uopz": "*"
1253 | },
1254 | "type": "library",
1255 | "extra": {
1256 | "branch-alias": {
1257 | "dev-master": "1.0-dev"
1258 | }
1259 | },
1260 | "autoload": {
1261 | "classmap": [
1262 | "src/"
1263 | ]
1264 | },
1265 | "notification-url": "https://packagist.org/downloads/",
1266 | "license": [
1267 | "BSD-3-Clause"
1268 | ],
1269 | "authors": [
1270 | {
1271 | "name": "Sebastian Bergmann",
1272 | "email": "sebastian@phpunit.de"
1273 | }
1274 | ],
1275 | "description": "Snapshotting of global state",
1276 | "homepage": "http://www.github.com/sebastianbergmann/global-state",
1277 | "keywords": [
1278 | "global state"
1279 | ],
1280 | "time": "2015-10-12T03:26:01+00:00"
1281 | },
1282 | {
1283 | "name": "sebastian/recursion-context",
1284 | "version": "1.0.5",
1285 | "source": {
1286 | "type": "git",
1287 | "url": "https://github.com/sebastianbergmann/recursion-context.git",
1288 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7"
1289 | },
1290 | "dist": {
1291 | "type": "zip",
1292 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7",
1293 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7",
1294 | "shasum": ""
1295 | },
1296 | "require": {
1297 | "php": ">=5.3.3"
1298 | },
1299 | "require-dev": {
1300 | "phpunit/phpunit": "~4.4"
1301 | },
1302 | "type": "library",
1303 | "extra": {
1304 | "branch-alias": {
1305 | "dev-master": "1.0.x-dev"
1306 | }
1307 | },
1308 | "autoload": {
1309 | "classmap": [
1310 | "src/"
1311 | ]
1312 | },
1313 | "notification-url": "https://packagist.org/downloads/",
1314 | "license": [
1315 | "BSD-3-Clause"
1316 | ],
1317 | "authors": [
1318 | {
1319 | "name": "Jeff Welch",
1320 | "email": "whatthejeff@gmail.com"
1321 | },
1322 | {
1323 | "name": "Sebastian Bergmann",
1324 | "email": "sebastian@phpunit.de"
1325 | },
1326 | {
1327 | "name": "Adam Harvey",
1328 | "email": "aharvey@php.net"
1329 | }
1330 | ],
1331 | "description": "Provides functionality to recursively process PHP variables",
1332 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
1333 | "time": "2016-10-03T07:41:43+00:00"
1334 | },
1335 | {
1336 | "name": "sebastian/version",
1337 | "version": "1.0.6",
1338 | "source": {
1339 | "type": "git",
1340 | "url": "https://github.com/sebastianbergmann/version.git",
1341 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
1342 | },
1343 | "dist": {
1344 | "type": "zip",
1345 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
1346 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
1347 | "shasum": ""
1348 | },
1349 | "type": "library",
1350 | "autoload": {
1351 | "classmap": [
1352 | "src/"
1353 | ]
1354 | },
1355 | "notification-url": "https://packagist.org/downloads/",
1356 | "license": [
1357 | "BSD-3-Clause"
1358 | ],
1359 | "authors": [
1360 | {
1361 | "name": "Sebastian Bergmann",
1362 | "email": "sebastian@phpunit.de",
1363 | "role": "lead"
1364 | }
1365 | ],
1366 | "description": "Library that helps with managing the version number of Git-hosted PHP projects",
1367 | "homepage": "https://github.com/sebastianbergmann/version",
1368 | "time": "2015-06-21T13:59:46+00:00"
1369 | },
1370 | {
1371 | "name": "symfony/yaml",
1372 | "version": "v3.3.10",
1373 | "source": {
1374 | "type": "git",
1375 | "url": "https://github.com/symfony/yaml.git",
1376 | "reference": "8c7bf1e7d5d6b05a690b715729cb4cd0c0a99c46"
1377 | },
1378 | "dist": {
1379 | "type": "zip",
1380 | "url": "https://api.github.com/repos/symfony/yaml/zipball/8c7bf1e7d5d6b05a690b715729cb4cd0c0a99c46",
1381 | "reference": "8c7bf1e7d5d6b05a690b715729cb4cd0c0a99c46",
1382 | "shasum": ""
1383 | },
1384 | "require": {
1385 | "php": "^5.5.9|>=7.0.8"
1386 | },
1387 | "require-dev": {
1388 | "symfony/console": "~2.8|~3.0"
1389 | },
1390 | "suggest": {
1391 | "symfony/console": "For validating YAML files using the lint command"
1392 | },
1393 | "type": "library",
1394 | "extra": {
1395 | "branch-alias": {
1396 | "dev-master": "3.3-dev"
1397 | }
1398 | },
1399 | "autoload": {
1400 | "psr-4": {
1401 | "Symfony\\Component\\Yaml\\": ""
1402 | },
1403 | "exclude-from-classmap": [
1404 | "/Tests/"
1405 | ]
1406 | },
1407 | "notification-url": "https://packagist.org/downloads/",
1408 | "license": [
1409 | "MIT"
1410 | ],
1411 | "authors": [
1412 | {
1413 | "name": "Fabien Potencier",
1414 | "email": "fabien@symfony.com"
1415 | },
1416 | {
1417 | "name": "Symfony Community",
1418 | "homepage": "https://symfony.com/contributors"
1419 | }
1420 | ],
1421 | "description": "Symfony Yaml Component",
1422 | "homepage": "https://symfony.com",
1423 | "time": "2017-10-05T14:43:42+00:00"
1424 | },
1425 | {
1426 | "name": "webmozart/assert",
1427 | "version": "1.2.0",
1428 | "source": {
1429 | "type": "git",
1430 | "url": "https://github.com/webmozart/assert.git",
1431 | "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f"
1432 | },
1433 | "dist": {
1434 | "type": "zip",
1435 | "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f",
1436 | "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f",
1437 | "shasum": ""
1438 | },
1439 | "require": {
1440 | "php": "^5.3.3 || ^7.0"
1441 | },
1442 | "require-dev": {
1443 | "phpunit/phpunit": "^4.6",
1444 | "sebastian/version": "^1.0.1"
1445 | },
1446 | "type": "library",
1447 | "extra": {
1448 | "branch-alias": {
1449 | "dev-master": "1.3-dev"
1450 | }
1451 | },
1452 | "autoload": {
1453 | "psr-4": {
1454 | "Webmozart\\Assert\\": "src/"
1455 | }
1456 | },
1457 | "notification-url": "https://packagist.org/downloads/",
1458 | "license": [
1459 | "MIT"
1460 | ],
1461 | "authors": [
1462 | {
1463 | "name": "Bernhard Schussek",
1464 | "email": "bschussek@gmail.com"
1465 | }
1466 | ],
1467 | "description": "Assertions to validate method input/output with nice error messages.",
1468 | "keywords": [
1469 | "assert",
1470 | "check",
1471 | "validate"
1472 | ],
1473 | "time": "2016-11-23T20:04:58+00:00"
1474 | }
1475 | ],
1476 | "aliases": [],
1477 | "minimum-stability": "stable",
1478 | "stability-flags": [],
1479 | "prefer-stable": false,
1480 | "prefer-lowest": false,
1481 | "platform": {
1482 | "php": ">=5.4.0"
1483 | },
1484 | "platform-dev": []
1485 | }
1486 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 | ./tests
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/JsonBehavior.php:
--------------------------------------------------------------------------------
1 | function () { $this->initialization(); },
35 | ActiveRecord::EVENT_AFTER_FIND => function () { $this->decode(); },
36 | ActiveRecord::EVENT_BEFORE_INSERT => function () { $this->encode(); },
37 | ActiveRecord::EVENT_BEFORE_UPDATE => function () { $this->encode(); },
38 | ActiveRecord::EVENT_AFTER_INSERT => function () { $this->decode(); },
39 | ActiveRecord::EVENT_AFTER_UPDATE => function () { $this->decode(); },
40 | ActiveRecord::EVENT_BEFORE_VALIDATE => function () {
41 | if ($this->encodeBeforeValidation) {
42 | $this->encodeValidate();
43 | }
44 | },
45 | ActiveRecord::EVENT_AFTER_VALIDATE => function () {
46 | if ($this->encodeBeforeValidation) {
47 | $this->decode();
48 | }
49 | },
50 | ];
51 | }
52 |
53 | /**
54 | */
55 | protected function initialization()
56 | {
57 | foreach ($this->attributes as $attribute) {
58 | $this->owner->setAttribute($attribute, new JsonField());
59 | }
60 | }
61 |
62 | /**
63 | */
64 | protected function decode()
65 | {
66 | foreach ($this->attributes as $attribute) {
67 | $value = $this->owner->getAttribute($attribute);
68 | if (!$value instanceof JsonField) {
69 | $value = new JsonField($value);
70 | }
71 | $this->owner->setAttribute($attribute, $value);
72 | }
73 | }
74 |
75 | /**
76 | */
77 | protected function encode()
78 | {
79 | foreach ($this->attributes as $attribute) {
80 | $field = $this->owner->getAttribute($attribute);
81 | if (!$field instanceof JsonField) {
82 | $field = new JsonField($field);
83 | }
84 | $this->owner->setAttribute($attribute, (string)$field ?: $this->emptyValue);
85 | }
86 | }
87 |
88 | /**
89 | */
90 | protected function encodeValidate()
91 | {
92 | foreach ($this->attributes as $attribute) {
93 | $field = $this->owner->getAttribute($attribute);
94 | if ($field instanceof JsonField) {
95 | $this->owner->setAttribute($attribute, (string)$field ?: null);
96 | }
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/JsonField.php:
--------------------------------------------------------------------------------
1 | set($value);
23 | }
24 |
25 | /**
26 | * @return string
27 | */
28 | public function __toString()
29 | {
30 | return $this->value ? Json::encode($this->value) : '';
31 | }
32 |
33 | /**
34 | * @param string|array $value
35 | */
36 | public function set($value)
37 | {
38 | if ($value === null || $value === '') {
39 | $value = [];
40 | } elseif (is_string($value)) {
41 | $value = Json::decode($value, true);
42 | if (!is_array($value)) {
43 | throw new InvalidParamException('Value is scalar');
44 | }
45 | }
46 | if (!is_array($value)) {
47 | throw new InvalidParamException('Value is not array');
48 | } else {
49 | $this->value = $value;
50 | }
51 | }
52 |
53 | /**
54 | * @inheritdoc
55 | */
56 | public function fields()
57 | {
58 | $fields = array_keys($this->value);
59 | return array_combine($fields, $fields);
60 | }
61 |
62 | /**
63 | * @inheritdoc
64 | */
65 | public function extraFields()
66 | {
67 | return [];
68 | }
69 |
70 | /**
71 | * @inheritdoc
72 | */
73 | public function toArray(array $fields = [], array $expand = [], $recursive = true)
74 | {
75 | return empty($fields) ? $this->value : array_intersect_key($this->value, array_flip($fields));
76 | }
77 |
78 | /**
79 | * @return bool
80 | */
81 | public function isEmpty()
82 | {
83 | return !$this->value;
84 | }
85 |
86 | /**
87 | * @inheritdoc
88 | */
89 | #[\ReturnTypeWillChange]
90 | public function offsetExists($offset)
91 | {
92 | return isset($this->value[$offset]);
93 | }
94 |
95 | /**
96 | * @inheritdoc
97 | */
98 | #[\ReturnTypeWillChange]
99 | public function &offsetGet($offset)
100 | {
101 | $null = null;
102 | if (isset($this->value[$offset])) {
103 | return $this->value[$offset];
104 | } else {
105 | return $null;
106 | }
107 | }
108 |
109 | /**
110 | * @inheritdoc
111 | */
112 | #[\ReturnTypeWillChange]
113 | public function offsetSet($offset, $value)
114 | {
115 | if ($offset === null) {
116 | $this->value[] = $value;
117 | } else {
118 | $this->value[$offset] = $value;
119 | }
120 | }
121 |
122 | /**
123 | * @inheritdoc
124 | */
125 | #[\ReturnTypeWillChange]
126 | public function offsetUnset($offset)
127 | {
128 | unset($this->value[$offset]);
129 | }
130 |
131 | /**
132 | * @inheritDoc
133 | */
134 | #[\ReturnTypeWillChange]
135 | public function getIterator()
136 | {
137 | return new ArrayIterator($this->value);
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/src/JsonValidator.php:
--------------------------------------------------------------------------------
1 | $attribute;
28 | if (!$value instanceof JsonField) {
29 | try {
30 | $new = new JsonField($value);
31 | if ($this->merge) {
32 | /** @var BaseActiveRecord $model */
33 | $old = new JsonField($model->getOldAttribute($attribute));
34 | $new = new JsonField(array_merge($old->toArray(), $new->toArray()));
35 | }
36 | $model->$attribute = $new;
37 | } catch (InvalidParamException $e) {
38 | $this->addError($model, $attribute, $this->getErrorMessage($e));
39 | $model->$attribute = new JsonField();
40 | }
41 | }
42 | }
43 |
44 | /**
45 | * @param \Exception $exception
46 | * @return string
47 | */
48 | protected function getErrorMessage($exception)
49 | {
50 | $code = $exception->getCode();
51 | if (isset($this->errorMessages[$code])) {
52 | return $this->errorMessages[$code];
53 | }
54 | return $exception->getMessage();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/tests/BehaviorTest.php:
--------------------------------------------------------------------------------
1 |
5 | * @license MIT (https://github.com/paulzi/yii2-json-behavior/blob/master/LICENSE)
6 | */
7 |
8 | namespace paulzi\jsonBehavior\tests;
9 |
10 | use tests\Item;
11 | use tests\ItemMerge;
12 | use tests\ItemRequired;
13 | use tests\TestMigration;
14 | use paulzi\jsonBehavior\JsonField;
15 |
16 | /**
17 | * @author PaulZi
18 | */
19 | class BehaviorTest extends \PHPUnit_Framework_TestCase
20 | {
21 | public function testInitEmpty()
22 | {
23 | $model = new JsonField();
24 | $this->assertSame((string)$model, '');
25 |
26 | $model = new JsonField('');
27 | $this->assertSame((string)$model, '');
28 |
29 | $model = new JsonField(null);
30 | $this->assertSame((string)$model, '');
31 |
32 | $model = new JsonField([]);
33 | $this->assertSame((string)$model, '');
34 | }
35 |
36 | public function testInitString()
37 | {
38 | $model = new JsonField('{ "test": false }');
39 | $this->assertSame((string)$model, '{"test":false}');
40 |
41 | $model = new JsonField('{ "test": [1, 2, 3] }');
42 | $this->assertSame((string)$model, '{"test":[1,2,3]}');
43 |
44 | $model = new JsonField('{ "test": { "best": true}, "best": 2 }');
45 | $this->assertSame((string)$model, '{"test":{"best":true},"best":2}');
46 |
47 | $model = new JsonField('[1, false, "test", null]');
48 | $this->assertSame((string)$model, '[1,false,"test",null]');
49 | }
50 |
51 | /**
52 | * @expectedException \yii\base\InvalidParamException
53 | */
54 | public function testInitStringParseException()
55 | {
56 | $model = new JsonField('{test:}');
57 | }
58 |
59 | /**
60 | * @expectedException \yii\base\InvalidParamException
61 | */
62 | public function testInitStringNumberScalarException()
63 | {
64 | $model = new JsonField('0');
65 | }
66 |
67 | /**
68 | * @expectedException \yii\base\InvalidParamException
69 | */
70 | public function testInitStringNullScalarException()
71 | {
72 | $model = new JsonField('null');
73 | }
74 |
75 | /**
76 | * @expectedException \yii\base\InvalidParamException
77 | */
78 | public function testInitStringFalseScalarException()
79 | {
80 | $model = new JsonField('false');
81 | }
82 |
83 | /**
84 | * @expectedException \yii\base\InvalidParamException
85 | */
86 | public function testInitStringTrueScalarException()
87 | {
88 | $model = new JsonField('true');
89 | }
90 |
91 | public function testInitArray()
92 | {
93 | $model = new JsonField(['test' => false]);
94 | $this->assertSame((string)$model, '{"test":false}');
95 |
96 | $model = new JsonField(['test' => [1, 2, 3]]);
97 | $this->assertSame((string)$model, '{"test":[1,2,3]}');
98 |
99 | $model = new JsonField([1, false, "test", null]);
100 | $this->assertSame((string)$model, '[1,false,"test",null]');
101 | }
102 |
103 | /**
104 | * @expectedException \yii\base\InvalidParamException
105 | */
106 | public function testInitArrayException()
107 | {
108 | $model = new JsonField(new \stdClass());
109 | }
110 |
111 | public function testSetString()
112 | {
113 | $model = new JsonField();
114 |
115 | $model->set('{ "test": false }');
116 | $this->assertSame((string)$model, '{"test":false}');
117 |
118 | $model->set('{ "test": [1, 2, 3] }');
119 | $this->assertSame((string)$model, '{"test":[1,2,3]}');
120 |
121 | $model->set('{ "test": { "best": true}, "best": 2 }');
122 | $this->assertSame((string)$model, '{"test":{"best":true},"best":2}');
123 |
124 | $model->set('[1, false, "test", null]');
125 | $this->assertSame((string)$model, '[1,false,"test",null]');
126 | }
127 |
128 | /**
129 | * @expectedException \yii\base\InvalidParamException
130 | */
131 | public function testSetStringParseException()
132 | {
133 | $model = new JsonField();
134 | $model->set('{test:}');
135 | }
136 |
137 | /**
138 | * @expectedException \yii\base\InvalidParamException
139 | */
140 | public function testSetStringNumberScalarException()
141 | {
142 | $model = new JsonField();
143 | $model->set('0');
144 | }
145 |
146 | /**
147 | * @expectedException \yii\base\InvalidParamException
148 | */
149 | public function testSetStringNullScalarException()
150 | {
151 | $model = new JsonField();
152 | $model->set('null');
153 | }
154 |
155 | /**
156 | * @expectedException \yii\base\InvalidParamException
157 | */
158 | public function testSetStringFalseScalarException()
159 | {
160 | $model = new JsonField();
161 | $model->set('false');
162 | }
163 |
164 | /**
165 | * @expectedException \yii\base\InvalidParamException
166 | */
167 | public function testSetStringTrueScalarException()
168 | {
169 | $model = new JsonField();
170 | $model->set('true');
171 | }
172 |
173 | public function testSetArray()
174 | {
175 | $model = new JsonField();
176 |
177 | $model->set(['test' => false]);
178 | $this->assertSame((string)$model, '{"test":false}');
179 |
180 | $model->set(['test' => [1, 2, 3]]);
181 | $this->assertSame((string)$model, '{"test":[1,2,3]}');
182 |
183 | $model->set(['test' => ['best' => true], 'best' => 2]);
184 | $this->assertSame((string)$model, '{"test":{"best":true},"best":2}');
185 |
186 | $model->set([1, false, "test", null]);
187 | $this->assertSame((string)$model, '[1,false,"test",null]');
188 | }
189 |
190 | /**
191 | * @expectedException \yii\base\InvalidParamException
192 | */
193 | public function testSetArrayException()
194 | {
195 | $model = new JsonField(new \stdClass());
196 | }
197 |
198 | public function testArrayObjectAccess()
199 | {
200 | $model = new JsonField('{ "one": { "test": true }, "two": 2, "three": [1, 2, 3], "four": "4" }');
201 | $this->assertSame($model['one'], ['test' => true]);
202 | $this->assertSame($model['one']['test'], true);
203 | $this->assertSame($model['two'], 2);
204 | $this->assertSame($model['three'][2], 3);
205 | $this->assertSame($model['four'], '4');
206 |
207 | $model['one']['test'] = false;
208 | $model['two'] = 3;
209 | $model['three'][2] = 0;
210 | $model['four'] = null;
211 | $this->assertSame((string)$model, '{"one":{"test":false},"two":3,"three":[1,2,0],"four":null}');
212 | }
213 |
214 | public function testArrayArrayAccess()
215 | {
216 | $model = new JsonField('[1, false, "test", null]');
217 | $this->assertSame($model[0], 1);
218 | $this->assertSame($model[1], false);
219 | $this->assertSame($model[2], 'test');
220 | $this->assertSame($model[3], null);
221 |
222 | $model[0] = 2;
223 | $model[1] = true;
224 | $model[2] = 'best';
225 | $model[3] = ['test' => 'test'];
226 | $this->assertSame((string)$model, '[2,true,"best",{"test":"test"}]');
227 | }
228 |
229 | public function testFields()
230 | {
231 | $model = new JsonField('{ "test": { "best": true}, "best": 2 }');
232 | $this->assertSame($model->fields(), ['test' => 'test', 'best' => 'best']);
233 | }
234 |
235 | public function testToArray()
236 | {
237 | $model = new JsonField('{ "test": false }');
238 | $this->assertSame($model->toArray(), ['test' => false]);
239 |
240 | $model = new JsonField('{ "test": [1, null, 3] }');
241 | $this->assertSame($model->toArray(), ['test' => [1, null, 3]]);
242 |
243 | $model = new JsonField('{ "test": { "best": true}, "best": 2 }');
244 | $this->assertSame($model->toArray(), ['test' => ['best' => true], 'best' => 2]);
245 |
246 | $model = new JsonField('[1, false, "test", null]');
247 | $this->assertSame($model->toArray(), [1, false, "test", null]);
248 |
249 | $model = new JsonField('{ "test": { "best": true}, "best": 2 }');
250 | $this->assertSame($model->toArray(['test']), ['test' => ['best' => true]]);
251 | }
252 |
253 | public function testIsEmpty()
254 | {
255 | $model = new JsonField();
256 | $this->assertSame($model->isEmpty(), true);
257 |
258 | $model->set('{}');
259 | $this->assertSame($model->isEmpty(), true);
260 |
261 | $model->set('[]');
262 | $this->assertSame($model->isEmpty(), true);
263 |
264 | $model->set('[false]');
265 | $this->assertSame($model->isEmpty(), false);
266 |
267 | $model->set('[0]');
268 | $this->assertSame($model->isEmpty(), false);
269 |
270 | $model->set('[[]]');
271 | $this->assertSame($model->isEmpty(), false);
272 | }
273 |
274 | public function testBehavior()
275 | {
276 | $item = new Item();
277 | $item->params['one'] = 'value';
278 | $item->params['two'] = [];
279 | $item->params['two']['test'] = true;
280 | $this->assertSame($item->toArray(), [
281 | 'params' => [
282 | 'one' => 'value',
283 | 'two' => ['test' => true],
284 | ],
285 | ]);
286 | $this->assertSame($item->params->toArray(['one']), ['one' => 'value']);
287 | $this->assertSame($item->save(false), true);
288 | $item->params['one'] = 42;
289 | $this->assertSame($item->params['one'], 42);
290 |
291 | $item = Item::findOne($item->id);
292 | $this->assertSame($item->params['one'], 'value');
293 | $this->assertSame($item->params['two']['test'], true);
294 | }
295 |
296 | public function testRefresh()
297 | {
298 | $item = new Item();
299 | $item->params['one'] = 3;
300 | $item->params['two'] = 2;
301 | $this->assertSame($item->save(false), true);
302 | $item->params['one'] = 'one';
303 | $item->params['three'] = 3;
304 | $item->refresh();
305 | $this->assertSame($item->params->toArray(), ['one' => 3, 'two' => 2]);
306 | }
307 |
308 | public function testDirtyAttributesOnUpdate()
309 | {
310 | $item = new Item();
311 | $testChanged = null;
312 | $item->on($item::EVENT_AFTER_UPDATE, function ($event) use (&$testChanged) {
313 | $this->assertSame($event->changedAttributes, $testChanged);
314 | });
315 | $item->params['one'] = 3;
316 | $item->params['two'] = 2;
317 | $this->assertSame($item->save(false), true);
318 | $testChanged = [];
319 | $this->assertSame($item->update(false), 0);
320 | $item->params['one'] = 1;
321 | $testChanged = ['params' => '{"one":3,"two":2}'];
322 | $this->assertSame($item->update(false), 1);
323 | }
324 |
325 | public function testEmptyValue()
326 | {
327 | $item = new Item();
328 | $this->assertSame($item->save(false), true);
329 | $item->refresh();
330 | $this->assertSame($item->getOldAttribute('params'), null);
331 |
332 | $item = new ItemMerge();
333 | $this->assertSame($item->save(false), true);
334 | $item->refresh();
335 | $this->assertSame($item->getOldAttribute('params'), '{}');
336 | }
337 |
338 | public function testValidatorTest()
339 | {
340 | $item = new Item();
341 |
342 | $item->attributes = ['params' => '{"json": true}'];
343 | $this->assertSame($item->validate(), true);
344 |
345 | $item->attributes = ['params' => ['json' => true]];
346 | $this->assertSame($item->validate(), true);
347 |
348 | $item->attributes = ['params' => '{json:}'];
349 | $this->assertSame($item->validate(), false);
350 | $this->assertArrayHasKey('params', $item->errors);
351 |
352 | $item->attributes = ['params' => 'true'];
353 | $this->assertSame($item->validate(), false);
354 | $this->assertArrayHasKey('params', $item->errors);
355 | }
356 |
357 | public function testValidatorMergeTest()
358 | {
359 | $item = new ItemMerge();
360 | $item->params['test1'] = 123;
361 | $item->params['test2'] = 456;
362 | $item->save();
363 |
364 | $item->load(['params' => '{"test2": 789}'], '');
365 | $this->assertSame($item->validate(), true);
366 | $this->assertSame($item->params->toArray(), ['test1' => 123, 'test2' => 789]);
367 |
368 | $item->load(['params' => ['test2' => 789]], '');
369 | $this->assertSame($item->validate(), true);
370 | $this->assertSame($item->params->toArray(), ['test1' => 123, 'test2' => 789]);
371 | }
372 |
373 | public function testValidatorRequiredTest()
374 | {
375 | $item = new ItemRequired();
376 | $item->params->set(null);
377 | $this->assertSame($item->validate(), false);
378 |
379 | $item = new ItemRequired();
380 | $item->params->set('{}');
381 | $this->assertSame($item->validate(), false);
382 |
383 | $item = new ItemRequired();
384 | $item->params['test'] = 1;
385 | $this->assertSame($item->validate(), true);
386 | }
387 |
388 | public function testIterator()
389 | {
390 | $model = new JsonField('{"test":"best"}');
391 | foreach ($model as $key => $value) {
392 | $this->assertSame($key, 'test');
393 | $this->assertSame($value, 'best');
394 | }
395 | }
396 |
397 | /**
398 | * @inheritdoc
399 | */
400 | public static function setUpBeforeClass()
401 | {
402 | (new TestMigration())->up();
403 | parent::setUpBeforeClass();
404 | }
405 | }
--------------------------------------------------------------------------------
/tests/Item.php:
--------------------------------------------------------------------------------
1 | JsonBehavior::className(),
26 | 'attributes' => ['params'],
27 | ]
28 | ];
29 | }
30 |
31 | /**
32 | * @inheritdoc
33 | */
34 | public function rules()
35 | {
36 | return [
37 | [['params'], JsonValidator::className()],
38 | ];
39 | }
40 | }
--------------------------------------------------------------------------------
/tests/ItemMerge.php:
--------------------------------------------------------------------------------
1 | JsonBehavior::className(),
34 | 'attributes' => ['params'],
35 | 'emptyValue' => '{}',
36 | ]
37 | ];
38 | }
39 |
40 | /**
41 | * @inheritdoc
42 | */
43 | public function rules()
44 | {
45 | return [
46 | [['params'], JsonValidator::className(), 'merge' => true],
47 | ];
48 | }
49 | }
--------------------------------------------------------------------------------
/tests/ItemRequired.php:
--------------------------------------------------------------------------------
1 | JsonBehavior::className(),
34 | 'attributes' => ['params'],
35 | ]
36 | ];
37 | }
38 |
39 | /**
40 | * @inheritdoc
41 | */
42 | public function rules()
43 | {
44 | return [
45 | [['params'], 'required'],
46 | [['params'], JsonValidator::className()],
47 | ];
48 | }
49 | }
--------------------------------------------------------------------------------
/tests/TestMigration.php:
--------------------------------------------------------------------------------
1 |
5 | * @license MIT (https://github.com/paulzi/yii2-json-behavior/blob/master/LICENSE)
6 | */
7 |
8 | namespace tests;
9 |
10 | use yii\db\Schema;
11 | use yii\db\Migration;
12 |
13 | /**
14 | * @author PaulZi
15 | */
16 | class TestMigration extends Migration
17 | {
18 | public function up()
19 | {
20 | ob_start();
21 | if ($this->db->getTableSchema('{{%item}}', true) !== null) {
22 | $this->dropTable('{{%item}}');
23 | }
24 | $this->createTable('{{%item}}', [
25 | 'id' => $this->primaryKey(),
26 | 'params' => $this->text(),
27 | ]);
28 |
29 | // update cache (sqlite bug)
30 | $this->db->getSchema()->getTableSchema('{{%item}}', true);
31 | ob_end_clean();
32 | }
33 | }
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 |
5 | * @license MIT (https://github.com/paulzi/yii2-adjacency-list/blob/master/LICENSE)
6 | */
7 |
8 | defined('YII_DEBUG') or define('YII_DEBUG', true);
9 | defined('YII_ENV') or define('YII_ENV', 'test');
10 |
11 | require(__DIR__ . '/../vendor/autoload.php');
12 | require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
13 |
14 | Yii::setAlias('@tests', __DIR__);
15 |
16 | new \yii\console\Application([
17 | 'id' => 'unit',
18 | 'basePath' => __DIR__,
19 | 'components' => [
20 | 'db' => [
21 | 'class' => 'yii\db\Connection',
22 | 'dsn' => 'sqlite::memory:',
23 | ],
24 | ],
25 | ]);
--------------------------------------------------------------------------------