1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* |
5
|
|
|
* @package sitemaker |
6
|
|
|
* @copyright (c) 2013 Daniel A. (blitze) |
7
|
|
|
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 |
8
|
|
|
* |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace blitze\sitemaker\services\menus; |
12
|
|
|
|
13
|
|
|
class display extends \blitze\sitemaker\services\tree\display |
14
|
|
|
{ |
15
|
|
|
/** @var \phpbb\user */ |
16
|
|
|
protected $user; |
17
|
|
|
|
18
|
|
|
/** @var bool */ |
19
|
|
|
private $expanded = true; |
20
|
|
|
|
21
|
|
|
/** @var integer */ |
22
|
|
|
private $max_depth = 100; |
23
|
|
|
|
24
|
|
|
/** @var integer */ |
25
|
|
|
private $min_depth = 0; |
26
|
|
|
|
27
|
|
|
/** @var array */ |
28
|
|
|
private $parental_depth; |
29
|
|
|
|
30
|
|
|
/** @var array */ |
31
|
|
|
private $current_item; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Construct |
35
|
|
|
* |
36
|
|
|
* @param \phpbb\db\driver\driver_interface $db Database connection |
37
|
|
|
* @param \phpbb\user $user User Object |
38
|
|
|
* @param string $menu_items_table Menu Items table |
39
|
|
|
* @param string $pk Primary key |
40
|
|
|
*/ |
41
|
|
|
public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, $menu_items_table, $pk) |
42
|
|
|
{ |
43
|
|
|
parent::__construct($db, $menu_items_table, $pk); |
44
|
|
|
|
45
|
|
|
$this->user = $user; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @param array $params |
50
|
|
|
* @return void |
51
|
|
|
*/ |
52
|
|
|
public function set_params(array $params) |
53
|
|
|
{ |
54
|
|
|
$this->expanded = (bool) ((isset($params['expanded'])) ? $params['expanded'] : true); |
55
|
|
|
$this->max_depth = (int) ((isset($params['max_depth'])) ? $params['max_depth'] : 100); |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @param array $data |
60
|
|
|
* @param \phpbb\template\twig\twig $template |
61
|
|
|
* @param string $handle |
62
|
|
|
* @return void |
63
|
|
|
*/ |
64
|
|
|
public function display_navlist(array $data, \phpbb\template\twig\twig &$template, $handle = 'tree') |
65
|
|
|
{ |
66
|
|
|
$this->set_current_item($data); |
67
|
|
|
$this->prepare_items($data['items']); |
68
|
|
|
|
69
|
|
|
if (sizeof($data['items'])) |
70
|
|
|
{ |
71
|
|
|
$this_depth = 0; |
72
|
|
|
foreach ($data['items'] as $row) |
73
|
|
|
{ |
74
|
|
|
$prev_depth = $row['prev_depth']; |
75
|
|
|
$this_depth = $row['this_depth']; |
76
|
|
|
$row['num_kids'] = $this->count_descendants($row); |
77
|
|
|
|
78
|
|
|
$template->assign_block_vars($handle, array_change_key_case($row, CASE_UPPER)); |
79
|
|
|
$this->close_open_tags($template, $handle . '.close', (int) abs($prev_depth - $this_depth)); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
$this->close_open_tags($template, 'close_' . $handle, ($this_depth - $this->min_depth)); |
83
|
|
|
} |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* @param array $data |
88
|
|
|
* @return bool |
89
|
|
|
*/ |
90
|
|
|
protected function set_current_item(array $data) |
91
|
|
|
{ |
92
|
|
|
$paths = (array) $data['paths']; |
93
|
|
|
$this->min_depth = 0; |
94
|
|
|
|
95
|
|
|
arsort($paths); |
96
|
|
|
|
97
|
|
|
$curr_path = $this->get_current_path(); |
98
|
|
|
foreach ($paths as $item_id => $test_url) |
99
|
|
|
{ |
100
|
|
|
if (strpos($curr_path, $test_url) !== false) |
101
|
|
|
{ |
102
|
|
|
$row = $data['items'][$item_id]; |
103
|
|
|
$this->adjust_depth($row); |
104
|
|
|
$this->current_item = $row; |
105
|
|
|
|
106
|
|
|
return true; |
107
|
|
|
} |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
$this->current_item = $this->default_current_item(); |
111
|
|
|
return false; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* @return string |
116
|
|
|
*/ |
117
|
|
|
protected function get_current_path() |
118
|
|
|
{ |
119
|
|
|
$curr_page = '/' . ltrim($this->user->page['page_dir'] . '/' . $this->user->page['page_name'], './'); |
120
|
|
|
$curr_parts = explode('&', $this->user->page['query_string']); |
121
|
|
|
|
122
|
|
|
sort($curr_parts); |
123
|
|
|
|
124
|
|
|
return $curr_page . '?' . join('&', $curr_parts); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* return void |
129
|
|
|
*/ |
130
|
|
|
protected function default_current_item() |
131
|
|
|
{ |
132
|
|
|
$this->max_depth = ($this->expanded) ? $this->max_depth : 0; |
133
|
|
|
$this->min_depth = 0; |
134
|
|
|
|
135
|
|
|
return array( |
136
|
|
|
$this->column_item_id => 0, |
137
|
|
|
$this->column_parent_id => 0, |
138
|
|
|
$this->column_left_id => 0, |
139
|
|
|
$this->column_right_id => 0, |
140
|
|
|
$this->column_depth => 0, |
141
|
|
|
); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* @param array $data |
146
|
|
|
* @return void |
147
|
|
|
*/ |
148
|
|
|
protected function prepare_items(array &$data) |
149
|
|
|
{ |
150
|
|
|
$leaf = array(); |
151
|
|
|
$prev_depth = $this->min_depth; |
152
|
|
|
$this->parental_depth = array(0 => -1); |
153
|
|
|
|
154
|
|
|
foreach ($data as $item_id => $row) |
155
|
|
|
{ |
156
|
|
|
// Skip branch |
157
|
|
|
if ($this->should_skip_branch($row, $leaf)) |
158
|
|
|
{ |
159
|
|
|
$this->adjust_right_id($leaf[$this->column_item_id], $data, $leaf); |
160
|
|
|
unset($data[$item_id]); |
161
|
|
|
continue; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
[$is_current_item, $is_parent] = $this->get_current_item($row); |
165
|
|
|
$this_depth = $this->get_parental_depth($row) + 1; |
166
|
|
|
$leaf = $this->get_leaf_node($row, $is_current_item, $is_parent); |
167
|
|
|
|
168
|
|
|
$this->parental_depth[$row[$this->pk]] = $this_depth; |
169
|
|
|
|
170
|
|
|
if ($row[$this->column_depth] < $this->min_depth) |
171
|
|
|
{ |
172
|
|
|
unset($data[$item_id]); |
173
|
|
|
continue; |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
$data[$item_id] = array_merge($data[$item_id], array( |
177
|
|
|
'prev_depth' => $prev_depth, |
178
|
|
|
'this_depth' => $this_depth, |
179
|
|
|
'is_current' => $is_current_item, |
180
|
|
|
'is_parent' => $is_parent, |
181
|
|
|
'full_url' => $this->get_full_url($row), |
182
|
|
|
)); |
183
|
|
|
|
184
|
|
|
$prev_depth = $this_depth; |
185
|
|
|
} |
186
|
|
|
unset($this->parental_depth, $data); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* @param array $row |
191
|
|
|
* @return int |
192
|
|
|
*/ |
193
|
|
|
protected function get_parental_depth(array $row) |
194
|
|
|
{ |
195
|
|
|
$parent_id = $row[$this->column_parent_id]; |
196
|
|
|
return isset($this->parental_depth[$parent_id]) ? $this->parental_depth[$parent_id] : -1; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
/** |
200
|
|
|
* @param array $row |
201
|
|
|
* @param array $leaf |
202
|
|
|
* @return bool |
203
|
|
|
*/ |
204
|
|
|
protected function should_skip_branch(array $row, array $leaf) |
205
|
|
|
{ |
206
|
|
|
return (sizeof($leaf) && $row[$this->column_left_id] < $leaf[$this->column_right_id]); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* @param array $row |
211
|
|
|
* @return array |
212
|
|
|
*/ |
213
|
|
|
protected function get_current_item(array $row) |
214
|
|
|
{ |
215
|
|
|
$is_current_item = $is_parent = false; |
216
|
|
|
|
217
|
|
|
if ($this->current_item) |
|
|
|
|
218
|
|
|
{ |
219
|
|
|
$is_current_item = $this->is_current_item($row); |
220
|
|
|
$is_parent = $this->is_parent_of_current_item($row); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
return [$is_current_item, $is_parent]; |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* @param array $row |
228
|
|
|
* @return bool |
229
|
|
|
*/ |
230
|
|
|
protected function is_current_item(array $row) |
231
|
|
|
{ |
232
|
|
|
return ($row[$this->column_item_id] === $this->current_item[$this->column_item_id]) ? true : false; |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
/** |
236
|
|
|
* @param array $row |
237
|
|
|
* @return bool |
238
|
|
|
*/ |
239
|
|
|
protected function is_parent_of_current_item(array $row) |
240
|
|
|
{ |
241
|
|
|
return ($row[$this->column_left_id] < $this->current_item[$this->column_left_id] && $row[$this->column_right_id] > $this->current_item[$this->column_right_id]) ? true : false; |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
/** |
245
|
|
|
* Does the branch end here? |
246
|
|
|
* |
247
|
|
|
* @param array $row |
248
|
|
|
* @param bool $is_current_item |
249
|
|
|
* @param bool $is_current_items_parent |
250
|
|
|
* @return array |
251
|
|
|
*/ |
252
|
|
|
protected function get_leaf_node(array $row, $is_current_item, $is_current_items_parent) |
253
|
|
|
{ |
254
|
|
|
return ($this->must_not_expand($row, $is_current_items_parent) && !$is_current_item && $row['is_expandable']) ? $row : array(); |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
/** |
258
|
|
|
* @param array $row |
259
|
|
|
* @param bool $is_current_items_parent |
260
|
|
|
* @return bool |
261
|
|
|
*/ |
262
|
|
|
protected function must_not_expand(array $row, $is_current_items_parent) |
263
|
|
|
{ |
264
|
|
|
return ($row[$this->column_depth] === $this->max_depth || !$is_current_items_parent && !$this->expanded) ? true : false; |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
/** |
268
|
|
|
* @param \phpbb\template\twig\twig $template |
269
|
|
|
* @param string $handle |
270
|
|
|
* @param int $repeat |
271
|
|
|
* @return void |
272
|
|
|
*/ |
273
|
|
|
protected function close_open_tags(\phpbb\template\twig\twig &$template, $handle, $repeat) |
274
|
|
|
{ |
275
|
|
|
for ($i = 0; $i < $repeat; $i++) |
276
|
|
|
{ |
277
|
|
|
$template->assign_block_vars($handle, array()); |
278
|
|
|
} |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
/** |
282
|
|
|
* @param int $items_depth |
283
|
|
|
* return bool |
284
|
|
|
* @return bool |
285
|
|
|
*/ |
286
|
|
|
protected function needs_adjustment($items_depth) |
287
|
|
|
{ |
288
|
|
|
return (!$this->expanded && $items_depth >= $this->max_depth) ? true : false; |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
/** |
292
|
|
|
* @param array $row |
293
|
|
|
* @return void |
294
|
|
|
*/ |
295
|
|
|
protected function adjust_depth(array $row) |
296
|
|
|
{ |
297
|
|
|
$depth = (int) $row[$this->column_depth]; |
298
|
|
|
if ($this->needs_adjustment($depth)) |
299
|
|
|
{ |
300
|
|
|
$adjustment = ($this->count_descendants($row)) ? 1 : 0; |
301
|
|
|
$this->set_depth_limits($depth, $adjustment); |
302
|
|
|
} |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
/** |
306
|
|
|
* @param int $item_id |
307
|
|
|
* @param array $data |
308
|
|
|
* @param array $leaf |
309
|
|
|
* @return void |
310
|
|
|
*/ |
311
|
|
|
protected function adjust_right_id($item_id, array &$data, array $leaf) |
312
|
|
|
{ |
313
|
|
|
if (isset($data[$item_id])) |
314
|
|
|
{ |
315
|
|
|
$data[$leaf[$this->column_item_id]][$this->column_right_id] -= 2; |
316
|
|
|
} |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
/** |
320
|
|
|
* Append session id to local, non-directory paths |
321
|
|
|
* |
322
|
|
|
* @param array $row |
323
|
|
|
* @return string |
324
|
|
|
*/ |
325
|
|
|
protected function get_full_url(array $row) |
326
|
|
|
{ |
327
|
|
|
$full_url = $row['full_url']; |
328
|
|
|
if ($row['is_navigable']) |
329
|
|
|
{ |
330
|
|
|
$full_url = append_sid($row['full_url'], false, false); |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
return $full_url; |
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
/** |
337
|
|
|
* @param int $depth |
338
|
|
|
* @param int $adjustment |
339
|
|
|
*/ |
340
|
|
|
protected function set_depth_limits($depth, $adjustment) |
341
|
|
|
{ |
342
|
|
|
$this->min_depth = ($this->max_depth && $depth >= $this->max_depth) ? $depth - $this->max_depth + $adjustment : 0; |
343
|
|
|
$this->max_depth = $depth + $adjustment; |
344
|
|
|
} |
345
|
|
|
} |
346
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.