Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
PaginatedResultNormalizer
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
6 / 6
10
100.00% covered (success)
100.00%
1 / 1
 supportsNormalization
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 normalize
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
2
 renderFirst
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 renderLast
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 renderPrev
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 renderNext
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2namespace Apie\Serializer\Normalizers;
3
4use Apie\Core\Datalayers\Lists\PaginatedResult;
5use Apie\Core\Entities\EntityInterface;
6use Apie\Core\Lists\ItemHashmap;
7use Apie\Serializer\Context\ApieSerializerContext;
8use Apie\Serializer\Interfaces\NormalizerInterface;
9use Psr\Http\Message\ServerRequestInterface;
10
11class PaginatedResultNormalizer implements NormalizerInterface
12{
13    public function supportsNormalization(mixed $object, ApieSerializerContext $apieSerializerContext): bool
14    {
15        return $object instanceof PaginatedResult;
16    }
17
18    /**
19     * @param PaginatedResult<EntityInterface> $object
20     */
21    public function normalize(mixed $object, ApieSerializerContext $apieSerializerContext): ItemHashmap
22    {
23        $context = $apieSerializerContext->getContext();
24        $uri = $object->id->asUrl();
25        if ($context->hasContext(ServerRequestInterface::class)) {
26            // TODO extract URI from request.
27        }
28        return new ItemHashmap(array_filter(
29            [
30                'totalCount' => $object->totalCount,
31                'filteredCount' => $object->filteredCount,
32                'list' => $apieSerializerContext->normalizeAgain($object->list),
33                'first' => $this->renderFirst($uri, $object),
34                'last' => $this->renderLast($uri, $object),
35                'prev' => $this->renderPrev($uri, $object),
36                'next' => $this->renderNext($uri, $object),
37            ],
38            function (mixed $value) {
39                return $value !== null;
40            }
41        ));
42    }
43
44    /**
45     * @param PaginatedResult<EntityInterface> $object
46     */
47    private function renderFirst(string $uri, PaginatedResult $object): string
48    {
49        return $uri . $object->querySearch->withPageIndex(0)->toHttpQuery();
50    }
51
52    /**
53     * @param PaginatedResult<EntityInterface> $object
54     */
55    private function renderLast(string $uri, PaginatedResult $object): string
56    {
57        $pageIndex = 1 + floor($object->totalCount / $object->pageSize);
58        if ($pageIndex * $object->pageSize > $object->totalCount) {
59            $pageIndex--;
60        }
61        return $uri . $object->querySearch->withPageIndex((int) $pageIndex)->toHttpQuery();
62    }
63
64    /**
65     * @param PaginatedResult<EntityInterface> $object
66     */
67    private function renderPrev(string $uri, PaginatedResult $object): ?string
68    {
69        if ($object->pageNumber > 0) {
70            return $object->querySearch->withPageIndex($object->pageNumber - 1)->toHttpQuery();
71        }
72
73        return null;
74    }
75
76    /**
77     * @param PaginatedResult<EntityInterface> $object
78     */
79    private function renderNext(string $uri, PaginatedResult $object): ?string
80    {
81        $pageIndex = $object->pageNumber + 1;
82        if ($pageIndex * $object->pageSize > $object->totalCount) {
83            return null;
84        }
85        return $uri . $object->querySearch->withPageIndex((int) $pageIndex)->toHttpQuery();
86    }
87}