J'avais posté une ébauche de classe permettant de manipuler des fichiers Opendocuments avec PHP il y a qq temps. Avec l'aide d'un collègue (julien Pauli), on a fait évoluer cette classe et on gère maintenant les ajouts d'images et les boucles.
Voici le code :
<?php
class odfDocException extends Exception { }
/**
* Classe de templating pour fichier odt
* requière PHP 5.2 minimum
*
* @copyright Copyright (c) 2008 Anaska (http://www.anaska.com)
* @license http://www.gnu.org/copyleft/gpl.html GPL License
* @version 1.0
*/
class odf
{
const DELIMITER_LEFT = '{';
const DELIMITER_RIGHT = '}';
private $file;
private $content;
private $tmpfile;
private $vars = array(); // Array with all the data to change
private $segments = array();
private $segmentss = array();
/**
* Constructeur de classe
*
* @param string $filename nom du fichier odt
* @throws odfDocException
*/
public function __construct($filename)
{
if (!class_exists('ZipArchive'))
{
throw new odfDocException('Zip extension not loaded - check your php settings');
}
$this->file = new ZipArchive();
if ($this->file->open($filename) !== true)
{
throw new odfDocException("Error while Opening the file '$filename' - Check your odt file");
}
$this->content = $this->file->getFromName('content.xml');
if ($this->content == NULL)
{
throw new odfDocException("Nothing to parse - check that the content.xml file is correctly formed\n");
}
$tmp = tempnam(null,md5(uniqid())).'.odt';
copy($filename,$tmp);
$this->tmpfile = $tmp;
}
/**
* Affecte une variable de template
*
* @param string $key nom de la variable dans le template
* @param string $value valeur de remplacement
* @return $this
*/
public function setVars($key, $value)
{
$this->vars[self::DELIMITER_LEFT.$key.self::DELIMITER_RIGHT] = utf8_encode($value);
return $this;
}
public function setImage($key, $value)
{
$filename = strtok(strrchr($value,'/'),'/.');
$file = substr(strrchr($value,'/'),1);
$xml = <<<IMG
<draw:frame draw:style-name="fr1" draw:name="$filename" text:anchor-type="paragraph" svg:width="5cm" svg:height="8cm" draw:z-index="0"><draw:image xlink:href="Pictures/$file" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad"/></draw:frame>
IMG;
$this->file->addFile($value,'Pictures/'.$file);
$this->setVars($key,$xml);
}
/**
* Fusionne les variables de template
*
* @param string $segment si précisé : ne fusionne que ce segment
* @return $this
*/
public function parse($segment = null)
{
if (is_null($segment))
{
$this->content = str_replace(array_keys($this->vars), array_values($this->vars), $this->content);
}else{
@$this->segmentss[$segment] .= str_replace(array_keys($this->vars), array_values($this->vars), $this->segments[$segment]);
}
return $this;
}
/**
* Rajoute le segment fusionné au document
*
* @param string $segment
* @return $this
*/
public function mergeSegment($segment)
{
$this->content = str_replace(array_values($this->segments), array_values($this->segmentss), html_entity_decode($this->content));
$reg = "/[ \t]*\[!--\s+BEGIN $segment\s+--\]\s*?\n?(\s*.*?\n?)\s*\[!--\s+END $segment\s+--\]\s*?\n?/sm";
$this->content = preg_replace($reg, '$1',$this->content);
return $this;
}
/**
* Affiche toutes les variables de templates actuelles
*
*/
public function printVars()
{
echo '<pre>';
print_r($this->vars);
echo '</pre>';
}
/**
* Affiche le fichier de contenu xml du document odt
* tel qu'il est à cet instant
*
* @return string
*/
public function __toString()
{
return $this->content;
}
/**
* Affiche les segments de boucles déclarés avec setblock
*
*/
public function printSegments()
{
echo '<pre>';
print_r($this->segments);
echo '</pre>';
}
/**
* Déclare un segment pour une utilisation en boucle
*
*
* @param string $segment
* @return $this
*/
public function setBlock($segment)
{
$reg = "/[ \t]*\[!--\s+BEGIN $segment\s+--\]\s*?\n?(\s*.*?\n?)\s*\[!--\s+END $segment\s+--\]\s*?\n?/sm";
if (preg_match($reg, html_entity_decode($this->content), $m) == 0)
{
throw new odfDocException("'$segment' segment not found in the document");
}
$this->segments[$segment] = $m[0];
return $this;
}
/**
* Sauvegarde le fichier odt sur le disque
*
* @param string $newfile si précisé: sauve dans ce fichier, sinon écrase
* le fichier actuellement ouvert
*/
public function saveToDisk($newfile = null)
{
if (!is_null($newfile) && $this->file->open($newfile, ZIPARCHIVE::CREATE) !== true)
{
throw new odfDocException('Same filename');
}
if (!$this->file->addFromString('content.xml', $this->content))
{
throw new odfDocException('Error during the file saving');
}
$this->file->close();
unset($this);
}
/**
* Exporte le contenu complet du fichier odt
*
* @return string
*/
public function export()
{
if ($this->file->open($this->tmpfile, ZIPARCHIVE::CREATE) !== true)
{
throw new odfDocException('Error');
}
if (!$this->file->addFromString('content.xml', $this->content))
{
throw new odfDocException('Error during the file exporting');
}
$this->file->close();
return readfile($this->tmpfile);
}
}
Pour y faire appel on utilise le code suivant :
<?php
$odf = new odf("modele_template.odt");
$odf->setImage('logo',"C:/Users/Administrateur/Desktop/image/sl.gif");
$odf->parse();
header('Content-type: multipart/x-zip');
header("Content-Disposition: attachment; filename=toto.odt");
echo $odf->export();
Dans le fichier OpenDocument il suffit de mettre des "tags" comme :{societe}
{societe_cp} {societe_ville}
{logo}
La classe va encore évoluer mais si vous avez des remarques sur le code, sur les fonctionnalités ou juste besoin d'infos mail me.
++
cyruss