Command/SyncDocumentsCommand.php
changeset 42 0e57c730bb18
parent 34 21fab44f46fe
child 57 186c4121c7b3
equal deleted inserted replaced
39:b403086580f7 42:0e57c730bb18
    11 namespace IRI\Bundle\WikiTagBundle\Command;
    11 namespace IRI\Bundle\WikiTagBundle\Command;
    12 
    12 
    13 use IRI\Bundle\WikiTagBundle\Event\WikiTagEvents;
    13 use IRI\Bundle\WikiTagBundle\Event\WikiTagEvents;
    14 use IRI\Bundle\WikiTagBundle\Event\DocumentTagEvent;
    14 use IRI\Bundle\WikiTagBundle\Event\DocumentTagEvent;
    15 use Doctrine\ORM\Query;
    15 use Doctrine\ORM\Query;
    16 use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
       
    17 use Symfony\Component\Console\Input\InputArgument;
    16 use Symfony\Component\Console\Input\InputArgument;
    18 use Symfony\Component\Console\Input\InputInterface;
    17 use Symfony\Component\Console\Input\InputInterface;
    19 use Symfony\Component\Console\Input\InputOption;
    18 use Symfony\Component\Console\Input\InputOption;
    20 use Symfony\Component\Console\Output\OutputInterface;
    19 use Symfony\Component\Console\Output\OutputInterface;
    21 
    20 
    22 class SyncDocumentsCommand extends ContainerAwareCommand
    21 /**
       
    22  *
       
    23  * This class implement a command to synchronize the wikita document table and index to the host application documents.
       
    24  * options :
       
    25  * - tags: Synchronize the tag string of the wikitag documents, otherwise, synchronize the document themselves (default not set).
       
    26  *     The tags string is the concatenation (with comma) of all tag's label of a wikita document. It allows the indexation of the tags.
       
    27  * - clear: Clear the wikitag documents. (default not set)
       
    28  * - all: if set, process all objects, if not process only those that need it. (default not set)
       
    29  *     - --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),
       
    30  *         otherwise create only the missing wikitag document.
       
    31  *     - --tags set: if --all is set, recalculate the tags string for all document, otherwise, only calculate the tag string wher it is null.
       
    32  *     - --clear: if --all is set, delete all wikitag documents, otherwise clear only those not linked to a host document.
       
    33  * - force: force document deletion (default not set)
       
    34  *
       
    35  * @author ymh
       
    36  *
       
    37  */
       
    38 class SyncDocumentsCommand extends ProgressContainerAwareCommand
    23 {
    39 {
    24     protected function configure()
    40     protected function configure()
    25     {
    41     {
    26         parent::configure();
    42         parent::configure();
    27         
    43         
    28         $this
    44         $this
    29             ->setName('wikitag:sync-doc')
    45             ->setName('wikitag:sync-doc')
    30             ->setDescription('Synchronize and index document class')
    46             ->setDescription('Synchronize and index document class')
    31             ->addOption('missing', 'm', InputOption::VALUE_NONE, "process missing")
    47             ->addOption('force', 'f', InputOption::VALUE_NONE, "Force document deletion")
    32             ->addOption('tags', 't', InputOption::VALUE_NONE, "update tags")
    48             ->addOption('tags', 't', InputOption::VALUE_NONE, "update tags")
    33             ->addOption('clear', 'c', InputOption::VALUE_NONE, "clear all docs");
    49             ->addOption('clear', 'c', InputOption::VALUE_NONE, "Clear documents")
    34     }
    50             ->addOption('all', 'a', InputOption::VALUE_NONE, "clear all docs");
    35 
    51         
    36     protected function execute(InputInterface $input, OutputInterface $output)
    52     }
       
    53     
       
    54     private function execute_tags(InputInterface $input, OutputInterface $output)
       
    55     {
       
    56         $doctrine = $this->getContainer()->get('doctrine');
       
    57         
       
    58         $docrep = $doctrine->getRepository('WikiTagBundle:Document');
       
    59         $all = $input->getOption('all');
       
    60         
       
    61         if($all)
       
    62         {
       
    63             $docquery = $doctrine->getEntityManager()->createQuery("SELECT doc from WikiTagBundle:Document doc");
       
    64             $doccountquery = $doctrine->getEntityManager()->createQuery("SELECT COUNT(doc.id) from WikiTagBundle:Document doc");
       
    65         }
       
    66         else
       
    67         {
       
    68             $docquery = $doctrine->getEntityManager()->createQuery("SELECT doc from WikiTagBundle:Document doc WHERE doc.tagsStr IS NULL");
       
    69             $doccountquery = $doctrine->getEntityManager()->createQuery("SELECT COUNT(doc.id) from WikiTagBundle:Document doc WHERE doc.tagsStr IS NULL");
       
    70         }
       
    71         
       
    72         
       
    73         $total = $doccountquery->getSingleScalarResult();
       
    74         $done = 0;
       
    75         $iterable = $docquery->iterate();
       
    76         $todetach = array();
       
    77         while (($row = $iterable->next()) !== false) {
       
    78             $done++;
       
    79             $memory = ((($done%10)==0)?" - mem: ".strval(memory_get_usage(true)):"");
       
    80             $doc = $row[0];
       
    81             $todetach[] = $doc;
       
    82         
       
    83             $this->showProgress($output, $done, $total, "id : ".$doc->getId()."%$memory", 50);
       
    84             $docrep->updateTagsStr($doc);
       
    85             //dispatch event
       
    86             $event_dispatcher = $this->getContainer()->get('event_dispatcher');
       
    87             $event = new DocumentTagEvent($doc);
       
    88             $event_dispatcher->dispatch(WikiTagEvents::onTagChanged, $event);
       
    89         
       
    90             if($done%10 == 0)
       
    91             {
       
    92                 $doctrine->getEntityManager()->flush();
       
    93                 foreach($todetach as $obj)
       
    94                 {
       
    95                     $doctrine->getEntityManager()->detach($obj);
       
    96                 }
       
    97                 $todetach = array();
       
    98             }
       
    99         }
       
   100         $doctrine->getEntityManager()->flush();
       
   101         $doctrine->getEntityManager()->clear();
       
   102     }
       
   103 
       
   104     private function execute_clear(InputInterface $input, OutputInterface $output)
    37     {
   105     {
    38         $class = $this->getContainer()->getParameter('wiki_tag.document_class');
   106         $class = $this->getContainer()->getParameter('wiki_tag.document_class');
    39         $clear = $input->getOption('clear');
   107         $doctrine = $this->getContainer()->get('doctrine');
    40         $missing = $input->getOption('missing');
   108         $all = $input->getOption('all');
    41      
   109         $force = $input->getOption('force');
    42         
   110         
    43         $doctrine = $this->getContainer()->get('doctrine');
   111         
    44         
   112         if($all)
       
   113         {
       
   114             // delete all documents
       
   115             $query_str = "DELETE WikiTagBundle:Document wtdoc";
       
   116             $count_query_str = "SELECT COUNT(wtdoc.id) FROM WikiTagBundle:Document wtdoc";
       
   117         }
       
   118         else
       
   119         {
       
   120             // delete only wikitag document that have no conterpart
       
   121             $query_str = "DELETE WikiTagBundle:Document wtdoc WHERE wtdoc.externalId IS NULL OR wtdoc.externalId NOT IN (SELECT doc FROM $class doc)";
       
   122             $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)";
       
   123         }
       
   124         
       
   125         $count_query = $doctrine->getEntityManager()->createQuery($count_query_str);
       
   126         $total = $count_query->getSingleScalarResult();
       
   127         
       
   128         if($total === 0)
       
   129         {
       
   130             $output->writeln("No wikitag document to delete. Exit.");
       
   131             return;
       
   132         }
       
   133         
       
   134         $output->writeln("$total wikitag document(s) to delete.");
       
   135         if(!$force && $input->isInteractive())
       
   136         {
       
   137             $dialog = $this->getHelper('dialog');
       
   138             if (!$dialog->askConfirmation($output, '<question>Confirm deletion? (y/N) : </question>', false)) {
       
   139                 return;
       
   140             }
       
   141         }
       
   142                
       
   143         $req = $doctrine->getEntityManager()->createQuery($query_str);
       
   144         
       
   145         $nb_deleted = $req->getResult();
       
   146         
       
   147         $output->writeln("$nb_deleted wikitag document(s) deleted.");
       
   148         
       
   149         $doctrine->getEntityManager()->flush();
       
   150     
       
   151     }
       
   152     
       
   153     private function execute_docs(InputInterface $input, OutputInterface $output)
       
   154     {
       
   155         $all = $input->getOption('all');
       
   156         $doctrine = $this->getContainer()->get('doctrine');
    45         $docrep = $doctrine->getRepository('WikiTagBundle:Document');
   157         $docrep = $doctrine->getRepository('WikiTagBundle:Document');
    46         $rep = $doctrine->getRepository($class);
   158         
    47         
   159         if($all)
    48         if(is_null($rep)) {
   160         {
    49             //TODO : translate
   161             $docquery = $doctrine->getEntityManager()->createQuery("SELECT doc FROM $class doc");
    50             $output->writeln("$class does not have a repository : exiting.");
   162             $doccountquery = $doctrine->getEntityManager()->createQuery("SELECT count(doc.id) FROM $class doc");
    51             return ;
   163         }
    52         }
   164         else
    53         
       
    54         if($input->getOption('tags'))
       
    55         {
       
    56             if(!$missing)
       
    57             {
       
    58                 $docquery = $doctrine->getEntityManager()->createQuery("SELECT doc from WikiTagBundle:Document doc");
       
    59                 $doccountquery = $doctrine->getEntityManager()->createQuery("SELECT COUNT(doc.id) from WikiTagBundle:Document doc");
       
    60             }
       
    61             else
       
    62             {
       
    63                 $docquery = $doctrine->getEntityManager()->createQuery("SELECT doc from WikiTagBundle:Document doc WHERE doc.tagsStr IS NULL");
       
    64                 $doccountquery = $doctrine->getEntityManager()->createQuery("SELECT COUNT(doc.id) from WikiTagBundle:Document doc WHERE doc.tagsStr IS NULL");
       
    65             }
       
    66             
       
    67             
       
    68             $total = $doccountquery->getSingleScalarResult();
       
    69             $done = 0;
       
    70             $iterable = $docquery->iterate();
       
    71             $todetach = array();
       
    72             while (($row = $iterable->next()) !== false) {
       
    73                 $done++;
       
    74                 $memory = ((($done%10)==0)?" - mem: ".strval(memory_get_usage(true)):"");
       
    75                 $doc = $row[0];
       
    76                 $todetach[] = $doc;
       
    77                 $output->writeln("Process doc id ".$doc->getId()." $done/$total ".strval(intval(floatval($done)/floatval($total)*100.0))."%$memory");
       
    78                 $docrep->updateTagsStr($doc);
       
    79                 //dispatch event
       
    80                 $event_dispatcher = $this->getContainer()->get('event_dispatcher');
       
    81                 $event = new DocumentTagEvent($doc);
       
    82                 $event_dispatcher->dispatch(WikiTagEvents::onTagChanged, $event);
       
    83                 
       
    84                 if($done%10 == 0)
       
    85                 {
       
    86                     $doctrine->getEntityManager()->flush();
       
    87                     foreach($todetach as $obj)
       
    88                     {
       
    89                         $doctrine->getEntityManager()->detach($obj);
       
    90                     }
       
    91                     $todetach = array();
       
    92                 }
       
    93             }
       
    94             $doctrine->getEntityManager()->flush();
       
    95                         
       
    96             return;
       
    97             
       
    98         }
       
    99         
       
   100         //TODO : check class to implement DocumentInterface
       
   101         //TODO : write progress
       
   102         if($missing)
       
   103         {
   165         {
   104             $docquery = $doctrine->getEntityManager()->createQuery("SELECT doc FROM $class doc WHERE doc.id not in (SELECT wtdoc FROM WikiTagBundle:Document wtdoc)");
   166             $docquery = $doctrine->getEntityManager()->createQuery("SELECT doc FROM $class doc WHERE doc.id not in (SELECT wtdoc FROM WikiTagBundle:Document wtdoc)");
   105             $doccountquery = $doctrine->getEntityManager()->createQuery("SELECT count(doc.id) FROM $class doc WHERE doc.id not in (SELECT wtdoc FROM WikiTagBundle:Document wtdoc)");
   167             $doccountquery = $doctrine->getEntityManager()->createQuery("SELECT count(doc.id) FROM $class doc WHERE doc.id not in (SELECT wtdoc FROM WikiTagBundle:Document wtdoc)");
   106             //$doclist = $doctrine->getEntityManager()->createQuery("SELECT doc FROM $class doc WHERE doc.id not in (SELECT wtdoc FROM WikiTagBundle:Document wtdoc)")->getResult();
       
   107         }
       
   108         else
       
   109         {
       
   110             $docquery = $doctrine->getEntityManager()->createQuery("SELECT doc FROM $class doc");
       
   111             $doccountquery = $doctrine->getEntityManager()->createQuery("SELECT count(doc.id) FROM $class doc");
       
   112             //$doclist = $rep->findAll();
       
   113         }
   168         }
   114         $total = $doccountquery->getSingleScalarResult();
   169         $total = $doccountquery->getSingleScalarResult();
   115         $done = 0;
   170         $done = 0;
   116         $iterable = $docquery->iterate();
   171         $iterable = $docquery->iterate();
   117         while (($row = $iterable->next()) !== false) {
   172         while (($row = $iterable->next()) !== false) {
   118             $done++;
   173             $done++;
   119             $doc = $row[0];
   174             $doc = $row[0];
   120             $memory = ((($done%10)==0)?" - mem: ".strval(memory_get_usage(true)):"");
   175             $memory = ((($done%10)==0)?" - mem: ".strval(memory_get_usage(true)):"");
   121             $output->writeln("Process doc id ".$doc->getId()." $done/$total ".strval(intval(floatval($done)/floatval($total)*100.0))."%$memory");
   176             $this->showProgress($output, $done, $total, "id : ".$doc->getId()."%$memory", 50);
   122             $docrep->writeDocument($doc, $this->getContainer()->getParameter('wiki_tag.document_id_column'), $this->getContainer()->getParameter('wiki_tag.fields'));
   177             $docrep->writeDocument($doc, $this->getContainer()->getParameter('wiki_tag.document_id_column'), $this->getContainer()->getParameter('wiki_tag.fields'));
   123             if($done%10 == 0)
   178             if($done%10 == 0)
   124             {
   179             {
   125                 $doctrine->getEntityManager()->flush();
   180                 $doctrine->getEntityManager()->flush();
   126                 $doctrine->getEntityManager()->clear();
   181                 $doctrine->getEntityManager()->clear();
   127             }
   182             }
   128         }
   183         }
   129         $doctrine->getEntityManager()->flush();
   184         $doctrine->getEntityManager()->flush();
   130         
   185         $doctrine->getEntityManager()->clear();
   131         if($clear) {
   186         
   132             
   187     }
   133             $req = $doctrine->getEntityManager()->createQuery("DELETE WikiTagBundle:Document wtdoc WHERE wtdoc.externalId NOT IN (SELECT doc FROM $class doc)");
   188     
   134             $req->getResult();
   189     
   135             $doctrine->getEntityManager()->flush();
   190     protected function execute(InputInterface $input, OutputInterface $output)
   136         }
   191     {
   137 
   192         $clear = $input->getOption('clear');
   138         $output->writeln(strval(count($doclist)) ." documents imported.");
   193         $tags = $input->getOption('tags');
       
   194         
       
   195      
       
   196         $class = $this->getContainer()->getParameter('wiki_tag.document_class');
       
   197         $doctrine = $this->getContainer()->get('doctrine');
       
   198         $rep = $doctrine->getRepository($class);
       
   199         
       
   200         if(is_null($rep))
       
   201         {
       
   202             $output->writeln("$class does not have a repository : exiting.");
       
   203             return ;
       
   204         }
       
   205         
       
   206         if($tags)
       
   207         {
       
   208             $this->execute_tags($input, $output);
       
   209         }
       
   210         elseif($clear)
       
   211         {
       
   212             $this->execute_clear($input, $output);
       
   213         }
       
   214         else
       
   215         {
       
   216             $this->execute_docs($input, $output);
       
   217         }
       
   218 
   139     }
   219     }
   140 }
   220 }