merge 1c4e3fdba170
authorymh <ymh.work@gmail.com>
Sun, 27 Nov 2011 23:35:54 +0100
changeset 44 c114504de4a8
parent 41 1c4e3fdba170 (current diff)
parent 43 54f204bceb28 (diff)
child 45 e25a00a6f9e1
merge 1c4e3fdba170
Resources/public/js/wikiTag.js
--- a/Command/CreateSchemaDoctrineCommand.php	Thu Nov 24 13:05:33 2011 +0100
+++ b/Command/CreateSchemaDoctrineCommand.php	Sun Nov 27 23:35:54 2011 +0100
@@ -21,6 +21,7 @@
 use Doctrine\ORM\Tools\SchemaTool;
 use Doctrine\ORM\Tools\Console\Command\SchemaTool\CreateCommand;
 use Symfony\Bundle\DoctrineBundle\Command\Proxy\DoctrineCommandHelper;
+use IRI\Bundle\WikiTagBundle\Utils\FilteredSchemaTool;
 
 /**
  * Command to execute the SQL needed to generate the database schema for
@@ -78,42 +79,14 @@
         $this->container = $container;
     }
     
-    
-    protected function filterCreateSchema($sqls)
-    {
         
-        // get service
-        $schema_utils = $this->getContainer()->get("wikitag.shema_utils");
-        
-        $res_sqls = $schema_utils->filter_foreign_key($sqls);
-        $res_sqls = $schema_utils->filter_index_creation($res_sqls);
-        
-        
-        return $res_sqls;
-    }
-    
     protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas)
     {
-        $output->write('ATTENTION: This operation should not be executed in a production environment.' . PHP_EOL . PHP_EOL);
-        $sqls = $schemaTool->getCreateSchemaSql($metadatas);
         
-        $createSchemaSql = $this->filterCreateSchema($sqls);
+        $filteredSchemaTool = new FilteredSchemaTool($this->getHelper("em")->getEntityManager(), $this->getContainer());
         
-        if ($input->getOption('dump-sql') === true) {
-                        
-            $output->write(implode(';' . PHP_EOL, $createSchemaSql) . PHP_EOL);
-        } else {
-            $output->write('Creating database schema...' . PHP_EOL);
-            $emHelper = $this->getHelper('em');
-            
-            $conn = $emHelper->getEntityManager()->getConnection();
-            
-            foreach ($createSchemaSql as $sql) {
-                $conn->executeQuery($sql);
-            }
-            $output->write('Database schema created successfully!' . PHP_EOL);
-        }
-        
+        parent::executeSchemaCommand($input, $output, $filteredSchemaTool, $metadatas);
+                
     }
 
     protected function execute(InputInterface $input, OutputInterface $output)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Command/ProgressContainerAwareCommand.php	Sun Nov 27 23:35:54 2011 +0100
@@ -0,0 +1,46 @@
+<?php
+/*
+ * This file is part of the WikiTagBundle package.
+ *
+ * (c) IRI <http://www.iri.centrepompidou.fr/>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace IRI\Bundle\WikiTagBundle\Command;
+
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
+
+abstract class ProgressContainerAwareCommand extends ContainerAwareCommand
+{
+    protected function showProgress(OutputInterface $output, $current, $total, $label, $width)
+    {
+        $percent = (floatval($current)/floatval($total)) * 100.0;
+        $marks = intval(floor(floatval($width) * ($percent / 100.0) ));
+        $spaces = $width - $marks;
+        
+        $status_bar="\r[";
+        $status_bar.=str_repeat("=", $marks);
+        if($marks<$width){
+            $status_bar.=">";
+            $status_bar.=str_repeat(" ", $spaces);
+        } else {
+            $status_bar.="=";
+        }
+        
+        $disp=str_pad(number_format($percent, 0),3, " ", STR_PAD_LEFT);
+        
+        $label = str_pad(substr($label,0,50), 50, " ");
+        $current_str = str_pad($current, strlen("$total"), " ", STR_PAD_LEFT);
+        
+        $status_bar.="] $disp%  $current_str/$total : $label";
+        
+        $output->write("$status_bar  ");
+        
+        if($current == $total) {
+            $output->writeln("");
+        }
+    }
+    
+}
\ No newline at end of file
--- a/Command/QueryWikipediaCommand.php	Thu Nov 24 13:05:33 2011 +0100
+++ b/Command/QueryWikipediaCommand.php	Sun Nov 27 23:35:54 2011 +0100
@@ -11,68 +11,22 @@
 
 use IRI\Bundle\WikiTagBundle\Utils\WikiTagUtils;
 
+use IRI\Bundle\WikiTagBundle\Model\Tag;
 use Doctrine\ORM\QueryBuilder;
-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 QueryWikipediaCommand extends ContainerAwareCommand
+class QueryWikipediaCommand extends ProgressContainerAwareCommand
 {
 
-    private function showProgress(OutputInterface $output, $current, $total, $label, $width)
-    {
-        $percent = (floatval($current)/floatval($total)) * 100.0;
-        $marks = intval(floor(floatval($width) * ($percent / 100.0) ));
-        $spaces = $width - $marks;
-        
-        $status_bar="\r[";
-        $status_bar.=str_repeat("=", $marks);
-        if($marks<$width){
-            $status_bar.=">";
-            $status_bar.=str_repeat(" ", $spaces);
-        } else {
-            $status_bar.="=";
-        }
-        
-        $disp=str_pad(number_format($percent, 0),3, " ", STR_PAD_LEFT);
-        
-        $label = str_pad(substr($label,0,50), 50, " ");
-        $current_str = str_pad($current, strlen("$total"), " ", STR_PAD_LEFT);
-        
-        $status_bar.="] $disp%  $current_str/$total : $label";
-        
-        $output->write("$status_bar  ");
-        
-        if($current == $total) {
-            $output->writeln("");
-        }
-        
-    }
-    
     private function processTag($tag, $em)
     {
         $tag_label_normalized = WikiTagUtils::normalizeTag($tag->getLabel());
         $wp_response = WikiTagUtils::getWikipediaInfo($tag_label_normalized);
         
-        $new_label = $wp_response['new_label'];
-        $status = $wp_response['status'];
-        $url = $wp_response['wikipedia_url'];
-        $pageid = $wp_response['pageid'];
-        $dbpedia_uri = $wp_response["dbpedia_uri"];
-        $wikipedia_revision_id = $wp_response['revision_id'];
-        
-        # We save the datas
-        if($new_label!=null){
-            $tag->setLabel($new_label);
-        }
-        if($status!=null){
-            $tag->setUrlStatus($status);
-        }
-        $tag->setWikipediaUrl($url);
-        $tag->setWikipediaPageId($pageid);
-        $tag->setDbpediaUri($dbpedia_uri);
+        $tag->setWikipediaInfo($wp_response);
         
         // Save datas.
         $em->persist($tag);
@@ -88,7 +42,8 @@
             ->setName('wikitag:query-wikipedia')
             ->setDescription('Query wikipedia for tags.')
             ->addOption("force","f",InputOption::VALUE_NONE, "Force remove tags")
-            ->addOption("all","a",InputOption::VALUE_NONE, "Force remove tags")
+            ->addOption("all","a",InputOption::VALUE_NONE, "all")
+            ->addOption("redirection",null,InputOption::VALUE_NONE, "Treat redirections")
             ->addOption("random","r",InputOption::VALUE_NONE, "randomize query on tags")
             ->addOption("site","S",InputOption::VALUE_OPTIONAL, "the url for the wikipedia site", "http://fr.wikipedia.org/w/api.php")
             ->addOption("limit","l",InputOption::VALUE_OPTIONAL, "number of tag to process", -1)
@@ -101,6 +56,7 @@
         $force = $input->getOption('force');
         $all = $input->getOption('all');
         $random = $input->getOption('random');
+        $redirection = $input->getOption('redirection');
         $site = $input->getOption('site');
         $limit = intval($input->getOption('limit'));
         $start = intval($input->getOption('start'));
@@ -113,7 +69,12 @@
         
         if(!$all)
         {
-            $qb->where($qb->expr()->isNull("t.urlStatus"));
+            if($redirection) {
+                $qb->where($qb->expr()->andx($qb->expr()->eq("t.urlStatus",Tag::$TAG_URL_STATUS_DICT['redirection']), $qb->expr()->isNull("t.alternativeLabel")));
+            }
+            else {
+                $qb->where($qb->expr()->isNull("t.urlStatus"));
+            }
         }
         
         if($start > 0)
@@ -133,6 +94,12 @@
         $count = count($qb_count->getQuery()->getScalarResult());
         $doctrine->getEntityManager()->clear();
         
+        if($count === 0)
+        {
+            $output->writeln("No tag to process, exit.");
+            return;
+        }
+        
         if(! $force && $input->isInteractive())
         {
             $dialog = $this->getHelper('dialog');
--- a/Command/SyncDocumentsCommand.php	Thu Nov 24 13:05:33 2011 +0100
+++ b/Command/SyncDocumentsCommand.php	Sun Nov 27 23:35:54 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
--- a/Command/UpdateSchemaDoctrineCommand.php	Thu Nov 24 13:05:33 2011 +0100
+++ b/Command/UpdateSchemaDoctrineCommand.php	Sun Nov 27 23:35:54 2011 +0100
@@ -21,6 +21,7 @@
 use Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand;
 use Doctrine\ORM\Tools\SchemaTool;
 use Symfony\Bundle\DoctrineBundle\Command\Proxy\DoctrineCommandHelper;
+use IRI\Bundle\WikiTagBundle\Utils\FilteredSchemaTool;
 
 
 /**
@@ -90,64 +91,13 @@
         $this->container = $container;
     }
     
-    
-    protected function filterUpdateSchema($sqls)
-    {
-    
-        // get service
-        $schema_utils = $this->getContainer()->get("wikitag.shema_utils");
-    
-        $res_sqls = $schema_utils->filter_foreign_key($sqls);
-        $res_sqls = $schema_utils->filter_index_creation($res_sqls);
-    
-    
-        return $res_sqls;
-    }
-    
+        
     protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas)
     {
-        // Defining if update is complete or not (--complete not defined means $saveMode = true)
-        $saveMode = ($input->getOption('complete') !== true);
-    
-        $sqls = $schemaTool->getUpdateSchemaSql($metadatas, $saveMode);
-        $sqls = $this->filterUpdateSchema($sqls);
-        if (0 == count($sqls)) {
-            $output->writeln('Nothing to update - your database is already in sync with the current entity metadata.');
-    
-            return;
-        }
-    
-        $dumpSql = (true === $input->getOption('dump-sql'));
-        $force = (true === $input->getOption('force'));
-        if ($dumpSql && $force) {
-            throw new \InvalidArgumentException('You can pass either the --dump-sql or the --force option (but not both simultaneously).');
-        }
-    
-        if ($dumpSql) {
-            $output->writeln(implode(';' . PHP_EOL, $sqls));
-        } else if ($force) {
-            $output->writeln('Updating database schema...');
-            
-            $emHelper = $this->getHelper('em');
-            
-            $conn = $emHelper->getEntityManager()->getConnection();
-            
-            foreach ($sqls as $sql) {
-                $conn->executeQuery($sql);
-            }
-            $output->writeln(sprintf('Database schema updated successfully! "<info>%s</info>" queries were executed', count($sqls)));
-        } else {
-            $output->writeln('<comment>ATTENTION</comment>: This operation should not be executed in a production environment.');
-            $output->writeln('           Use the incremental update to detect changes during development and use');
-            $output->writeln('           the SQL DDL provided to manually update your database in production.');
-            $output->writeln('');
-    
-            $output->writeln(sprintf('The Schema-Tool would execute <info>"%s"</info> queries to update the database.', count($sqls)));
-            $output->writeln('Please run the operation by passing one of the following options:');
-    
-            $output->writeln(sprintf('    <info>%s --force</info> to execute the command', $this->getName()));
-            $output->writeln(sprintf('    <info>%s --dump-sql</info> to dump the SQL statements to the screen', $this->getName()));
-        }
+        $filteredSchemaTool = new FilteredSchemaTool($this->getHelper("em")->getEntityManager(), $this->getContainer());
+        
+        return parent::executeSchemaCommand($input, $output, $filteredSchemaTool, $metadatas);
+        
     }
     
     
--- a/Controller/WikiTagController.php	Thu Nov 24 13:05:33 2011 +0100
+++ b/Controller/WikiTagController.php	Sun Nov 27 23:35:54 2011 +0100
@@ -45,15 +45,17 @@
 
     /**
      * Renders the little html to add the javascript
-     * TODO: review why this injection in javascript, t10n?
+     *
+     * @param unknown_type $tags_list
+     * @return \Symfony\Bundle\FrameworkBundle\Controller\Response
      */
