phpDocumentor lodel-logic
[ class tree: lodel-logic ] [ index: lodel-logic ] [ all elements ]

Source for file class.entities.php

Documentation is available at class.entities.php

  1. <?php
  2. /**    
  3.  * Logique des entités
  4.  *
  5.  * PHP versions 4 et 5
  6.  *
  7.  * LODEL - Logiciel d'Edition ELectronique.
  8.  *
  9.  * Home page: http://www.lodel.org
  10.  * E-Mail: lodel@lodel.org
  11.  *
  12.  * All Rights Reserved
  13.  *
  14.  * This program is free software; you can redistribute it and/or modify
  15.  * it under the terms of the GNU General Public License as published by
  16.  * the Free Software Foundation; either version 2 of the License, or
  17.  * (at your option) any later version.
  18.  *
  19.  * This program is distributed in the hope that it will be useful,
  20.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22.  * GNU General Public License for more details.
  23.  *
  24.  * You should have received a copy of the GNU General Public License
  25.  * along with this program; if not, write to the Free Software
  26.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  27.  *
  28.  * @author Ghislain Picard
  29.  * @author Jean Lamy
  30.  * @copyright 2001-2002, Ghislain Picard, Marin Dacos
  31.  * @copyright 2003, Ghislain Picard, Marin Dacos, Luc Santeramo, Nicolas Nutten, Anne Gentil-Beccot
  32.  * @copyright 2004, Ghislain Picard, Marin Dacos, Luc Santeramo, Anne Gentil-Beccot, Bruno Cénou
  33.  * @copyright 2005, Ghislain Picard, Marin Dacos, Luc Santeramo, Gautier Poupeau, Jean Lamy, Bruno Cénou
  34.  * @copyright 2006, Marin Dacos, Luc Santeramo, Bruno Cénou, Jean Lamy, Mikaël Cixous, Sophie Malafosse
  35.  * @copyright 2007, Marin Dacos, Bruno Cénou, Sophie Malafosse, Pierre-Alain Mignot
  36.  * @licence http://www.gnu.org/copyleft/gpl.html
  37.  * @since Fichier ajouté depuis la version 0.8
  38.  * @version CVS:$Id: class.entities.php 4006 2007-10-05 11:53:41Z malafosse $
  39.  */
  40.  
  41.  
  42.  
  43. /**
  44.  * Classe de logique des entités
  45.  * 
  46.  * @package lodel/logic
  47.  * @author Ghislain Picard
  48.  * @author Jean Lamy
  49.  * @copyright 2001-2002, Ghislain Picard, Marin Dacos
  50.  * @copyright 2003, Ghislain Picard, Marin Dacos, Luc Santeramo, Nicolas Nutten, Anne Gentil-Beccot
  51.  * @copyright 2004, Ghislain Picard, Marin Dacos, Luc Santeramo, Anne Gentil-Beccot, Bruno Cénou
  52.  * @copyright 2005, Ghislain Picard, Marin Dacos, Luc Santeramo, Gautier Poupeau, Jean Lamy, Bruno Cénou
  53.  * @copyright 2006, Marin Dacos, Luc Santeramo, Bruno Cénou, Jean Lamy, Mikaël Cixous, Sophie Malafosse
  54.  * @copyright 2007, Marin Dacos, Bruno Cénou, Sophie Malafosse, Pierre-Alain Mignot
  55.  * @licence http://www.gnu.org/copyleft/gpl.html
  56.  * @since Classe ajouté depuis la version 0.8
  57.  * @see logic.php
  58.  */
  59. class EntitiesLogic extends Logic
  60. {
  61.  
  62.     /**
  63.     * generic equivalent assoc array
  64.     */
  65.     var $g_name;
  66.  
  67.     /**
  68.      * Constructor
  69.      */
  70.     function EntitiesLogic()
  71.     {
  72.         $this->Logic("entities");
  73.     }
  74.  
  75.  
  76.     /**
  77.      * Affichage d'un objet
  78.      *
  79.      * @param array &$context le contexte passé par référence
  80.      * @param array &$error le tableau des erreurs éventuelles passé par référence
  81.      */
  82.     function viewAction(&$context&$error)
  83.     {
  84.         die("EntitiesLogic::viewAction");
  85.     }
  86.  
  87.  
  88.     /**
  89.      * Changement du rang d'un objet
  90.      *
  91.      * @param array &$context le contexte passé par référence
  92.      * @param array &$error le tableau des erreurs éventuelles passé par référence
  93.      */
  94.     function changeRankAction(&$context&$error)
  95.     {
  96.         global $db;
  97.         $id  intval($context['id']);
  98.         $dao $this->_getMainTableDAO();
  99.         $vo  $dao->getById($id,"idparent");
  100.         $this->_changeRank($id,$context['dir']"status<64 AND idparent='"$vo->idparent"'");
  101.         update();
  102.         return '_back';
  103.     }
  104.  
  105.     /**
  106.      * Ajout d'un nouvel objet ou Edition d'un objet existant
  107.      *
  108.      * Cette méthode est abstraite ici. On utilise die() pour simuler le fonctionnement
  109.      * d'une méthode abstraite.
  110.      *
  111.      * @param array &$context le contexte passé par référence
  112.      * @param array &$error le tableau des erreurs éventuelles passé par référence
  113.      */
  114.     function editAction(&$context,&$error)
  115.     {
  116.         die("EntitiesLogic::editAction");
  117.     }
  118.  
  119.  
  120.     /**
  121.      * Opérations de masse : suppression massive, publication ou dépublication massive
  122.      *
  123.      * @param array &$context le contexte passé par référence
  124.      * @param array &$error le tableau des erreurs éventuelles passé par référence
  125.      */
  126.     function massAction(&$context,&$error)
  127.     {
  128.         if (!$context['entity']{
  129.             return "_back";
  130.         }
  131.         $context['id'array();
  132.         foreach(array_keys($context['entity']as $id{
  133.             $context['id'][intval($id);
  134.         }
  135.  
  136.         if ($context['delete']{
  137.             return $this->deleteAction($context,$error);
  138.         elseif ($context['publish']{
  139.             $context['status'1;
  140.             return $this->publishAction($context,$error);
  141.         elseif ($context['unpublish']{
  142.             $context['status'= -1;
  143.             return $this->publishAction($context,$error);
  144.         }
  145.         trigger_error("unknow mass operation",E_USER_ERROR);
  146.     }
  147.  
  148.  
  149.     /**
  150.      * Suppression d'un objet
  151.      *
  152.      * @param array &$context le contexte passé par référence
  153.      * @param array &$error le tableau des erreurs éventuelles passé par référence
  154.      */
  155.     function deleteAction(&$context&$error)
  156.     {
  157.         global $db;
  158.         // get the entities to modify and ancillary information
  159.         if (!rightonentity("delete",$context)) die("ERROR: you don't have the right to perform this operation");
  160.         $this->_getEntityHierarchy($context['id'],"write","",$ids,$classes,$softprotectedids,$lockids);
  161.         if (!$ids{
  162.             return '_back';
  163.         }
  164.         if ($lockedids)  {
  165.             die("ERROR: some entities are locked in the family. No operation is allowed");
  166.         }
  167.  
  168.         // needs confirmation ?
  169.         if (!$context['confirm'&& $softprotectedids{
  170.             $context['softprotectedentities'$softprotectedids;
  171.             $this->define_loop_protectedentities();
  172.             return 'delete_confirm';
  173.         }
  174.  
  175.         // delete all the entities
  176.         $dao $this->_getMainTableDAO();
  177.         $dao->deleteObject($ids);
  178.  
  179.         // delete in the joint table
  180.         foreach(array_keys($classesas $class{
  181.             $db->execute(lq("DELETE FROM #_TP_$class WHERE identity ".sql_in_array($ids))) or dberror();
  182.         }
  183.  
  184.         // delete the relations
  185.         $this->_deleteSoftRelation($ids);
  186.  
  187.         // delete other relations
  188.         $db->execute(lq("DELETE FROM #_TP_relations WHERE id1 ".sql_in_array($ids)." OR id2 ".sql_in_array($ids))) or dberror();
  189.  
  190.         // delete the entity from the search_engine table
  191.         $db->execute(lq("DELETE FROM #_TP_search_engine WHERE identity ".sql_in_array($ids))) or dberror();
  192.  
  193.         update();
  194.         return '_back';
  195.     }
  196.  
  197.     /**
  198.      * Publication ou dépublication d'une entité
  199.      *
  200.      * Change le status de l'entité à 1 (publication) ou -1 (dépublication).
  201.      * Fonction récursive
  202.      * Ne modifie pas les entités dont le status est inférieur ou égal à -8
  203.      *
  204.      * @param array &$context le contexte passé par référence
  205.      * @param array &$error le tableau des erreurs éventuelles passé par référence
  206.      */
  207.  
  208.     function publishAction (&$context&$error
  209.     {
  210.         global $db;
  211.         $status intval ($context['status']);
  212.         $this->_isAuthorizedStatus($status);
  213.         if ($status == 0{
  214.             die ("error in publishAction");
  215.         }
  216.         if (!rightonentity ($status 'publish' 'unpublish'$context)) {
  217.             die ("ERROR: you don't have the right to perform this operation");
  218.         }
  219.  
  220.         // get the entities to modify and ancillary information
  221.         $access abs ($status>= 32 'protect' 'write';
  222.         $this->_getEntityHierarchy($context['id']$access,"#_TP_entities.status>-8"$ids$classes$softprotectedids$lockedids);
  223.  
  224.         if (!$ids{
  225.             return '_back';
  226.         }
  227.  
  228.         if ($lockedids && $status 0{
  229.             die("ERROR: some entities are locked in the family. No operation is allowed");
  230.         }
  231.  
  232.         // depublish protected entity ? need confirmation.
  233.         if (!$context['confirm'&& $status && $softprotectedids{
  234.             $context['softprotectedentities'$softprotectedids;
  235.             $this->define_loop_protectedentities();
  236.             return 'unpublish_confirm';
  237.         }
  238.         $criteria=" id IN ("join(","$ids)')';
  239.  
  240.         // mais attention, il ne faut pas reduire le status quand on publie
  241.         if ($status 0{
  242.             $criteria.= " AND status < '$status'";
  243.         }
  244.         //mise à jour des entités
  245.         $db->execute(lq("UPDATE #_TP_entities SET status=$status WHERE "$criteria)) or dberror();
  246.  
  247.         // check if the entities have an history field defined
  248.         $this->_processSpecialFields('history'$context$status);
  249.  
  250.         //mise à jour des personnes et entrées liées à ces entités
  251.         $this->_publishSoftRelation($ids$status);
  252.         update();
  253.         return '_back';
  254.         }
  255.  
  256.     
  257.     
  258.  
  259.     /**
  260.      * Suppressions des relations entre une entité et des persons et des entries
  261.      *
  262.      * Dans la table relations, le champ nature = G ou E (G = gens, E=entrées)
  263.      * @access private
  264.      * @param array $ids les identifiants numériques des entités
  265.      */
  266.     function _deleteSoftRelation($ids
  267.     {
  268.         // most of this should be transfered in the entries and persons logic
  269.         global $db;
  270.         $criteria 'id1 'sql_in_array($ids);
  271.         $result $db->execute(lq("SELECT idrelation,nature FROM #_TP_relations WHERE $criteria AND nature IN ('G','E')")) or dberror();
  272.         $idrelation array();
  273.         while(!$result->EOF{
  274.             $nature $result->fields['nature'];
  275.             $idrelation[$nature][$result->fields['idrelation'];
  276.             $result->MoveNext();
  277.         }
  278.  
  279.         // select all the items not in entities_$table
  280.         // those with status<=1 must be deleted
  281.         // thise with status> must be depublished
  282.         foreach(array_keys($idrelationas $nature{
  283.             $idlist=join(",",$idrelation[$nature]);
  284.             $table=$nature=='G' "persons" "entries";
  285.             $db->execute(lq("DELETE FROM #_TP_relations WHERE idrelation IN (".$idlist.")")) or dberror();
  286.  
  287.             $result=$db->execute(lq("SELECT id,status FROM #_TP_$table LEFT JOIN #_TP_relations ON id2=id WHERE id1 is NULL")) or dberror();
  288.     
  289.             $idstodelete=array();
  290.             $idstounpublish=array();
  291.             while (!$result->EOF{
  292.                 if (abs($result->fields['status'])==1{
  293.                     $idstodelete[]=$result->fields['id']
  294.                 else {
  295.                     $idstounpublish[]=$result->fields['id']
  296.                 }
  297.                 $result->MoveNext();
  298.             }
  299.  
  300.             if ($idstodelete{
  301.                 $logic=&getLogic($table);
  302.                 $localcontext=array("id"=>$idstodelete,"idrelation"=>$idrelation[$nature]);
  303.                 $localerror=array();
  304.                 $logic->deleteAction($localcontext,$localerror);
  305.             }
  306.  
  307.             if ($idstounpublish{
  308.             // should be in $table dao or logic
  309.             $db->execute(lq("UPDATE #_TP_$table SET status=-abs(statusWHERE id IN ("join(","$idstounpublish)") AND status>=32")) or dberror()
  310.             }
  311.         // tables
  312.     }
  313.  
  314.     /**
  315.      * Mise à jour du status des objets liées (liaisons 'soft', c'est à dire des personnes
  316.      * ou des entrées d'index.
  317.      *
  318.      * Lors d'une publication c'est simple, le status des entrées ou personnes liées à l'entité
  319.      * est mis à +32 ou +1 suivant si l'entrée ou la personne est permanente.
  320.      *
  321.      * Lors d'une dépublication, c'est plus compliqué, il ne faut pas toucher aux entrées qui ont
  322.      * publiées par d'autres entités. Ensuite de la même manière le status est mis à -32 ou -1
  323.      *
  324.      * @param array les identifiants
  325.      * @param integer le status de l'entité concernée ou des entités concernées
  326.      * @access private
  327.      */
  328.     function _publishSoftRelation($ids$status)
  329.     {
  330.         global $db;
  331.         $criteria "id1 IN ("join(","$ids)")";
  332.         $status $status : -1// dans les tables le status est seulement a +1 ou -1
  333.         $result $db->execute(lq("SELECT id2,nature FROM #_TP_relations WHERE nature IN ('E','G') AND "$criteria)) or dberror();
  334.         $ids array();
  335.         while (!$result->EOF{
  336.             $ids[$result->fields['nature']][$result->fields['id2']] true;
  337.             $result->MoveNext();
  338.         }
  339.         if (!$ids{
  340.             return// get back, nothing to do
  341.         }
  342.         foreach(array_keys($idsas $nature{
  343.             $idlist join(','array_keys($ids[$nature]));
  344.             $table $nature == 'G' 'persons' 'entries';
  345.  
  346.             //------- PUBLISH ---------
  347.             if ($status 0{
  348.                 // simple : on doit mettre le status à positif : +32 ou +1 si l'entree ou la personne
  349.                 // est permanente ou non
  350.                 
  351.                 $db->execute(lq("UPDATE #_TP_$table SET status=abs(statusWHERE id IN ($idlist)")) or dberror();
  352.     
  353.             //------- UNPUBLISH ---------
  354.             else // status < 0
  355.                 // plus difficile. On vérifie si les entries ou persons sont attachés à des entités publiées.
  356.                 $result =  $db->execute(lq("SELECT id1,id2 FROM #_TP_relations INNER JOIN #_TP_entities ON id1=id WHERE #_TP_entities.status>0 AND id2 IN ("$idlist") AND nature='".$nature."' GROUP BY id2")) or dberror();
  357.                 while (!$result->EOF{
  358.                     unset($ids[$nature][$result->fields['id2']])// remove the id from the list to unpublish
  359.                     $result->MoveNext();
  360.                 }
  361.                 if ($ids[$nature]{
  362.                     $idlist join(','array_keys($ids[$nature]));
  363.                     // dépublie les entrées ou personnes qui n'ont pas été publiés par d'autres entités :
  364.                     $db->execute(lq("UPDATE #_TP_$table SET status=-abs(statusWHERE id IN ($idlist)")) or dberror();
  365.                 }
  366.             // status < 0
  367.         // foreach
  368.     }
  369.  
  370.     /**
  371.      * Récupère une entité et tous ses fils
  372.      *
  373.      * Récupère une entité et tous ses fils pour une opération donnée et par accès.
  374.      * On obtiens une liste d'identifiant, d'entité protégés et les classes auxquelles elles
  375.      * appartiennent.
  376.      *
  377.      * @param integer $id Identifiant de l'entité
  378.      * @param string $access l'accès
  379.      * @param string $criteria les critères de sélections
  380.      * @param array &$ids les identifiants des fils et de l'entité, tableau passé par référence
  381.      * @param array &$classes les classes des differentes entités de $ids, tableau passé par
  382.      *  référence
  383.      * @param array &$softprotectedids les entités protégés de $ids, tableau passé par référence
  384.      * @param array &$lockedids les entités verrouillées de $ids, tableau passé par référence
  385.      */
  386.     function _getEntityHierarchy($id$access$criteria&$ids&$classes&$softprotectedids&$lockedids)
  387.     {
  388.         global $db;
  389.  
  390.         // check the rights to $access the current entity
  391.         $dao $this->_getMainTableDAO();
  392.         $hasrights="(1 ".$dao->rightsCriteria($access).") as hasrights";
  393.  
  394.         // get the central object
  395.         if ($criteria{
  396.             $criteria=" AND ".$criteria;
  397.         }
  398.         $result $db->execute(lq("SELECT #_TP_entities.id,#_TP_entities.status,$hasrights,class FROM #_entitiestypesjoin_ WHERE #_TP_entities.id ".sql_in_array($id).$criteria));
  399.  
  400.         // list the entities
  401.         $ids              array();
  402.         $classes          array();
  403.         $softprotectedids array();
  404.         $lockedids        array();
  405.         while (!$result->EOF{
  406.             if (!$result->fields['hasrights']trigger_error("This object is locked. Please report the bug",E_USER_ERROR);
  407.             if ($result->fields['id']>0$ids[]=$result->fields['id'];
  408.             $classes[$result->fields['class']]=true;
  409.             if ($result->fields['status']>=8$softprotectedids[]=$result->fields['id'];      
  410.             if ($result->fields['status']>=16$lockedids[]=$result->fields['id'];      
  411.             $result->MoveNext();
  412.         }
  413.         
  414.         // check the rights to delete the sons and get their ids
  415.         // criteria to determin if one of the sons is locked
  416.         $result $db->execute(lq("SELECT #_TP_entities.id,#_TP_entities.status,$hasrights,class FROM #_entitiestypesjoin_ INNER JOIN #_TP_relations ON id2=#_TP_entities.id WHERE id1 "sql_in_array($id)" AND nature='P' "$criteria)) or dberror();
  417.  
  418.         while (!$result->EOF{
  419.             if (!$result->fields['hasrights']trigger_error("This object is locked. Please report the bug",E_USER_ERROR);
  420.             if ($result->fields['id']>0$ids[]=$result->fields['id'];
  421.             $classes[$result->fields['class']]=true;
  422.             if ($result->fields['status']>=8$softprotectedids[]=$result->fields['id'];
  423.             if ($result->fields['status']>=16$lockedids[]=$result->fields['id'];
  424.             $result->MoveNext();
  425.         }
  426.     }
  427.     
  428.     function define_loop_protectedentities()
  429.     {
  430.         function loop_protectedentities($context,$funcname{
  431.             global $db;
  432.             $result=$db->execute(lq("SELECT * FROM #_TP_entities WHERE id ".sql_in_array($context['softprotectedentities']))) or dberror();
  433.             while(!$result->EOF{
  434.                 $localcontext=array_merge($context,$result->fields);
  435.                 call_user_func("code_do_$funcname",$localcontext);
  436.                 $result->MoveNext();
  437.             }
  438.         // loop
  439.     }
  440.  
  441.     // begin{publicfields} automatic generation  //
  442.  
  443.     /**
  444.      * Retourne la liste des champs publics
  445.      * @access private
  446.      */
  447.     function _publicfields(
  448.     {</