Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.45% covered (success)
95.45%
21 / 22
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
RecordNavigationResult
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
5 / 5
7
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasPrev
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasNext
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toArray
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
1
 fromArray
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5/** @license For full copyright and license information, please see the LICENSE.md file. */
6
7namespace App\Core\Engine\Domain\Model;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11/**
12 * Record Navigation Result Value Object.
13 *
14 * Immutable data structure representing record navigation metadata (previous, next,
15 * current position, total records in active filter) within the Central Engine.
16 *
17 * @package App\Core\Engine\Domain\Model
18 */
19final readonly class RecordNavigationResult
20{
21    /**
22     * RecordNavigationResult constructor.
23     *
24     * @param int|null $prevId          Previous record primary key, or null if at first position.
25     * @param int|null $nextId          Next record primary key, or null if at last position.
26     * @param int      $currentPosition 1-indexed position of the active record within the dataset.
27     * @param int      $totalRecords    Total matching records in active filter/query.
28     * @param int      $page            Current page number in the list window.
29     * @param int      $totalPages      Total available pages.
30     */
31    public function __construct(
32        public ?int $prevId,
33        public ?int $nextId,
34        public int  $currentPosition,
35        public int  $totalRecords,
36        public int  $page,
37        public int  $totalPages,
38    ) {
39    }
40
41    /**
42     * Checks if a previous record exists.
43     *
44     * @return bool True if previous record exists.
45     */
46    public function hasPrev(): bool
47    {
48        return $this->prevId !== null;
49    }
50
51    /**
52     * Checks if a next record exists.
53     *
54     * @return bool True if next record exists.
55     */
56    public function hasNext(): bool
57    {
58        return $this->nextId !== null;
59    }
60
61    /**
62     * Converts navigation result to array format for API serialization.
63     *
64     * @return array{
65     *     prev_id: int|null,
66     *     next_id: int|null,
67     *     current_position: int,
68     *     total_records: int,
69     *     page: int,
70     *     total_pages: int,
71     *     has_prev: bool,
72     *     has_next: bool
73     * } Array representation.
74     */
75    public function toArray(): array
76    {
77        return [
78            'prev_id'          => $this->prevId,
79            'next_id'          => $this->nextId,
80            'current_position' => $this->currentPosition,
81            'total_records'    => $this->totalRecords,
82            'page'             => $this->page,
83            'total_pages'      => $this->totalPages,
84            'has_prev'         => $this->hasPrev(),
85            'has_next'         => $this->hasNext(),
86        ];
87    }
88
89    /**
90     * Reconstructs navigation result from array representation.
91     *
92     * @param array<string, mixed> $data Array representation.
93     * @return self Reconstructed navigation result.
94     */
95    public static function fromArray(array $data): self
96    {
97        return new self(
98            prevId: isset($data['prev_id']) ? (int) $data['prev_id'] : null,
99            nextId: isset($data['next_id']) ? (int) $data['next_id'] : null,
100            currentPosition: (int) ($data['current_position'] ?? 1),
101            totalRecords: (int) ($data['total_records'] ?? 0),
102            page: (int) ($data['page'] ?? 1),
103            totalPages: (int) ($data['total_pages'] ?? 1),
104        );
105    }
106}