Skip to content

Commit 5fbc2e3

Browse files
committed
Encapsulate the facet distribution and facet stats in our own objects
1 parent adc4885 commit 5fbc2e3

12 files changed

+346
-108
lines changed

src/Engine/FacetDistribution.php

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Setono\SyliusMeilisearchPlugin\Engine;
6+
7+
use Webmozart\Assert\Assert;
8+
9+
/**
10+
* @implements \IteratorAggregate<string, FacetValues>
11+
* @implements \ArrayAccess<string, FacetValues>
12+
*/
13+
final class FacetDistribution implements \Countable, \IteratorAggregate, \ArrayAccess
14+
{
15+
/** @var array<string, FacetValues> */
16+
private array $facetValues = [];
17+
18+
/**
19+
* @param array<string, mixed> $facetDistribution
20+
*/
21+
public function __construct(array $facetDistribution)
22+
{
23+
foreach ($facetDistribution as $facet => $facetValues) {
24+
Assert::isArray($facetValues);
25+
26+
$this->facetValues[$facet] = new FacetValues($facet, $facetValues);
27+
}
28+
}
29+
30+
/**
31+
* @psalm-assert-if-true FacetValues $this->facetValues[$facet]
32+
*/
33+
public function has(string $facet): bool
34+
{
35+
return isset($this->facetValues[$facet]);
36+
}
37+
38+
public function get(string $facet): FacetValues
39+
{
40+
if (!$this->has($facet)) {
41+
throw new \InvalidArgumentException(sprintf('Facet "%s" does not exist', $facet));
42+
}
43+
44+
return $this->facetValues[$facet];
45+
}
46+
47+
/**
48+
* @return \ArrayIterator<string, FacetValues>
49+
*/
50+
public function getIterator(): \ArrayIterator
51+
{
52+
return new \ArrayIterator($this->facetValues);
53+
}
54+
55+
public function count(): int
56+
{
57+
return count($this->facetValues);
58+
}
59+
60+
public function isEmpty(): bool
61+
{
62+
return [] === $this->facetValues;
63+
}
64+
65+
public function offsetExists(mixed $offset): bool
66+
{
67+
return $this->has($offset);
68+
}
69+
70+
public function offsetGet(mixed $offset): FacetValues
71+
{
72+
return $this->get($offset);
73+
}
74+
75+
public function offsetSet(mixed $offset, mixed $value): void
76+
{
77+
throw new \LogicException('You cannot set an offset');
78+
}
79+
80+
public function offsetUnset(mixed $offset): void
81+
{
82+
throw new \LogicException('You cannot unset an offset');
83+
}
84+
}

src/Engine/FacetStat.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Setono\SyliusMeilisearchPlugin\Engine;
6+
7+
final class FacetStat
8+
{
9+
public readonly float|int $min;
10+
11+
public readonly float|int $max;
12+
13+
public function __construct(
14+
public readonly string $name,
15+
array $values,
16+
) {
17+
if (!isset($values['min'], $values['max'])) {
18+
throw new \InvalidArgumentException('The $values must contain a min and a max key');
19+
}
20+
21+
if (!is_numeric($values['min']) || !is_numeric($values['max'])) {
22+
throw new \InvalidArgumentException('The $values must contain numeric values');
23+
}
24+
25+
$this->min = $values['min'] + 0;
26+
$this->max = $values['max'] + 0;
27+
}
28+
}

src/Engine/FacetStats.php

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Setono\SyliusMeilisearchPlugin\Engine;
6+
7+
use Webmozart\Assert\Assert;
8+
9+
/**
10+
* @implements \IteratorAggregate<string, FacetStat>
11+
* @implements \ArrayAccess<string, FacetStat>
12+
*/
13+
final class FacetStats implements \Countable, \IteratorAggregate, \ArrayAccess
14+
{
15+
/** @var array<string, FacetStat> */
16+
private array $facetStats = [];
17+
18+
/**
19+
* @param array<string, mixed> $facetStats
20+
*/
21+
public function __construct(array $facetStats)
22+
{
23+
foreach ($facetStats as $facet => $facetStat) {
24+
Assert::isArray($facetStat);
25+
26+
$this->facetStats[$facet] = new FacetStat($facet, $facetStat);
27+
}
28+
}
29+
30+
/**
31+
* @psalm-assert-if-true FacetStat $this->facetStats[$facet]
32+
*/
33+
public function has(string $facet): bool
34+
{
35+
return isset($this->facetStats[$facet]);
36+
}
37+
38+
public function get(string $facet): FacetStat
39+
{
40+
if (!$this->has($facet)) {
41+
throw new \InvalidArgumentException(sprintf('Facet "%s" does not exist', $facet));
42+
}
43+
44+
return $this->facetStats[$facet];
45+
}
46+
47+
/**
48+
* @return \ArrayIterator<string, FacetStat>
49+
*/
50+
public function getIterator(): \ArrayIterator
51+
{
52+
return new \ArrayIterator($this->facetStats);
53+
}
54+
55+
public function count(): int
56+
{
57+
return count($this->facetStats);
58+
}
59+
60+
public function isEmpty(): bool
61+
{
62+
return [] === $this->facetStats;
63+
}
64+
65+
public function offsetExists(mixed $offset): bool
66+
{
67+
return $this->has($offset);
68+
}
69+
70+
public function offsetGet(mixed $offset): FacetStat
71+
{
72+
return $this->get($offset);
73+
}
74+
75+
public function offsetSet(mixed $offset, mixed $value): void
76+
{
77+
throw new \LogicException('You cannot set an offset');
78+
}
79+
80+
public function offsetUnset(mixed $offset): void
81+
{
82+
throw new \LogicException('You cannot unset an offset');
83+
}
84+
}

