@@ -224,6 +224,84 @@ public function getBreadcrumbsForPage(PageResource $page): array
224224 return $ breadcrumbs ;
225225 }
226226
227+ /**
228+ * Get the next page in the documentation tree after the given page.
229+ *
230+ * Traverses the documentation tree in depth-first order to determine
231+ * the next page. Returns null if the given page is the last page.
232+ *
233+ * @param PageResource $page The current page
234+ *
235+ * @return PageResource|null The next page, or null if at the end
236+ */
237+ public function getNextPageForPage (PageResource $ page ): ?PageResource
238+ {
239+ return $ this ->getAdjacentPage ($ page , 1 );
240+ }
241+
242+ /**
243+ * Get the previous page in the documentation tree before the given page.
244+ *
245+ * Traverses the documentation tree in depth-first order to determine
246+ * the previous page. Returns null if the given page is the first page.
247+ *
248+ * @param PageResource $page The current page
249+ *
250+ * @return PageResource|null The previous page, or null if at the beginning
251+ */
252+ public function getPreviousPageForPage (PageResource $ page ): ?PageResource
253+ {
254+ return $ this ->getAdjacentPage ($ page , -1 );
255+ }
256+
257+ /**
258+ * Get an adjacent page in the documentation tree relative to the given page.
259+ *
260+ * @param PageResource $page The current page
261+ * @param int $offset The offset (+1 for next, -1 for previous)
262+ *
263+ * @return PageResource|null The adjacent page, or null if not found
264+ */
265+ protected function getAdjacentPage (PageResource $ page , int $ offset ): ?PageResource
266+ {
267+ $ flatPages = $ this ->getFlattenedTree ($ page ->getVersion ()->id );
268+ $ slugs = array_keys ($ flatPages );
269+ $ currentIndex = array_search ($ page ->getSlug (), $ slugs , true );
270+
271+ if ($ currentIndex === false || !isset ($ slugs [$ currentIndex + $ offset ])) {
272+ return null ;
273+ }
274+
275+ return $ flatPages [$ slugs [$ currentIndex + $ offset ]];
276+ }
277+
278+ /**
279+ * Get a flattened list of pages in tree order (depth-first traversal).
280+ * Uses page slugs as array keys for efficient lookups.
281+ *
282+ * @param string|null $version
283+ *
284+ * @return array<string, PageResource> Array keyed by page slug
285+ */
286+ protected function getFlattenedTree (?string $ version = null ): array
287+ {
288+ $ tree = $ this ->getTree ($ version );
289+ $ flat = [];
290+
291+ $ flatten = function (array $ pages ) use (&$ flatten , &$ flat ) {
292+ foreach ($ pages as $ page ) {
293+ $ flat [$ page ->getSlug ()] = $ page ;
294+ if ($ page ->getChildren ()) {
295+ $ flatten ($ page ->getChildren ());
296+ }
297+ }
298+ };
299+
300+ $ flatten ($ tree );
301+
302+ return $ flat ;
303+ }
304+
227305 /**
228306 * Get a versioned image resource by path and version.
229307 *
0 commit comments