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

Source for file class.data.php

Documentation is available at class.data.php

  1. <?php
  2. /**
  3.  * Fichier de classe pour les backups
  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.  * @package lodel/logic
  29.  * @author Ghislain Picard
  30.  * @author Jean Lamy
  31.  * @copyright 2001-2002, Ghislain Picard, Marin Dacos
  32.  * @copyright 2003, Ghislain Picard, Marin Dacos, Luc Santeramo, Nicolas Nutten, Anne Gentil-Beccot
  33.  * @copyright 2004, Ghislain Picard, Marin Dacos, Luc Santeramo, Anne Gentil-Beccot, Bruno Cénou
  34.  * @copyright 2005, Ghislain Picard, Marin Dacos, Luc Santeramo, Gautier Poupeau, Jean Lamy, Bruno Cénou
  35.  * @copyright 2006, Marin Dacos, Luc Santeramo, Bruno Cénou, Jean Lamy, Mikaël Cixous, Sophie Malafosse
  36.  * @copyright 2007, Marin Dacos, Bruno Cénou, Sophie Malafosse, Pierre-Alain Mignot
  37.  * @licence http://www.gnu.org/copyleft/gpl.html
  38.  * @since Fichier ajouté depuis la version 0.8
  39.  * @version CVS:$Id: class.data.php 4468 2008-07-17 14:13:31Z mignot $
  40.  */
  41.  
  42. /**
  43.  * Classe de logique permettant de gérer les backup et import de données et de ME
  44.  * 
  45.  * @package lodel/logic
  46.  * @author Jean Lamy
  47.  * @author Sophie Malafosse
  48.  * @author Pierre-Alain Mignot
  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ée depuis la version 0.8
  57.  * @see backupfunc.php, pma/sql-modified.php
  58.  */
  59. class DataLogic
  60. {
  61.  
  62.     /**
  63.      * Prefix du fichier (pour l'import de ME et l'import de données)
  64.      * @var string 
  65.      */
  66.     var $filePrefix;
  67.  
  68.     /**
  69.      * Expression utilisée pour filtrer les fichiers pour un import
  70.      * @var string 
  71.      */
  72.     var $fileRegexp;
  73.  
  74.     /**
  75.      * Extension du fichier d'import
  76.      * @var string 
  77.      */
  78.     var $fileExtension;
  79.  
  80.     /* IMPORT ME XML */
  81.     /**
  82.      * Tables correspondantes au ME
  83.      * @var array 
  84.      */
  85.     private $_tables
  86.  
  87.     /**
  88.      * Tables enregistrées lors du parsage du fichier XML
  89.      * @var array 
  90.      */
  91.     private $_recordedTables;
  92.  
  93.     /**
  94.      * Structure de la base XML
  95.      * @var array 
  96.      */
  97.     private $_xmlStruct
  98.  
  99.     /**
  100.      * Structure de la base SQL
  101.      * @var array 
  102.      */
  103.     private $_sqlStruct
  104.  
  105.     /**
  106.      * Liste des tables différentes entre SQL/XML
  107.      * @var array 
  108.      */
  109.     private $_changedTables
  110.     
  111.     /**
  112.      * Liste des champs différents entre chaque table SQL/XML
  113.      * @var array 
  114.      */
  115.     private $_changedFields;
  116.  
  117.     /**
  118.      * Donnés récupérées dans le XML
  119.      * @var array 
  120.      */
  121.      private $_xmlDatas;
  122.  
  123.     /**
  124.      * Tables à créer (présentes dans le XML et non dans la base)
  125.      * @var array 
  126.      */
  127.     private $_tableToCreate;
  128.  
  129.     /**
  130.      * Tableau des requêtes à effectuer
  131.      * @var array 
  132.      */    
  133.     private $_sql;
  134.  
  135.     /**
  136.      * Tableau des champs absent du XML mais présent dans la base
  137.      * @var array 
  138.      */    
  139.     private $_fieldsToKeep;
  140.  
  141.     /**
  142.      * Tableau des types (entité ou entrée) n'ayant pas trouvé leur équivalent dans le XML
  143.      * @var array 
  144.      */
  145.     private $_changedTypes;
  146.     /* FIN IMPORT ME XML */
  147.  
  148.     /**
  149.      * Constructeur
  150.      *
  151.      * Interdit l'accès aux utilisateurs qui ne sont pas ADMIN
  152.      */
  153.     function DataLogic()
  154.     {
  155.          if ($GLOBALS['lodeluser']['rights'LEVEL_ADMIN
  156.                 || ($GLOBALS['lodeluser']['rights'== LEVEL_ADMIN && ($GLOBALS['context']['do'== 'import'
  157.                 || $GLOBALS['context']['do'== 'backup'
  158.                 || $GLOBALS['context']['do'== 'importmodel'
  159.                 || $GLOBALS['context']['do'== 'importxmlmodel'))) {
  160.                         die("ERROR: you don't have the right to access this feature");
  161.                 }
  162.  
  163.         $this->fileExtension = 'zip';
  164.     }
  165.  
  166.     /**
  167.      * Importation des données
  168.      *
  169.      * Cette fonction importe les données issus d'un backup de lodel : le dump SQL, les fichiers associés (si ils ont été sauvegardés).
  170.      *
  171.      * @param array $context le contexte passé par référence
  172.      * @param array $error les éventuelles erreur, passées par référence
  173.      */
  174.     function importAction(&$context&$error)
  175.     {
  176.         global $db;
  177.         require_once 'func.php';
  178.         $context['importdir'$GLOBALS['importdir'];
  179.         $this->fileRegexp = $context['fileregexp''(site|revue)-[a-z0-9\-]+-\d{6}.'$this->fileExtension;
  180.  
  181.         // les répertoires d'import
  182.         $context['importdirs'array('CACHE');
  183.         if ($context['importdir']{
  184.           $context['importdirs'][$context['importdir'];
  185.         }
  186.  
  187.         $file $this->_extractImport($context);
  188.  
  189.         if ($file// Si on a bien spécifié un fichier
  190.             do // control block
  191.  
  192.                 set_time_limit(120)//pas d'effet si safe_mode on ; on met le temps à unlimited
  193.                 //nom du fichier SQL
  194.                 $sqlfile tempnam(tmpdir()'lodelimport_');
  195.                 //noms des répertoires acceptés
  196.                 $accepteddirs array('lodel/txt''lodel/rtf''lodel/sources''lodel/icons''docannexe/file''docannexe/image');
  197.         
  198.                 require_once 'backupfunc.php';
  199.                 if (!importFromZip($file$accepteddirsarray()$sqlfile)) {
  200.                     
  201.                     $err $error['error_extract''extract';
  202.                     return 'import';
  203.                 }
  204.                 #require_once 'connect.php';
  205.                 // drop les tables existantes
  206.                 //$db->execute(lq('DROP TABLE IF EXISTS '. join(',', $GLOBALS['lodelsitetables']))) or dberror();
  207.                 //execution du dump SQL
  208.                 if (!$this->_execute_dump($sqlfile)) {
  209.                     $error['error_execute_dump'$err $db->errormsg();
  210.                 }
  211.                 @unlink($sqlfile);
  212.         
  213.                 require_once 'cachefunc.php';
  214.                 removefilesincache(SITEROOTSITEROOT'lodel/edition'SITEROOT'lodel/admin');
  215.         
  216.                 // verifie les .htaccess dans le CACHE
  217.                 $this->_checkFiles($context);
  218.             while(0);
  219.         else {
  220.             $error['file''unknown_file';
  221.             return 'import';
  222.         }
  223.         if(!$error{
  224.                 $context['success'1;
  225.         }
  226.         return 'import';
  227.     }
  228.  
  229.     /**
  230.      * Sauvegarde des données
  231.      *
  232.      * Fait un dump de la base de données du site et si indiqué sauve aussi les fichiers annexes et source.
  233.      *
  234.      * @param array $context le contexte passé par référence
  235.      * @param array $error les éventuelles erreurs, passées par référence
  236.      */
  237.     function backupAction(&$context&$error)
  238.     {
  239.         global $zipcmd;
  240.         $context['importdir'$GLOBALS['importdir'];
  241.         #print_r($context);
  242.         if ($context['backup']// si on a demandé le backup
  243.             require_once 'func.php';
  244.             require_once 'backupfunc.php';
  245.             $site $context['site'];
  246.             $outfile "site-$site.sql";
  247.  
  248.             //$uselodelprefix = true; // ? NON UTILISE
  249.             $GLOBALS['tmpdir'$tmpdir tmpdir();
  250.             $errors array();
  251.             $fh fopen($tmpdir'/'$outfile'w');
  252.             if (!$fh{
  253.                 die ("ERROR: unable to open a temporary file in write mode");
  254.             }
  255.             $this->_dump($site$tmpdir'/'$outfile$errors$fh);
  256.             fclose($fh);
  257.             if($errors{
  258.                 $error $errors;
  259.                 return 'backup';
  260.             }
  261.             // verifie que le fichier SQL n'est pas vide
  262.             if (filesize($tmpdir'/'$outfile<= 0{
  263.                 $error['mysql''dump_failed';
  264.                 return 'backup';
  265.             }
  266.         
  267.             // zip le site et ajoute la base
  268.             $archivetmp      tempnam($tmpdir'lodeldump_')'.zip';
  269.             $archivefilename "site-$site-"date("dmy")'.zip';
  270.             // fichiers à exclure de l'archive
  271.             $GLOBALS['excludes'$excludes array('lodel/sources/.htaccess',
  272.                         'docannexe/fichier/.htaccess',
  273.                         'docannexe/image/index.html',
  274.                         'docannexe/index.html',
  275.                         'docannexe/image/tmpdir-\*',
  276.                         'docannexe/tmp\*');
  277.             // répertoires à inclure
  278.             $sitedirs array('lodel/icons''lodel/sources''docannexe');
  279.  
  280.             // si sauvegarde des répertoires demandée (en + de la base)
  281.             if (!$context['sqlonly']{
  282.                     //verifie que les repertoires sont accessibles en lecture
  283.                     foreach ($sitedirs as $sitedir{
  284.                         if(is_readable(SITEROOT $sitedir)){
  285.                             $good_dirs[$sitedir;
  286.                         else {
  287.                             $bad_dirs[$sitedir;
  288.                         }
  289.                     }
  290.                     // initialise $error pour affichage dans le template backup.html
  291.                     if (is_array($bad_dirs)) $error['files'implode(', '$bad_dirs)}
  292.                     
  293.                     // conversion en chaîne pour ligne de commande
  294.                     $dirs implode(' '$good_dirs);
  295.                 }
  296.             else    $dirs ''}
  297.  
  298.             if ($zipcmd && $zipcmd != 'pclzip'//Commande ZIP
  299.  
  300.                 if (!$context['sqlonly']{
  301.                     if (!chdir(SITEROOT)) {
  302.                         die ("ERROR: can't chdir in SITEROOT");
  303.                     }
  304.                     $prefixdir    $tmpdir[0== "/" '' 'lodel/admin/';
  305.                     $excludefiles $excludes " -x "join(" -x "$excludes"";
  306.                     system($zipcmd" -q $prefixdir$archivetmp -r $dirs $excludefiles");
  307.                     if (!chdir("lodel/admin")) {
  308.                         die ("ERROR: can't chdir in lodel/admin");
  309.                     }
  310.                     system($zipcmd" -q -g $archivetmp -j $tmpdir/$outfile");
  311.                 else {
  312.                     system($zipcmd" -q $archivetmp -j $tmpdir/$outfile");
  313.                 }
  314.             else // Comande PCLZIP
  315.  
  316.                 require_once 'pclzip/pclzip.lib.php';
  317.                 $archive new PclZip($archivetmp);
  318.                 if (!$context['sqlonly']{
  319.                     // function to exclude files and rename directories
  320.                     function preadd($p_event&$p_header
  321.                     {
  322.                         global $excludes$tmpdir// that's bad to depend on globals like that
  323.                         $p_header['stored_filename'preg_replace("/^"preg_quote($tmpdir"/")"\//"""$p_header['stored_filename']);
  324.                         foreach ($excludes as $exclude{
  325.                             if (preg_match ("/^"str_replace('\\\\\*''.*'preg_quote($exclude"/"))"$/"$p_header['stored_filename'])) {
  326.                                 return 0;
  327.                             }
  328.                         }
  329.                         return 1;
  330.                     }
  331.                     // end of function to exclude files
  332.  
  333.                     // ajout de la racine du site aux chemins des répertoires
  334.                     for($i=$i<count($good_dirs$i++){
  335.                         $good_dirs[$iSITEROOT$good_dirs[$i];
  336.                     }
  337.                     // ajout du fichier sql issu du dump de la base du site
  338.                     array_push($good_dirs$tmpdir'/'$outfile);
  339.                     // création de l'archive
  340.                     $archive->create($good_dirs,
  341.                             PCLZIP_OPT_REMOVE_PATH,SITEROOT,
  342.                             PCLZIP_CB_PRE_ADD'preadd');
  343.                 else {
  344.                     $archive->create($tmpdir"/"$outfilePCLZIP_OPT_REMOVE_ALL_PATH);
  345.                 }
  346.             // end of pclzip option
  347.         
  348.             if (!file_exists($archivetmp)) {
  349.                 die ("ERROR: the zip command or library does not produce any output");
  350.             }
  351.             @unlink($tmpdir'/'$outfile)// delete the sql file
  352.             
  353.             if($error// Pour avoir accès aux erreurs dans les templates
  354.                 $context['error'$error;}
  355.  
  356.             if (operation($context['operation']$archivetmp$archivefilename$context)) {
  357.                 $context['success'1;
  358.                 return 'backup';
  359.             }
  360.             else {
  361.                 $context['success'1;
  362.                 return 'backup';
  363.             }
  364.             
  365.             return 'backup';
  366.         }
  367.         else {
  368.             return 'backup';
  369.         }
  370.     }
  371.  
  372.     /**
  373.      * Backup global des données. Seulement autorisé pour un admin lodel
  374.      *
  375.      * Cela crée un backup de la base principale mais aussi de tous les sites
  376.      *
  377.      * @param array $context le contexte passé par référence
  378.      * @param array $error les éventuelles erreurs, passées par référence
  379.      * @return le nom du template utilisé pour cette action : backup
  380.      * @todo Trouver une alternative à la commande système tar
  381.      */
  382.     function globalbackupAction(&$context&$error)
  383.     {
  384.         global $db;
  385.         if($context['lodeluser']['rights'128{
  386.             die('ERROR : You d\'ont have the rights to use this feature');
  387.         }
  388.         require_once 'backupfunc.php';
  389.         $context['importdir'$GLOBALS['importdir'];
  390.         $operation $context['operation'];
  391.         if ($context['backup']{
  392.             // il faut locker la base parce que le dump ne doit pas se faire en meme temps que quelqu'un ecrit un fichier.
  393.             $dirtotar  array();
  394.             $dirlocked tempnam('/tmp''lodeldump_')'.dir'// this allow to be sure to have a unique dir.
  395.             mkdir($dirlocked0700);
  396.             $outfile 'lodel.sql';
  397.             $fh fopen($dirlocked'/'$outfile'w');
  398.             
  399.             if (!$fh{
  400.                 die ("ERROR: unable to open a temporary file in write mode");
  401.             }
  402.             // save the main database
  403.             if (fputs($fh'DROP DATABASE IF EXISTS 'DATABASE";\nCREATE DATABASE "DATABASE";USE "DATABASE";\n"=== FALSE{
  404.                 die("ERROR: unable to write in the temporary file");
  405.             }
  406.  
  407.             $GLOBALS['currentprefix''#_MTP_';
  408.             set_time_limit(60)// pas d'effet en safe mode
  409.             require_once 'backupfunc.php';
  410.             mysql_dump(DATABASE$GLOBALS['lodelbasetables']''$fh);
  411.             
  412.             // Trouve les sites a inclure au backup.
  413.             //$errors = array();
  414.             $result $db->execute(lq('SELECT name, path FROM #_MTP_sites WHERE status > -32')) or dberror();
  415.             chdir(LODELROOT)
  416.             set_time_limit(60)// pas d'effet en safe mode
  417.             $GLOBALS['currentprefix''#_TP_';
  418.             while (!$result->EOF{
  419.                 $name $result->fields['name'];
  420.                 $sitepath $result->fields['path'];
  421.                 if (fputs($fh'DROP DATABASE IF EXISTS '$name";\nCREATE DATABASE "$name";USE "$name";\n"=== FALSE{
  422.                 die("ERROR: unable to write in the temporary file");
  423.             }
  424.                 $this->_dump($name$outfile$errors$fh);
  425.                 if (!$context['sqlonly']
  426.                     if ($sitepath == '/'$root ''// site à la racine
  427.                     else $root $name '/'}
  428.                     // liste des répertoires du site à archiver
  429.                     $sitedirs array('lodel/icons''lodel/sources''docannexe');
  430.  
  431.                     //verifie que les repertoires sont accessibles en lecture
  432.                     foreach ($sitedirs as $sitedir{
  433.                         if(is_readable($root $sitedir))$dirtotar[$root $sitedir;}
  434.                         else $bad_dirs[$root $sitedir;}
  435.                     }
  436.                      if (is_array($bad_dirs)) $error['files'implode(', '$bad_dirs)}
  437.                 }
  438.                 $result->MoveNext();
  439.             }
  440.             fclose($fh);
  441.             $db->selectDB(DATABASE)//selectionne la base principale.
  442.  
  443.             // tar les sites et ajoute la base
  444.             $archivetmp      tempnam('/tmp''lodeldump_');
  445.             $archivefilename 'lodel-'date('dmy')'.tar.gz';
  446.             // Attention ce qui suit ne fonctionnera que sous Linux
  447.             system("tar czf $archivetmp "join(' '$dirtotar)" -C $dirlocked $outfile"!== false or die ("impossible d'executer tar");
  448.             unlink($dirlocked'/'$outfile);
  449.             rmdir($dirlocked);
  450.             chdir('lodeladmin'($GLOBALS['version''-'$GLOBALS['version'''));
  451.             if (operation($operation$archivetmp$archivefilename$context)) {
  452.                 return 'backup';
  453.             }
  454.         }
  455.         
  456.         //$context['error'] = $errors;
  457.         return 'backup';
  458.     }
  459.  
  460.