-    public function addJavascriptAction($tags_list=FALSE)
+    public function addJavascriptAction($tags_list=false)
     {
         $cats = $this->getDoctrine()->getRepository('WikiTagBundle:Category')->findOrderedCategories();
         // $cats is {"Label":"Créateur"},{"Label":"Datation"},...
         $nbCats = count($cats);
         $ar = array('' => '');
-        for($i=0;$i<$nbCats;$i++){
+        for($i=0;$i<$nbCats;$i++) {
             $temp = array($cats[$i]["label"] => $cats[$i]["label"]);
             $ar = array_merge($ar, $temp);
         }
@@ -96,7 +98,8 @@
 
     /**
      *
-     * TODO : Enter description here ...
+     * The action called when a tag is moved in a document tag list.
+     *
      * @return \Symfony\Bundle\FrameworkBundle\Controller\Response
      */
     public function tagUpDownAction()
@@ -137,8 +140,7 @@
     }
 
     /**
-     *
-     * TODO: Enter description here ...
+     * Action to remove a tag from a document tag list
      * @return \Symfony\Bundle\FrameworkBundle\Controller\Response
      */
     public function removeTagFromListAction()
@@ -147,7 +149,6 @@
         $id_tag = $this->getRequest()->request->get('tag_id');
         // We get the DocumentTag meant to be deleted, and remove it.
         $em = $this->getDoctrine()->getEntityManager();
-        //TODO: use external id
         
         $dt = $this->getDoctrine()->getRepository('WikiTagBundle:DocumentTag')->findOneByDocumentExternalId($id_doc, array('tag' => $id_tag));
         $em->remove($dt);
@@ -185,7 +186,7 @@
                 return new Response(json_encode(array('error' => 'duplicate_tag', 'message' => sprintf("Le tag %s existe déjà pour cette fiche.", $tag_label))),400);
             }
             // We create the new tag or get the already existing tag. $tag, $revision_id, $created
