Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example to index taxon #172

Merged
merged 31 commits into from
Jul 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
86eff35
Rename product box dist file template
maximehuran Jul 25, 2023
a89c61f
Add stuffs for test app to index taxons
maximehuran Jul 25, 2023
c1368d2
Add lines in documentation links
maximehuran Jul 25, 2023
aa1fb7c
fix: find the global analyzers in all config directories
delyriand Jul 25, 2023
3e2da15
fix: replace type for taxon dto mapper
delyriand Jul 25, 2023
3fea7bf
Fix PHP CS
maximehuran Jul 26, 2023
f0664ed
Make taxons appears in instant search
maximehuran Jul 26, 2023
f886d9e
Display taxon name same as product name in search result in test app
maximehuran Jul 26, 2023
4e945e0
fix: should index parent taxon data
delyriand Jul 26, 2023
d2120c1
Be able to search on many entities displayed by tabs
maximehuran Jul 27, 2023
e76d68e
feat: add position on documentables to change the order
delyriand Jul 27, 2023
155832d
test: change position of app_taxon to display first
delyriand Jul 27, 2023
b79b209
feat: use the first documentable as default
delyriand Jul 27, 2023
8c54d63
feat: allow to change document type for taxon route
delyriand Jul 27, 2023
c32319a
doc: add filter documentation
delyriand Jul 27, 2023
d5ebb8c
Update requests to be used only in YAML
maximehuran Jul 27, 2023
75992c6
Change dist files for Taxons requests
maximehuran Jul 27, 2023
cd6702e
Rename document_type parameter in URLs and don't loose it in filters
maximehuran Jul 27, 2023
931060b
Update services.yaml lines links in doc
maximehuran Jul 27, 2023
08044a7
Update docs to add custom entities documentation
maximehuran Jul 27, 2023
10d20d1
Fix PHP CS
maximehuran Jul 27, 2023
629663d
Move Channel filter and EnabledFilter
maximehuran Jul 27, 2023
923c0a4
Add basic search term filter and use it for products
maximehuran Jul 27, 2023
c998a52
fix: phpstan errors
delyriand Jul 27, 2023
3fa4b54
fix: phpmd errors
delyriand Jul 27, 2023
175d6f0
Manage translation by code in search like the instant search
maximehuran Jul 27, 2023
c6f58b7
Finalize custom entities doc
maximehuran Jul 27, 2023
ea8f69b
Nested fields limit documentation
maximehuran Jul 27, 2023
7d14589
Remove todo
maximehuran Jul 27, 2023
9b7a188
Add links to docs folder in README
maximehuran Jul 27, 2023
6896d8c
Fix PHP CS
maximehuran Jul 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,10 @@ test.composer: ## Validate composer.json
${COMPOSER} validate --strict

test.phpstan: ## Run PHPStan
${COMPOSER} phpstan || true
${COMPOSER} phpstan

test.phpmd: ## Run PHPMD
${COMPOSER} phpmd || true
${COMPOSER} phpmd

test.phpunit: ## Run PHPUnit
${COMPOSER} phpunit
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ use Sylius\Component\Product\Model\ProductAttribute as BaseProductAttribute;

4. Run the populate command.

## Documentation

[Documentation is available in the *docs* folder.](docs/index.md)

## Infrastructure

