-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMorrayBehavior.php
127 lines (100 loc) · 4.45 KB
/
MorrayBehavior.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
<?php
/**
* MorrayBehavior (Model to Array Behavior)
*
* ver 1.0 | https://github.com/Arne-S/Morray
*
* Converts an AR model to an array, retaining associated relations.
*
**/
class MorrayBehavior extends CBehavior
{
public function toArray($opts=array())
{
// option 'scenario', use a scenario to only display safe attributes
// default: empty (no scenario)
if (!isset($opts['scenario'])) $opts['scenario'] = "";
// option 'relname', key name of the array holding the relations
// use empty string to use no new array for relations
if (!isset($opts['relname'])) $opts['relname'] = "";
// get the owner class
$owner = $this->getOwner();
// check if the owner class is an AR class
if (is_subclass_of($owner, 'CActiveRecord')) {
// this function recursively loops all attributes and relations of a supplied object
// return the result by calling the recursive function
return $this->loop($owner, $opts);
}
return false;
}
public function loop($obj, $opts = array(), $arr = array())
{
// store current object attribute values
$attributes = $obj->attributes;
// check if user supplied a scenario, and if this object has any rules
if ((!empty($opts['scenario'])) && (is_array($obj->rules()))) {
// loop the rules, search for a matching scenario
foreach ($obj->rules() as $rule) {
// check if this scenario name matches the supplied one
if (isset($rule['on']) && $rule['on'] == $opts['scenario']) {
// check if this is the 'safe' option
if (isset($rule[1]) && $rule[1] == "safe") {
// put the safe attributes in an array
$safe_attributes = explode(",", $rule[0]);
// new array for putting only the values of the safe attributes
$attributes_values = array();
// loop the safe attributes
foreach ($safe_attributes as $safe_attribute) {
// trim in case there are any spaces
$safe_attribute = trim($safe_attribute);
// get attribute from object
$attributes_values[$safe_attribute] = $obj->{$safe_attribute};
}
// assign the safe attributes over the the array containing all the attributes
$attributes = $attributes_values;
}
}
}
}
// assign the attributes of current rel to array
$arr = $attributes;
// get relations from current rel
$relations = $obj->relations();
// put the keys (rel names) in an array
if ($rel_ids = array_keys($relations)) {
// loop relations
foreach ($rel_ids as $rel_id) {
// check if sub rel is loaded (using scopes or 'with')
if ($obj->hasRelated($rel_id)) {
$rel = $obj->{$rel_id};
// if sub rel is an object, there is 1 rel being returned
if (is_object($rel)) {
// if relname is supplied, use that to store the rel in
if (!empty($opts['relname'])) {
$arr[$opts['relname']][$rel_id] = $this->loop($rel, $opts, $arr);
}
else {
// if no relname is supplied, store directly in current array
$arr[$rel_id] = $this->loop($rel, $opts, $arr);
}
}
// if sub rel is an array, there are multiple relations being returned
if (is_array($rel)) {
// do a foreach on each sub rel
foreach ($rel as $sub_rel) {
// if relname is supplied, use that to store the rel in
if (!empty($opts['relname'])) {
$arr[$opts['relname']][$rel_id][] = $this->loop($sub_rel, $opts, $arr);
}
else {
// if no relname is supplied, store directly in current array
$arr[$rel_id][] = $this->loop($sub_rel, $opts, $arr);
}
}
}
}
}
}
return $arr;
}
}