-            $ar = WikiTagUtils::getOrCreateTag($tag_label, $this->getDoctrine());
+            $ar = $this->getDoctrine()->getRepository('WikiTagBundle:Tag')->getOrCreateTag($tag_label);
             $tag = $ar[0];
             $revision_id = $ar[1];
             $created = $ar[2];
@@ -220,9 +221,8 @@
     }
 
     /**
-     *
-     * TODO : Enter description here ...
-     * TODO : implement
+     * The action called to reorder the the tags of a document. The tags are reordered according to the indexation score of the tag label on the document.
+     * The fields taken into account for calculating the score are defined in the wikitag configuration.
      */
     public function reorderTagDocumentAction()
     {
@@ -243,8 +243,7 @@
     }
 
     /**
-     *
-     * TODO: Enter description here ...
+     * The action called to add a new tag (especially from the completion box)
      */
     public function addTagAction()
     {
@@ -269,7 +268,7 @@
             return new Response(json_encode(array('error' => 'duplicate_tag', 'message' => sprintf("Le tag %s existe déjà pour cette fiche.", $tag_label))),400);
         }
         // returns array($tag, $revision_id, $created)
-        $ar = WikiTagUtils::getOrCreateTag($tag_label, $this->getDoctrine());// tag, revision_id, created = get_or_create_tag(tag_label)
+        $ar = $this->getDoctrine()->getRepository('WikiTagBundle:Tag')->getOrCreateTag($tag_label);// tag, revision_id, created = get_or_create_tag(tag_label)
         $tag = $ar[0];
         $revision_id = $ar[1];
         $created = $ar[2];
@@ -282,7 +281,6 @@
             // The result is a double array. And reset(reset($newOrderAr)) is not allowed. And a string is returned.
             $a1 = reset($new_order_ar);
             $new_order = intval(reset($a1)) + 1;
-            // TODO: use a factory that returns an DocumentTagInterface
             $new_DT = new DocumentTag();
             $new_DT->setDocument($this->getDoctrine()->getRepository('WikiTagBundle:Document')->findOneByExternalId($id_doc));
             $new_DT->setTag($tag);
@@ -298,8 +296,8 @@
 
 
     /**
+     * Action to remove the wikipedia link form a tag. This action create a copy of the original tag with all the link to wikipedia set to null.
      *
-     * TODO: Enter description here ...
      * @return \Symfony\Bundle\FrameworkBundle\Controller\Response
      */
     public function removeWpLinkAction()
