Skip to content

Commit

Permalink
initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
mike4git committed Jan 16, 2024
1 parent 50d3a87 commit 87825d1
Show file tree
Hide file tree
Showing 43 changed files with 1,166 additions and 0 deletions.
3 changes: 3 additions & 0 deletions bin/composer
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

exec docker compose run --rm --user "$(id -u):$(id -g)" --no-deps php composer "$@"
4 changes: 4 additions & 0 deletions bin/run-tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh

docker compose run --rm --user "$(id -u):$(id -g)" php composer tests
docker compose down
5 changes: 5 additions & 0 deletions config/index/elastically.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
services:

Neusta\ElasticBundle\Index\Elastically\IndexesRepository:
arguments:
$client: '@JoliCode\Elastically\Client'
11 changes: 11 additions & 0 deletions config/index/registry.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
services:

neusta.elastic_bundle.registry.converter:
class: Neusta\ElasticBundle\Index\Registry\ObjectRegistry
arguments:
$name: 'converter'

neusta.elastic_bundle.registry.repository:
class: Neusta\ElasticBundle\Index\Registry\ObjectRegistry
arguments:
$name: 'repository'
12 changes: 12 additions & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
imports:
- { resource: index/* }

services:
_defaults:
autowire: true
autoconfigure: true

JoliCode\Elastically\Client:
arguments:
$config:
elastically_index_class_mapping: []
45 changes: 45 additions & 0 deletions src/Command/CreateIndexCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php declare(strict_types=1);

namespace Neusta\ElasticIndexBundle\Command;

use JoliCode\Elastically\Client;
use Neusta\ElasticIndexBundle\Index\Elastically\IndexesRepository;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

final class CreateIndexCommand extends Command
{
protected static $defaultName = 'neusta:elastic:index:create';

private Client $client;
private IndexesRepository $indexesRepository;

public function __construct(Client $client, IndexesRepository $indexesRepository)
{
parent::__construct();
$this->client = $client;
$this->indexesRepository = $indexesRepository;
}

protected function configure(): void
{
$this->setDescription('Create Elasticsearch indexes.');
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln('Start creating new indexes and move aliases.');

$indexBuilder = $this->client->getIndexBuilder();

foreach ($this->indexesRepository->getAllIndexes() as $indexName) {
$indexBuilder->markAsLive($indexBuilder->createIndex($indexName), $indexName);
$indexBuilder->purgeOldIndices($indexName);
}

$output->writeln('Creating indexes done');

return Command::SUCCESS;
}
}
62 changes: 62 additions & 0 deletions src/Command/IndexCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php declare(strict_types=1);

namespace Neusta\ElasticIndexBundle\Command;

use Neusta\ElasticIndexBundle\Index\Data\DataRepository;
use Neusta\ElasticIndexBundle\Index\Data\Filter\DataFilter;
use Neusta\ElasticIndexBundle\Index\Data\Messenger\DataMessageFactory;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Messenger\MessageBusInterface;

final class IndexCommand extends Command
{
protected static $defaultName = 'neusta:elastic:index:data';

public function __construct(
private DataRepository $repository,
private DataFilter $filter,
private DataMessageFactory $messageFactory,
private MessageBusInterface $bus,
) {
parent::__construct();
}

protected function configure(): void
{
$this->setDescription('Re-index your data.');
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$dataObjects = $this->repository->findAll();

$filteredElements = $this->filter->filter($dataObjects);

$io = new SymfonyStyle($input, $output);

$io->title('Start indexing');
$io->writeln([
sprintf('Repository returns %s items.', \count($dataObjects)),
'(The number of Elements returned from the Repository may differ from the number of actually indexed Elements due to filter constraints.)',
'',
]);

$io->section('Index counter');

foreach ($io->progressIterate($filteredElements) as $dataObject) {
$message = $this->messageFactory->create($dataObject);
$this->bus->dispatch($message);
}

$output->writeln([
'',
'',
'Done',
]);

return Command::SUCCESS;
}
}
24 changes: 24 additions & 0 deletions src/DependencyInjection/Compiler/ConverterRegistryPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php declare(strict_types=1);

namespace Neusta\ElasticIndexBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

final class ConverterRegistryPass implements CompilerPassInterface
{
private const TAG_NAME = 'neusta.elastic_bundle.converter';
private const REGISTRY_KEY = 'registry_key'; // @phpstan-ignore-line

public function process(ContainerBuilder $container): void
{
$registryDefinition = $container->getDefinition('neusta.elastic_bundle.registry.converter');

foreach ($container->findTaggedServiceIds(self::TAG_NAME, true) as $id => $tags) {
foreach ($tags as [self::REGISTRY_KEY => $registryKey]) {
$registryDefinition->addMethodCall('register', [$registryKey, new Reference($id)]);
}
}
}
}
24 changes: 24 additions & 0 deletions src/DependencyInjection/Compiler/RepositoryRegistryPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php declare(strict_types=1);

namespace Neusta\ElasticIndexBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

final class RepositoryRegistryPass implements CompilerPassInterface
{
private const TAG_NAME = 'neusta.elastic_bundle.repository';
private const REGISTRY_KEY = 'registry_key'; // @phpstan-ignore-line

public function process(ContainerBuilder $container): void
{
$registryDefinition = $container->getDefinition('neusta.elastic_bundle.registry.repository');

foreach ($container->findTaggedServiceIds(self::TAG_NAME, true) as $id => $tags) {
foreach ($tags as [self::REGISTRY_KEY => $registryKey]) {
$registryDefinition->addMethodCall('register', [$registryKey, new Reference($id)]);
}
}
}
}
66 changes: 66 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php declare(strict_types=1);

namespace Neusta\ElasticIndexBundle\DependencyInjection;

use Neusta\ElasticIndexBundle\Index\Data\Filter\NoOperationFilter;
use Neusta\ElasticIndexBundle\Pimcore\Index\DataObjectRepository;
use Neusta\ElasticIndexBundle\Pimcore\Index\PageRepository;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

/**
* This is the class that validates and merges configuration from your app/config files.
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/configuration.html}
*/
final class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder('neusta_elastic');
$root = $treeBuilder->getRootNode();

$root
->children()
->arrayNode('hosts')
->scalarPrototype()->end()
->defaultValue(['elasticsearch:9200'])
->end()
->arrayNode('commands')
->addDefaultsIfNotSet()
->children()
->arrayNode('data_object')
->addDefaultsIfNotSet()
->children()
->booleanNode('enable_default_handler')->defaultTrue()->end()
->scalarNode('repository')
->info('Service id of the "DataObjectRepository" that is used in the neusta:elastic:index:objects command.')
->defaultValue(DataObjectRepository::class)
->end()
->scalarNode('filter')
->info('Service id of the "DataObjectFilter" that is used in the neusta:elastic:index:objects command.')
->defaultValue(NoOperationFilter::class)
->end()
->end()
->end()
->arrayNode('page')
->addDefaultsIfNotSet()
->children()
->booleanNode('enable_default_handler')->defaultTrue()->end()
->scalarNode('repository')
->info('Service id of the "PageRepository" that is used in the neusta:elastic:index:pages command.')
->defaultValue(PageRepository::class)
->end()
->scalarNode('filter')
->info('Service id of the "PageFilter" that is used in the neusta:elastic:index:pages command.')
->defaultValue(NoOperationFilter::class)
->end()
->end()
->end()
->end()
->end()
->end();

return $treeBuilder;
}
}
42 changes: 42 additions & 0 deletions src/DependencyInjection/NeustaElasticExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php declare(strict_types=1);

