Patrice Ferlet
Patrice Ferlet
Créateur de ce blog.
Publié le oct. 7, 2009 Temps de lecture: 3 min

Me suivre sur Mastodon

ZipArchive et ODT bug

Je viens enfin de rendre mon article à PHP Solutions magazine qui devrait paraître en novembre sur l’édition de document OpenOffice via PHP. Durant la rédaction, je remarque que plus aucun de mes anciens exemples ne fonctionnent, la faute à ZipArchive qui a un bug depuis quelques versions. Vous trouverez ici l’explication http://bugs.php.net/bug.php?id=48763.

J’ai donc une solution: dériver ZipArchive pour faire ce dont j’ai besoin: décompresser tout, virer l’archive, recompresser… c’est plus lent, mais ça marche.

Voici donc pour vous mes chers lecteurs, la classe ZipArchive_Proxy, présentée dans le magazine PHP Solutions du mois prochain, qui permet de recréer une archive correcte.

`

-@license GNU/GPLv3 - class ZipArchive_Proxy{ //temporary directory private $temp=''; //file to use private $file = ''; /** -Create/open zip instance * -@param string $filename - public function __construct($file = null) { if(!is_null($file)) $this->open($file); } /** -Init zip handler -@param string $filename -@return class instance - public function open($file){ $this->file = $file; //prepare temporary directory if(is_dir('/dev/shm')) { $this->temp = '/dev/shm/'.uniqid('tmp_zip_'); $this->cleanDir($this->temp); } else { $this->temp = sys_get_temp_dir().'/'.uniqid('tmp_zip_'); $this->cleanDir($this->temp); } mkdir($this->temp); //unzip archive in temporary directory $zip = new ZipArchive(); $zip->open($file); $zip->extractTo($this->temp); $zip->close(); return $this; } /** -Return content by filename from archive * -@param string $filename -@return string file_content or null - public function getFromName ($file){ $curpath = getcwd(); chdir($this->temp); if(file_exists($file)) $toReturn = file_get_contents($file); else $toReturn = false; chdir($curpath); return $toReturn; } /** -Insert content in file in archive * -@param string $filename -@param mixed content -@return class instance - public function addFromString ($file, $content){ echo "current path: ". getcwd(); $curpath = getcwd(); chdir($this->temp); file_put_contents($file, $content); chdir($curpath); } /** -Close archive -@return bool $ok - public function close(){ unlink($this->file); $zip = new ZipArchive(); $zip->open($this->file, ZIPARCHIVE::CREATE); $curpath = getcwd(); chdir($this->temp); $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('.')); foreach ($iterator as $key=>$value) { $key = preg_replace('/^\.\//','',$key); echo "Append: $key::$key\n"; $zip->addFile($key,$key ) or die ("ERROR: Could not add file: $key"); } $zip->close(); chdir($curpath); $this->cleanDir($this->temp); return true; } /** -Recursive method to clean directory - private function cleanDir($dir){ if(!is_dir($dir)) return; $handle = opendir($dir); while (($entry = readdir($handle)) !== FALSE) { if( $entry == '.' || $entry == '..') continue; //ne pas compresser les répertoires parents $path = $dir.'/'.$entry; if (is_dir($path)) $this->cleanDir($path); //supprime le répertoire trouvé else unlink ($path); //supprime le fichier } closedir($handle); //et en fin on supprime le répertoire parent rmdir($dir); } } ` Ainsi, voici comment je m'y prend pour modifier le content.xml contenu dans un odt: //ouvre l'archive odt $zip = new ZipArchive_Proxy('test.odt'); //récupère le contenu de content.xml et modifie le contenu $content = $zip->getFromName('content.xml'); $content = str_replace ('{titre}', 'Le titre du document', $content); //on remet content.xml en place $zip->addFromString('content.xml',$content); //et on ferme $zip->close(); Pour information, j'utilise si possible */dev/shm* afin de taper dans la mémoire plutôt que le disque dur, si cela est impossible alors j'utilise le répertoire temporaire proposé par le système d'exploitation. En espérant que cela vous rende service. PS: L'article en question qui paraitra dans PHP Solutions parle évidemment de [odtPHP](http://www.odtphp.com/ "wikilink"), la classe incontournable pour éditer du ODT en PHP. Je vous donne rendez-vous au prochain numéro !
comments powered by Disqus