trinity-cms-bundles/src/Trinity/Bundle/SearchBundle/Command/BuildIndexCommand.php

204 lines
6.6 KiB
PHP

<?php
namespace Trinity\Bundle\SearchBundle\Command;
use Sensio\Bundle\GeneratorBundle\Command\Helper\DialogHelper;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Finder\Finder;
class BuildIndexCommand extends ContainerAwareCommand
{
protected function configure()
{
$this
->setName('wd:lucene:build-index')
->setDescription('Synchronize the index with the database')
->setHelp(
<<<EOF
This command allow to initalize, build or sync an index define by a culture.
EOF
);
}
protected function getQuerynameFromFile($file)
{
$lines = file($file);
$namespace = null;
foreach ($lines as $line) {
$line = trim($line, " ;\n\r");
$parts = explode(' ', $line);
if ($parts[0] == 'namespace') {
$namespace = '\\'.ltrim(end($parts), '\\');
continue;
}
}
if ($namespace === null) {
return null;
}
return $namespace.'\\'.str_replace('.php', 'Query', $file->getFilename());
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$dialog = $this->getDialogHelper();
if ($input->isInteractive()) {
if (!$dialog->askConfirmation($output, $dialog->getQuestion('Do you confirm generation', 'yes', '?'), true)) {
$output->writeln(
array(
'',
'<error>Command aborted</error>',
''
)
);
return 1;
}
}
$culture = $dialog->ask(
$output,
$dialog->getQuestion('Lucene index to generate ', 'fr_FR'),
'fr_FR'
);
$output->writeln(
array(
'',
'You are allowed to choose between two methods :',
'- <comment>init</comment> : will remove old index entries for all <comment>Indexable</comment> objects',
' present in your project. We recommend this option if you use the',
' <info>'.$culture.' index</info> for third part data',
'- <comment>build</comment> : will remove the index and build it from scratch',
'- <comment>sync</comment> : will add new index entries for all <comment>Indexable</comment> objects',
' which aren\'t indexed yet',
'',
)
);
$method = $dialog->askAndValidate(
$output,
$dialog->getQuestion('Choose the method to process on the index', 'sync'),
array($this, 'validateMethod'),
false,
'sync',
array('build', 'sync', 'init')
);
$root_app_dir = $this->getContainer()->get('kernel')->getRootDir();
$finder = new Finder();
$files = $finder
->files()
->path('/Model/')
->notPath('/Model/map')
->notPath('/Model/om')
->contains('IndexableInterface')
->notName('IndexableInterface.php')
->in($root_app_dir.'/../src')
->in($root_app_dir.'/../vendor/trinity');
if ($method == 'build') {
$this->getContainer()->get('ivory_lucene_search')->eraseIndex($culture);
}
$index = $this->getContainer()->get('ivory_lucene_search')->getIndex($culture);
foreach ($files as $file) {
$query = $this->getQuerynameFromFile($file);
if (null === $query) {
continue;
}
$objects = $query::create()->find();
$output->writeln(
array(
'<info>'.$query.'</info> number of elements indexable : <comment>'.count($objects).'</comment>',
)
);
$indexed_elements = 0;
foreach ($objects as $object) {
$hits = $index->find('pk:'.$object->getIndexKey());
if ($method == 'init') {
foreach ($hits as $hit) {
$index->delete($hit->id);
$index->commit();
}
}
if ($method == 'sync' && count($hits) > 0) {
continue;
}
$document = $object->getLuceneDocument($culture);
if (!$document) {
continue;
}
$index->addDocument($document);
$index->commit();
$index->optimize();
$indexed_elements++;
}
$output->writeln(
array(
'<info>'.$query.'</info> number of indexed elements : <comment>'.$indexed_elements.'</comment>',
'----------------------------------------------------------------------------',
)
);
}
$output->writeln(
array(
'',
'The <comment>'.$culture.'</comment> index has been successfully <info>'.$method.'</infos>',
'<info>'.$culture.'</info> index information : ',
'Index format version : <comment>'.$index->getFormatVersion().'</comment>',
'Max buffered documents : <comment>'.$index->getMaxBufferedDocs().'</comment>',
'Number of documents (with deleted) : <comment>'.$index->count().'</comment>',
'Number of documents (without deleted) : <comment>'.$index->numDocs().'</comment>',
'<info>Unique fields</info> in index : '.implode(', ', $index->getFieldNames()).'',
'',
)
);
}
public function validateMethod($method)
{
$allowed_method = array('sync', 'build', 'init');
if (!in_array($method, $allowed_method)) {
throw new \InvalidArgumentException('This method isn\'t allowed by this command.');
}
return $method;
}
/**
* @return DialogHelper|\Symfony\Component\Console\Helper\HelperInterface
*/
protected function getDialogHelper()
{
$dialog = $this->getHelperSet()->get('dialog');
if (!$dialog || get_class($dialog) !== 'Sensio\Bundle\GeneratorBundle\Command\Helper\DialogHelper') {
$this->getHelperSet()->set($dialog = new DialogHelper());
}
return $dialog;
}
}