Skip to content

Commit

Permalink
Merge pull request #1 from mdiyakov/v1.1
Browse files Browse the repository at this point in the history
V1.1
  • Loading branch information
mdiyakov authored Jul 1, 2018
2 parents e45ec13 + fbdfa9e commit 0662c2e
Show file tree
Hide file tree
Showing 22 changed files with 555 additions and 25 deletions.
173 changes: 173 additions & 0 deletions Command/ClearIndexCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
<?php

namespace Mdiyakov\DoctrineSolrBundle\Command;

use Doctrine\Bundle\DoctrineBundle\Registry;
use Doctrine\ORM\EntityNotFoundException;
use Mdiyakov\DoctrineSolrBundle\Config\Config;
use Mdiyakov\DoctrineSolrBundle\Exception\EntityNotIndexedException;
use Mdiyakov\DoctrineSolrBundle\Query\UpdateQueryBuilder;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command;

class ClearIndexCommand extends Command
{

/**
* @var OutputInterface
*/
private $output;

/**
* @var Config
*/
private $config;

/**
* @var UpdateQueryBuilder
*/
private $updateQueryBuilder;

/**
* @var Registry
*/
private $registry;

/**
* @param Config $config
* @param UpdateQueryBuilder $updateQueryBuilder
* @param Registry $registry
*/
public function __construct(
Config $config,
UpdateQueryBuilder $updateQueryBuilder,
Registry $registry
)
{
$this->config = $config;
$this->possibleEntityTypes = array_keys($this->getAssocEntitiesClasses());
$this->updateQueryBuilder = $updateQueryBuilder;
$this->registry = $registry;

parent::__construct();
}

/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('doctrine-solr:clear-index')
->addArgument(
'entity-type',
InputArgument::OPTIONAL,
'Specify type of entity to be removed. Possible values are "all", "' . join('","', $this->possibleEntityTypes),
'all'
)
->addArgument(
'id',
InputArgument::OPTIONAL,
'Specify id of entity to be removed. Value must be integer. Also entity-type must be specify'
)
;
}

/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->output = $output;
$entityType = $input->getArgument('entity-type');
$entityId = (int) $input->getArgument('id');

if ($entityType == 'all') {
foreach ($this->config->getIndexedEntities() as $entityConfig) {
$this->deleteByEntityConfig(
$entityConfig
);
}
} else {
$entitiesClasses = $this->getAssocEntitiesClasses();
if (!array_key_exists($entityType, $entitiesClasses )) {
throw new \Exception('There is no such possible entity-type. Check help section for possible values');
}
$entityClass = $entitiesClasses[$entityType];
$entityConfig = $this->config->getEntityConfig($entityClass);
if (!$entityConfig) {
throw new EntityNotIndexedException(
sprintf('Entity class %s is not found in config', $entityClass)
);
}

$this->deleteByEntityConfig(
$entityConfig,
$entityId
);
}
}

/**
* @return string[]
*/
private function getAssocEntitiesClasses()
{
$entitiesConfigs = $this->config->getIndexedEntities();

$result = [];
foreach ($entitiesConfigs as $entityKey => $entityConfig) {
$result[$entityKey] = $entityConfig['class'];
}

return $result;
}

/**
* @param string[][] $entityConfig
* @param null|int $id
* @throws EntityNotFoundException
*/
private function deleteByEntityConfig($entityConfig, $id = null)
{
$schemaName = $entityConfig['schema'];
$updateQuery = $this->updateQueryBuilder->buildUpdateQueryBySchemaName($schemaName);
$schema = $this->config->getSchemaByName($schemaName);
$em = $this->registry->getManagerForClass($entityConfig['class']);

if (empty($id)) {
$discriminatorField = $schema->getDiscriminatorConfigField();
$discriminatorValue = $discriminatorField->getValue($entityConfig);
$updateQuery->addDeleteCriteriaByConfigField(
$discriminatorField->getDocumentFieldName(),
$discriminatorValue
);
$message = sprintf('Removing of %s is completed successfully', $entityConfig['class']);
} else {
$entityClass = $entityConfig['class'];
$repository = $em->getRepository($entityClass);
$entity = $repository->find($id);

if (!$entity) {
throw new EntityNotFoundException(
sprintf('% with %s id is not found', $entityClass, $id)
);
}

$updateQuery->addDeleteCriteriaByUniqueFieldValue(
$schema->getDocumentUniqueField()->getValue($entity, $entityConfig)
);

$message = sprintf('Removing of %s with id %s is completed successfully',
$entityClass,
$id
);

}

$updateQuery->update();
$this->output->writeln($message);
}
}
27 changes: 18 additions & 9 deletions Command/IndexEntitiesCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Mdiyakov\DoctrineSolrBundle\Command;