@@ -314,19 +312,21 @@
         $un_tag_created = FALSE;
         if(!$un_tag){
             // Create another tag almost identical, without the W info
-            // TODO: use a factory that return a TagInterface
             $un_tag = new Tag();
             $un_tag->setLabel($tag->getLabel());
             $un_tag->setOriginalLabel($tag->getOriginalLabel());
             $un_tag->setUrlStatus(Tag::$TAG_URL_STATUS_DICT['null_result']);
             $un_tag->setWikipediaUrl(null);
             $un_tag->setWikipediaPageId(null);
+            $un_tag->setAlternativeWikipediaUrl(null);
+            $un_tag->setAlternativeWikipediaPageId(null);
+            $un_tag->setAlternativeLabel(null);
             $un_tag->setDbpediaUri(null);
             $un_tag->setCategory($tag->getCategory());
             $un_tag->setAlias($tag->getAlias());
             $un_tag->setPopularity($tag->getPopularity());
             $em->persist($un_tag);
-            $un_tag_created = TRUE;
+            $un_tag_created = true;
         }
         
         if($id_doc && $id_doc!=""){
@@ -355,8 +355,8 @@
 
 
     /**
-     *
-     * TODO: Enter description here ...
+     * Action to update a tag category.
+     * @return \Symfony\Bundle\FrameworkBundle\Controller\Response
      */
     public function updateTagCategoryAction()
     {
@@ -402,9 +402,8 @@
 
 
     /**
-     *
-     * TODO : Enter description here ...
-     * TODO : implement
+     * Action to update the tag alias.
+	 *
      * @return \Symfony\Bundle\FrameworkBundle\Controller\Response
      */
     public function updateTagAliasAction()
@@ -433,8 +432,9 @@
     }
     
     /**
-     * List of all tags
-     * TODO: Enter description here ...
+     * List all tags, with pagination and search.
+     *
+     * @return \Symfony\Bundle\FrameworkBundle\Controller\Response
      */
     public function allTagsAction()
     {
@@ -551,22 +551,9 @@
                 // We get the Wikipedia informations for the sent label
                 $tag_label_normalized = WikiTagUtils::normalizeTag($label);
                 $wp_response = WikiTagUtils::getWikipediaInfo($tag_label_normalized);
-                $new_label = $wp_response['new_label'];
-                $status = $wp_response['status'];
-                $url = $wp_response['wikipedia_url'];
-                $pageid = $wp_response['pageid'];
-                $dbpedia_uri = $wp_response["dbpedia_uri"];
-                $wikipedia_revision_id = $wp_response['revision_id'];
-                // We save the datas : we DO NOT create a new tag, we change the current tag's informations
-                if($new_label!=null){
-                    $tag->setLabel($new_label);
-                }
-                if($status!=null){
-                    $tag->setUrlStatus($status);
-                }
-                $tag->setWikipediaUrl($url);
-                $tag->setWikipediaPageId($pageid);
-                $tag->setDbpediaUri($dbpedia_uri);
+                
+                $tag->setWikipediaInfo($wp_response);
+
                 // Save datas.
                 $em = $this->getDoctrine()->getEntityManager();
                 $em->persist($tag);
--- a/Entity/DocumentRepository.php	Thu Nov 24 13:05:33 2011 +0100
+++ b/Entity/DocumentRepository.php	Sun Nov 27 23:35:54 2011 +0100
@@ -2,12 +2,15 @@
 
 namespace IRI\Bundle\WikiTagBundle\Entity;
 
+use IRI\Bundle\WikiTagBundle\Model\DocumentInterface;
+
 use Doctrine\ORM\EntityRepository;
 use IRI\Bundle\WikiTagBundle\Entity\Document;
 use Doctrine\ORM\Query\ResultSetMapping;
 use \ReflectionClass;
 use Doctrine\ORM\AbstractQuery;
 use Doctrine\ORM\Mapping\ClassMetadataInfo;
+use IRI\Bundle\WikiTagBundle\Model\ModelException;
 
 /**
  * DocumentRepository
@@ -18,20 +21,29 @@
 class DocumentRepository extends EntityRepository
 {
     /**
-     *
-     * TODO : Enter description here ...
+     * The cache for the host document class
      * @var ReflectionClass
      */
     private $reflection_class;
+    
+    /**
+     * The cache for the wikitag document class
+     * @var ReflectionClass
+     */
     private $reflection_doc_class;
     private $set_methods = array();
     private $get_methods = array();
-    
-    function findOneByExternalId($external_id)
+
+    /**
+     * Find one wikitagRepository by its externalId i.e. the host document id.
+     * @param $external_id
+     */
+    public function findOneByExternalId($external_id)
     {
         return $this->findOneBy(array("externalId" => $external_id));
     }
     
+    
     private function reflectionSetField($object, $method_name, $value)
     {
         if(isset($this->set_methods[$method_name]))
@@ -126,14 +138,12 @@
                 }
                 else
                 {
-                    //TODO : custom exception
-                    throw new \Exception("Bad reflection object type");
+                    throw new ModelException("Bad reflection object type");
                 }
             }
         }
         
-        //TODO: replace by custom exception
-        throw new \Exception("Unknown accessor $accessor");
+        throw new ModelException("Unknown accessor $accessor");
     }
     
     
@@ -161,6 +171,13 @@
         return $res;
     }
     
+    /**
+     * Write a wikitag document given the host document and the field list.
+     * @param $document The source document
+     * @param $document_id_column the name of the source document id column
+     * @param $fields The list of field definition. This is an associative array [<field name>=><field definition>].
+     *     See the @IRI\Bundle\WikiTagBundle\DependencyInjection\Configuration documentation
+     */
     public function writeDocument($document,  $document_id_column, $fields)
     {
         // get document from id
@@ -202,7 +219,12 @@
     
     }
     
-    function removeDocument($document, $document_id_column)
+    /**
+     * Remove a Wikitag doument given the host docuument.
+     * @param $document The host document
+     * @param string $document_id_column The host document id column name
+     */
+    public function removeDocument($document, $document_id_column)
     {
         $docid = $this->reflectionGetField($document, $document_id_column);
         $baseDocument = $this->findOneByExternalId($docid);
@@ -212,7 +234,13 @@
         }
     }
     
-    function getTagsStr($document)
+    
+    /**
+     * return the list of a wikitag documents the tags label.
+     * @param DocumentInterface $document the wikitag document
+     * @return array
+     */
+    public function getTagsStr($document)
     {
         $em = $this->getEntityManager();
         $query = $em->createQuery("SELECT t.label FROM WikiTagBundle:DocumentTag dt JOIN dt.tag t WHERE dt.document = :docid");
@@ -225,7 +253,11 @@
         return $tagstr;
     }
     
-    function updateTagsStr($document)
+    /**
+     * Update a wikitag document tags string.
+     * @param DocumentInterface $document the wikitag document
+     */
+    function updateTagsStr(DocumentInterface $document)
     {
         
         $tagstr = $this->getTagsStr($document);
@@ -236,11 +268,11 @@
     
 
     /**
+     * Search wikitag documents using the index.
      *
-     * Enter description here ...
      * @param array $values : key: the fields to search into, value : array('value'=>value, 'weight'=>weight)
      * @param array $conditions : array : key : field name, value : simple value (operator is "=") or array(valuea, value2,...) (operatr is IN) or array("operator"=>"", "value"=>value)
-     * @return Ambigous <multitype:, \Doctrine\ORM\mixed, \Doctrine\DBAL\Driver\Statement, \Doctrine\ORM\Internal\Hydration\mixed>
+     * @return array [["id" => <the wikitag document id>, "externalId" => <the host document ids>, "score" => <the score for this document>]]
      */
     function search(array $values, array $conditions=NULL)
     {
@@ -332,8 +364,6 @@
         $res = $query->getResult();
         
         return $res;
-        
-        
     }
         
 }
\ No newline at end of file
--- a/Entity/TagRepository.php	Thu Nov 24 13:05:33 2011 +0100
+++ b/Entity/TagRepository.php	Sun Nov 27 23:35:54 2011 +0100
@@ -3,6 +3,8 @@
 namespace IRI\Bundle\WikiTagBundle\Entity;
 
 use Doctrine\ORM\EntityRepository;
