Skip to content

Commit

Permalink
Create a sorting form builder
Browse files Browse the repository at this point in the history
  • Loading branch information
loevgaard committed Dec 7, 2024
1 parent b71f342 commit 1874f92
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 21 deletions.
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@
"lexik/jwt-authentication-bundle": "^2.17",
"matthiasnoback/symfony-dependency-injection-test": "^4.3 || ^5.1",
"nyholm/psr7": "^1.8",
"phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.6.17",
"phpspec/prophecy-phpunit": "^2.3",
"phpunit/phpunit": "^9.6.21",
"psalm/plugin-phpunit": "^0.18.4",
"setono/code-quality-pack": "^2.8.3",
"sylius/sylius": "~1.12.18",
"sylius/sylius": "~1.12.19",
"symfony/browser-kit": "^5.4 || ^6.4 || ^7.0",
"symfony/debug-bundle": "^5.4 || ^6.4 || ^7.0",
"symfony/dotenv": "^5.4 || ^6.4 || ^7.0",
Expand Down
4 changes: 1 addition & 3 deletions src/Document/Attribute/Sortable.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ final class Sortable
final public const DESC = 'desc';

public function __construct(
/**
* The direction of the sorting. If null, both directions are allowed
*/
/** The direction of the sorting. If null, both directions are allowed */
public readonly ?string $direction = null,
) {
}
Expand Down
1 change: 1 addition & 0 deletions src/Document/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class Product extends Document implements UrlAwareInterface

public ?float $originalPrice = null;

#[Sortable(direction: Sortable::DESC)]
public float $popularity = 0.0;

/**
Expand Down
12 changes: 2 additions & 10 deletions src/Form/Builder/SearchFormBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ final class SearchFormBuilder implements SearchFormBuilderInterface
public function __construct(

Check failure on line 19 in src/Form/Builder/SearchFormBuilder.php

View workflow job for this annotation

GitHub Actions / Backwards Compatibility Check

The number of required arguments for Setono\SyliusMeilisearchPlugin\Form\Builder\SearchFormBuilder#__construct() increased from 4 to 5

Check failure on line 19 in src/Form/Builder/SearchFormBuilder.php

View workflow job for this annotation

GitHub Actions / Backwards Compatibility Check

The parameter $metadataFactory of Setono\SyliusMeilisearchPlugin\Form\Builder\SearchFormBuilder#__construct() changed from Setono\SyliusMeilisearchPlugin\Document\Metadata\MetadataFactoryInterface to a non-contravariant Setono\SyliusMeilisearchPlugin\Form\Builder\SortingFormBuilderInterface

Check failure on line 19 in src/Form/Builder/SearchFormBuilder.php

View workflow job for this annotation

GitHub Actions / Backwards Compatibility Check

The parameter $index of Setono\SyliusMeilisearchPlugin\Form\Builder\SearchFormBuilder#__construct() changed from Setono\SyliusMeilisearchPlugin\Config\Index to a non-contravariant Setono\SyliusMeilisearchPlugin\Document\Metadata\MetadataFactoryInterface
private readonly FormFactoryInterface $formFactory,
private readonly FacetFormBuilderInterface $facetFormBuilder,
private readonly SortingFormBuilderInterface $sortingFormBuilder,
private readonly MetadataFactoryInterface $metadataFactory,
private readonly Index $index,
) {
Expand Down Expand Up @@ -119,16 +120,7 @@ public function build(SearchResult $searchResult): FormInterface

$searchFormBuilder->add($facetsFormBuilder);

$searchFormBuilder->add(SearchRequest::QUERY_PARAMETER_SORT, ChoiceType::class, [
'choices' => [
'Cheapest first' => 'price:asc',
'Biggest discount' => 'discount:desc',
'Newest first' => 'createdAt:desc',
'Relevance' => '',
],
'required' => false,
'placeholder' => 'Sort by',
]);
$this->sortingFormBuilder->build($searchFormBuilder, $metadata);

Check warning on line 123 in src/Form/Builder/SearchFormBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/Form/Builder/SearchFormBuilder.php#L123

Added line #L123 was not covered by tests

$this->buildPagination($searchResult, $searchFormBuilder);

Expand Down
42 changes: 42 additions & 0 deletions src/Form/Builder/SortingFormBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusMeilisearchPlugin\Form\Builder;

use Setono\SyliusMeilisearchPlugin\Document\Attribute\Sortable as SortableAttribute;
use Setono\SyliusMeilisearchPlugin\Document\Metadata\MetadataInterface;
use Setono\SyliusMeilisearchPlugin\Document\Metadata\Sortable;
use Setono\SyliusMeilisearchPlugin\Engine\SearchRequest;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;

final class SortingFormBuilder implements SortingFormBuilderInterface
{
public function build(FormBuilderInterface $searchFormBuilder, MetadataInterface $metadata): void
{
$choices = [];
foreach ($metadata->getSortableAttributes() as $sortable) {
foreach (self::resolveDirections($sortable) as $direction) {
$choices[sprintf('setono_sylius_meilisearch.form.search.sorting.%s.%s', $sortable->name, $direction)] = sprintf('%s:%s', $sortable->name, $direction);
}
}
$searchFormBuilder->add(SearchRequest::QUERY_PARAMETER_SORT, ChoiceType::class, [
'choices' => $choices,
'required' => false,
'placeholder' => 'setono_sylius_meilisearch.form.search.sorting.placeholder',
]);
}

/**
* @return list<string>
*/
private static function resolveDirections(Sortable $sortable): array
{
if (null === $sortable->direction) {
return [SortableAttribute::ASC, SortableAttribute::DESC];
}

return [$sortable->direction];
}
}
13 changes: 13 additions & 0 deletions src/Form/Builder/SortingFormBuilderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusMeilisearchPlugin\Form\Builder;

