Diff: STRATO-apps/wordpress_03/app/wp-includes/class-wp-walker.php
Keine Baseline-Datei – Diff nur gegen leer.
1
-
1
+
<?php
2
+
/**
3
+
* A class for displaying various tree-like structures.
4
+
*
5
+
* Extend the Walker class to use it, see examples below. Child classes
6
+
* do not need to implement all of the abstract methods in the class. The child
7
+
* only needs to implement the methods that are needed.
8
+
*
9
+
* @since 2.1.0
10
+
*
11
+
* @package WordPress
12
+
* @abstract
13
+
*/
14
+
#[AllowDynamicProperties]
15
+
class Walker {
16
+
/**
17
+
* What the class handles.
18
+
*
19
+
* @since 2.1.0
20
+
* @var string
21
+
*/
22
+
public $tree_type;
23
+
24
+
/**
25
+
* DB fields to use.
26
+
*
27
+
* @since 2.1.0
28
+
* @var string[]
29
+
*/
30
+
public $db_fields;
31
+
32
+
/**
33
+
* Max number of pages walked by the paged walker.
34
+
*
35
+
* @since 2.7.0
36
+
* @var int
37
+
*/
38
+
public $max_pages = 1;
39
+
40
+
/**
41
+
* Whether the current element has children or not.
42
+
*
43
+
* To be used in start_el().
44
+
*
45
+
* @since 4.0.0
46
+
* @var bool
47
+
*/
48
+
public $has_children;
49
+
50
+
/**
51
+
* Starts the list before the elements are added.
52
+
*
53
+
* The $args parameter holds additional values that may be used with the child
54
+
* class methods. This method is called at the start of the output list.
55
+
*
56
+
* @since 2.1.0
57
+
* @abstract
58
+
*
59
+
* @param string $output Used to append additional content (passed by reference).
60
+
* @param int $depth Depth of the item.
61
+
* @param array $args An array of additional arguments.
62
+
*/
63
+
public function start_lvl( &$output, $depth = 0, $args = array() ) {}
64
+
65
+
/**
66
+
* Ends the list of after the elements are added.
67
+
*
68
+
* The $args parameter holds additional values that may be used with the child
69
+
* class methods. This method finishes the list at the end of output of the elements.
70
+
*
71
+
* @since 2.1.0
72
+
* @abstract
73
+
*
74
+
* @param string $output Used to append additional content (passed by reference).
75
+
* @param int $depth Depth of the item.
76
+
* @param array $args An array of additional arguments.
77
+
*/
78
+
public function end_lvl( &$output, $depth = 0, $args = array() ) {}
79
+
80
+
/**
81
+
* Starts the element output.
82
+
*
83
+
* The $args parameter holds additional values that may be used with the child
84
+
* class methods. Also includes the element output.
85
+
*
86
+
* @since 2.1.0
87
+
* @since 5.9.0 Renamed `$object` (a PHP reserved keyword) to `$data_object` for PHP 8 named parameter support.
88
+
* @abstract
89
+
*
90
+
* @param string $output Used to append additional content (passed by reference).
91
+
* @param object $data_object The data object.
92
+
* @param int $depth Depth of the item.
93
+
* @param array $args An array of additional arguments.
94
+
* @param int $current_object_id Optional. ID of the current item. Default 0.
95
+
*/
96
+
public function start_el( &$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0 ) {}
97
+
98
+
/**
99
+
* Ends the element output, if needed.
100
+
*
101
+
* The $args parameter holds additional values that may be used with the child class methods.
102
+
*
103
+
* @since 2.1.0
104
+
* @since 5.9.0 Renamed `$object` (a PHP reserved keyword) to `$data_object` for PHP 8 named parameter support.
105
+
* @abstract
106
+
*
107
+
* @param string $output Used to append additional content (passed by reference).
108
+
* @param object $data_object The data object.
109
+
* @param int $depth Depth of the item.
110
+
* @param array $args An array of additional arguments.
111
+
*/
112
+
public function end_el( &$output, $data_object, $depth = 0, $args = array() ) {}
113
+
114
+
/**
115
+
* Traverses elements to create list from elements.
116
+
*
117
+
* Display one element if the element doesn't have any children otherwise,
118
+
* display the element and its children. Will only traverse up to the max
119
+
* depth and no ignore elements under that depth. It is possible to set the
120
+
* max depth to include all depths, see walk() method.
121
+
*
122
+
* This method should not be called directly, use the walk() method instead.
123
+
*
124
+
* @since 2.5.0
125
+
*
126
+
* @param object $element Data object.
127
+
* @param array $children_elements List of elements to continue traversing (passed by reference).
128
+
* @param int $max_depth Max depth to traverse.
129
+
* @param int $depth Depth of current element.
130
+
* @param array $args An array of arguments.
131
+
* @param string $output Used to append additional content (passed by reference).
132
+
*/
133
+
public function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) {
134
+
if ( ! $element ) {
135
+
return;
136
+
}
137
+
138
+
$max_depth = (int) $max_depth;
139
+
$depth = (int) $depth;
140
+
141
+
$id_field = $this->db_fields['id'];
142
+
$id = $element->$id_field;
143
+
144
+
// Display this element.
145
+
$this->has_children = ! empty( $children_elements[ $id ] );
146
+
if ( isset( $args[0] ) && is_array( $args[0] ) ) {
147
+
$args[0]['has_children'] = $this->has_children; // Back-compat.
148
+
}
149
+
150
+
$this->start_el( $output, $element, $depth, ...array_values( $args ) );
151
+
152
+
// Descend only when the depth is right and there are children for this element.
153
+
if ( ( 0 === $max_depth || $max_depth > $depth + 1 ) && isset( $children_elements[ $id ] ) ) {
154
+
155
+
foreach ( $children_elements[ $id ] as $child ) {
156
+
157
+
if ( ! isset( $newlevel ) ) {
158
+
$newlevel = true;
159
+
// Start the child delimiter.
160
+
$this->start_lvl( $output, $depth, ...array_values( $args ) );
161
+
}
162
+
$this->display_element( $child, $children_elements, $max_depth, $depth + 1, $args, $output );
163
+
}
164
+
unset( $children_elements[ $id ] );
165
+
}
166
+
167
+
if ( isset( $newlevel ) && $newlevel ) {
168
+
// End the child delimiter.
169
+
$this->end_lvl( $output, $depth, ...array_values( $args ) );
170
+
}
171
+
172
+
// End this element.
173
+
$this->end_el( $output, $element, $depth, ...array_values( $args ) );
174
+
}
175
+
176
+
/**
177
+
* Displays array of elements hierarchically.
178
+
*
179
+
* Does not assume any existing order of elements.
180
+
*
181
+
* $max_depth = -1 means flatly display every element.
182
+
* $max_depth = 0 means display all levels.
183
+
* $max_depth > 0 specifies the number of display levels.
184
+
*
185
+
* @since 2.1.0
186
+
* @since 5.3.0 Formalized the existing `...$args` parameter by adding it
187
+
* to the function signature.
188
+
*
189
+
* @param array $elements An array of elements.
190
+
* @param int $max_depth The maximum hierarchical depth.
191
+
* @param mixed ...$args Optional additional arguments.
192
+
* @return string The hierarchical item output.
193
+
*/
194
+
public function walk( $elements, $max_depth, ...$args ) {
195
+
$output = '';
196
+
197
+
$max_depth = (int) $max_depth;
198
+
199
+
// Invalid parameter or nothing to walk.
200
+
if ( $max_depth < -1 || empty( $elements ) ) {
201
+
return $output;
202
+
}
203
+
204
+
$parent_field = $this->db_fields['parent'];
205
+
206
+
// Flat display.
207
+
if ( -1 === $max_depth ) {
208
+
$empty_array = array();
209
+
foreach ( $elements as $e ) {
210
+
$this->display_element( $e, $empty_array, 1, 0, $args, $output );
211
+
}
212
+
return $output;
213
+
}
214
+
215
+
/*
216
+
* Need to display in hierarchical order.
217
+
* Separate elements into two buckets: top level and children elements.
218
+
* Children_elements is two dimensional array. Example:
219
+
* Children_elements[10][] contains all sub-elements whose parent is 10.
220
+
*/
221
+
$top_level_elements = array();
222
+
$children_elements = array();
223
+
foreach ( $elements as $e ) {
224
+
if ( empty( $e->$parent_field ) ) {
225
+
$top_level_elements[] = $e;
226
+
} else {
227
+
$children_elements[ $e->$parent_field ][] = $e;
228
+
}
229
+
}
230
+
231
+
/*
232
+
* When none of the elements is top level.
233
+
* Assume the first one must be root of the sub elements.
234
+
*/
235
+
if ( empty( $top_level_elements ) ) {
236
+
237
+
$first = array_slice( $elements, 0, 1 );
238
+
$root = $first[0];
239
+
240
+
$top_level_elements = array();
241
+
$children_elements = array();
242
+
foreach ( $elements as $e ) {
243
+
if ( $root->$parent_field === $e->$parent_field ) {
244
+
$top_level_elements[] = $e;
245
+
} else {
246
+
$children_elements[ $e->$parent_field ][] = $e;
247
+
}
248
+
}
249
+
}
250
+
251
+
foreach ( $top_level_elements as $e ) {
252
+
$this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );
253
+
}
254
+
255
+
/*
256
+
* If we are displaying all levels, and remaining children_elements is not empty,
257
+
* then we got orphans, which should be displayed regardless.
258
+
*/
259
+
if ( ( 0 === $max_depth ) && count( $children_elements ) > 0 ) {
260
+
$empty_array = array();
261
+
foreach ( $children_elements as $orphans ) {
262
+
foreach ( $orphans as $op ) {
263
+
$this->display_element( $op, $empty_array, 1, 0, $args, $output );
264
+
}
265
+
}
266
+
}
267
+
268
+
return $output;
269
+
}
270
+
271
+
/**
272
+
* Produces a page of nested elements.
273
+
*
274
+
* Given an array of hierarchical elements, the maximum depth, a specific page number,
275
+
* and number of elements per page, this function first determines all top level root elements
276
+
* belonging to that page, then lists them and all of their children in hierarchical order.
277
+
*
278
+
* $max_depth = 0 means display all levels.
279
+
* $max_depth > 0 specifies the number of display levels.
280
+
*
281
+
* @since 2.7.0
282
+
* @since 5.3.0 Formalized the existing `...$args` parameter by adding it
283
+
* to the function signature.
284
+
*
285
+
* @param array $elements An array of elements.
286
+
* @param int $max_depth The maximum hierarchical depth.
287
+
* @param int $page_num The specific page number, beginning with 1.
288
+
* @param int $per_page Number of elements per page.
289
+
* @param mixed ...$args Optional additional arguments.
290
+
* @return string XHTML of the specified page of elements.
291
+
*/
292
+
public function paged_walk( $elements, $max_depth, $page_num, $per_page, ...$args ) {
293
+
$output = '';
294
+
295
+
$max_depth = (int) $max_depth;
296
+
297
+
if ( empty( $elements ) || $max_depth < -1 ) {
298
+
return $output;
299
+
}
300
+
301
+
$parent_field = $this->db_fields['parent'];
302
+
303
+
$count = -1;
304
+
if ( -1 === $max_depth ) {
305
+
$total_top = count( $elements );
306
+
}
307
+
if ( $page_num < 1 || $per_page < 0 ) {
308
+
// No paging.
309
+
$paging = false;
310
+
$start = 0;
311
+
if ( -1 === $max_depth ) {
312
+
$end = $total_top;
313
+
}
314
+
$this->max_pages = 1;
315
+
} else {
316
+
$paging = true;
317
+
$start = ( (int) $page_num - 1 ) * (int) $per_page;
318
+
$end = $start + $per_page;
319
+
if ( -1 === $max_depth ) {
320
+
$this->max_pages = (int) ceil( $total_top / $per_page );
321
+
}
322
+
}
323
+
324
+
// Flat display.
325
+
if ( -1 === $max_depth ) {
326
+
if ( ! empty( $args[0]['reverse_top_level'] ) ) {
327
+
$elements = array_reverse( $elements );
328
+
$oldstart = $start;
329
+
$start = $total_top - $end;
330
+
$end = $total_top - $oldstart;
331
+
}
332
+
333
+
$empty_array = array();
334
+
foreach ( $elements as $e ) {
335
+
++$count;
336
+
if ( $count < $start ) {
337
+
continue;
338
+
}
339
+
if ( $count >= $end ) {
340
+
break;
341
+
}
342
+
$this->display_element( $e, $empty_array, 1, 0, $args, $output );
343
+
}
344
+
return $output;
345
+
}
346
+
347
+
/*
348
+
* Separate elements into two buckets: top level and children elements.
349
+
* Children_elements is two dimensional array, e.g.
350
+
* $children_elements[10][] contains all sub-elements whose parent is 10.
351
+
*/
352
+
$top_level_elements = array();
353
+
$children_elements = array();
354
+
foreach ( $elements as $e ) {
355
+
if ( empty( $e->$parent_field ) ) {
356
+
$top_level_elements[] = $e;
357
+
} else {
358
+
$children_elements[ $e->$parent_field ][] = $e;
359
+
}
360
+
}
361
+
362
+
$total_top = count( $top_level_elements );
363
+
if ( $paging ) {
364
+
$this->max_pages = (int) ceil( $total_top / $per_page );
365
+
} else {
366
+
$end = $total_top;
367
+
}
368
+
369
+
if ( ! empty( $args[0]['reverse_top_level'] ) ) {
370
+
$top_level_elements = array_reverse( $top_level_elements );
371
+
$oldstart = $start;
372
+
$start = $total_top - $end;
373
+
$end = $total_top - $oldstart;
374
+
}
375
+
if ( ! empty( $args[0]['reverse_children'] ) ) {
376
+
foreach ( $children_elements as $parent => $children ) {
377
+
$children_elements[ $parent ] = array_reverse( $children );
378
+
}
379
+
}
380
+
381
+
foreach ( $top_level_elements as $e ) {
382
+
++$count;
383
+
384
+
// For the last page, need to unset earlier children in order to keep track of orphans.
385
+
if ( $end >= $total_top && $count < $start ) {
386
+
$this->unset_children( $e, $children_elements );
387
+
}
388
+
389
+
if ( $count < $start ) {
390
+
continue;
391
+
}
392
+
393
+
if ( $count >= $end ) {
394
+
break;
395
+
}
396
+
397
+
$this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );
398
+
}
399
+
400
+
if ( $end >= $total_top && count( $children_elements ) > 0 ) {
401
+
$empty_array = array();
402
+
foreach ( $children_elements as $orphans ) {
403
+
foreach ( $orphans as $op ) {
404
+
$this->display_element( $op, $empty_array, 1, 0, $args, $output );
405
+
}
406
+
}
407
+
}
408
+
409
+
return $output;
410
+
}
411
+
412
+
/**
413
+
* Calculates the total number of root elements.
414
+
*
415
+
* @since 2.7.0
416
+
*
417
+
* @param array $elements Elements to list.
418
+
* @return int Number of root elements.
419
+
*/
420
+
public function get_number_of_root_elements( $elements ) {
421
+
$num = 0;
422
+
$parent_field = $this->db_fields['parent'];
423
+
424
+
foreach ( $elements as $e ) {
425
+
if ( empty( $e->$parent_field ) ) {
426
+
++$num;
427
+
}
428
+
}
429
+
return $num;
430
+
}
431
+
432
+
/**
433
+
* Unsets all the children for a given top level element.
434
+
*
435
+
* @since 2.7.0
436
+
*
437
+
* @param object $element The top level element.
438
+
* @param array $children_elements The children elements.
439
+
*/
440
+
public function unset_children( $element, &$children_elements ) {
441
+
if ( ! $element || ! $children_elements ) {
442
+
return;
443
+
}
444
+
445
+
$id_field = $this->db_fields['id'];
446
+
$id = $element->$id_field;
447
+
448
+
if ( ! empty( $children_elements[ $id ] ) && is_array( $children_elements[ $id ] ) ) {
449
+
foreach ( (array) $children_elements[ $id ] as $child ) {
450
+
$this->unset_children( $child, $children_elements );
451
+
}
452
+
}
453
+
454
+
unset( $children_elements[ $id ] );
455
+
}
456
+
}
457
+