use Doctrine\Bundle\DoctrineBundle\Registry;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Console\Input\InputArgument;
Expand All @@ -17,9 +18,9 @@ class IndexEntitiesCommand extends Command
const BUNCH_COUNT = 100;

/**
* @var EntityManager
* @var Registry
*/
private $em;
private $registry;

/**
* @var Config
Expand All @@ -44,14 +45,14 @@ class IndexEntitiesCommand extends Command
/**
* @param Config $config
* @param IndexProcessManager $indexProcessManager
* @param EntityManager $em
* @param Registry $registry
*/
public function __construct(Config $config, IndexProcessManager $indexProcessManager, EntityManager $em)
public function __construct(Config $config, IndexProcessManager $indexProcessManager, Registry $registry)
{
$this->config = $config;
$this->indexProcessManager = $indexProcessManager;
$this->possibleEntityTypes = array_keys($this->getAssocEntitiesClasses());
$this->em = $em;
$this->registry = $registry;

parent::__construct();
}
Expand Down Expand Up @@ -105,10 +106,16 @@ protected function execute(InputInterface $input, OutputInterface $output)
* @param string $entityClass
* @param int|null $id
* @throws \Exception
* @throws \LogicException
*/
private function indexEntityClass($entityClass, $id = null)
{
$repository = $this->em->getRepository($entityClass);
$em = $this->registry->getManagerForClass($entityClass);
if (!$em instanceof EntityManager) {
throw new \LogicException('EntityManager must be instance of EntityManager');
}

$repository = $em->getRepository($entityClass);
if ($id) {
$entity = $repository->find($id);
if (!$entity) {
Expand All @@ -118,21 +125,23 @@ private function indexEntityClass($entityClass, $id = null)
}
$this->processEntity($entity);
} else {
$this->processRepository($repository);
$this->processRepository($repository, $em);
}
}

/**
* @param EntityRepository $repository
* @param EntityManager $em
*/
private function processRepository(EntityRepository $repository)
private function processRepository(EntityRepository $repository, EntityManager $em)
{
$offset = 0;
while ($entities = $repository->findBy([],['id'=> 'asc'], self::BUNCH_COUNT, $offset)) {
foreach ($entities as $entity) {
$this->processEntity($entity);
}
$this->em->clear($repository->getClassName());

$em->clear($repository->getClassName());
$offset += self::BUNCH_COUNT;
}
}
Expand Down
94 changes: 94 additions & 0 deletions Manager/EntityManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

namespace Mdiyakov\DoctrineSolrBundle\Manager;

use Doctrine\Bundle\DoctrineBundle\Registry;
use Doctrine\ORM\EntityManagerInterface;

class EntityManager
{
/**
* @var IndexProcessManager
*/
private $indexProcessManager;

/**
* @var Registry
*/
private $registry;

/**
* @param IndexProcessManager $indexProcessManager
* @param Registry $registry
*/
public function __construct(
IndexProcessManager $indexProcessManager,
Registry $registry
) {
$this->indexProcessManager = $indexProcessManager;
$this->registry = $registry;
}

/**
* @param object $entity
* @throws \Doctrine\ORM\ORMException
* @throws \InvalidArgumentException
* @throws \LogicException
* @throws \Exception
*/
public function flush($entity)
{
if (!is_object($entity)) {
throw new \InvalidArgumentException('Entity must be an object');
}

if (!method_exists($entity, 'getId')) {
throw new \LogicException('Entity must have method "getId" to handle rollback');
}

/** @var \Doctrine\ORM\EntityManager $em */
$em = $this->getEm($entity);
try {
$em->persist($entity);
$em->flush($entity);
} catch (\Exception $e) {
if (!$em->isOpen()) {
$em = $em->create(
$em->getConnection(), $em->getConfiguration()
);
}

$previousEntity = $em->getRepository(get_class($entity))->find($entity->getId());
if ($previousEntity) {
$this->indexProcessManager->reindex($previousEntity);
} else {
$this->indexProcessManager->remove($entity);
}

throw $e;
}
}

/**
* @param object $entity
* @throws \InvalidArgumentException
* @return EntityManagerInterface
*/
private function getEm($entity)
{
$em = $this->registry->getManagerForClass(get_class($entity));
if (!$em) {
throw new \InvalidArgumentException(
sprintf('There is no entity manager for "%s" class', get_class($entity))
);
}

if (!$em instanceof EntityManagerInterface) {
throw new \InvalidArgumentException(
'Entity manager must be instance of "EntityManagerInterface" class'
);
}

return $em;
}
}
Loading

0 comments on commit 0662c2e

Please sign in to comment.