Passed
Pull Request — master (#13)
by
unknown
13:38
created

HalProvider::getValue()   B

Complexity

Conditions 8
Paths 6

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 11
c 1
b 0
f 0
nc 6
nop 2
dl 0
loc 16
rs 8.4444
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ElevenLabs\Api\Service\Pagination\Provider;
6
7
use ElevenLabs\Api\Definition\ResponseDefinition;
8
use ElevenLabs\Api\Service\Pagination\Pagination;
9
use ElevenLabs\Api\Service\Pagination\PaginationLinks;
10
use Psr\Http\Message\ResponseInterface;
11
12
/**
13
 * Class HalProvider.
14
 */
15
class HalProvider implements PaginationProviderInterface
16
{
17
    /**
18
     * @var array
19
     */
20
    const DEFAULT_PAGINATION_VALUE = [
21
        // current page
22
        'page' => '_links.self.href.page',
23
24
        // number of items per page
25
        'perPage' => 'itemsPerPage',
26
27
        // number of items available in total
28
        'totalPages' => '_links.last.href.page',
29
30
        // number of pages available
31
        'totalItems' => 'totalItems',
32
    ];
33
34
    /**
35
     * @var array
36
     */
37
    private $paginationName;
38
39
    /**
40
     * @param array $config
41
     */
42
    public function __construct(array $config = [])
43
    {
44
        foreach (self::DEFAULT_PAGINATION_VALUE as $name => $value) {
45
            if (isset($config[$name])) {
46
                $value = $config[$name];
47
            }
48
            $this->paginationName[$name] = explode('.', $value);
49
        }
50
    }
51
52
    /**
53
     * @param array              $data
54
     * @param ResponseInterface  $response
55
     * @param ResponseDefinition $responseDefinition
56
     *
57
     * @return bool
58
     */
59
    public function supportPagination(array $data, ResponseInterface $response, ResponseDefinition $responseDefinition): bool
60
    {
61
        $totalItems = $this->getValue($data, $this->paginationName['totalItems']);
62
        if (0 === $totalItems) {
63
            return true;
64
        }
65
        $perPage = $this->getValue($data, $this->paginationName['perPage']);
66
        foreach ($this->paginationName as $key => $value) {
67
            if ('totalPages' === $key && $totalItems < $perPage) {
68
                continue;
69
            }
70
            if (null === $this->getValue($data, $value)) {
71
                return false;
72
            }
73
        }
74
75
        return isset($data['_embedded']['item']);
76
    }
77
78
    /**
79
     * @param array              $data
80
     * @param ResponseInterface  $response
81
     * @param ResponseDefinition $responseDefinition
82
     *
83
     * @return Pagination
84
     */
85
    public function getPagination(array &$data, ResponseInterface $response, ResponseDefinition $responseDefinition): Pagination
86
    {
87
        $paginationLinks = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $paginationLinks is dead and can be removed.
Loading history...
88
        $links = $data['_links'] ?? [];
89
        $paginationLinks = new PaginationLinks(
90
            $links['first']['href'] ?? $links['self']['href'] ?? '',
91
            $links['last']['href'] ?? $links['self']['href'] ?? '',
92
            $links['next']['href'] ?? null,
93
            $links['prev']['href'] ?? null
94
        );
95
        $pagination = [
96
            'page' => $this->getValue($data, $this->paginationName['page']),
97
            'perPage' => $this->getValue($data, $this->paginationName['perPage']),
98
            'totalItems' => $this->getValue($data, $this->paginationName['totalItems']),
99
        ];
100
        $data = array_map(function ($data) {
101
            $relations = $this->removeEmbedded($data['_embedded'] ?? []);
102
            unset($data['_links'], $data['_embedded']);
103
104
            return array_merge($relations, $data);
105
        }, $data['_embedded']['item'] ?? []);
106
107
        return new Pagination(
108
            $pagination['page'] ?? 1,
0 ignored issues
show
Bug introduced by
It seems like $pagination['page'] ?? 1 can also be of type array; however, parameter $page of ElevenLabs\Api\Service\P...gination::__construct() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

108
            /** @scrutinizer ignore-type */ $pagination['page'] ?? 1,
Loading history...
109
            $pagination['perPage'],
110
            $pagination['totalItems'],
111
            (int) ceil($pagination['totalItems'] / $pagination['perPage']),
112
            $paginationLinks
113
        );
114
    }
115
116
    /**
117
     * @param array $items
118
     * @param array $values
119
     *
120
     * @return array|int|mixed|null
121
     */
122
    private function getValue(array $items, array $values)
123
    {
124
        $value = $items;
125
        foreach ($values as $item) {
126
            if (isset($value[$item])) {
127
                $value = $value[$item];
128
            } elseif (is_string($value) && 1 === preg_match('#'.$item.'=([^&]*)#', $value, $tab)) {
129
                $value = isset($tab[1]) ? (int) $tab[1] : null;
130
            } elseif (is_string($value) && 0 === preg_match('#'.$item.'=([^&]*)#', $value)) {
131
                return 1;
132
            } else {
133
                return null;
134
            }
135
        }
136
137
        return $value;
138
    }
139
140
    private function removeEmbedded(array $items): array
141
    {
142
        return array_map(function ($item) {
143
            if ($this->isArray($item)) {
144
                $relations = [];
145
                foreach ($item as $i) {
146
                    $relation = $this->removeEmbedded($i['_embedded'] ?? []);
147
                    unset($i['_links'], $i['_embedded']);
148
                    $relations[] = array_merge($relation, $i);
149
                }
150
151
                return $relations;
152
            } else {
153
                $relations = $this->removeEmbedded($item['_embedded'] ?? []);
154
                unset($item['_links'], $item['_embedded']);
155
            }
156
157
            return array_merge($relations, $item);
158
        }, $items);
159
    }
160
161
    private function isArray(array $items): bool
162
    {
163
        foreach (array_keys($items) as $a) {
164
            if (!is_int($a)) {
165
                return false;
166
            }
167
        }
168
169
        return true;
170
    }
171
}
172