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 } |