The plugin was developed for Elasticsearch 7.16.x versions. You need to have analysis-icu and analysis-phonetic elasticsearch plugin installed.
Expand Down
3 changes: 2 additions & 1 deletion UPGRADE-2.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
- Remove `MonsieurBiz\SyliusSearchPlugin\Search\Request\PostFilter\ProductTaxonRegistry` service to use an iterator of services tagged `monsieurbiz.search.request.product_post_filter`
- Remove `MonsieurBiz\SyliusSearchPlugin\Search\Request\Sorting\ProductSorterRegistry` service to use an iterator of services tagged `monsieurbiz.search.request.product_sorter`
- Remove `\MonsieurBiz\SyliusSearchPlugin\Search\Request\FunctionScore\ProductFunctionScoreRegistry` service to use an iterator of services tagged `monsieurbiz.search.request.product_function_score`
- The `MonsieurBiz\SyliusSearchPlugin\Mapping\YamlWithLocaleProvider` is no longer a decorator. Some constructor parameters are removed : `$decorated`, `$configurationDirectory` and `$attributeRepository`, and we have `$yamlProviderFactory`, `$fileLocator` and `$configurationDirectories`.
- The `MonsieurBiz\SyliusSearchPlugin\Mapping\YamlWithLocaleProvider` is no longer a decorator. Some constructor parameters are removed : `$decorated`, `$configurationDirectory` and `$attributeRepository`, and we add `$fileLocator` and `$configurationDirectories`.
- New setting `monsieurbiz_sylius_search.elastically_configuration_paths` to define paths of elasticsearch mapping files. By default it's `['@MonsieurBizSyliusSearchPlugin/Resources/config/elasticsearch']`.
- New method `deleteByDocumentIds` in the `MonsieurBiz\SyliusSearchPlugin\Index\IndexerInterface` interface
- Deprecated the method `deleteByDocuments` in the `MonsieurBiz\SyliusSearchPlugin\Index\IndexerInterface` interface. Use `deleteByDocumentIds` instead.
- `ChannelFilter` and `EnabledFilter` in `MonsieurBiz\SyliusSearchPlugin\Search\Request\QueryFilter\Product` were moved to `MonsieurBiz\SyliusSearchPlugin\Search\Request\QueryFilter`

# UPGRADE FROM v1.X.X TO v2.0.x

Expand Down
1 change: 1 addition & 0 deletions dist/src/Resources/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ parameters:

imports:
- { resource: "services.yaml" }
- { resource: "search/taxons.yaml" }
51 changes: 51 additions & 0 deletions dist/src/Resources/config/elasticsearch/app_taxon_mapping.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
mappings:
dynamic: false
properties:
code:
type: keyword
enabled:
type: boolean
name:
type: text
fields:
keyword:
type: keyword
autocomplete:
type: text
analyzer: search_autocomplete
search_analyzer: standard
description:
type: text
created_at:
type: date
format: yyyy-MM-dd HH:mm:ss||strict_date_optional_time||epoch_second
position:
type: integer
level:
type: integer
left:
type: integer
right:
type: integer
parent_taxon:
type: nested
properties:
code:
type: keyword
enabled:
type: boolean
name:
type: keyword
description:
type: text
created_at:
type: date
format: yyyy-MM-dd HH:mm:ss||strict_date_optional_time||epoch_second
position:
type: integer
level:
type: integer
left:
type: integer
right:
type: integer
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ mappings:
fields:
keyword: # add keyword field for sorting
type: keyword
settings:
mapping:
nested_fields:
limit: 1000
23 changes: 23 additions & 0 deletions dist/src/Resources/config/search/taxons.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
monsieurbiz_sylius_search:
documents:
app_taxon:
#prefix: '…' # define a custom index prefix on index names and aliases
#document_class: '…' # by default MonsieurBiz\SyliusSearchPlugin\Model\Documentable\Documentable
instant_search_enabled: true # by default false
limits:
search: [9, 18, 27]
taxon: [9, 18, 27]
instant_search: [5]
source: 'Sylius\Component\Core\Model\TaxonInterface'
target: 'App\Search\Model\Taxon\TaxonDTO'
templates:
item: '@MonsieurBizSyliusSearchPlugin/Search/Taxon/_box.html.twig'
instant: '@MonsieurBizSyliusSearchPlugin/Instant/Taxon/_box.html.twig'
#mapping_provider: '...' # by default monsieurbiz.search.mapper_provider
datasource: 'App\Search\Model\Datasource\TaxonDatasource' # by default MonsieurBiz\SyliusSearchPlugin\Model\Datasource\RepositoryDatasource
position: -1
automapper_classes:
sources:
taxon: '%sylius.model.taxon.class%'
targets:
app_taxon: 'App\Search\Model\Taxon\TaxonDTO'
39 changes: 39 additions & 0 deletions dist/src/Resources/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ services:
autowire: true
autoconfigure: true
public: false
bind:
$documentableRegistry: '@monsieurbiz.search.registry.documentable'