+use IRI\Bundle\WikiTagBundle\Utils\WikiTagUtils;
+use IRI\Bundle\WikiTagBundle\Entity\Tag;
 
 /**
  * TagRepository
@@ -41,4 +43,90 @@
         return $query->getResult();
         
     }
+    
+    /**
+    * Get or create tag. Returns an array(tag:WikiTagTag, revision_id=int, created:Boolean)
+    * @param $tag_label
+    * @param $doctrine
+    * @return multitype:boolean Ambigous <NULL, \IRI\Bundle\WikiTagBundle\Entity\Tag> Ambigous <NULL, unknown, mixed, string> (array(\IRI\Bundle\WikiTagBundle\Model\TagInterface, revision_id=int, created:Boolean))
+    */
+    public function getOrCreateTag($tag_label)
+    {
+        $tag_label_normalized = WikiTagUtils::normalizeTag($tag_label);
+        // We get the wikipedia references for the tag_label
+        // We get or create the tag object
+        $tags = $this->findBy(array('normalizedLabel' => $tag_label_normalized));
+        $tag = null;
+        foreach ($tags as $t) {
+            if($tag==null || $t->getUrlStatus()!=Tag::$TAG_URL_STATUS_DICT['null_result']) {
+                $tag = $t;
+                if($t->getUrlStatus()!=Tag::$TAG_URL_STATUS_DICT['null_result']) {
+                    break;
+                }
+            }
+        }
+        $wp_request_done = false;
+        if($tag==null) {
+            $tag = new Tag();
+            $tag->setLabel($tag_label_normalized);
+            $tag->setOriginalLabel($tag_label);
+            $tag->setNormalizedLabel($tag_label_normalized);
+            $created = true;
+        }
+        else {
+            $created = false;
+            $match_exists = false;
+            // Even if a tag with the normalised label exists, IF this tag is not wikipedia semantised,
+            // we search if a wikipedia semantised version exists in the base
+            foreach ($tags as $t) {
+                if($t->getUrlStatus()==Tag::$TAG_URL_STATUS_DICT['match']) {
+                    $tag = $t;
+                    $match_exists = true;
+                    break;
+                }
+            }
+            if($match_exists==false) {
+                $wp_response = WikiTagUtils::getWikipediaInfo($tag_label_normalized);
+                $status = $wp_response['status'];
+                if($status==Tag::$TAG_URL_STATUS_DICT['match']) {
+                    $tag = new Tag();
+                    $tag->setLabel($tag_label_normalized);
+                    $tag->setOriginalLabel($tag_label);
+                    $tag->setNormalizedLabel($tag_label_normalized);
+                    $created = true;
+                    $wp_request_done = true;
+                }
+            }
+        }
+    
+        // We request Wikipedia if the tag is created
+        if($created==true) {
+            
+            if($wp_request_done==false) {
+                $wp_response = WikiTagUtils::getWikipediaInfo($tag_label_normalized);
+            }
+            
+            $tag->setWikipediaInfo($wp_response);
+    
+            // Save datas.
+            $em = $this->getEntityManager();
+            $em->persist($tag);
+            $em->flush();
+                
+            $wikipedia_revision_id = $wp_response['revision_id'];
+    
+        }
+        else if($tag!=null && $tag->getWikipediaPageId()!=null) {
+            
+            $wp_response = WikiTagUtils::getWikipediaInfo(null, $tag->getWikipediaPageId());
+            $wikipedia_revision_id = $wp_response['revision_id'];
+        }
+        else {
+            $wikipedia_revision_id = null;
+        }
+    
+        return array($tag, $wikipedia_revision_id, $created);//, $wpReponse);
+    }
+    
+    
 }
\ No newline at end of file
--- a/Listener/WikiTagDocumentListener.php	Thu Nov 24 13:05:33 2011 +0100
+++ b/Listener/WikiTagDocumentListener.php	Sun Nov 27 23:35:54 2011 +0100
@@ -60,8 +60,8 @@
     
     
     /**
+     * callback function executed when the locadClassMetadata event is raised.
      *
-     * Enter description here ...
      * @param LoadClassMetadataEventArgs $args
      */
     public function loadClassMetadata(LoadClassMetadataEventArgs $args)
--- a/Model/DocumentInterface.php	Thu Nov 24 13:05:33 2011 +0100
+++ b/Model/DocumentInterface.php	Sun Nov 27 23:35:54 2011 +0100
@@ -24,14 +24,14 @@
     
     
     /**
-     * TODO: Enter description here ...
+     * Set the external id i.e. the host document id
      *
      * @param text $externalId
      */
     function setExternalId($externalId);
     
     /**
-     * TODO: Enter description here ...
+     * Get the external id, i.e. the host document id
      */
     function getExternalId();
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Model/ModelException.php	Sun Nov 27 23:35:54 2011 +0100
@@ -0,0 +1,25 @@
+<?php
+/*
+ * This file is part of the WikiTagBundle package.
+ *
+ * (c) IRI <http://www.iri.centrepompidou.fr/>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace IRI\Bundle\WikiTagBundle\Model;
+
+class ModelException extends \Exception
+{
+    /**
+     * Construct exception
+     * @param $message[optional]
+     * @param $code[optional]
+     * @param $previous[optional]
+     */
+    public function __construct($message=null, $code=null, $previous=null)
+    {
+        parent::__construct($message,$code,$previous);
+    }
+    
+}
\ No newline at end of file
--- a/Model/Tag.php	Thu Nov 24 13:05:33 2011 +0100
+++ b/Model/Tag.php	Sun Nov 27 23:35:54 2011 +0100
@@ -36,6 +36,11 @@
      * @var string $originalLabel
      */
     protected $originalLabel;
+    
+    /**
+     * @var $alternativeLabel
+     */
+    protected $alternativeLabel;
 
     /**
      * @var string $alias
@@ -48,10 +53,21 @@
     protected $wikipediaUrl;
 
     /**
+    * @var string $alternativeWikipediaUrl
+    */
+    protected $alternativeWikipediaUrl;
+        
+    
+    /**
      * @var bigint $wikipediaPageId
      */
     protected $wikipediaPageId;
 
+   /**
+    * @var bigint $alternativeWikipediaPageId
+    */
+    protected $alternativeWikipediaPageId;
+    
     /**
      * @var smallint $urlStatus
      */
