SelectQuery::params()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 6
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Solr Client Symfony package.
7
 *
8
 * (c) ingatlan.com Zrt. <[email protected]>
9
 *
10
 * This source file is subject to the MIT license that is bundled
11
 * with this source code in the file LICENSE.
12
 */
13
14
namespace iCom\SolrClient\Query;
15
16
use iCom\SolrClient\JsonHelper;
17
use iCom\SolrClient\JsonQuery;
18
19
/**
20
 * @psalm-immutable
21
 */
22
final class SelectQuery implements JsonQuery
23
{
24
    use JsonHelper;
25
26
    /**
27
     * @var array<string, string>
28
     */
29
    private array $types = [
30
        // to keep key order consistent
31
        'query' => 'string',
32
        'filter' => 'array',
33
        'fields' => 'array',
34
        'facet' => 'array',
35
        'sort' => 'string',
36
        'offset' => 'int',
37
        'limit' => 'int',
38
        'params' => 'array',
39
    ];
40
41
    /**
42
     * @psalm-var array{
43
     *      query?: string,
44
     *      filter?: array,
45
     *      fields?: array,
46
     *      facet?: array,
47
     *      sort?: string,
48
     *      offset?: int,
49
     *      limit?: int,
50
     *      params?: array,
51
     * }
52
     */
53
    private array $body;
54
55
    /**
56
     * @psalm-param array<string, string|array|int> $body
57
     */
58
    public function __construct(array $body = [])
59
    {
60
        if ([] !== $invalid = array_diff_key($body, $this->types)) {
61
            throw new \InvalidArgumentException(sprintf('Invalid keys "%s" found. Valid keys are "%s".', implode(', ', array_keys($invalid)), implode(', ', array_keys($this->types))));
62
        }
63
64
        foreach ($body as $key => $value) {
65
            if ($this->types[$key] !== $type = \get_debug_type($value)) {
66
                throw new \InvalidArgumentException(sprintf('Type of field "%s" should be "%s", "%s" given.', $key, $this->types[$key], $type));
67
            }
68
        }
69
70
        /** @psalm-suppress InvalidPropertyAssignmentValue */
71
        $this->body = array_replace(array_fill_keys(array_keys($this->types), null), $body);
72
    }
73
74
    /**
75
     * @psalm-param array<string, string|array|int> $body
76
     */
77
    public static function create(array $body = []): self
78
    {
79
        return new self($body);
80
    }
81
82
    public function query(string $query): self
83
    {
84
        $q = clone $this;
85
        $q->body['query'] = $query;
86
87
        return $q;
88
    }
89
90
    public function filter(array $filters): self
91
    {
92
        $q = clone $this;
93
        $q->body['filter'] = array_map(static function ($filter) use ($q): string { return $q->parseFilter($filter); }, $filters);
94
95
        return $q;
96
    }
97
98
    /**
99
     * @param mixed $filter
100
     */
101
    public function withFilter($filter): self
102
    {
103
        $q = clone $this;
104
        $q->body['filter'][] = $this->parseFilter($filter);
105
106
        return $q;
107
    }
108
109
    public function fields(array $fields): self
110
    {
111
        $q = clone $this;
112
        $q->body['fields'] = $fields;
113
114
        return $q;
115
    }
116
117
    public function sort(string $sort): self
118
    {
119
        $q = clone $this;
120
        $q->body['sort'] = $sort;
121
122
        return $q;
123
    }
124
125
    public function facet(array $facet): self
126
    {
127
        $q = clone $this;
128
        $q->body['facet'] = $facet;
129
130
        return $q;
131
    }
132
133
    public function params(array $params): self
134
    {
135
        $q = clone $this;
136
        $q->body['params'] = $params;
137
138
        return $q;
139
    }
140
141
    public function offset(int $offset): self
142
    {
143
        $q = clone $this;
144
        $q->body['offset'] = $offset;
145
146
        return $q;
147
    }
148
149
    public function limit(int $limit): self
150
    {
151
        $q = clone $this;
152
        $q->body['limit'] = $limit;
153
154
        return $q;
155
    }
156
157
    public function toJson(): string
158
    {
159
        return self::jsonEncode(new \ArrayObject(array_filter($this->body)), \JSON_UNESCAPED_UNICODE);
160
    }
161
162
    /**
163
     * @param mixed $filter
164
     */
165
    private function parseFilter($filter): string
166
    {
167
        if ($filter instanceof QueryHelper) {
168
            return $filter->toString();
169
        }
170
171
        if (!\is_string($filter)) {
172
            throw new \InvalidArgumentException(sprintf('SelectQuery filter can accept only string or "%s", but "%s" given.', QueryHelper::class, \get_debug_type($filter)));
173
        }
174
175
        return $filter;
176
    }
177
}
178