diff -r b403086580f7 -r 0e57c730bb18 Command/SyncDocumentsCommand.php --- a/Command/SyncDocumentsCommand.php Fri Nov 18 17:54:30 2011 +0100 +++ b/Command/SyncDocumentsCommand.php Fri Nov 25 18:55:42 2011 +0100 @@ -13,13 +13,29 @@ use IRI\Bundle\WikiTagBundle\Event\WikiTagEvents; use IRI\Bundle\WikiTagBundle\Event\DocumentTagEvent; use Doctrine\ORM\Query; -use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class SyncDocumentsCommand extends ContainerAwareCommand +/** + * + * This class implement a command to synchronize the wikita document table and index to the host application documents. + * options : + * - tags: Synchronize the tag string of the wikitag documents, otherwise, synchronize the document themselves (default not set). + * The tags string is the concatenation (with comma) of all tag's label of a wikita document. It allows the indexation of the tags. + * - clear: Clear the wikitag documents. (default not set) + * - all: if set, process all objects, if not process only those that need it. (default not set) + * - --tags not set : if --all is set, recreate a wikitag document for all host document (you may have to run the commant with the clear option first), + * otherwise create only the missing wikitag document. + * - --tags set: if --all is set, recalculate the tags string for all document, otherwise, only calculate the tag string wher it is null. + * - --clear: if --all is set, delete all wikitag documents, otherwise clear only those not linked to a host document. + * - force: force document deletion (default not set) + * + * @author ymh + * + */ +class SyncDocumentsCommand extends ProgressContainerAwareCommand { protected function configure() { @@ -28,88 +44,127 @@ $this ->setName('wikitag:sync-doc') ->setDescription('Synchronize and index document class') - ->addOption('missing', 'm', InputOption::VALUE_NONE, "process missing") + ->addOption('force', 'f', InputOption::VALUE_NONE, "Force document deletion") ->addOption('tags', 't', InputOption::VALUE_NONE, "update tags") - ->addOption('clear', 'c', InputOption::VALUE_NONE, "clear all docs"); + ->addOption('clear', 'c', InputOption::VALUE_NONE, "Clear documents") + ->addOption('all', 'a', InputOption::VALUE_NONE, "clear all docs"); + } - - protected function execute(InputInterface $input, OutputInterface $output) + + private function execute_tags(InputInterface $input, OutputInterface $output) { - $class = $this->getContainer()->getParameter('wiki_tag.document_class'); - $clear = $input->getOption('clear'); - $missing = $input->getOption('missing'); - - $doctrine = $this->getContainer()->get('doctrine'); $docrep = $doctrine->getRepository('WikiTagBundle:Document'); - $rep = $doctrine->getRepository($class); + $all = $input->getOption('all'); - if(is_null($rep)) { - //TODO : translate - $output->writeln("$class does not have a repository : exiting."); - return ; + if($all) + { + $docquery = $doctrine->getEntityManager()->createQuery("SELECT doc from WikiTagBundle:Document doc"); + $doccountquery = $doctrine->getEntityManager()->createQuery("SELECT COUNT(doc.id) from WikiTagBundle:Document doc"); + } + else + { + $docquery = $doctrine->getEntityManager()->createQuery("SELECT doc from WikiTagBundle:Document doc WHERE doc.tagsStr IS NULL"); + $doccountquery = $doctrine->getEntityManager()->createQuery("SELECT COUNT(doc.id) from WikiTagBundle:Document doc WHERE doc.tagsStr IS NULL"); } - if($input->getOption('tags')) - { - if(!$missing) + + $total = $doccountquery->getSingleScalarResult(); + $done = 0; + $iterable = $docquery->iterate(); + $todetach = array(); + while (($row = $iterable->next()) !== false) { + $done++; + $memory = ((($done%10)==0)?" - mem: ".strval(memory_get_usage(true)):""); + $doc = $row[0]; + $todetach[] = $doc; + + $this->showProgress($output, $done, $total, "id : ".$doc->getId()."%$memory", 50); + $docrep->updateTagsStr($doc); + //dispatch event + $event_dispatcher = $this->getContainer()->get('event_dispatcher'); + $event = new DocumentTagEvent($doc); + $event_dispatcher->dispatch(WikiTagEvents::onTagChanged, $event); + + if($done%10 == 0) { - $docquery = $doctrine->getEntityManager()->createQuery("SELECT doc from WikiTagBundle:Document doc"); - $doccountquery = $doctrine->getEntityManager()->createQuery("SELECT COUNT(doc.id) from WikiTagBundle:Document doc"); - } - else - { - $docquery = $doctrine->getEntityManager()->createQuery("SELECT doc from WikiTagBundle:Document doc WHERE doc.tagsStr IS NULL"); - $doccountquery = $doctrine->getEntityManager()->createQuery("SELECT COUNT(doc.id) from WikiTagBundle:Document doc WHERE doc.tagsStr IS NULL"); + $doctrine->getEntityManager()->flush(); + foreach($todetach as $obj) + { + $doctrine->getEntityManager()->detach($obj); + } + $todetach = array(); } - - - $total = $doccountquery->getSingleScalarResult(); - $done = 0; - $iterable = $docquery->iterate(); - $todetach = array(); - while (($row = $iterable->next()) !== false) { - $done++; - $memory = ((($done%10)==0)?" - mem: ".strval(memory_get_usage(true)):""); - $doc = $row[0]; - $todetach[] = $doc; - $output->writeln("Process doc id ".$doc->getId()." $done/$total ".strval(intval(floatval($done)/floatval($total)*100.0))."%$memory"); - $docrep->updateTagsStr($doc); - //dispatch event - $event_dispatcher = $this->getContainer()->get('event_dispatcher'); - $event = new DocumentTagEvent($doc); - $event_dispatcher->dispatch(WikiTagEvents::onTagChanged, $event); - - if($done%10 == 0) - { - $doctrine->getEntityManager()->flush(); - foreach($todetach as $obj) - { - $doctrine->getEntityManager()->detach($obj); - } - $todetach = array(); - } - } - $doctrine->getEntityManager()->flush(); - - return; - + } + $doctrine->getEntityManager()->flush(); + $doctrine->getEntityManager()->clear(); + } + + private function execute_clear(InputInterface $input, OutputInterface $output) + { + $class = $this->getContainer()->getParameter('wiki_tag.document_class'); + $doctrine = $this->getContainer()->get('doctrine'); + $all = $input->getOption('all'); + $force = $input->getOption('force'); + + + if($all) + { + // delete all documents + $query_str = "DELETE WikiTagBundle:Document wtdoc"; + $count_query_str = "SELECT COUNT(wtdoc.id) FROM WikiTagBundle:Document wtdoc"; + } + else + { + // delete only wikitag document that have no conterpart + $query_str = "DELETE WikiTagBundle:Document wtdoc WHERE wtdoc.externalId IS NULL OR wtdoc.externalId NOT IN (SELECT doc FROM $class doc)"; + $count_query_str = "SELECT COUNT(wtdoc.id) FROM WikiTagBundle:Document wtdoc WHERE wtdoc.externalId IS NULL OR wtdoc.externalId NOT IN (SELECT doc FROM $class doc)"; } - //TODO : check class to implement DocumentInterface - //TODO : write progress - if($missing) + $count_query = $doctrine->getEntityManager()->createQuery($count_query_str); + $total = $count_query->getSingleScalarResult(); + + if($total === 0) + { + $output->writeln("No wikitag document to delete. Exit."); + return; + } + + $output->writeln("$total wikitag document(s) to delete."); + if(!$force && $input->isInteractive()) + { + $dialog = $this->getHelper('dialog'); + if (!$dialog->askConfirmation($output, 'Confirm deletion? (y/N) : ', false)) { + return; + } + } + + $req = $doctrine->getEntityManager()->createQuery($query_str); + + $nb_deleted = $req->getResult(); + + $output->writeln("$nb_deleted wikitag document(s) deleted."); + + $doctrine->getEntityManager()->flush(); + + } + + private function execute_docs(InputInterface $input, OutputInterface $output) + { + $all = $input->getOption('all'); + $doctrine = $this->getContainer()->get('doctrine'); + $docrep = $doctrine->getRepository('WikiTagBundle:Document'); + + if($all) + { + $docquery = $doctrine->getEntityManager()->createQuery("SELECT doc FROM $class doc"); + $doccountquery = $doctrine->getEntityManager()->createQuery("SELECT count(doc.id) FROM $class doc"); + } + else { $docquery = $doctrine->getEntityManager()->createQuery("SELECT doc FROM $class doc WHERE doc.id not in (SELECT wtdoc FROM WikiTagBundle:Document wtdoc)"); $doccountquery = $doctrine->getEntityManager()->createQuery("SELECT count(doc.id) FROM $class doc WHERE doc.id not in (SELECT wtdoc FROM WikiTagBundle:Document wtdoc)"); - //$doclist = $doctrine->getEntityManager()->createQuery("SELECT doc FROM $class doc WHERE doc.id not in (SELECT wtdoc FROM WikiTagBundle:Document wtdoc)")->getResult(); - } - else - { - $docquery = $doctrine->getEntityManager()->createQuery("SELECT doc FROM $class doc"); - $doccountquery = $doctrine->getEntityManager()->createQuery("SELECT count(doc.id) FROM $class doc"); - //$doclist = $rep->findAll(); } $total = $doccountquery->getSingleScalarResult(); $done = 0; @@ -118,7 +173,7 @@ $done++; $doc = $row[0]; $memory = ((($done%10)==0)?" - mem: ".strval(memory_get_usage(true)):""); - $output->writeln("Process doc id ".$doc->getId()." $done/$total ".strval(intval(floatval($done)/floatval($total)*100.0))."%$memory"); + $this->showProgress($output, $done, $total, "id : ".$doc->getId()."%$memory", 50); $docrep->writeDocument($doc, $this->getContainer()->getParameter('wiki_tag.document_id_column'), $this->getContainer()->getParameter('wiki_tag.fields')); if($done%10 == 0) { @@ -127,14 +182,39 @@ } } $doctrine->getEntityManager()->flush(); + $doctrine->getEntityManager()->clear(); - if($clear) { - - $req = $doctrine->getEntityManager()->createQuery("DELETE WikiTagBundle:Document wtdoc WHERE wtdoc.externalId NOT IN (SELECT doc FROM $class doc)"); - $req->getResult(); - $doctrine->getEntityManager()->flush(); + } + + + protected function execute(InputInterface $input, OutputInterface $output) + { + $clear = $input->getOption('clear'); + $tags = $input->getOption('tags'); + + + $class = $this->getContainer()->getParameter('wiki_tag.document_class'); + $doctrine = $this->getContainer()->get('doctrine'); + $rep = $doctrine->getRepository($class); + + if(is_null($rep)) + { + $output->writeln("$class does not have a repository : exiting."); + return ; + } + + if($tags) + { + $this->execute_tags($input, $output); + } + elseif($clear) + { + $this->execute_clear($input, $output); + } + else + { + $this->execute_docs($input, $output); } - $output->writeln(strval(count($doclist)) ." documents imported."); } } \ No newline at end of file