Completed
Push — 6.0 ( ec25ec...df7e4e )
by liu
03:51
created

Conversion::visible()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
ccs 0
cts 3
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
// +----------------------------------------------------------------------
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: liu21st <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think\model\concern;
14
15
use think\App;
16
use think\Collection;
17
use think\Exception;
18
use think\Model;
19
use think\model\Collection as ModelCollection;
20
use think\model\relation\OneToOne;
21
22
/**
23
 * 模型数据转换处理
24
 */
5 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
25
trait Conversion
26
{
27
    /**
28
     * 数据输出显示的属性
29
     * @var array
30
     */
31
    protected $visible = [];
32
33
    /**
34
     * 数据输出隐藏的属性
35
     * @var array
36
     */
37
    protected $hidden = [];
38
39
    /**
40
     * 数据输出需要追加的属性
41
     * @var array
42
     */
43
    protected $append = [];
44
45
    /**
46
     * 数据集对象名
47
     * @var string
48
     */
49
    protected $resultSetType;
50
51
    /**
52
     * 设置需要附加的输出属性
53
     * @access public
54
     * @param  array $append   属性列表
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 3 found
Loading history...
55
     * @return $this
56
     */
57
    public function append(array $append = [])
58
    {
59
        $this->append = $append;
60
61
        return $this;
62
    }
63
64
    /**
65
     * 设置附加关联对象的属性
66
     * @access public
67
     * @param  string       $attr    关联属性
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 4 found
Loading history...
68
     * @param  string|array $append  追加属性名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
69
     * @return $this
70
     * @throws Exception
71
     */
72
    public function appendRelationAttr(string $attr, array $append)
73
    {
74
        $relation = App::parseName($attr, 1, false);
75
76
        if (isset($this->relation[$relation])) {
77
            $model = $this->relation[$relation];
78
        } else {
79
            $model = $this->getRelationData($this->$relation());
0 ignored issues
show
Bug introduced by
It seems like getRelationData() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

79
            /** @scrutinizer ignore-call */ 
80
            $model = $this->getRelationData($this->$relation());
Loading history...
80
        }
81
82
        if ($model instanceof Model) {
83
            foreach ($append as $key => $attr) {
84
                $key = is_numeric($key) ? $attr : $key;
85
                if (isset($this->data[$key])) {
86
                    throw new Exception('bind attr has exists:' . $key);
87
                } else {
88
                    $this->data[$key] = $model->$attr;
0 ignored issues
show
Bug Best Practice introduced by
The property data does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
89
                }
90
            }
91
        }
92
93
        return $this;
94
    }
95
96
    /**
97
     * 设置需要隐藏的输出属性
98
     * @access public
99
     * @param  array $hidden   属性列表
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 3 found
Loading history...
100
     * @return $this
101
     */
102
    public function hidden(array $hidden = [])
103
    {
104
        $this->hidden = $hidden;
105
106
        return $this;
107
    }
108
109
    /**
110
     * 设置需要输出的属性
111
     * @access public
112
     * @param  array $visible
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
113
     * @return $this
114
     */
115
    public function visible(array $visible = [])
116
    {
117
        $this->visible = $visible;
118
119
        return $this;
120
    }
121
122
    /**
123
     * 转换当前模型对象为数组
124
     * @access public
125
     * @return array
126
     */
127
    public function toArray(): array
128
    {
129
        $item       = [];
130
        $hasVisible = false;
131
132
        foreach ($this->visible as $key => $val) {
133
            if (is_string($val)) {
134
                if (strpos($val, '.')) {
135
                    list($relation, $name)      = explode('.', $val);
136
                    $this->visible[$relation][] = $name;
137
                } else {
138
                    $this->visible[$val] = true;
139
                    $hasVisible          = true;
140
                }
141
                unset($this->visible[$key]);
142
            }
143
        }
144
145
        foreach ($this->hidden as $key => $val) {
146
            if (is_string($val)) {
147
                if (strpos($val, '.')) {
148
                    list($relation, $name)     = explode('.', $val);
149
                    $this->hidden[$relation][] = $name;
150
                } else {
151
                    $this->hidden[$val] = true;
152
                }
153
                unset($this->hidden[$key]);
154
            }
155
        }
156
157
        // 合并关联数据
158
        $data = array_merge($this->data, $this->relation);
159
160
        foreach ($data as $key => $val) {
161
            if ($val instanceof Model || $val instanceof ModelCollection) {
162
                // 关联模型对象
163
                if (isset($this->visible[$key])) {
164
                    $val->visible($this->visible[$key]);
165
                } elseif (isset($this->hidden[$key])) {
166
                    $val->hidden($this->hidden[$key]);
167
                }
168
                // 关联模型对象
169
                $item[$key] = $val->toArray();
170
            } elseif (isset($this->visible[$key])) {
171
                $item[$key] = $this->getAttr($key);
0 ignored issues
show
Bug introduced by
The method getAttr() does not exist on think\model\concern\Conversion. Did you maybe mean getBindAttr()? ( Ignorable by Annotation )

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

171
                /** @scrutinizer ignore-call */ 
172
                $item[$key] = $this->getAttr($key);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
172
            } elseif (!isset($this->hidden[$key]) && !$hasVisible) {
173
                $item[$key] = $this->getAttr($key);
174
            }
175
        }
176
177
        // 追加属性(必须定义获取器)
178
        foreach ($this->append as $key => $name) {
179
            $this->appendAttrToArray($item, $key, $name);
180
        }
181
182
        return $item;
183
    }
184
185
    protected function appendAttrToArray(array &$item, $key, $name)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function appendAttrToArray()
Loading history...
186
    {
187
        if (is_array($name)) {
188
            // 追加关联对象属性
189
            $relation = $this->getRelation($key);
0 ignored issues
show
Bug introduced by
It seems like getRelation() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

189
            /** @scrutinizer ignore-call */ 
190
            $relation = $this->getRelation($key);
Loading history...
190
191
            if (!$relation) {
192
                $relation = $this->getAttr($key);
193
                $relation->visible($name);
194
            }
195
196
            $item[$key] = $relation->append($name)->toArray();
197
        } elseif (strpos($name, '.')) {
198
            list($key, $attr) = explode('.', $name);
199
            // 追加关联对象属性
200
            $relation = $this->getRelation($key);
201
202
            if (!$relation) {
203
                $relation = $this->getAttr($key);
204
                $relation->visible([$attr]);
205
            }
206
207
            $item[$key] = $relation->append([$attr])->toArray();
208
        } else {
209
            $value       = $this->getAttr($name);
210
            $item[$name] = $value;
211
212
            $this->getBindAttr($name, $value, $item);
213
        }
214
    }
215
216
    protected function getBindAttr(string $name, $value, array &$item = [])
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getBindAttr()
Loading history...
217
    {
218
        $relation = $this->isRelationAttr($name);
0 ignored issues
show
Bug introduced by
It seems like isRelationAttr() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

218
        /** @scrutinizer ignore-call */ 
219
        $relation = $this->isRelationAttr($name);
Loading history...
219
        if (!$relation) {
220
            return false;
221
        }
222
223
        $modelRelation = $this->$relation();
224
225
        if ($modelRelation instanceof OneToOne) {
226
            $bindAttr = $modelRelation->getBindAttr();
227
228
            if (!empty($bindAttr)) {
229
                unset($item[$name]);
230
            }
231
232
            foreach ($bindAttr as $key => $attr) {
233
                $key = is_numeric($key) ? $attr : $key;
234
235
                if (isset($item[$key])) {
236
                    throw new Exception('bind attr has exists:' . $key);
237
                }
238
239
                $item[$key] = $value ? $value->getAttr($attr) : null;
240
            }
241
        }
242
    }
243
244
    /**
245
     * 转换当前模型对象为JSON字符串
246
     * @access public
247
     * @param  integer $options json参数
248
     * @return string
249
     */
250
    public function toJson(int $options = JSON_UNESCAPED_UNICODE): string
251
    {
252
        return json_encode($this->toArray(), $options);
253
    }
254
255
    public function __toString()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __toString()
Loading history...
256
    {
257
        return $this->toJson();
258
    }
259
260
    // JsonSerializable
261
    public function jsonSerialize()
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
262
    {
263
        return $this->toArray();
264
    }
265
266
    /**
267
     * 转换数据集为数据集对象
268
     * @access public
269
     * @param  array|Collection $collection 数据集
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
270
     * @param  string           $resultSetType 数据集类
271
     * @return Collection
272
     */
273
    public function toCollection(iterable $collection = [], string $resultSetType = null): Collection
274
    {
275
        $resultSetType = $resultSetType ?: $this->resultSetType;
276
277
        if ($resultSetType && false !== strpos($resultSetType, '\\')) {
278
            $collection = new $resultSetType($collection);
279
        } else {
280
            $collection = new ModelCollection($collection);
281
        }
282
283
        return $collection;
284
    }
285
286
}
287