namespace Neusta\ElasticIndexBundle\DependencyInjection;

use Neusta\ElasticIndexBundle\Pimcore\Index\Command\IndexDataObjectsCommand;
use Neusta\ElasticIndexBundle\Pimcore\Index\Command\IndexPagesCommand;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\ConfigurableExtension;

final class NeustaElasticExtension extends ConfigurableExtension
{
protected function loadInternal(array $mergedConfig, ContainerBuilder $container): void // @phpstan-ignore-line
{
$loader = new Loader\YamlFileLoader($container, new FileLocator(\dirname(__DIR__, 2) . '/config'));
$loader->load('services.yaml');

$container->setParameter('neusta_elastic.elasticsearch_hosts', $mergedConfig['hosts']);

// 'commands.data_object' config
if (true === $mergedConfig['commands']['data_object']['enable_default_handler']) {
$loader->load('services/pimcore/default_handler_data_object.yaml');
}
$serviceIdRepository = $mergedConfig['commands']['data_object']['repository'];
$serviceIdFilter = $mergedConfig['commands']['data_object']['filter'];
$indexDataObjectsCommand = $container->getDefinition(IndexDataObjectsCommand::class);
$indexDataObjectsCommand->setArgument('$repository', new Reference($serviceIdRepository));
$indexDataObjectsCommand->setArgument('$filter', new Reference($serviceIdFilter));

// 'commands.page' config
if (true === $mergedConfig['commands']['page']['enable_default_handler']) {
$loader->load('services/pimcore/default_handler_page.yaml');
}
$serviceIdRepository = $mergedConfig['commands']['page']['repository'];
$serviceIdFilter = $mergedConfig['commands']['page']['filter'];
$indexPagesCommand = $container->getDefinition(IndexPagesCommand::class);
$indexPagesCommand->setArgument('$repository', new Reference($serviceIdRepository));
$indexPagesCommand->setArgument('$filter', new Reference($serviceIdFilter));
}
}
14 changes: 14 additions & 0 deletions src/Index/Data/DataCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php declare(strict_types=1);