@@ -150,6 +166,28 @@
     }
 
     /**
+    * Set alternativeLabel
+    *
+    * @param string $alternativeLabel
+    */
+    public function setAlternativeLabel($alternativeLabel)
+    {
+        $this->alternativeLabel = $alternativeLabel;
+    }
+    
+    /**
+     * Get alternativeLabel
+     *
+     * @return string
+     */
+    public function getAlternativeLabel()
+    {
+        return $this->alternativeLabel;
+    }
+    
+    
+    
+    /**
      * Set alias
      *
      * @param string $alias
@@ -189,6 +227,28 @@
         return $this->wikipediaUrl;
     }
 
+    
+    /**
+    * Set alternativeWikipediaUrl
+    *
+    * @param string $alternativeWikipediaUrl
+    */
+    public function setAlternativeWikipediaUrl($alternativeWikipediaUrl)
+    {
+        $this->alternativeWikipediaUrl = $alternativeWikipediaUrl;
+    }
+    
+    /**
+     * Get alternativeWikipediaUrl
+     *
+     * @return string
+     */
+    public function getAlternativeWikipediaUrl()
+    {
+        return $this->alternativeWikipediaUrl;
+    }
+    
+    
     /**
      * Set wikipediaPageId
      *
@@ -210,6 +270,27 @@
     }
 
     /**
+    * Set alternativeWikipediaPageId
+    *
+    * @param bigint $alternativeWikipediaPageId
+    */
+    function setAlternativeWikipediaPageId($alternativeWikipediaPageId)
+    {
+        $this->alternativeWikipediaPageId = $alternativeWikipediaPageId;
+    }
+    
+    /**
+     * Get alternativeWikipediaPageId
+     *
+     * @return bigint
+     */
+    function getAlternativeWikipediaPageId()
+    {
+        return $this->alternativeWikipediaPageId;
+    }
+    
+    
+    /**
      * Set urlStatus
      *
      * @param smallint $urlStatus
@@ -328,5 +409,42 @@
         return $this->setCategory(NULL);
     }
     
+    
+    /**
+     * (non-PHPdoc)
+     * @see IRI\Bundle\WikiTagBundle\Model.TagInterface::setWikipediaInfo()
+     */
+    function setWikipediaInfo($wikipedia_info)
+    {
+        $new_label = $wikipedia_info['new_label'];
+        $status = $wikipedia_info['status'];
+        $url = $wikipedia_info['wikipedia_url'];
+        $pageid = $wikipedia_info['pageid'];
+        $dbpedia_uri = $wikipedia_info["dbpedia_uri"];
+        $wikipedia_revision_id = $wikipedia_info['revision_id'];
+        $alternative_label = array_key_exists('alternative_label', $wikipedia_info) ? $wikipedia_info['alternative_label'] : null;
+        $alternative_url = array_key_exists('wikipedia_alternative_url', $wikipedia_info) ? $wikipedia_info['wikipedia_alternative_url'] : null;
+        $alternative_pageid = array_key_exists('alternative_pageid', $wikipedia_info) ? $wikipedia_info['alternative_pageid'] : null;
+        
+        # We save the datas
+        if(! is_null($new_label))
+        {
+            $this->setLabel($new_label);
+        }
+        
+        if(! is_null($status))
+        {
+            $this->setUrlStatus($status);
+        }
+
+        $this->setWikipediaUrl($url);
+        $this->setWikipediaPageId($pageid);
+        $this->setDbpediaUri($dbpedia_uri);
+        $this->setAlternativeLabel($alternative_label);
+        $this->setAlternativeWikipediaUrl($alternative_url);
+        $this->setAlternativeWikipediaPageId($alternative_pageid);
+        
+    }
+    
      
  }
\ No newline at end of file
--- a/Model/TagInterface.php	Thu Nov 24 13:05:33 2011 +0100
+++ b/Model/TagInterface.php	Sun Nov 27 23:35:54 2011 +0100
@@ -56,7 +56,7 @@
      * @param string $originalLabel
      */
     function setOriginalLabel($originalLabel);
-    
+        
     /**
      * Get originalLabel
      *
@@ -65,6 +65,20 @@
     function getOriginalLabel();
     
     /**
+     * Set the alternative label
+     *
+     * @param string $alternativeLabel
+     */
+    function setAlternativeLabel($alternativeLabel);
+    
+    /**
+     * Get the alternative label.
+     *
+     * @return string
+     */
+    function getAlternativeLabel();
+    
+    /**
      * Set alias
      *
      * @param string $alias
@@ -93,6 +107,21 @@
     function getWikipediaUrl();
     
     /**
+    * Set alternativeWikipediaUrl
+    *
+    * @param string $alternativeWikipediaUrl
+    */
+    function setAlternativeWikipediaUrl($alternativeWikipediaUrl);
+    
+    /**
+     * Get alternativeWikipediaUrl
+     *
+     * @return string
+     */
+    function getAlternativeWikipediaUrl();
+    
+    
+    /**
      * Set wikipediaPageId
      *
      * @param bigint $wikipediaPageId
@@ -105,6 +134,23 @@
      * @return bigint
      */
     function getWikipediaPageId();
+
+    
+   /**
+    * Set aletrnativeWikipediaPageId
+    *
+    * @param bigint $alternativeWikipediaPageId
+    */
+    function setAlternativeWikipediaPageId($alternativeWikipediaPageId);
+    
+    /**
+     * Get alternativeWikipediaPageId
+     *
+     * @return bigint
+     */
+    function getAlternativeWikipediaPageId();
+    
+    
     
     /**
      * Set urlStatus
@@ -185,4 +231,10 @@
     function nullCategory();
     
     
+    /**
+     * Set wikipedia info.
+     * @param $wikipedia_info
+     */
+    function setWikipediaInfo($wikipedia_info);
+    
 }
\ No newline at end of file
--- a/Resources/config/doctrine/Tag.orm.yml	Thu Nov 24 13:05:33 2011 +0100
+++ b/Resources/config/doctrine/Tag.orm.yml	Sun Nov 27 23:35:54 2011 +0100
@@ -19,6 +19,11 @@
       type: string
       length: '1024'
       column: original_label
+    alternativeLabel:
+      type: string
+      length: '1024'
+      column: alternative_label
+      nullable: true
     alias:
       type: string
       length: '1024'
@@ -28,9 +33,18 @@
       length: '2048'
       column: wikipedia_url
       nullable: true
