Основний метод, який запускається першим. Повертає сформований HTML код на основі переданого масиву об’єктів елементів, з яких треба побудувати список або іншу структуру (плоску або деревоподібну). Працює на основі методу display_element() .
Відображає один елемент, якщо дочірніх елементів немає або більше, якщо є. Коли елемент має вкладеність, то метод замикається сам на себе, проходячи всі рівні вкладеності вглиб. Максимальна вкладеність визначена аргументом $max_depth. Якщо $max_depth = 1 , будуть оброблені лише елементи першого рівня, а дочірні пропущені. Цей метод не слід викликати безпосередньо, натомість використовуйте метод walk() . Для формування елементів використовує методи start_el() -> start_lvl() -> end_lvl() -> end_el() .
Створює сторінку вкладених елементів. Враховуючи масив ієрархічних елементів, максимальну глибину, конкретний номер сторінки та кількість елементів на сторінці, цей метод спочатку визначає всі кореневі елементи верхнього рівня, що належать цій сторінці, а потім перераховує їх та всіх дітей у ієрархічному порядку. Працює на основі методів display_element() і unset_children . Наочним прикладом є використання методу класом Walker_Comment , створюючи список із коментарів, у тому числі й дочірніх.
Відкріплює всі дочірні елементи від заданого верхнього рівня. Метод замикається сам на себе у випадку, якщо вкладеність більша за 1, щоб обійти всю ієрархію переданих елементів.
class Walker {
/**
* What the class handles.
*
* @ Since 2.1.0
* @var string
*/
public $tree_type;
/**
* DB fields to use.
*
* @ Since 2.1.0
* @var string[]
*/
public $db_fields;
/**
Max number of pages walked by the paged walker.
*
* @ Since 2.7.0
* @var int
*/
$max_pages = 1;
/**
* Який поточний елемент має children or not.
*
* To be used in start_el().
*
* @ Since 4.0.0
* @var bool
*/
public $has_children;
/**
* Starts the list before the elements are added.
*
* The $args parameter holds additional values that may be used with the child
* class methods. Цей метод називається запуском output list.
*
* @ Since 2.1.0
* @abstract
*
* @param string $output Використовується для отримання додаткового вмісту (passed by reference).
* @param int $depth Відповідь на тему.
* @param array $args На array of additional arguments.
*/
public function start_lvl( &$output, $depth = 0, $args = array() ) {}
/**
* Ends the list of after the elements are added.
*
* The $args parameter holds additional values that may be used with the child
* class methods. Цей метод вказує на те, що лист наприкінці випуску елементів.
*
* @ Since 2.1.0
* @abstract
*
* @param string $output Використовується для отримання додаткового вмісту (passed by reference).
* @param int $depth Відповідь на тему.
* @param array $args На array of additional arguments.
*/
public function end_lvl( &$output, $depth = 0, $args = array() ) {}
/**
* Starts the element output.
*
* The $args parameter holds additional values that may be used with the child
* class methods. Також включають елемент output.
*
* @ Since 2.1.0
* @since 5.9.0 Renamed `$object` (a PHP reserved keyword) до `$data_object` для PHP 8 намічений параметр підтримки.
* @abstract
*
* @param string $output Використовується для отримання додаткового вмісту (passed by reference).
* @param object $data_object The data object.
* @param int $depth Відповідь на тему.
* @param array $args На array of additional arguments.
* @param int $current_object_id Optional. ID of the current item. Default 0
*/
public function start_el( &$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0 ) {}
/**
* Ends the element output, if needed.
*
* The $args parameter holds additional values that may be used with the child class methods.
*
* @ Since 2.1.0
* @since 5.9.0 Renamed `$object` (a PHP reserved keyword) до `$data_object` для PHP 8 намічений параметр підтримки.
* @abstract
*
* @param string $output Використовується для отримання додаткового вмісту (passed by reference).
* @param object $data_object The data object.
* @param int $depth Відповідь на тему.
* @param array $args На array of additional arguments.
*/
public function end_el( &$output, $data_object, $depth = 0, $args = array() ) {}
/**
* Traverses elements to create list from elements.
*
* Відтворення одного елемента, якщо елемент не має будь-яких дітей з іншогоwise,
* Display the element and its children. Will тільки traverse up to the max
* depth and no ignore elements under that depth. It is possible to set the
* max depth включати all depths, see walk() method.
*
* Цей метод не повинен бути названий безпосередньо, використовуючи walk() метод instead.
*
* @ Since 2.5.0
*
* @param object $element Data object.
* @param array $children_elements List of elements to continue traversing (passed by reference).
* @param int $max_depth Max depth to traverse.
* @param int $depth Depth of current element.
* @param array $args An array of arguments.
* @param string $output Використовується для отримання додаткового вмісту (passed by reference).
*/
public function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) {
if ( ! $element ) {
return;
}
$id_field = $this->db_fields['id'];
$id = $element->$id_field;
// Display this element.
$this->has_children = ! empty($children_elements[$id]);
if ( isset( $args[0] ) && is_array( $args[0] ) ) {
$args[0]['has_children'] = $this->has_children; // Back-compat.
}
$this->start_el( $output, $element, $depth, ...array_values( $args ) );
// Descend only when the depth is right and there are children for this element.
if ( ( 0 == $max_depth || $max_depth > $depth + 1 ) && isset( $children_elements[ $id ] ) ) {
foreach ( $children_elements[ $id ] as $child ) {
if ( ! isset ( $ newlevel ) ) {
$newlevel = true;
// Start the child delimiter.
$this->start_lvl( $output, $depth, ...array_values( $args ) );
}
$this->display_element( $child, $children_elements, $max_depth, $depth + 1, $args, $output );
}
unset($children_elements[$id]);
}
if ( isset( $newlevel ) && $newlevel ) {
// End the child delimiter.
$this->end_lvl( $output, $depth, ...array_values( $args ) );
}
// End this element.
$this->end_el( $output, $element, $depth, ...array_values( $args ) );
}
/**
* Displays array of elements hierarchically.
*
* Does not assume any existing order of elements.
*
* $max_depth = -1 means flatly display every element.
* $max_depth = 0 means display all levels.
* $max_depth > 0 specifies the number of display levels.
*
* @ Since 2.1.0
* @since 5.3.0 Formalized the existing `...$args` parameter by adding it
* до функції signature.
*
* @param array $elements An array of elements.
* @param int $max_depth The maximum hierarchical depth.
* @param mixed ...$args Optional additional arguments.
* @Return string The hierarchical item output.
*/
public function walk( $elements, $max_depth, ...$args ) {
$output = '';
// Invalid parameter or nothing to walk.
if ( $max_depth < -1 || empty( $elements ) ) {
return $output;
}
$parent_field = $this->db_fields['parent'];
// Flat display.
if (-1 == $max_depth) {
$empty_array = array();
foreach ($ elements as $ e) {
$this->display_element( $e, $empty_array, 1, 0, $args, $output );
}
return $output;
}
/*
* Необхідний для відтворення в hierarchical order.
* Separate elements в два buckets: top level and children elements.
* Children_elements is 2 dimensional array. Example:
* Children_elements[10][] contains all sub-elements whose parent is 10.
*/
$top_level_elements = array();
$children_elements = array();
foreach ($ elements as $ e) {
if ( empty( $e->$parent_field ) ) {
$top_level_elements[] = $e;
} else {
$children_elements[ $e->$parent_field ][] = $e;
}
}
/*
* Якщо немає елементів, які є top level.
* Assume the first one must be root of the sub elements.
*/
if (empty($top_level_elements)) {
$ first = array_slice ($ elements, 0, 1);
$root = $first[0];
$top_level_elements = array();
$children_elements = array();
foreach ($ elements as $ e) {
if ( $root->$parent_field == $e->$parent_field ) {
$top_level_elements[] = $e;
} else {
$children_elements[ $e->$parent_field ][] = $e;
}
}
}
foreach ($top_level_elements as $e) {
$this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );
}
/*
* Якщо ми відтворюємо всі рівні, і залишки children_elements is not empty,
* then we got orphans, which should be displayed regardless.
*/
if ( ( 0 == $max_depth ) && count( $children_elements ) > 0 ) {
$empty_array = array();
foreach ( $children_elements as $orphans ) {
foreach ( $orphans as $op ) {
$this->display_element( $op, $empty_array, 1, 0, $args, $output );
}
}
}
return $output;
}
/**
* Produces a page of nested elements.
*
* Given array of hierarchical elements, maximum depth, a specific page number,
* and number of elements per page, ця функція перших determines all top level root elements
* Повідомляючи, що сторінка, вони матимуть список і всі їхніх дітей в hierarchical order.
*
* $max_depth = 0 means display all levels.
* $max_depth > 0 specifies the number of display levels.
*
* @ Since 2.7.0
* @since 5.3.0 Formalized the existing `...$args` parameter by adding it
* до функції signature.
*
* @param array $elements An array of elements.
* @param int $max_depth The maximum hierarchical depth.
* @param int $page_num Ця конкретна page number, beginning with 1.
* @param int $per_page Number of elements per page.
* @param mixed ...$args Optional additional arguments.
* @return string XHTML особливу сторінку елементів.
*/
public function paged_walk( $elements, $max_depth, $page_num, $per_page, ...$args ) {
if ( empty( $elements ) || $max_depth < -1 ) {
return '';
}
$output = '';
$parent_field = $this->db_fields['parent'];
$ count = -1;
if (-1 == $max_depth) {
$ total_top = count ($ elements);
}
if ( $page_num < 1 || $per_page < 0 ) {
// No paging.
$ paging = false;
$ start = 0;
if (-1 == $max_depth) {
$ end = $ total_top;
}
$this->max_pages = 1;
} else {
$ paging = true;
$start = ((int) $page_num - 1) * (int) $per_page;
$end = $start + $per_page;
if (-1 == $max_depth) {
$this->max_pages = ceil( $total_top / $per_page );
}
}
// Flat display.
if (-1 == $max_depth) {
if ( ! empty( $args[0]['reverse_top_level'] ) ) {
$ elements = array_reverse ($ elements);
$oldstart = $start;
$start = $total_top - $end;
$ end = $ total_top - $ oldstart;
}
$empty_array = array();
foreach ($ elements as $ e) {
$ count++;
if ( $count < $start ) {
continue;
}
if ( $count >= $end ) {
break;
}
$this->display_element( $e, $empty_array, 1, 0, $args, $output );
}
return $output;
}
/*
* Separate elements в два buckets: top level and children elements.
* Children_elements is 2 dimensional array, eg
* $children_elements[10][] contains all sub-elements whose parent is 10.
*/
$top_level_elements = array();
$children_elements = array();
foreach ($ elements as $ e) {
if ( empty( $e->$parent_field ) ) {
$top_level_elements[] = $e;
} else {
$children_elements[ $e->$parent_field ][] = $e;
}
}
$ total_top = count ($ top_level_elements);
if ($paging) {
$this->max_pages = ceil( $total_top / $per_page );
} else {
$ end = $ total_top;
}
if ( ! empty( $args[0]['reverse_top_level'] ) ) {
$top_level_elements = array_reverse($top_level_elements);
$oldstart = $start;
$start = $total_top - $end;
$ end = $ total_top - $ oldstart;
}
if ( ! empty( $args[0]['reverse_children'] ) ) {
foreach ( $children_elements as $parent => $children ) {
$children_elements[ $parent ] = array_reverse( $children );
}
}
foreach ($top_level_elements as $e) {
$ count++;
// Для останніх сторінок, потрібна до небагатьох школярів в ордері, щоб потрапити в орфани.
if ( $end >= $total_top && $count < $start ) {
$this->unset_children( $e, $children_elements );
}
if ( $count < $start ) {
continue;
}
if ( $count >= $end ) {
break;
}
$this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );
}
if ( $end >= $total_top && count( $children_elements ) > 0 ) {
$empty_array = array();
foreach ( $children_elements as $orphans ) {
foreach ( $orphans as $op ) {
$this->display_element( $op, $empty_array, 1, 0, $args, $output );
}
}
}
return $output;
}
/**
* Calculates the total number of root elements.
*
* @ Since 2.7.0
*
* @param array $elements Elements to list.
* @return int Number of root elements.
*/
public function get_number_of_root_elements( $elements ) {
$num = 0;
$parent_field = $this->db_fields['parent'];
foreach ($ elements as $ e) {
if ( empty( $e->$parent_field ) ) {
$num++;
}
}
return $num;
}
/**
* Unsets all the children for given top level element.
*
* @ Since 2.7.0
*
* @param object $element The top level element.
* @param array $children_elements Children elements.
*/
public function unset_children( $element, &$children_elements ) {
if ( ! $element || ! $children_elements ) {
return;
}
$id_field = $this->db_fields['id'];
$id = $element->$id_field;
if ( ! empty( $children_elements[ $id ] ) && is_array( $children_elements[ $id ] ) ) {
foreach ((array) $children_elements[ $id ] as $child ) {
$this->unset_children( $child, $children_elements );
}
}
unset($children_elements[$id]);
}
}