1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace EventEspresso\core\services\orm\tree_traversal; |
4
|
|
|
|
5
|
|
|
use EE_Base_Class; |
6
|
|
|
use Exception; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* Class ModelObjNodeTreeDTO |
10
|
|
|
* |
11
|
|
|
* Class for storing the discovered tree of model object dependencies. It is stored in a format that can be easily and |
12
|
|
|
* efficiently serialized for persistence, and unserialized with minimal memory usage, and so we can pickup where |
13
|
|
|
* we left off. |
14
|
|
|
* A tree of objects would be more convenient (my original implementation used that) but we'd need to either unserialize |
15
|
|
|
* to a PHP array and then ALSO build that data structure (which would be trouble when there could be thousands of |
16
|
|
|
* entries); or we'd need to write our own parser (which was fun excercise in school, but no thank you.) |
17
|
|
|
* |
18
|
|
|
* @package Event Espresso |
19
|
|
|
* @author Mike Nelson |
20
|
|
|
* @since $VID:$ |
21
|
|
|
* |
22
|
|
|
*/ |
23
|
|
|
class ModelObjNodeTreeDTO |
24
|
|
|
{ |
25
|
|
|
const INDEX_PATH = 'ip'; |
26
|
|
|
const ROOTS = 'rts'; |
27
|
|
|
const MODEL = 'm'; |
28
|
|
|
const ITEMS = 'i'; |
29
|
|
|
const ID = 'id'; |
30
|
|
|
const RELATIONSHIPS = 'r'; |
31
|
|
|
const COUNT = 'c'; |
32
|
|
|
/** |
33
|
|
|
* @var array with a special structure. Like the following: |
34
|
|
|
* { |
35
|
|
|
* "index_path": [0,3,1,2], |
36
|
|
|
* "roots": [ |
37
|
|
|
* { |
38
|
|
|
* "model": "Event", |
39
|
|
|
* "items": [ |
40
|
|
|
* { |
41
|
|
|
* "id": 123, |
42
|
|
|
* "rels": [ |
43
|
|
|
* { |
44
|
|
|
* "model": "Datetime" |
45
|
|
|
* "count": 3 |
46
|
|
|
* "items": [ |
47
|
|
|
* { |
48
|
|
|
* "id": 456, |
49
|
|
|
* "rels": [ |
50
|
|
|
* { |
51
|
|
|
* "model": "Datetime_Ticket", |
52
|
|
|
* "count": 1, |
53
|
|
|
* "items": [ |
54
|
|
|
* { |
55
|
|
|
* "id": 789, |
56
|
|
|
* "rels": [ |
57
|
|
|
* { |
58
|
|
|
* "model": "Extra_Meta", |
59
|
|
|
* "count": 0, |
60
|
|
|
* "items":[], |
61
|
|
|
* } |
62
|
|
|
* // ... other models that have foreign keys to Datetime_Ticket |
63
|
|
|
* ] |
64
|
|
|
* }. |
65
|
|
|
* ] |
66
|
|
|
* }, |
67
|
|
|
* // ... other models that have foreign keys to Datetime |
68
|
|
|
* ] |
69
|
|
|
* }, |
70
|
|
|
* // ... 2 more datetimes (unless we haven't fetched them from the DB yet. The count |
71
|
|
|
* // is useful here to know if we need to fetch more or not |
72
|
|
|
* ] |
73
|
|
|
* }, |
74
|
|
|
* // ...other models that have foreign keys to events, including implicit join models |
75
|
|
|
* ] |
76
|
|
|
* }, |
77
|
|
|
* // ...other root events that we want to traverse |
78
|
|
|
* ], |
79
|
|
|
* /// ...other models with root nodes |
80
|
|
|
* } |
81
|
|
|
*/ |
82
|
|
|
protected $data; |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* @since $VID:$ |
86
|
|
|
* @param EE_Base_Class[] $model_objs |
87
|
|
|
*/ |
88
|
|
|
public function initializeRootNodes($model_objs){ |
89
|
|
|
$this->data = [ |
90
|
|
|
self::INDEX_PATH => [0,0], |
91
|
|
|
self::ROOTS => [] |
92
|
|
|
]; |
93
|
|
|
foreach($model_objs as $model_obj) { |
94
|
|
|
if (!$model_obj instanceof EE_Base_Class) { |
95
|
|
|
throw new \InvalidArgumentException(esc_html__('You must initialize a ModelObjNodeTreeDTO with an array of EE_Base_Class.', 'event_espresso')); |
96
|
|
|
} |
97
|
|
|
if (!isset($this->data[ self::ROOTS ])){ |
98
|
|
|
$this->data[ self::ROOTS ][ $model_obj->get_model()->get_this_model_name() ] = []; |
99
|
|
|
} |
100
|
|
|
$this->data[self::ROOTS][$model_obj->get_model()->get_this_model_name()][] = [ |
101
|
|
|
self::ID => $model_obj->ID(), |
102
|
|
|
self::RELATIONSHIPS => [] |
103
|
|
|
]; |
104
|
|
|
} |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @since $VID:$ |
109
|
|
|
* @param array $data |
110
|
|
|
*/ |
111
|
|
|
public function loadData(&$data) |
112
|
|
|
{ |
113
|
|
|
$this->data = $data; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Returns a reference to the data (so it's not duplicated, because it could be really big). |
118
|
|
|
* @since $VID:$ |
119
|
|
|
* @return array |
120
|
|
|
*/ |
121
|
|
|
public function &getData() |
122
|
|
|
{ |
123
|
|
|
return $this->data; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* @since $VID:$ |
128
|
|
|
* @param EE_Base_Class $model_obj |
129
|
|
|
*/ |
130
|
|
|
public function addDiscoveredItem($model_obj){ |
131
|
|
|
// Figure out where our current spot in the tree. |
132
|
|
|
$current_items_list = $this->getCurrentItemList(); |
|
|
|
|
133
|
|
|
|
134
|
|
|
// Ensure the data is of the correct type. |
135
|
|
|
|
136
|
|
|
// Add data that corresponds to it to that spot. |
137
|
|
|
|
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* Returns a list of indexes to follow. |
142
|
|
|
* @since $VID:$ |
143
|
|
|
* @return array |
144
|
|
|
*/ |
145
|
|
|
protected function getIndexPath() |
146
|
|
|
{ |
147
|
|
|
return $this->data[self::INDEX_PATH]; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* @since $VID:$ |
152
|
|
|
*/ |
153
|
|
|
public function getCurrentItemList() |
154
|
|
|
{ |
155
|
|
|
$traverser = &$this->data[ self::ROOTS ]; |
156
|
|
|
foreach ($this->getIndexPath() as $index) { |
157
|
|
|
if (isset($traverser[ $index ])) { |
158
|
|
|
if (isset($traverser[ $index ][ self::ID ])) { |
159
|
|
|
$traverser = &$traverser[ $index ][ self::RELATIONSHIPS ]; |
160
|
|
|
} else { |
161
|
|
|
$traverser = &$traverser[ $index ][ self::ITEMS ]; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
} else { |
165
|
|
|
throw new Exception(esc_html__('Index out of sync', 'event_espresso')); |
166
|
|
|
} |
167
|
|
|
} |
168
|
|
|
return $traverser; |
169
|
|
|
} |
170
|
|
|
} |
171
|
|
|
// End of file ModelObjNodeTreeDTO.php |
172
|
|
|
// Location: EventEspresso\core\services\orm\tree_traversal/ModelObjNodeTreeDTO.php |
173
|
|
|
|
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVar
assignment in line 1 and the$higher
assignment in line 2 are dead. The first because$myVar
is never used and the second because$higher
is always overwritten for every possible time line.