use Setono\SyliusMeilisearchPlugin\Document\Metadata\MetadataInterface;
use Symfony\Component\Form\FormBuilderInterface;

interface SortingFormBuilderInterface
{
public function build(FormBuilderInterface $searchFormBuilder, MetadataInterface $metadata): void;
}
7 changes: 7 additions & 0 deletions src/Resources/config/services/form.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,20 @@
<tag name="setono_sylius_meilisearch.facet_form_builder" priority="80"/>
</service>

<!-- Sorting form builder -->
<service id="Setono\SyliusMeilisearchPlugin\Form\Builder\SortingFormBuilderInterface"
alias="Setono\SyliusMeilisearchPlugin\Form\Builder\SortingFormBuilder"/>

<service id="Setono\SyliusMeilisearchPlugin\Form\Builder\SortingFormBuilder"/>

<!-- Search form builder -->
<service id="Setono\SyliusMeilisearchPlugin\Form\Builder\SearchFormBuilderInterface"
alias="Setono\SyliusMeilisearchPlugin\Form\Builder\SearchFormBuilder"/>

<service id="Setono\SyliusMeilisearchPlugin\Form\Builder\SearchFormBuilder">
<argument type="service" id="form.factory"/>
<argument type="service" id="Setono\SyliusMeilisearchPlugin\Form\Builder\FacetFormBuilderInterface"/>
<argument type="service" id="Setono\SyliusMeilisearchPlugin\Form\Builder\SortingFormBuilderInterface"/>
<argument type="service" id="Setono\SyliusMeilisearchPlugin\Document\Metadata\MetadataFactoryInterface"/>
<argument type="service" id="setono_sylius_meilisearch.index.search"/>

Expand Down
2 changes: 1 addition & 1 deletion src/Resources/public/js/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class SearchManager {
field.dispatchEvent(new CustomEvent('search:filter-changed', { bubbles: true }));
} else if(field.name === 'p') {
field.dispatchEvent(new CustomEvent('search:page-changed', { bubbles: true }));
} else if(field.classList.contains('sort')) {
} else if(field.classList.contains('ssm-sort')) {
field.dispatchEvent(new CustomEvent('search:sort-changed', { bubbles: true }));
}
});
Expand Down
14 changes: 14 additions & 0 deletions src/Resources/translations/messages.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ setono_sylius_meilisearch:
previous: Previous
next: Next
q_placeholder: Search...
sorting:
placeholder: Sort by...
price:
asc: "Price: low to high"
desc: "Price: high to low"
createdAt:
asc: "Oldest"
desc: "Newest"
discount:
asc: "Discount: low to high"
desc: "Discount: high to low"
popularity:
asc: "Least popular"
desc: "Most popular"
synonym:
term: Term
synonym: Synonym
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,5 @@
margin: 0 !important;
text-align-last: right;
}
.ssm-sort option {
direction: rtl;
}
</style>
{% endblock %}
46 changes: 46 additions & 0 deletions tests/Unit/Form/Builder/SortingFormBuilderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusMeilisearchPlugin\Tests\Unit\Form\Builder;

use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Setono\SyliusMeilisearchPlugin\Document\Attribute\Sortable as SortableAttribute;
use Setono\SyliusMeilisearchPlugin\Document\Metadata\MetadataInterface;
use Setono\SyliusMeilisearchPlugin\Document\Metadata\Sortable;
use Setono\SyliusMeilisearchPlugin\Engine\SearchRequest;
use Setono\SyliusMeilisearchPlugin\Form\Builder\SortingFormBuilder;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;

final class SortingFormBuilderTest extends TestCase
{
use ProphecyTrait;

/**
* @test
*/
public function it_builds(): void
{
$searchFormBuilder = $this->prophesize(FormBuilderInterface::class);
$searchFormBuilder->add(SearchRequest::QUERY_PARAMETER_SORT, ChoiceType::class, [
'choices' => [
'setono_sylius_meilisearch.form.search.sorting.name.asc' => 'name:asc',
'setono_sylius_meilisearch.form.search.sorting.name.desc' => 'name:desc',
'setono_sylius_meilisearch.form.search.sorting.price.desc' => 'price:desc',
],
'required' => false,
'placeholder' => 'setono_sylius_meilisearch.form.search.sorting.placeholder',
])->willReturn($searchFormBuilder)->shouldBeCalledOnce();

$metadata = $this->prophesize(MetadataInterface::class);
$metadata->getSortableAttributes()->willReturn([
new Sortable('name'),
new Sortable('price', SortableAttribute::DESC),
]);

$builder = new SortingFormBuilder();
$builder->build($searchFormBuilder->reveal(), $metadata->reveal());
}
}

0 comments on commit 1874f92

Please sign in to comment.