+    alternativeWikipediaUrl:
+      type: string
+      length: '2048'
+      column: wikipedia_alternative_url
+      nullable: true
     wikipediaPageId:
       type: bigint
-      column: normalized_pageid
+      column: wikipedia_pageid
+      nullable: true
+    alternativeWikipediaPageId:
+      type: bigint
+      column: alternative_wikipedia_pageid
       nullable: true
     urlStatus:
       type: smallint
--- a/Resources/public/js/wikiTag.js	Thu Nov 24 13:05:33 2011 +0100
+++ b/Resources/public/js/wikiTag.js	Sun Nov 27 23:35:54 2011 +0100
@@ -64,7 +64,7 @@
 							return {
 								label: item,
 								value: item
-							}
+							};
 						}));
 					}
 				});
@@ -176,7 +176,7 @@
                         return {
                             label: item,
                             value: item
-                        }
+                        };
                     }));
                 }
             });
@@ -231,7 +231,7 @@
             t = document.selection.createRange().text;
         }
         return t;
-    }
+    ;
     Kolich.Selector.mouseup = function(e){
       var st = Kolich.Selector.getSelected();
       if(st!=''){
@@ -241,7 +241,7 @@
         $("#wikitag_context_div #wikitag_wp_search_context").val(st);
         $("#wikitag_context_div #wikitag_wp_search_context").autocomplete("search");
       }
-    }
+    ;
     $(document).ready(function(){
         for(c in reactive_selectors){
             $(reactive_selectors[c]).bind("mouseup", Kolich.Selector.mouseup);
@@ -275,7 +275,7 @@
                             label: item["title"],
                             snippet: item["snippet"],
                             value: item["title"]
-                        }
+                        };
                     }));
                 }
             });
@@ -307,7 +307,7 @@
             add_tag($("#wikitag_wp_search_context").val());
         }
     });
-}
+};
 
 function wikitag_update_tag(btn)
 {
@@ -431,6 +431,8 @@
             wikitag_init_tags_events();
             // And scroll to the bottom
             $("html").animate({ scrollTop: $(document).height() }, 500);
+            //TODO ; translate
+        	alert("Important : le pré-classement automatique est terminé. Veuillez affiner l’ordre des tags manuellement.");            
         },
         complete: function(){
         	$("#wikitag_tags_sort").attr("src",tag_sort_old_src);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utils/FilteredSchemaTool.php	Sun Nov 27 23:35:54 2011 +0100
@@ -0,0 +1,63 @@
+<?php
+/*
+ * This file is part of the WikiTagBundle package.
+ *
+ * (c) IRI <http://www.iri.centrepompidou.fr/>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace IRI\Bundle\WikiTagBundle\Utils;
+
+use Doctrine\ORM\Tools\SchemaTool;
+
+class FilteredSchemaTool extends SchemaTool
+{
+    
+    private $container;
+    
+    public function getContainer()
+    {
+        return $this->container;
+    }
+    
+    public function __construct($em, $container)
+    {
+        parent::__construct($em);
+        $this->container = $container;
+    }
+    
+    private function filterSchemaSql($sqls)
+    {
+        // get service
+        $schema_utils = $this->getContainer()->get("wikitag.shema_utils");
+        
+        $res_sqls = $schema_utils->filter_foreign_key($sqls);
+        $res_sqls = $schema_utils->filter_index_creation($res_sqls);
+        
+        
+        return $res_sqls;
+    }
+    
+    /**
+     * (non-PHPdoc)
+     * @see Doctrine\ORM\Tools.SchemaTool::getCreateSchemaSql()
+     */
+    public function getCreateSchemaSql(array $classes)
+    {
+        $res_sqls = parent::getCreateSchemaSql($classes);
+        return $this->filterSchemaSql($res_sqls);
+    }
+    
+    /**
+     * (non-PHPdoc)
+     * @see Doctrine\ORM\Tools.SchemaTool::getUpdateSchemaSql()
+     */
+    public function getUpdateSchemaSql(array $classes, $saveMode=false)
+    {
+        $res_sqls = parent::getUpdateSchemaSql($classes, $saveMode);
+        return $this->filterSchemaSql($res_sqls);
+    }
+    
+}
\ No newline at end of file
--- a/Utils/WikiTagUtils.php	Thu Nov 24 13:05:33 2011 +0100
+++ b/Utils/WikiTagUtils.php	Sun Nov 27 23:35:54 2011 +0100
@@ -13,106 +13,6 @@
     
     
     /**
-     * Get or create tag. Returns an array(tag:WikiTagTag, revision_id=int, created:Boolean)
-     */
-    
-    /**
-     *
-     * Enter description here ...
-     * @param unknown_type $tag_label
-     * @param unknown_type $doctrine
-     * @return multitype:boolean Ambigous <NULL, \IRI\Bundle\WikiTagBundle\Entity\Tag> Ambigous <NULL, unknown, mixed, string> (array(\IRI\Bundle\WikiTagBundle\Model\TagInterface, revision_id=int, created:Boolean))
-     */
-    public static function getOrCreateTag($tag_label, $doctrine)
-    {
-        $tag_label_normalized = WikiTagUtils::normalizeTag($tag_label);
-        // We get the wikipedia references for the tag_label
-        // We get or create the tag object
-        $tags = $doctrine->getRepository('WikiTagBundle:Tag')->findBy(array('normalizedLabel' => $tag_label_normalized));
-        $tag = null;
-        foreach ($tags as $t){
-            if($tag==null || $t->getUrlStatus()!=Tag::$TAG_URL_STATUS_DICT['null_result']){
-                $tag = $t;
-                if($t->getUrlStatus()!=Tag::$TAG_URL_STATUS_DICT['null_result']){
-                    break;
-                }
-            }
-        }
-        $wp_request_done = false;
-        if($tag==null){
-            $tag = new Tag();
-            $tag->setLabel($tag_label_normalized);
-            $tag->setOriginalLabel($tag_label);
-            $tag->setNormalizedLabel($tag_label_normalized);
-            $created = true;
-        }
-        else{
-            $created = false;
-            $match_exists = false;
-            // Even if a tag with the normalised label exists, IF this tag is not wikipedia semantised,
-            // we search if a wikipedia semantised version exists in the base
-            foreach ($tags as $t){
-                if($t->getUrlStatus()==Tag::$TAG_URL_STATUS_DICT['match']){
-                    $tag = $t;
-                    $match_exists = true;
-                    break;
-                }
-            }
-            if($match_exists==false){
-                $wp_response = WikiTagUtils::getWikipediaInfo($tag_label_normalized);
-                $status = $wp_response['status'];
-                if($status==Tag::$TAG_URL_STATUS_DICT['match']){
-                    $tag = new Tag();
-                    $tag->setLabel($tag_label_normalized);
-                    $tag->setOriginalLabel($tag_label);
-                    $tag->setNormalizedLabel($tag_label_normalized);
-                    $created = true;
-                    $wp_request_done = true;
-                }
-            }
-        }
-        
-        // We request Wikipedia if the tag is created
-        if($created==true){
-            if($wp_request_done==false){
-                $wp_response = WikiTagUtils::getWikipediaInfo($tag_label_normalized);
-            }
-            $new_label = $wp_response['new_label'];
-            $status = $wp_response['status'];
-            $url = $wp_response['wikipedia_url'];
-            $pageid = $wp_response['pageid'];
-            $dbpedia_uri = $wp_response["dbpedia_uri"];
-            $wikipedia_revision_id = $wp_response['revision_id'];
-            
-            # We save the datas
-            if($new_label!=null){
-                $tag->setLabel($new_label);
-            }
-            if($status!=null){
-                $tag->setUrlStatus($status);
-            }
-            $tag->setWikipediaUrl($url);
-            $tag->setWikipediaPageId($pageid);
-            $tag->setDbpediaUri($dbpedia_uri);
-            
-            // Save datas.
-            $em = $doctrine->getEntityManager();
-            $em->persist($tag);
-            $em->flush();
-            
-        }
-        else if($tag!=null && $tag->getWikipediaPageId()!=null){
-            $wp_response = WikiTagUtils::getWikipediaInfo(null, $tag->getWikipediaPageId());
-            $wikipedia_revision_id = $wp_response['revision_id'];
-        }
-        else{
-            $wikipedia_revision_id = null;
-        }
-        
-        return array($tag, $wikipedia_revision_id, $created);//, $wpReponse);
-    }
-    
-    /**
      * Cleans the tag label
      */
     public static function normalizeTag($tag_label)
