Command/SyncDocumentsCommand.php
changeset 42 0e57c730bb18
parent 34 21fab44f46fe
child 57 186c4121c7b3
--- 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, '<question>Confirm deletion? (y/N) : </question>', 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