# Makes classes in src/ available to be used as services;
# this creates a service per class whose id is the fully-qualified class name
Expand Down Expand Up @@ -53,3 +55,40 @@ services:
App\Search\Request\FunctionScore\Product\BoostExpensiveProductFunction:
tags:
- { name: monsieurbiz.search.request.product_function_score }

# Define the taxon requests
app.search.request.taxon_instant_search:
class: MonsieurBiz\SyliusSearchPlugin\Search\Request\InstantSearch
arguments:
$documentType: app_taxon
$queryFilters: !tagged_iterator { tag: 'app.search.request.taxon_instant_search_filter' }
$functionScores: !tagged_iterator { tag: 'app.search.request.taxon_function_score' }

app.search.request.taxon_search:
class: MonsieurBiz\SyliusSearchPlugin\Search\Request\Search
arguments:
$documentType: app_taxon
$queryFilters: !tagged_iterator { tag: 'app.search.request.taxon_search_filter' }
$postFilters: !tagged_iterator { tag: 'app.search.request.taxon_post_filter' }
$sorters: !tagged_iterator { tag: 'app.search.request.taxon_sorter' }
$functionScores: !tagged_iterator { tag: 'app.search.request.taxon_function_score' }

# Define the taxon query filters
app.search.request.query_filter.taxon_instant_search.search_term_filter:
class: MonsieurBiz\SyliusSearchPlugin\Search\Request\QueryFilter\SearchTermFilter
arguments:
$fieldsToSearch:
- 'name^5'
- 'description'
- 'name.autocomplete'
tags:
- { name: app.search.request.taxon_instant_search_filter }

app.search.request.query_filter.taxon_search.search_term_filter:
class: MonsieurBiz\SyliusSearchPlugin\Search\Request\QueryFilter\SearchTermFilter
arguments:
$fieldsToSearch:
- 'name^5'
- 'description'
tags:
- { name: app.search.request.taxon_search_filter }
126 changes: 126 additions & 0 deletions dist/src/Search/Automapper/TaxonMapperConfiguration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?php

/*
* This file is part of Monsieur Biz' Search plugin for Sylius.
*
* (c) Monsieur Biz <[email protected]>
*
* For the full copyright and license information, please view the LICENSE.txt
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace App\Search\Automapper;

use App\Search\Model\Taxon\TaxonDTO;
use DateTimeInterface;
use Doctrine\Common\Proxy\Proxy;
use Doctrine\Common\Util\ClassUtils;
use Doctrine\ORM\EntityManagerInterface;
use Jane\Bundle\AutoMapperBundle\Configuration\MapperConfigurationInterface;
use Jane\Component\AutoMapper\AutoMapperInterface;
use Jane\Component\AutoMapper\MapperGeneratorMetadataInterface;
use Jane\Component\AutoMapper\MapperMetadata;
use MonsieurBiz\SyliusSearchPlugin\AutoMapper\ConfigurationInterface;
use Sylius\Component\Core\Model\TaxonInterface;

final class TaxonMapperConfiguration implements MapperConfigurationInterface
{
private ConfigurationInterface $configuration;

private AutoMapperInterface $autoMapper;

public function __construct(
ConfigurationInterface $configuration,
AutoMapperInterface $autoMapper,
private EntityManagerInterface $entityManager
) {
$this->configuration = $configuration;
$this->autoMapper = $autoMapper;
}

public function process(MapperGeneratorMetadataInterface $metadata): void
{
if (!$metadata instanceof MapperMetadata) {
return;
}

$metadata->forMember('id', function (TaxonInterface $taxon): int {
return $taxon->getId();
});

$metadata->forMember('code', function (TaxonInterface $taxon): ?string {
return $taxon->getCode();
});

$metadata->forMember('enabled', function (TaxonInterface $taxon): bool {
return $taxon->isEnabled();
});

$metadata->forMember('slug', function (TaxonInterface $taxon): ?string {
return $taxon->getSlug();
});

$metadata->forMember('name', function (TaxonInterface $taxon): ?string {
return $taxon->getName();
});

$metadata->forMember('description', function (TaxonInterface $taxon): ?string {
return $taxon->getDescription();
});

$metadata->forMember('created_at', function (TaxonInterface $taxon): ?DateTimeInterface {
return $taxon->getCreatedAt();
});

$metadata->forMember('position', function (TaxonInterface $taxon): ?int {
return $taxon->getPosition();
});

$metadata->forMember('level', function (TaxonInterface $taxon): ?int {
return $taxon->getLevel();
});

$metadata->forMember('left', function (TaxonInterface $taxon): ?int {
return $taxon->getLeft();
});

$metadata->forMember('right', function (TaxonInterface $taxon): ?int {
return $taxon->getRight();
});

/** @phpstan-ignore-next-line */
$metadata->forMember('parent_taxon', function (TaxonInterface $taxon): ?TaxonDTO {
return ($parent = $taxon->getParent()) ? $this->autoMapper->map(
$this->getRealTaxonEntity($parent),
$this->configuration->getTargetClass('app_taxon')
) : null;
});
}

