Skip to content

Commit f97a824

Browse files
committed
wip: basic combo searching functionality
1 parent 8eeaa87 commit f97a824

File tree

2 files changed

+203
-0
lines changed

2 files changed

+203
-0
lines changed
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
<?php
2+
3+
namespace App\JsonApi\V1\Extensions\SearchByComponents;
4+
5+
use App\Models\Device;
6+
use Illuminate\Database\Eloquent\Builder;
7+
use Illuminate\Support\Arr;
8+
use JsonApiPhp\JsonApi as Structure;
9+
use Tobyz\JsonApiServer\Context;
10+
use Tobyz\JsonApiServer\Extension\Extension;
11+
use Psr\Http\Message\ResponseInterface;
12+
use Tobyz\JsonApiServer\Exception\BadRequestException;
13+
use Tobyz\JsonApiServer\Exception\MethodNotAllowedException;
14+
use Tobyz\JsonApiServer\Serializer;
15+
16+
use function Tobyz\JsonApiServer\json_api_response;
17+
18+
class SearchByComponentsExtension extends Extension
19+
{
20+
public function uri(): string
21+
{
22+
return 'http://mobilecombos.com/ext/search-by-components';
23+
}
24+
25+
function queryToSQL($query)
26+
{
27+
$addSlashes = str_replace('?', "'?'", $query->toSql());
28+
29+
$sql = str_replace('%', '#', $addSlashes);
30+
31+
$sql = str_replace('?', '%s', $sql);
32+
33+
$sql = vsprintf($sql, $query->getBindings());
34+
35+
$sql = str_replace('#', '%', $sql);
36+
37+
return $sql;
38+
}
39+
40+
public function handle(Context $context): ?ResponseInterface
41+
{
42+
if (Arr::has(['/search-by-components'], $context->getPath())) {
43+
return null;
44+
}
45+
46+
$request = $context->getRequest();
47+
48+
if ($request->getMethod() !== 'POST') {
49+
throw new MethodNotAllowedException();
50+
}
51+
52+
$body = $context->getBody();
53+
$searchQuery = $body['query'] ?? null;
54+
55+
if (!isset($searchQuery)) {
56+
throw new BadRequestException('Missing combo search query');
57+
}
58+
59+
$serializer = new Serializer($context);
60+
61+
$query = Device::query();
62+
63+
$query = $this->buildQuery($searchQuery, $query);
64+
65+
// $query = $query->with([
66+
// 'deviceFirmwares',
67+
// 'deviceFirmwares.capabilitySets',
68+
// 'deviceFirmwares.capabilitySets.combos',
69+
// 'deviceFirmwares.capabilitySets.combos.nrComponents',
70+
// 'deviceFirmwares.capabilitySets.combos.lteComponents'
71+
// ]);
72+
73+
dd($this->queryToSQL($query));
74+
75+
$results = $query->get();
76+
77+
foreach ($results as $device) {
78+
$serializer->add(
79+
$context->getApi()->getResourceType('devices'),
80+
$device,
81+
[
82+
'deviceFirmwares' => [
83+
'capabilitySets' => [
84+
'combos' => [
85+
'nrComponents' => [],
86+
'lteComponents' => []
87+
]
88+
],
89+
],
90+
]
91+
);
92+
}
93+
94+
[$primary, $included] = $serializer->serialize();
95+
96+
return json_api_response(new Structure\CompoundDocument(
97+
new Structure\ResourceCollection(...$primary),
98+
new Structure\Included(...$included),
99+
// new Structure\Link\SelfLink($this->buildUrl($context->getRequest())),
100+
));
101+
}
102+
103+
protected function hashQueryComponent(array $component): string
104+
{
105+
return md5(serialize($component));
106+
}
107+
108+
protected function buildQuery(array $search, Builder $query): Builder
109+
{
110+
$searchWithQuantity = [];
111+
112+
foreach ($search as $componentQuery) {
113+
$hash = $this->hashQueryComponent($componentQuery);
114+
115+
if (!isset($searchWithQuantity[$hash])) {
116+
$searchWithQuantity[$hash] = [
117+
'quantity' => 1,
118+
'query' => $componentQuery
119+
];
120+
} else {
121+
$searchWithQuantity[$hash]['quantity']++;
122+
}
123+
}
124+
125+
foreach ($searchWithQuantity as $componentQuery) {
126+
$relation = 'deviceFirmwares.capabilitySets.combos.' .
127+
(strtolower(Arr::get($componentQuery, 'query.type')) === 'nr' ? 'nrComponents'
128+
: 'lteComponents');
129+
130+
$query = $query->whereHas($relation, function (Builder $query) use ($componentQuery) {
131+
$bands = Arr::get($componentQuery, 'query.bands');
132+
$dlClass = Arr::get($componentQuery, 'query.dlClass');
133+
$ulClass = Arr::get($componentQuery, 'query.ulClass');
134+
$mimo = Arr::get($componentQuery, 'query.mimo');
135+
$ul_mimo = Arr::get($componentQuery, 'query.ulMimo');
136+
$dl_modulation = Arr::get($componentQuery, 'query.dlModulation');
137+
$ul_modulation = Arr::get($componentQuery, 'query.ulModulation');
138+
139+
if (isset($bands)) {
140+
if (is_array($bands)) {
141+
$query->whereIn('band', $bands);
142+
} else {
143+
$query->where('band', $bands);
144+
}
145+
}
146+
147+
if (isset($dlClass)) {
148+
if (is_array($dlClass)) {
149+
$query->whereIn('dl_class', $dlClass);
150+
} else {
151+
$query->where('dl_class', $dlClass);
152+
}
153+
}
154+
155+
if (isset($ulClass)) {
156+
if (is_array($ulClass)) {
157+
$query->whereIn('ul_class', $ulClass);
158+
} else {
159+
$query->where('ul_class', $ulClass);
160+
}
161+
}
162+
163+
if (isset($mimo)) {
164+
if (is_array($mimo)) {
165+
$query->whereIn('mimo', $mimo);
166+
} else {
167+
$query->where('mimo', $mimo);
168+
}
169+
}
170+
171+
if (isset($ul_mimo)) {
172+
if (is_array($ul_mimo)) {
173+
$query->whereIn('ul_mimo', $ul_mimo);
174+
} else {
175+
$query->where('ul_mimo', $ul_mimo);
176+
}
177+
}
178+
179+
if (isset($dl_modulation)) {
180+
if (is_array($dl_modulation)) {
181+
$query->whereIn('dl_modulation', $dl_modulation);
182+
} else {
183+
$query->where('dl_modulation', $dl_modulation);
184+
}
185+
}
186+
187+
if (isset($ul_modulation)) {
188+
if (is_array($ul_modulation)) {
189+
$query->whereIn('ul_modulation', $ul_modulation);
190+
} else {
191+
$query->where('ul_modulation', $ul_modulation);
192+
}
193+
}
194+
195+
return $query;
196+
}, '=', $componentQuery['quantity']);
197+
}
198+
199+
return $query;
200+
}
201+
}

app/JsonApi/V1/JsonApiServer.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace App\JsonApi\V1;
44

5+
use App\JsonApi\V1\Extensions\SearchByComponents\SearchByComponentsExtension;
56
use Illuminate\Support\Facades\Config;
67
use Psr\Http\Message\ServerRequestInterface;
78
use Tobyz\JsonApiServer\ErrorProviderInterface;
@@ -28,6 +29,7 @@ public function requestHandler(ServerRequestInterface $request): \Psr\Http\Messa
2829
$this->addResources();
2930

3031
$this->server->extension(new Atomic());
32+
$this->server->extension(new SearchByComponentsExtension());
3133
}
3234

3335
if (!$request->hasHeader('Accept')) {

0 commit comments

Comments
 (0)