@@ -122,19 +22,30 @@
         }
         $tag_label = trim($tag_label);//tag.strip()
         $tag_label = str_replace("_", " ", $tag_label);//tag.replace("_", " ")
-        $tag_label = str_replace("Œ", "oe", $tag_label);
-        $tag_label = str_replace("œ", "oe", $tag_label);
-        $tag_label = preg_replace('/\s+/', ' ', $tag_label);//" ".join(tag.split())
+        $tag_label = preg_replace('/\s+/u', ' ', $tag_label);//" ".join(tag.split())
         $tag_label = ucfirst($tag_label);//tag[0].upper() + tag[1:]
         return $tag_label;
     }
     
     /**
+     * Query wikipedia with a normalized label or a pageid
+     * return an array with the form
+     * array(
+     *      'new_label'=>$new_label,
+     *   	'alternative_label'=>$alternative_label,
+     *   	'status'=>$status,
+     *   	'wikipedia_url'=>$url,
+     *      'wikipedia_alternative_url'=>$alternative_url,
+     *   	'pageid'=>$pageid,
+     *   	'alternative_pageid'=>$alternative_pageid,
+     *   	'dbpedia_uri'=>$dbpedia_uri,
+     *   	'revision_id'=> ,
+     *   	'response'=> the original wikipedia json response
+     *   	)
      *
-     * TODO: Enter description here ...
-     * @param unknown_type $tag_label_normalized
-     * @param unknown_type $page_id
-     * @return multitype:NULL unknown |multitype:Ambigous <NULL, unknown> multitype:number  mixed Ambigous <NULL, string> Ambigous <unknown, mixed>
+     * @param string $tag_label_normalized
+     * @param bigint $page_id
+     * @return array
      */
     public static function getWikipediaInfo($tag_label_normalized, $page_id=null)
     {
@@ -181,7 +92,11 @@
             $status = Tag::$TAG_URL_STATUS_DICT["match"];
         }
         // In redirection, we have to get more datas by adding redirects=true to the params
-        if($status==Tag::$TAG_URL_STATUS_DICT["redirection"]){
+        $alternative_label = null;
+        $alternative_url = null;
+        $alternative_pageid = null;
+        if($status==Tag::$TAG_URL_STATUS_DICT["redirection"])
+        {
             $params['redirects'] = "true";
             $ar = WikiTagUtils::requestWikipedia($params);
             $res = $ar[0];
@@ -192,6 +107,9 @@
             }
             // get first result
             $page = reset($pages);
+            $alternative_label = array_key_exists('title', $page) ? $page['title'] : null;
+            $alternative_url = array_key_exists('fullurl', $page) ? $page['fullurl'] : null;
+            $alternative_pageid = array_key_exists('pageid', $page) ? $page['pageid'] : null;
         }
         
         $revision_id = $page['lastrevid'];
@@ -214,17 +132,27 @@
             $dbpedia_uri = WikiTagUtils::getDbpediaUri($english_label);
         }
         
-        $wp_response = array('new_label'=>$new_label, 'status'=>$status, 'wikipedia_url'=>$url, 'pageid'=>$pageid, 'dbpedia_uri'=>$dbpedia_uri, 'revision_id'=>$revision_id, 'response'=>$original_response);
+        $wp_response = array(
+            'new_label'=>$new_label,
+        	'alternative_label'=>$alternative_label,
+        	'status'=>$status,
+        	'wikipedia_url'=>$url,
+            'wikipedia_alternative_url'=>$alternative_url,
+        	'pageid'=>$pageid,
+        	'alternative_pageid'=>$alternative_pageid,
+        	'dbpedia_uri'=>$dbpedia_uri,
+        	'revision_id'=>$revision_id,
+        	'response'=>$original_response);
         //return $url." <br/>RES =  ".$res/*." <br/>DUMP =  ".var_dump($pages)*/." <br/>COUNT =  ".count($pages)." <br/>page =  ".var_dump($page);
         return $wp_response;
     }
     
 
     /**
+     * build and do the request to Wikipedia.
      *
-     * TODO : Enter description here ...
-     * @param unknown_type $params
-     * @return multitype:unknown mixed
+     * @param array $params
+     * @return array
      */
     private static function requestWikipedia($params)
     {