src/Engine/FacetValues.php

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Setono\SyliusMeilisearchPlugin\Engine;
6+
7+
use Webmozart\Assert\Assert;
8+
9+
/**
10+
* @implements \ArrayAccess<string, int>
11+
* @implements \IteratorAggregate<string, int>
12+
*/
13+
final class FacetValues implements \Countable, \IteratorAggregate, \ArrayAccess
14+
{
15+
/**
16+
* This holds the facet values for the respective facet and search results. Examples for $values include:
17+
*
18+
* [
19+
* "Celsius Small" => 3
20+
* "Date & Banana" => 2
21+
* "Modern Wear" => 6
22+
* "You are breathtaking" => 10
23+
* ]
24+
*
25+
* [
26+
* "false" => 16
27+
* "true" => 5
28+
* ]
29+
*
30+
* [
31+
* "1.74" => 1
32+
* "12.21" => 1
33+
* "16.52" => 1
34+
* "21.06" => 1
35+
* "22.49" => 1
36+
* "24.19" => 1
37+
* ]
38+
*
39+
* @var array<string, int>
40+
*/
41+
private array $values = [];
42+
43+
public function __construct(
44+
public readonly string $name,
45+
array $values,
46+
) {
47+
foreach ($values as $key => $value) {
48+
Assert::string($key, 'The key of the facet value must be a string. Value was: %s');
49+
Assert::integer($value, 'The value of the facet value must be an integer. Value was: %s');
50+
51+
$this->values[$key] = $value;
52+
}
53+
}
54+
55+
/**
56+
* @return list<string>
57+
*/
58+
public function getValues(): array
59+
{
60+
return array_keys($this->values);
61+
}
62+
63+
public function getValueCount(string $value): int
64+
{
65+
if (!$this->has($value)) {
66+
throw new \InvalidArgumentException(sprintf('Facet value "%s" does not exist', $value));
67+
}
68+
69+
return $this->values[$value];
70+
}
71+
72+
/**
73+
* @psalm-assert-if-true int $this->values[$value]
74+
*/
75+
public function has(string $value): bool
76+
{
77+
return isset($this->values[$value]);
78+
}
79+
80+
/**
81+
* @return \ArrayIterator<string, int>
82+
*/
83+
public function getIterator(): \ArrayIterator
84+
{
85+
return new \ArrayIterator($this->values);
86+
}
87+
88+
public function offsetExists(mixed $offset): bool
89+
{
90+
return $this->has($offset);
91+
}
92+
93+
public function offsetGet(mixed $offset): int
94+
{
95+
return $this->values[$offset];
96+
}
97+
98+
public function offsetSet(mixed $offset, mixed $value): void
99+
{
100+
throw new \LogicException('You cannot set an offset');
101+
}
102+
103+
public function offsetUnset(mixed $offset): void
104+
{
105+
throw new \LogicException('You cannot unset an offset');
106+
}
107+
108+
public function count(): int
109+
{
110+
return count($this->values);
111+
}
112+
113+
public function isEmpty(): bool
114+
{
115+
return [] === $this->values;
116+
}
117+
}

src/Engine/SearchResult.php

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,8 @@ public function __construct(
2020
public readonly int $page,
2121
public readonly int $pageSize,
2222
public readonly int $totalPages,
23-
24-
/** @var array<string, mixed> $facetStats */
25-
public readonly array $facetStats,
26-
27-
/** @var array<string, mixed> $facetDistribution */
28-
public readonly array $facetDistribution,
23+
public readonly FacetStats $facetStats,
24+
public readonly FacetDistribution $facetDistribution,
2925
) {
3026
}
3127

@@ -54,8 +50,8 @@ public static function fromMeilisearchSearchResult(Index $index, MeilisearchSear
5450
$page,
5551
$pageSize,
5652
$totalPages,
57-
$meilisearchSearchResult->getFacetStats(),
58-
$meilisearchSearchResult->getFacetDistribution(),
53+
new FacetStats($meilisearchSearchResult->getFacetStats()),
54+
new FacetDistribution($meilisearchSearchResult->getFacetDistribution()),
5955
);
6056
}
6157
}

src/Form/Builder/CheckboxFilterFormBuilder.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
namespace Setono\SyliusMeilisearchPlugin\Form\Builder;
66

77
use Setono\SyliusMeilisearchPlugin\Document\Metadata\Facet;
8+
use Setono\SyliusMeilisearchPlugin\Engine\FacetStat;
9+
use Setono\SyliusMeilisearchPlugin\Engine\FacetValues;
810
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
911
use Symfony\Component\Form\FormBuilderInterface;
1012
use function Symfony\Component\String\u;
1113

1214
final class CheckboxFilterFormBuilder implements FilterFormBuilderInterface
1315
{
14-
public function build(FormBuilderInterface $builder, Facet $facet, array $values, array $stats = null): void
16+
public function build(FormBuilderInterface $builder, Facet $facet, FacetValues $values, FacetStat $stats = null): void
1517
{
1618
$builder->add($facet->name, CheckboxType::class, [
1719
'label' => sprintf('setono_sylius_meilisearch.form.search.facet.%s', u($facet->name)->snake()),
@@ -24,7 +26,7 @@ public function build(FormBuilderInterface $builder, Facet $facet, array $values
2426
]);
2527
}
2628

27-
public function supports(Facet $facet, array $values, array $stats = null): bool
29+
public function supports(Facet $facet, FacetValues $values, FacetStat $stats = null): bool
2830
{
2931
return $facet->type === 'bool' && match (count($values)) {
3032
1 => isset($values['true']),

0 commit comments

Comments
 (0)