namespace Neusta\ElasticIndexBundle\Index\Data;

/**
* @template T of object
*/
interface DataCollection extends \IteratorAggregate, \Countable
{
/**
* @return \Traversable<int, T>
*/
public function getIterator(): \Traversable;
}
14 changes: 14 additions & 0 deletions src/Index/Data/DataRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php declare(strict_types=1);

namespace Neusta\ElasticIndexBundle\Index\Data;

/**
* @template T of object
*/
interface DataRepository
{
/**
* @return DataCollection<T>
*/
public function findAll(): DataCollection;
}
15 changes: 15 additions & 0 deletions src/Index/Data/Factory/ElasticDocumentFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php declare(strict_types=1);

namespace Neusta\ElasticIndexBundle\Index\Data\Factory;

use Neusta\ConverterBundle\Converter\Context\GenericContext;
use Neusta\ConverterBundle\TargetFactory;
use Neusta\ElasticIndexBundle\Index\Document\ElasticDocument;

/**
* @extends TargetFactory<ElasticDocument, GenericContext>
*/
interface ElasticDocumentFactory extends TargetFactory
{
public function create(object $ctx = null): ElasticDocument;
}
32 changes: 32 additions & 0 deletions src/Index/Data/Filter/AbstractDataFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php declare(strict_types=1);

namespace Neusta\ElasticIndexBundle\Index\Data\Filter;

use Neusta\ElasticIndexBundle\Index\Data\DataCollection;

/**
* @template T of object
*
* @implements DataFilter<T>
*/
abstract class AbstractDataFilter implements DataFilter
{
/**
* @param DataCollection<T> $elements
*/
final public function filter(DataCollection $elements): iterable
{
foreach ($elements as $element) {
if (null !== $this->filterOne($element)) {
yield $element;
}
}
}

/**
* @param T $element
*
* @return T|null
*/
abstract public function filterOne(object $element): ?object;
}
Loading

0 comments on commit 87825d1

Please sign in to comment.