Passed
Push — master ( 822e4b...ef2696 )
by Marius
02:50
created

CursorBuilder::processValue()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Paysera\Pagination\Service;
5
6
use DateTimeInterface;
7
use Paysera\Pagination\Entity\OrderingConfiguration;
8
use Paysera\Pagination\Entity\ParsedCursor;
9
use Paysera\Pagination\Exception\InvalidCursorException;
10
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
11
12
class CursorBuilder implements CursorBuilderInterface
13
{
14
    private $propertyAccessor;
15
16 41
    public function __construct(PropertyAccessorInterface $propertyAccessor)
17
    {
18 41
        $this->propertyAccessor = $propertyAccessor;
19 41
    }
20
21 32
    public function parseCursor(string $cursor, int $requiredCount): ParsedCursor
22
    {
23 32
        $parsedCursor = new ParsedCursor();
24
25 32
        $serializedCursor = $cursor;
26 32
        if (substr($cursor, 0, 1) === '=') {
27 11
            $serializedCursor = substr($cursor, 1);
28 11
            $parsedCursor->setCursoredItemIncluded(true);
29
        }
30
31 32
        $decoded = json_decode(sprintf('[%s]', $serializedCursor), false);
32 32
        if (!is_array($decoded)) {
33
            throw new InvalidCursorException();
34
        }
35 32
        if (count($decoded) !== $requiredCount) {
36
            throw new InvalidCursorException();
37
        }
38 32
        foreach ($decoded as $value) {
39 32
            if (!is_string($value)) {
40 32
                throw new InvalidCursorException();
41
            }
42
        }
43
44 32
        return $parsedCursor->setCursorElements($decoded);
45
    }
46
47 4
    public function buildCursorWithIncludedItem(string $cursor): string
48
    {
49 4
        return '=' . $cursor;
50
    }
51
52 7
    public function invertCursorInclusion(string $cursor): string
53
    {
54 7
        return substr($cursor, 0, 1) === '=' ? substr($cursor, 1) : '=' . $cursor;
55
    }
56
57
    /**
58
     * @param mixed $item
59
     * @param array|\Paysera\Pagination\Entity\OrderingConfiguration[] $orderingConfigurations
60
     * @return string
61
     */
62 27
    public function getCursorFromItem($item, array $orderingConfigurations): string
63
    {
64 27
        $cursor = [];
65 27
        foreach ($orderingConfigurations as $orderingConfiguration) {
66 27
            $cursor[] = $this->getCursorItemValue($item, $orderingConfiguration);
67
        }
68
69 27
        return $this->convertArrayToCursor($cursor);
70
    }
71
72 27
    private function getCursorItemValue($item, OrderingConfiguration $orderingConfiguration): string
73
    {
74 27
        if ($orderingConfiguration->getAccessorPath() !== null) {
75 26
            $value = $this->propertyAccessor->getValue($item, $orderingConfiguration->getAccessorPath());
76
        } else {
77 1
            $value = call_user_func($orderingConfiguration->getAccessorClosure(), $item);
78
        }
79
80 27
        return $this->processValue($value);
81
    }
82
83 27
    private function processValue($value): string
84
    {
85 27
        if ($value instanceof DateTimeInterface) {
86 4
            return $value->format('Y-m-d H:i:s');
87
        }
88
89 27
        return (string)$value;
90
    }
91
92 27
    private function convertArrayToCursor(array $cursorElements): string
93
    {
94 27
        return trim(json_encode($cursorElements), '[]');
95
    }
96
}
97