Diff: STRATO-apps/wordpress_03/app/wp-includes/class-wp-walker.php

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
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 +