public function getSource(): string
{
return $this->configuration->getSourceClass('taxon');
}

public function getTarget(): string
{
return $this->configuration->getTargetClass('app_taxon');
}

private function getRealTaxonEntity(TaxonInterface $taxon): TaxonInterface
{
if ($taxon instanceof Proxy) {
// Clear the entity manager to detach the proxy object
$this->entityManager->clear(\get_class($taxon));
// Retrieve the original class name
$entityClassName = ClassUtils::getRealClass(\get_class($taxon));
// Find the object in repository from the ID
/** @var ?TaxonInterface $taxon */
$taxon = $this->entityManager->find($entityClassName, $taxon->getId());
}

return $taxon;
}
}
57 changes: 57 additions & 0 deletions dist/src/Search/Model/Datasource/TaxonDatasource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

/*
* This file is part of Monsieur Biz' Search plugin for Sylius.
*
* (c) Monsieur Biz <[email protected]>
*
* For the full copyright and license information, please view the LICENSE.txt
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace App\Search\Model\Datasource;

use Doctrine\ORM\EntityManagerInterface;
use MonsieurBiz\SyliusSearchPlugin\Model\Datasource\DatasourceInterface;
use Pagerfanta\Doctrine\ORM\QueryAdapter;
use Pagerfanta\Pagerfanta;
use Sylius\Component\Taxonomy\Repository\TaxonRepositoryInterface;
use Webmozart\Assert\Assert;

class TaxonDatasource implements DatasourceInterface
{
private EntityManagerInterface $entityManager;

public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}

public function getItems(string $sourceClass): iterable
{
$repository = $this->entityManager->getRepository($sourceClass);
/** @var TaxonRepositoryInterface $repository */
Assert::isInstanceOf($repository, TaxonRepositoryInterface::class);

$queryBuilder = $repository->createQueryBuilder('o')
->andWhere('o.enabled = :enabled')
->setParameter('enabled', true)
;

$paginator = new Pagerfanta(new QueryAdapter($queryBuilder, false, false));
$paginator->setMaxPerPage(self::DEFAULT_MAX_PER_PAGE);
$page = 1;
do {
$paginator->setCurrentPage($page);

foreach ($paginator->getIterator() as $item) {
yield $item;
}
$page = $paginator->hasNextPage() ? $paginator->getNextPage() : 1;
} while ($paginator->hasNextPage());

return null;
}
}
20 changes: 20 additions & 0 deletions dist/src/Search/Model/Taxon/TaxonDTO.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

/*
* This file is part of Monsieur Biz' Search plugin for Sylius.
*
* (c) Monsieur Biz <[email protected]>
*
* For the full copyright and license information, please view the LICENSE.txt
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace App\Search\Model\Taxon;

use Jacquesbh\Eater\Eater;

class TaxonDTO extends Eater
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% import "@SyliusShop/Common/Macro/money.html.twig" as money %}

<div class="result">
<div class="content">
<a href="{{ path('monsieurbiz_sylius_search_taxon', {'slug': item.slug, '_locale': sylius.localeCode}) }}" class="header sylius-product-name">{{ item.name }}</a>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% import "@SyliusShop/Common/Macro/money.html.twig" as money %}

<div class="ui fluid card">
<div class="content">
<a href="{{ path('monsieurbiz_sylius_search_taxon', {'slug': item.slug, '_locale': sylius.localeCode}) }}" class="header sylius-product-name">{{ item.name }}</a>
</div>
</div>
Loading
Loading