refactor: flatten src/AKSRT → src (drop theme-identifier dir)
Move all domain folders from src/AKSRT/{Domain} to src/{Domain}; remap
Composer PSR-4 "AKSRT\\": "src/"; update audit script + README + ADR
paths; remove dead tools/build-psr4-map.php (scanned deleted inc/classes).
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
/**
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
namespace AKSRT\Core;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class DocsPresenter {
|
||||
|
||||
private static $instance = null;
|
||||
|
||||
private function __construct() {}
|
||||
|
||||
public static function get_instance(): self {
|
||||
if (null === self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the document root page ID for a given page.
|
||||
*
|
||||
* @param int $page_id Current page ID.
|
||||
* @return int Root page ID (self if top-level, parent otherwise).
|
||||
*/
|
||||
public function get_root_id(int $page_id): int {
|
||||
$parent_id = wp_get_post_parent_id($page_id);
|
||||
return $parent_id ?: $page_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a flat ordered list of all pages under a document root.
|
||||
*
|
||||
* @param int $root_id Root page ID.
|
||||
* @param int $max_depth Maximum depth (default 4).
|
||||
* @return array Array of page objects with added '_depth' property.
|
||||
*/
|
||||
public function get_flat_tree(int $root_id, int $max_depth = 4): array {
|
||||
$result = [];
|
||||
$this->collect_children($root_id, $result, 0, $max_depth);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive helper to collect pages in order.
|
||||
*/
|
||||
private function collect_children(int $parent_id, array &$result, int $depth, int $max_depth): void {
|
||||
if ($depth >= $max_depth) {
|
||||
return;
|
||||
}
|
||||
|
||||
$children = get_pages([
|
||||
'parent' => $parent_id,
|
||||
'sort_column' => 'menu_order, post_title',
|
||||
'sort_order' => 'ASC',
|
||||
'post_status' => 'publish',
|
||||
]);
|
||||
|
||||
foreach ($children as $child) {
|
||||
$child->_depth = $depth;
|
||||
$result[] = $child;
|
||||
$this->collect_children($child->ID, $result, $depth + 1, $max_depth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sibling pages for chapter navigation (prev/next).
|
||||
*
|
||||
* @param int $page_id Current page ID.
|
||||
* @return array{prev: object|null, next: object|null}
|
||||
*/
|
||||
public function get_chapter_nav(int $page_id): array {
|
||||
$parent_id = wp_get_post_parent_id($page_id);
|
||||
|
||||
$siblings = get_pages([
|
||||
'parent' => $parent_id ?: 0,
|
||||
'sort_column' => 'menu_order, post_title',
|
||||
'sort_order' => 'ASC',
|
||||
'post_status' => 'publish',
|
||||
]);
|
||||
|
||||
$current_index = -1;
|
||||
foreach ($siblings as $i => $sibling) {
|
||||
if ((int) $sibling->ID === $page_id) {
|
||||
$current_index = $i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$prev = $current_index > 0 ? $siblings[$current_index - 1] : null;
|
||||
$next = ($current_index >= 0 && $current_index < count($siblings) - 1)
|
||||
? $siblings[$current_index + 1]
|
||||
: null;
|
||||
|
||||
return ['prev' => $prev, 'next' => $next];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get root-level document pages for the document navigation index.
|
||||
*
|
||||
* @param string $order Sort order: 'menu_order', 'date', 'title'.
|
||||
* @return array
|
||||
*/
|
||||
public function get_root_pages(string $order = 'menu_order'): array {
|
||||
$sort_column = 'menu_order, post_title';
|
||||
if ($order === 'title') {
|
||||
$sort_column = 'post_title';
|
||||
} elseif ($order === 'date') {
|
||||
$sort_column = 'post_date';
|
||||
}
|
||||
|
||||
return get_pages([
|
||||
'sort_column' => $sort_column,
|
||||
'sort_order' => 'ASC',
|
||||
'parent' => 0,
|
||||
'hierarchical' => 0,
|
||||
'post_status' => 'publish',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get recently modified pages for the sidebar.
|
||||
*
|
||||
* @param int $count Number of pages to return.
|
||||
* @return array
|
||||
*/
|
||||
public function get_recent_pages(int $count = 8): array {
|
||||
return get_pages([
|
||||
'sort_column' => 'post_modified',
|
||||
'sort_order' => 'DESC',
|
||||
'number' => $count,
|
||||
'post_status' => 'publish',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build breadcrumb trail for a document page.
|
||||
*
|
||||
* @param int $page_id Current page ID.
|
||||
* @return array Array of {id, title, url} objects.
|
||||
*/
|
||||
public function get_breadcrumbs(int $page_id): array {
|
||||
$trail = [];
|
||||
$current = get_post($page_id);
|
||||
|
||||
while ($current) {
|
||||
array_unshift($trail, [
|
||||
'id' => $current->ID,
|
||||
'title' => $current->post_title,
|
||||
'url' => get_permalink($current->ID),
|
||||
]);
|
||||
$parent_id = wp_get_post_parent_id($current->ID);
|
||||
$current = $parent_id ? get_post($parent_id) : null;
|
||||
}
|
||||
|
||||
return $trail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search document pages by keyword.
|
||||
*
|
||||
* @param string $keyword Search keyword.
|
||||
* @param int $root_id Optional root page ID to scope search.
|
||||
* @param int $limit Max results.
|
||||
* @return array Array of page objects with 'url' and 'excerpt' added.
|
||||
*/
|
||||
public function search_pages(string $keyword, int $root_id = 0, int $limit = 20): array {
|
||||
$args = [
|
||||
'post_type' => 'page',
|
||||
'post_status' => 'publish',
|
||||
's' => $keyword,
|
||||
'posts_per_page' => $limit,
|
||||
'orderby' => 'relevance',
|
||||
];
|
||||
|
||||
if ($root_id > 0) {
|
||||
$tree_ids = [$root_id];
|
||||
$this->collect_children($root_id, $tree_ids, 0, 4);
|
||||
$ids = array_map(static function ($item) {
|
||||
return is_object($item) ? $item->ID : (int) $item;
|
||||
}, $tree_ids);
|
||||
$ids[] = $root_id;
|
||||
$args['post__in'] = array_unique($ids);
|
||||
}
|
||||
|
||||
$query = new \WP_Query($args);
|
||||
$results = [];
|
||||
|
||||
foreach ($query->posts as $post) {
|
||||
$results[] = [
|
||||
'id' => $post->ID,
|
||||
'title' => $post->post_title,
|
||||
'url' => get_permalink($post->ID),
|
||||
'excerpt' => wp_trim_words(wp_strip_all_tags($post->post_content), 30),
|
||||
'modified' => $post->post_modified,
|
||||
'parent' => (int) $post->post_parent,
|
||||
];
|
||||
}
|
||||
|
||||
wp_reset_postdata();
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given page belongs to the docs mode.
|
||||
*
|
||||
* @param int $page_id Page ID.
|
||||
* @return bool
|
||||
*/
|
||||
public function is_docs_page(int $page_id): bool {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user