forked from sieppl/yii-json-dataprovider
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ModelToArrayConverter.php
174 lines (152 loc) · 5.06 KB
/
ModelToArrayConverter.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
<?php
class ModelToArrayConverter extends CComponent
{
protected $_models;
/**
*
* @var mixed If is set to null (default) all attributes of the model will be added.
* If a string is given, only this attribute will added.
* If an array of strings is given, all elements will be retrieved.
*/
protected $_attributes;
/**
*
* @var mixed If is set to null (default) no relations of the model will be added.
* If a string is given, only the mentioned relation will be added.
* If an array is given, there a two valid array formats:
*
* 1. array('relation1', 'relation2') will return the mentioned relations with all attributes, but no sub relations
* 2. array('relation1', 'relation2' => array('attributes' => array('foo', 'bar'), 'relations' => array('subRelation'))) will return configured attributes and relations for relation2
*
* Sub configurations of relations follow the same rules like the global configuration for attributes and relations
*/
protected $_relations;
/**
*
* @var array An array where the key is the original attribute name and the value the alias to be used instead when retrieving it. This will affect all retrieved models recursively.
*/
public $attributeAliases;
/**
*
* @var callable Callback to be called after an model was processed for json, the callback will receive the model itself, the attribute array and the relation array
*/
public $onAfterModelToArray = null;
/**
*
* @param mixed single $model or model array
* @param unknown_type $attributes
* @param unknown_type $relations
*/
public function __construct($models, $attributes = null, $relations = null)
{
$this->_models = $models;
$this->_attributes = $attributes;
$this->_relations = $relations;
}
/**
*
* @param CActiveRecord $model
* @param mixed $attributes If is set to null all attributes of the model will be added. If a string is given, only this attribute will added. If an array of strings is given, all elements will be retrieved.
* @param mixed $relations If is set to true, all relations will be retrieved. If a string is given, only one relation will be added. For array see the class definition of relations.
*/
protected function convertModel($model, $attributes = null, $relations = null)
{
$relationArray = array();
if ($attributes === null){
$attributes = array();
foreach ($model->attributes as $attr=>$type)
$attributes[] = $attr;
}
if ($relations === true || is_array($relations) || is_string($relations))
{
if ($relations === true)
{
//include all relations
$relations = array();
foreach ($model->getMetaData()->relations as $name => $relation)
{
$relations[] = $name;
}
}
if (is_string($relations))
$relations = array($relations);
foreach ($relations as $key => $relation)
{
$relAttributes = null;
$relRelations = null;
$relationName = $relation;
if (is_array($relation))
{
$relationName = $key;
if (!isset($relation['attributes']) && !isset($relation['relations']))
{
// for convenient configuration
$relAttributes = $relation;
}
else
{
$relAttributes = isset($relation['attributes']) ? $relation['attributes'] : null;
$relRelations = isset($relation['relations']) ? $relation['relations'] : null;
}
}
$relatedModels = $model->getRelated($relationName);
if (is_array($relatedModels))
{
foreach ($relatedModels as $relatedModel)
{
$relationArray[$relationName][] = $this->convertModel($relatedModel, $relAttributes, $relRelations);
}
}
else {
if ($relatedModels)
$relationArray[$relationName] = $this->convertModel($relatedModels, $relAttributes, $relRelations);
}
}
}
if (is_string($attributes))
$attributes = array($attributes);
if ($attributes === null)
$attributes = true;
foreach ($attributes as $attribute)
{
$attributeArray[$attribute] = $model->$attribute;
}
if ($this->attributeAliases)
{
$tempArray = array();
foreach ($attributeArray as $attributeName => $value)
{
if (isset($this->attributeAliases[$attributeName]))
{
$tempArray[$this->attributeAliases[$attributeName]] = $value;
}
else
$tempArray[$attributeName] = $value;
}
$attributeArray = $tempArray;
}
if ($this->onAfterModelToArray)
{
call_user_func_array($this->onAfterModelToArray, array($model, &$attributeArray, &$relationArray));
}
return array_merge($attributeArray, $relationArray);
}
public function convert()
{
if (is_array($this->_models))
{
$result = array();
foreach ($this->_models as $model)
{
$result[] = $this->convertModel($model, $this->_attributes, $this->_relations);
}
return $result;
}
else
return $this->convertModel($this->_models, $this->_attributes, $this->_relations);
}
public static function instance($models, $attributes = null, $relations = null)
{
return new ModelToArrayConverter($models, $attributes, $relations);
}
}