Skip to content

Commit

Permalink
Merge pull request #15 from Setono/synonyms
Browse files Browse the repository at this point in the history
Improve synonym functionality
  • Loading branch information
loevgaard authored Aug 22, 2024
2 parents a3565f2 + 3af518d commit 1978d46
Show file tree
Hide file tree
Showing 23 changed files with 326 additions and 48 deletions.
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"require": {
"php": ">=8.1",
"ext-json": "*",
"doctrine/collections": "^1.8 || ^2.0",
"doctrine/event-manager": "^1.2 || ^2.0",
"doctrine/orm": "^2.14 || ^3.0",
"doctrine/persistence": "^2.5 || ^3.0",
Expand All @@ -30,6 +31,7 @@
"sylius/core": "^1.0",
"sylius/core-bundle": "^1.0",
"sylius/currency": "^1.0",
"sylius/grid-bundle": "^1.11",
"sylius/locale": "^1.0",
"sylius/locale-bundle": "^1.0",
"sylius/product": "^1.0",
Expand All @@ -42,6 +44,7 @@
"symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0",
"symfony/form": "^5.4 || ^6.4 || ^7.0",
"symfony/http-foundation": "^5.4 || ^6.4 || ^7.0",
"symfony/http-kernel": "^5.4 || ^6.4 || ^7.0",
"symfony/messenger": "^5.4 || ^6.4 || ^7.0",
"symfony/options-resolver": "^5.4 || ^6.4 || ^7.0",
"symfony/routing": "^5.4 || ^6.4 || ^7.0",
Expand Down
65 changes: 61 additions & 4 deletions src/DependencyInjection/SetonoSyliusMeilisearchExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ public function prepend(ContainerBuilder $container): void
]);

$container->prependExtensionConfig('sylius_grid', [
'templates' => [
'filter' => [
'indexes' => '@SetonoSyliusMeilisearchPlugin/admin/grid/filter/indexes.html.twig',
],
],
'grids' => [
'setono_sylius_meilisearch_admin_synonym' => [
'driver' => [
Expand All @@ -108,23 +113,69 @@ public function prepend(ContainerBuilder $container): void
'type' => 'string',
'label' => 'setono_sylius_meilisearch.ui.synonym',
],
'enabled' => [
'type' => 'twig',
'label' => 'sylius.ui.enabled',
'options' => [
'template' => '@SyliusUi/Grid/Field/enabled.html.twig',
],
],
'indexes' => [
'type' => 'twig',
'label' => 'setono_sylius_meilisearch.ui.indexes',
'path' => '.',
'options' => [
'template' => '@SetonoSyliusMeilisearchPlugin/admin/grid/field/_indexes.html.twig',
],
],
'locale' => [
'type' => 'string',
'label' => 'sylius.ui.locale',
],
'channel' => [
'type' => 'string',
'label' => 'sylius.ui.channel',
'channels' => [
'type' => 'twig',
'label' => 'sylius.ui.channels',
'options' => [
'template' => '@SyliusAdmin/Grid/Field/_channels.html.twig',
],
],
],
'filters' => [
'search' => [
'type' => 'string',
'label' => 'sylius.ui.search',
'label' => 'setono_sylius_meilisearch.ui.search_term_and_synonym',
'options' => [
'fields' => ['term', 'synonym'],
],
],
'enabled' => [
'type' => 'boolean',
'label' => 'sylius.ui.enabled',
],
'indexes' => [
'type' => 'indexes',
'label' => 'setono_sylius_meilisearch.ui.indexes',
'form_options' => [
'placeholder' => 'sylius.ui.all',
],
],
'locale' => [
'type' => 'entity',
'label' => 'sylius.ui.locale',
'form_options' => [
'class' => '%sylius.model.locale.class%',
],
],
'channel' => [
'type' => 'entities',
'label' => 'sylius.ui.channel',
'form_options' => [
'class' => '%sylius.model.channel.class%',
],
'options' => [
'field' => 'channels.id',
],
],
],
'actions' => [
'main' => [
Expand All @@ -140,6 +191,12 @@ public function prepend(ContainerBuilder $container): void
'type' => 'delete',
],
],
// todo in the future it might be a good user experience if we had bulk actions for adding indexes and channels to synonyms
'bulk' => [
'delete' => [
'type' => 'delete',
],
],
],
],
],
Expand Down
25 changes: 24 additions & 1 deletion src/EventListener/Doctrine/SynonymListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
use Doctrine\Persistence\Event\LifecycleEventArgs;
use Setono\SyliusMeilisearchPlugin\Message\Command\UpdateSynonyms;
use Setono\SyliusMeilisearchPlugin\Model\SynonymInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Messenger\MessageBusInterface;

final class SynonymListener
final class SynonymListener implements EventSubscriberInterface
{
private bool $update = false;

public function __construct(private readonly MessageBusInterface $commandBus)
{
}
Expand All @@ -30,12 +34,31 @@ public function postRemove(LifecycleEventArgs $eventArgs): void
$this->handle($eventArgs);
}

/**
* This method can be called multiple times in the same request, therefore we set a flag to only dispatch the command once
*/
public function handle(LifecycleEventArgs $eventArgs): void
{
if (!$eventArgs->getObject() instanceof SynonymInterface) {
return;
}

$this->update = true;
}

public function dispatch(): void
{
if (!$this->update) {
return;
}

$this->commandBus->dispatch(new UpdateSynonyms());
}

public static function getSubscribedEvents(): array
{
return [
KernelEvents::RESPONSE => ['dispatch', 10],
];
}
}
5 changes: 4 additions & 1 deletion src/Factory/SynonymFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ public function createInverseFromExisting(SynonymInterface $synonym): SynonymInt
$obj->setTerm($synonym->getSynonym());
$obj->setSynonym($synonym->getTerm());
$obj->setLocale($synonym->getLocale());
$obj->setChannel($synonym->getChannel());

