-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fbd5913
commit 702b9d2
Showing
62 changed files
with
3,111 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#!/usr/bin/env php | ||
<?php | ||
// application.php | ||
|
||
require __DIR__.'/../vendor/autoload.php'; | ||
|
||
use Symfony\Component\Config\FileLocator; | ||
use Atoolo\Search\Console\Application; | ||
|
||
$container = new Symfony\Component\DependencyInjection\ContainerBuilder(); | ||
$loader = new Symfony\Component\DependencyInjection\Loader\YamlFileLoader( | ||
$container, | ||
new FileLocator(__DIR__ . '/../config')); | ||
|
||
$loader->load('services.yml'); | ||
$container->compile(); | ||
|
||
$application = $container->get(Application::class); | ||
|
||
$application->run(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
services: | ||
_defaults: | ||
autowire: true | ||
autoconfigure: true | ||
_instanceof: | ||
Symfony\Component\Console\Command\Command: | ||
tags: ['command'] | ||
|
||
Atoolo\Search\Console\: | ||
resource: '../src/Console' | ||
|
||
Atoolo\Search\Console\Application: | ||
public: true | ||
arguments: | ||
- !tagged command |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Atoolo\Search\Console; | ||
|
||
use Symfony\Component\Console\Application as BaseApplication; | ||
|
||
class Application extends BaseApplication | ||
{ | ||
public function __construct(iterable $commands = []) | ||
{ | ||
parent::__construct(); | ||
foreach ($commands as $command) { | ||
$this->add($command); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Atoolo\Search\Console\Command; | ||
|
||
use Atoolo\Resource\Exception\InvalidResourceException; | ||
use Atoolo\Resource\Loader\SiteKitLoader; | ||
use Atoolo\Resource\Loader\SiteKitNavigationHierarchyLoader; | ||
use Atoolo\Search\Console\Command\Io\IndexerProgressProgressBar; | ||
use Atoolo\Search\Dto\Indexer\IndexerParameter; | ||
use Atoolo\Search\Service\Indexer\SiteKit\DefaultSchema21DocumentEnricher; | ||
use Atoolo\Search\Service\Indexer\SolrIndexer; | ||
use Atoolo\Search\Service\SolrParameterClientFactory; | ||
use Symfony\Component\Console\Attribute\AsCommand; | ||
use Symfony\Component\Console\Command\Command; | ||
use Symfony\Component\Console\Input\InputArgument; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
use Symfony\Component\Console\Style\SymfonyStyle; | ||
|
||
#[AsCommand( | ||
name: 'atoolo:indexer', | ||
description: 'Fill a search index' | ||
)] | ||
class Indexer extends Command | ||
{ | ||
private IndexerProgressProgressBar $progressBar; | ||
private SymfonyStyle $io; | ||
private string $resourceDir; | ||
|
||
protected function configure(): void | ||
{ | ||
$this | ||
->setHelp('Command to fill a search index') | ||
->addArgument( | ||
'solr-core', | ||
InputArgument::REQUIRED, | ||
'Solr core to be used.' | ||
) | ||
->addArgument( | ||
'resource-dir', | ||
InputArgument::REQUIRED, | ||
'Resource directory whose data is to be indexed.' | ||
) | ||
->addArgument( | ||
'directories', | ||
InputArgument::OPTIONAL | InputArgument::IS_ARRAY, | ||
'Resources or directories of the resource to be indexed.' | ||
) | ||
->addOption( | ||
'cleanup-threshold', | ||
null, | ||
InputArgument::OPTIONAL, | ||
'Specifies the number of indexed documents from ' . | ||
'which indexing is considered successful and old entries ' . | ||
'can be deleted. Is only used for full indexing.', | ||
0 | ||
) | ||
; | ||
} | ||
|
||
protected function execute( | ||
InputInterface $input, | ||
OutputInterface $output | ||
): int { | ||
|
||
$this->io = new SymfonyStyle($input, $output); | ||
$this->progressBar = new IndexerProgressProgressBar($output); | ||
$this->resourceDir = $input->getArgument('resource-dir'); | ||
$directories = $input->getArgument('directories'); | ||
|
||
$cleanupThreshold = empty($directories) | ||
? $input->getArgument('cleanup-threshold') | ||
: 0; | ||
|
||
if (empty($directories)) { | ||
$this->io->title('Index all resources'); | ||
} else { | ||
$this->io->title('Index resources subdirectories'); | ||
$this->io->listing($directories); | ||
} | ||
|
||
$parameter = new IndexerParameter( | ||
$input->getArgument('solr-core'), | ||
$this->resourceDir, | ||
$cleanupThreshold, | ||
$directories | ||
); | ||
|
||
$indexer = $this->createIndexer(); | ||
$indexer->index($parameter); | ||
|
||
$this->errorReport(); | ||
|
||
return Command::SUCCESS; | ||
} | ||
|
||
protected function errorReport(): void | ||
{ | ||
foreach ($this->progressBar->getErrors() as $error) { | ||
if ($error instanceof InvalidResourceException) { | ||
$this->io->error( | ||
$error->getLocation() . ': ' . | ||
$error->getMessage() | ||
); | ||
} else { | ||
$this->io->error($error->getMessage()); | ||
} | ||
} | ||
} | ||
|
||
protected function createIndexer(): SolrIndexer | ||
{ | ||
$resourceLoader = new SiteKitLoader($this->resourceDir); | ||
$navigationLoader = new SiteKitNavigationHierarchyLoader( | ||
$resourceLoader | ||
); | ||
$schema21 = new DefaultSchema21DocumentEnricher( | ||
$navigationLoader | ||
); | ||
|
||
$clientFactory = new SolrParameterClientFactory(); | ||
return new SolrIndexer( | ||
[$schema21], | ||
$this->progressBar, | ||
$resourceLoader, | ||
$clientFactory, | ||
'internal' | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Atoolo\Search\Console\Command\Io; | ||
|
||
use Atoolo\Search\Service\Indexer\IndexerProgressHandler; | ||
use Exception; | ||
use Symfony\Component\Console\Helper\ProgressBar; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
|
||
class IndexerProgressProgressBar implements IndexerProgressHandler | ||
{ | ||
private OutputInterface $output; | ||
private ProgressBar $progressBar; | ||
|
||
private array $errors = []; | ||
|
||
public function __construct(OutputInterface $output) | ||
{ | ||
$this->output = $output; | ||
} | ||
|
||
public function start(int $total): void | ||
{ | ||
$this->progressBar = new ProgressBar($this->output, $total); | ||
$this->formatProgressBar('green'); | ||
} | ||
|
||
public function advance(int $step): void | ||
{ | ||
$this->progressBar->advance($step); | ||
} | ||
|
||
private function formatProgressBar(string $color): void | ||
{ | ||
$this->progressBar->setBarCharacter('<fg=' . $color . '>•</>'); | ||
$this->progressBar->setEmptyBarCharacter('<fg=' . $color . '>⚬</>'); | ||
$this->progressBar->setProgressCharacter('<fg=' . $color . '>➤</>'); | ||
$this->progressBar->setFormat( | ||
"%current%/%max% [%bar%] %percent:3s%%\n" . | ||
" %estimated:-20s% %memory:20s%" | ||
); | ||
} | ||
|
||
public function error(Exception $exception): void | ||
{ | ||
$this->formatProgressBar('red'); | ||
$this->errors[] = $exception; | ||
} | ||
|
||
public function finish(): void | ||
{ | ||
$this->progressBar->finish(); | ||
} | ||
|
||
/** | ||
* @return array<Exception> | ||
*/ | ||
public function getErrors(): array | ||
{ | ||
return $this->errors; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Atoolo\Search\Console\Command; | ||
|
||
use Atoolo\Resource\Loader\SiteKitLoader; | ||
use Atoolo\Search\Dto\Search\Query\MoreLikeThisQuery; | ||
use Atoolo\Search\Dto\Search\Result\ResourceSearchResult; | ||
use Atoolo\Search\Service\Search\ExternalResourceFactory; | ||
use Atoolo\Search\Service\Search\InternalMediaResourceFactory; | ||
use Atoolo\Search\Service\Search\InternalResourceFactory; | ||
use Atoolo\Search\Service\Search\SolrMoreLikeThis; | ||
use Atoolo\Search\Service\Search\SolrResultToResourceResolver; | ||
use Atoolo\Search\Service\SolrParameterClientFactory; | ||
use Psr\Log\NullLogger; | ||
use Symfony\Component\Console\Attribute\AsCommand; | ||
use Symfony\Component\Console\Command\Command; | ||
use Symfony\Component\Console\Input\InputArgument; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
use Symfony\Component\Console\Style\SymfonyStyle; | ||
|
||
#[AsCommand( | ||
name: 'atoolo:mlt', | ||
description: 'Performs a more-like-this search' | ||
)] | ||
class MoreLikeThis extends Command | ||
{ | ||
private SymfonyStyle $io; | ||
private string $solrCore; | ||
private string $resourceDir; | ||
|
||
protected function configure(): void | ||
{ | ||
$this | ||
->setHelp('Command to performs a more-like-this search') | ||
->addArgument( | ||
'solr-core', | ||
InputArgument::REQUIRED, | ||
'Solr core to be used.' | ||
) | ||
->addArgument( | ||
'resource-dir', | ||
InputArgument::REQUIRED, | ||
'Resource directory whose data is to be indexed.' | ||
) | ||
->addArgument( | ||
'location', | ||
InputArgument::REQUIRED, | ||
'Resource directory whose data is to be indexed.' | ||
) | ||
; | ||
} | ||
|
||
protected function execute( | ||
InputInterface $input, | ||
OutputInterface $output | ||
): int { | ||
|
||
$this->io = new SymfonyStyle($input, $output); | ||
|
||
$this->solrCore = $input->getArgument('solr-core'); | ||
$this->resourceDir = $input->getArgument('resource-dir'); | ||
$location = $input->getArgument('location'); | ||
|
||
$searcher = $this->createSearcher(); | ||
$query = $this->buildQuery($location); | ||
$result = $searcher->moreLikeThis($query); | ||
$this->outputResult($result); | ||
|
||
return Command::SUCCESS; | ||
} | ||
|
||
protected function createSearcher(): SolrMoreLikeThis | ||
{ | ||
$resourceLoader = new SiteKitLoader($this->resourceDir); | ||
$clientFactory = new SolrParameterClientFactory(); | ||
$resourceFactoryList = [ | ||
new ExternalResourceFactory(), | ||
new InternalResourceFactory($resourceLoader), | ||
new InternalMediaResourceFactory($resourceLoader) | ||
]; | ||
$solrResultToResourceResolver = new SolrResultToResourceResolver( | ||
$resourceFactoryList | ||
); | ||
|
||
return new SolrMoreLikeThis( | ||
$clientFactory, | ||
$solrResultToResourceResolver | ||
); | ||
} | ||
|
||
protected function buildQuery(string $location): MoreLikeThisQuery | ||
{ | ||
$filterList = []; | ||
return new MoreLikeThisQuery( | ||
$this->solrCore, | ||
$location, | ||
$filterList, | ||
5, | ||
['content'] | ||
); | ||
} | ||
|
||
protected function outputResult(ResourceSearchResult $result): void | ||
{ | ||
$this->io->text($result->getTotal() . " Results:"); | ||
foreach ($result as $resource) { | ||
$this->io->text($resource->getLocation()); | ||
} | ||
$this->io->text('Query-Time: ' . $result->getQueryTime() . 'ms'); | ||
} | ||
} |
Oops, something went wrong.