foreach ($synonym->getChannels() as $channel) {
$obj->addChannel($channel);
}

return $obj;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Setono\SyliusMeilisearchPlugin\EventSubscriber;
namespace Setono\SyliusMeilisearchPlugin\Form\EventSubscriber;

use Doctrine\Persistence\ManagerRegistry;
use Setono\Doctrine\ORMTrait;
Expand Down
37 changes: 37 additions & 0 deletions src/Form/Type/IndexChoiceType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusMeilisearchPlugin\Form\Type;

use Setono\SyliusMeilisearchPlugin\Config\IndexRegistryInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;

final class IndexChoiceType extends AbstractType
{
public function __construct(private readonly IndexRegistryInterface $indexRegistry)
{
}

public function configureOptions(OptionsResolver $resolver): void
{
$names = $this->indexRegistry->getNames();

$resolver->setDefaults([
'choices' => array_combine($names, $names),
'choice_label' => static fn (string $name): string => ucfirst($name),
]);
}

public function getParent(): string
{
return ChoiceType::class;
}

public function getBlockPrefix(): string
{
return 'setono_sylius_meilisearch_index_choice';
}
}
17 changes: 15 additions & 2 deletions src/Form/Type/SynonymType.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Sylius\Bundle\LocaleBundle\Form\Type\LocaleChoiceType;
use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
Expand Down Expand Up @@ -42,8 +43,20 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
->add('locale', LocaleChoiceType::class, [
'label' => 'sylius.ui.locale',
])
->add('channel', ChannelChoiceType::class, [
'label' => 'sylius.ui.channel',
->add('channels', ChannelChoiceType::class, [
'multiple' => true,
'expanded' => true,
'label' => 'sylius.ui.channels',
'required' => false,
])
->add('indexes', IndexChoiceType::class, [
'multiple' => true,
'expanded' => true,
'label' => 'setono_sylius_meilisearch.form.synonym.indexes',
'required' => false,
])
->add('enabled', CheckboxType::class, [
'label' => 'sylius.ui.enabled',
'required' => false,
])
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event): void {
Expand Down
20 changes: 20 additions & 0 deletions src/Grid/Filter/IndexFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusMeilisearchPlugin\Grid\Filter;

use Sylius\Component\Grid\Data\DataSourceInterface;
use Sylius\Component\Grid\Filtering\FilterInterface;

class IndexFilter implements FilterInterface
{
public function apply(DataSourceInterface $dataSource, string $name, $data, array $options): void
{
if (!is_string($data) || '' === $data) {
return;
}

$dataSource->restrict($dataSource->getExpressionBuilder()->like($name, '%"' . $data . '"%'));
}
}
7 changes: 1 addition & 6 deletions src/Meilisearch/SynonymResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,11 @@ public function __construct(private readonly SynonymRepositoryInterface $synonym

public function resolve(IndexScope $indexScope): array
{
// it doesn't make sense to resolve synonyms if the locale is not set
if (null === $indexScope->localeCode) {
return [];
}

/** @var list<array{term: non-empty-string, synonym: non-empty-string}> $synonyms */
$synonyms = array_map(static fn (SynonymInterface $synonym): array => [
'term' => (string) $synonym->getTerm(),
'synonym' => (string) $synonym->getSynonym(),
], $this->synonymRepository->findByLocaleAndChannel($indexScope->localeCode, $indexScope->channelCode));
], $this->synonymRepository->findEnabledByIndexScope($indexScope));

$resolvedSynonyms = [];
foreach ($synonyms as $synonym) {
Expand Down
66 changes: 61 additions & 5 deletions src/Model/Synonym.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,19 @@

namespace Setono\SyliusMeilisearchPlugin\Model;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Sylius\Component\Channel\Model\ChannelInterface;
use Sylius\Component\Locale\Model\LocaleInterface;
use Sylius\Component\Resource\Model\TimestampableTrait;
use Sylius\Component\Resource\Model\ToggleableTrait;
use function Symfony\Component\String\u;

class Synonym implements SynonymInterface
{
use TimestampableTrait;
use ToggleableTrait;

protected ?int $id = null;

protected ?string $term = null;
Expand All @@ -18,7 +25,16 @@ class Synonym implements SynonymInterface

protected ?LocaleInterface $locale = null;

protected ?ChannelInterface $channel = null;
/** @var Collection<array-key, ChannelInterface> */
protected Collection $channels;

/** @var list<string>|null */
protected ?array $indexes = null;

public function __construct()
{
$this->channels = new ArrayCollection();
}

public function getId(): ?int
{
Expand Down Expand Up @@ -55,13 +71,53 @@ public function setLocale(?LocaleInterface $locale): void
$this->locale = $locale;
}

public function getChannel(): ?ChannelInterface
public function getChannels(): Collection
{
return $this->channels;
}

public function addChannel(ChannelInterface $channel): void
{
if (!$this->hasChannel($channel)) {
$this->channels->add($channel);
}
}

public function removeChannel(ChannelInterface $channel): void
{
if ($this->hasChannel($channel)) {
$this->channels->removeElement($channel);
}
}

public function hasChannel(ChannelInterface $channel): bool
{
return $this->channels->contains($channel);
}

public function getIndexes(): array
{
return $this->indexes ?? [];
}

public function addIndex(string $index): void
{
$this->indexes[] = $index;
}

public function removeIndex(string $index): void
{
return $this->channel;
$indexes = $this->getIndexes();
$key = array_search($index, $indexes, true);
if ($key !== false) {
unset($indexes[$key]);
}

$this->indexes = [] === $indexes ? null : array_values($indexes);
}

public function setChannel(?ChannelInterface $channel): void
public function hasIndex(string $index): bool
{
$this->channel = $channel;
return in_array($index, $this->getIndexes(), true);
}
}
Loading

0 comments on commit 1978d46

Please sign in to comment.