17 include_once (
'Class.Layout.php');
18 include_once (
'Lib.FileMime.php');
28 public $encoding =
"utf-8";
30 private $saved_sections = array();
31 private $added_images = array();
32 private $removed_images = array();
37 public $content_template =
'';
38 public $style_template =
'';
39 public $meta_template =
'';
40 public $template =
'';
41 public $manifest =
'';
43 protected $arrayKeys = array();
44 protected $arrayMainKeys = array();
45 protected $rkeyxml = array();
50 protected $errors = array();
62 public function __construct($caneva = "", Action & $action = null, Doc & $doc = null)
64 $this->LOG = new Log("", "Layout");
67 $this->action = & $action;
68 $this->generation = "";
72 if ((!file_exists($file)) && ($file[0] != '/')) {
73 $file = DEFAULT_PUBDIR . "/$file"; // try absolute
76 if (file_exists($file)) {
77 if (filesize($file) > 0) {
78 $this->odf2content($file);
83 $this->template = "file [$caneva] not exists";
92 protected function innerXML(DOMnode & $node)
94 if (!$node) return false;
95 $document = $node->ownerDocument;
96 $nodeAsString = $document->saveXML($node);
97 preg_match('!<.*?>(.*)</.*?>!s', $nodeAsString, $match);
108 protected function parseListInBlock($block, $aid, $vkey)
110 deprecatedFunction();
111 $head = '<?xml version="1.0" encoding="UTF-8"?>
112 <office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" office:version="1.0">';
113 $foot = '</office:document-content>';
114 $domblock = new DOMDocument();
117 $block = trim($block);
118 if (substr($block, 0, 2) == '</') {
120 $firsttag = strpos($block, '>');
121 $lasttag = strrpos($block, '<');
122 $frag1 = substr($block, 0, $firsttag + 1);
123 $frag2 = substr($block, $lasttag);
124 $block = substr($block, $firsttag + 1, $lasttag - strlen($block));
125 // print("\nfrag1:$frag1 $lasttag rag2:$frag2\n");
126 // print("\n====================\n");
127 //print("\nNB:[$block]\n");
131 if (!$domblock->loadXML($head . $block . $foot)) {
132 print "\n=============\n";
133 print $head . trim($block) . $foot;
137 $lists = $domblock->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "list");
138 foreach ($lists as $list) {
142 $items = $list->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "list-item");
143 if ($items->length > 0) {
144 $item = $items->item(0);
146 if (preg_match('/\[V_[A-Z0-9_-]+\]/', $item->textContent, $reg)) {
148 // print "serack key : [$skey] [$aid] [$vkey]";
150 // $vkey=$this->rkey[$key];
151 $tvkey = explode('<text:tab/>', $vkey);
153 foreach ($tvkey as $key) {
154 $clone = $item->cloneNode(true);
155 $item->parentNode->appendChild($clone);
156 $this->replaceNodeText($clone, $reg[0], $key);
158 $item->parentNode->removeChild($item);
163 return $frag1 . $this->innerXML($domblock->firstChild) . $frag2;
164 //return $frag1 . $domblock->saveXML($domblock->firstChild->firstChild) . $frag2;
168 protected function getAncestor(&$node, $type)
171 while (!empty($mynode->parentNode)) {
172 $mynode = $mynode->parentNode;
173 if ($mynode->tagName == $type) {
184 private function getNodeDepth(DOMNode & $node)
188 while (!empty($mynode->parentNode)) {
190 $mynode = $mynode->parentNode;
195 protected function ParseBlock(&$out = null)
197 $this->template = preg_replace_callback('/(?m)\[BLOCK\s*([^\]]*)\](.*?)\[ENDBLOCK\s*\\1\]/s', function ($matches)
200 return $this->SetBlock($matches[1], $matches[2]);
212 protected function TestIf($name, $block, $not = false, $levelPath = null)
217 $val = $this->getArrayKeyValue($name, $levelPath);
218 if (is_array($val)) $val = null; // it is not the good level
219 if ($val !== null) $cond = ($val == true);
221 if (isset($this->rif[$name]) && $this->rif[$name] !== null) $cond = ($this->rif[$name] == true);
222 elseif (isset($this->rkey[$name]) && $this->rkey[$name] !== null) $cond = ($this->rkey[$name] == true);
224 if ($cond !== null) {
225 if ($cond xor $not) {
230 if ($not) $out = "[IFNOT $name]" . $block . "[ENDIF $name]";
231 else $out = "[IF $name]" . $block . "[ENDIF $name]";
233 if ($this->strip == 'Y') $out = str_replace("\\\"", "\"", $out);
241 protected function ParseIf(&$out = null)
245 //header('Content-type: text/xml; charset=utf-8');print $this->template;exit;
246 while ($templateori != $this->template && ($level < 10)) {
247 $templateori = $this->template;
248 $this->template = preg_replace_callback('/(?m)\[IF(NOT)?\s*([^\]]*)\](.*?)\[ENDIF\s*\\2\]/s', function ($matches)
250 return $this->TestIf($matches[2], $matches[3], $matches[1]);
253 $level++; // to prevent infinite loop
256 $this->fixSpanIf($this->template);
257 // header('Content-type: text/xml; charset=utf-8');print $this->template;exit;
258 // restore user fields
259 if (!$this->dom->loadXML($this->template)) {
260 print $this->template;
261 throw new Dcp\Exception("Error in parse condition");
263 //header('Content-type: text/xml; charset=utf-8');print $this->dom->saveXML();exit;
264 $lists = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "user-field-get");
266 $domElemsToRemove = array();
267 $domElemsToClean = array();
268 foreach ($lists as $list) {
272 if (!$list->getAttribute('office:string-value')) {
273 if ($list->textContent == '') {
274 $domElemsToRemove[] = $list;
276 //$list->setAttribute("text:name",'');
277 $domElemsToClean[] = $list;
284 foreach ($domElemsToRemove as $domElement) {
285 $domElement->parentNode->removeChild($domElement);
288 $this->template = $this->dom->saveXML();
293 protected function hideUserFieldSet()
295 //$this->dom->loadXML($this->template);
296 $lists = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "user-field-decl");
297 foreach ($lists as $list) {
301 $list->setAttribute('office:string-value', str_replace('[', '-CROCHET-', $list->getAttribute('office:string-value')));
302 $list->setAttribute('text:name', str_replace('[', '-CROCHET-', $list->getAttribute('text:name')));
304 // detect user field to force it into a span
305 $lists = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "user-field-get");
309 foreach ($lists as $list) {
311 * @var DOMElement $lp
313 $lp = $list->parentNode;
314 if ($lp->tagName != 'text:span') {
315 $nt = $this->dom->createElement("text:span");
316 $lp->insertBefore($nt, $list);
317 $nt->appendChild($list);
320 // header('Content-type: text/xml; charset=utf-8');print $this->dom->saveXML();exit;
321 $lists = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "user-field-get");
322 $userFields = array();
323 // set the key of fields to up
324 foreach ($lists as $list) {
325 $textContent = $list->nodeValue;
326 if (substr($textContent, 0, 1) == '[') {
327 $userFields[] = $list;
328 $nt = $this->dom->createTextNode($textContent);
329 $list->parentNode->insertBefore($nt, $list);
332 foreach ($userFields as $list) {
333 $list->parentNode->removeChild($list);
336 $this->template = $this->dom->saveXML();
344 protected function XmlLoader($strXml)
346 $this->dom = new \Dcp\Utils\XDOMDocument();
347 $this->dom->loadXML($strXml);
353 protected function restoreUserFieldSet()
356 $this->XmlLoader(\Dcp\Utils\htmlclean::cleanXMLUTF8($this->template));
358 catch(\Dcp\Utils\XDOMDocumentException $e) {
359 $outfile = uniqid(getTmpDir() . "/oooKo") . '.xml';
360 $this->addError("LAY0004", $outfile);
361 file_put_contents($outfile, $this->template);
362 $this->exitError($outfile);
364 /* if (!$this->dom->loadXML($this->template)) {
366 $xmlErr=libxml_get_last_error();
367 if (is_array($xmlErr)) $err=sprintf("XML error line %d, column %d,: %s",$xmlErr["line"],$xmlErr["column"], $xmlErr["message"]);
370 $outfile = uniqid(getTmpDir() . "/oooKo") . '.xml';
371 $this->addError("LAY0004", $outfile);
372 file_put_contents($outfile, $this->template);
373 $this->exitError($outfile);
376 $lists = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "user-field-decl");
378 foreach ($lists as $list) {
382 $list->setAttribute('office:string-value', str_replace('-CROCHET-', '[', $list->getAttribute('office:string-value')));
383 $list->setAttribute('text:name', str_replace('-CROCHET-', '[', $list->getAttribute('text:name')));
385 $this->template = $this->dom->saveXML();
394 protected function SetBlock($name, $block)
396 deprecatedFunction();
397 if ($this->strip == 'Y') {
398 // $block = StripSlashes($block);
399 $block = str_replace("\\\"", "\"", $block);
402 if (isset($this->data) && isset($this->data["$name"]) && is_array($this->data["$name"])) {
403 foreach ($this->data["$name"] as $k => $v) {
406 foreach ($this->corresp["$name"] as $k2 => $v2) {
408 if (strstr($v[$v2], '<text:tab/>')) {
410 $loc = $this->parseListInBlock($loc, $k2, $v[$v2]);
411 } elseif ((!is_object($v[$v2])) && (!is_array($v[$v2]))) $loc = str_replace($k2, $v[$v2], $loc);
414 // $this->ParseIf($loc);
418 // $this->ParseBlock($out);
426 protected function ParseZone(&$out)
428 deprecatedFunction();
430 $out = preg_replace_callback('/\[ZONE\s*([^:]*):([^\]]*)\]/', function ($matches)
432 return $this->execute($matches[1], $matches[2]);
440 protected function ParseKey(&$out = null)
442 if (isset($this->rkey)) {
443 $this->template = str_replace($this->pkey, $this->rkey, $this->template);
452 protected function odf2content($odtfile)
454 if (!file_exists($odtfile)) {
455 $this->addError("LAY0001", $odtfile);
458 $this->cibledir = uniqid(getTmpDir() . "/odf");
460 $cmd = sprintf("unzip %s -d %s 2>&1", escapeshellarg($odtfile) , escapeshellarg($this->cibledir));
461 if (exec($cmd, $out, $ret) === false) {
462 $err = error_get_last();
463 if (isset($err['message'])) {
464 $err = $err['message'];
466 $err = 'unknown PHP error...';
468 throw new Dcp\Core\Exception("LAY0006", $err);
471 $err = join("\n", $out);
472 throw new Dcp\Core\Exception("LAY0007", $odtfile, $err);
475 $contentxml = $this->cibledir . "/content.xml";
476 if (file_exists($contentxml)) {
477 $this->content_template = file_get_contents($contentxml);
480 $contentxml = $this->cibledir . "/META-INF/manifest.xml";
481 if (file_exists($contentxml)) {
482 $this->manifest = file_get_contents($contentxml);
485 $contentxml = $this->cibledir . "/styles.xml";
486 if (file_exists($contentxml)) {
487 $this->style_template = file_get_contents($contentxml);
490 $contentxml = $this->cibledir . "/meta.xml";
491 if (file_exists($contentxml)) {
492 $this->meta_template = file_get_contents($contentxml);
502 protected function content2odf($odsfile)
504 if (file_exists($odsfile)) return "file $odsfile must not be present";
506 $contentxml = $this->cibledir . "/content.xml";
508 $this->content_template = preg_replace("!</?text:bookmark-(start|end)([^>]*)>!s", "", $this->content_template);
509 //$this->content_template=preg_replace("!<text:section>(\s*<text:p/>)+!s","<text:section>",$this->content_template);
510 //$this->content_template=preg_replace("!(<text:p/>\s*)+</text:section>!s","</text:section>",$this->content_template);
511 //$this->content_template=preg_replace("/<text:span([^>]*)>\s*<text:section>/s","<text:section>",$this->content_template);
512 //$this->content_template=preg_replace("/<\/text:section>\s*<\/text:span>/s","</text:section>",$this->content_template);
513 //$this->content_template=preg_replace("/<text:p([^>]*)>\s*<text:section([^>]*)>/s","<text:section\\2>",$this->content_template);
514 //$this->content_template=preg_replace("/<\/text:section>\s*<\/text:p>/s","</text:section>",$this->content_template);
515 //$this->content_template=preg_replace("/<text:p ([^>]*)>\s*<text:([^\/]*)\/>\s*<text:section[^>]*>/s","<text:section><text:\\2/>",$this->content_template);
516 //$this->content_template=preg_replace("/<\/text:section>\s*<text:([^\/]*)\/>\s*<\/text:p>/s","</text:section><text:\\1/>",$this->content_template);
517 //$this->content_template=preg_replace("/<table:table-cell ([^>]*)>\s*<text:section>/s","<table:table-cell \\1>",$this->content_template);
518 //$this->content_template=preg_replace("/<\/text:section>\s*<\/table:table-cell>/s","</table:table-cell>",$this->content_template);
519 $this->content_template = str_replace("<text:line-break/>", "<text:line-break/>", $this->content_template);
520 // header('Content-type: text/xml; charset=utf-8');print($this->content_template);exit;
521 file_put_contents($contentxml, $this->content_template);
523 $contentxml = $this->cibledir . "/META-INF/manifest.xml";
524 file_put_contents($contentxml, $this->manifest);
526 $contentxml = $this->cibledir . "/styles.xml";
527 file_put_contents($contentxml, $this->style_template);
529 $contentxml = $this->cibledir . "/meta.xml";
530 file_put_contents($contentxml, $this->meta_template);
532 $cmd = sprintf("cd %s;zip -q -Z store -X %s mimetype ;zip -q -r -X -u %s * && /bin/rm -fr %s", escapeshellarg($this->cibledir) , escapeshellarg($odsfile) , escapeshellarg($odsfile) , escapeshellarg($this->cibledir));
535 //rmdir($this->cibledir);
539 protected function execute($appname, $actionargn)
542 if ($this->action == "") return ("Layout not used in a core environment");
543 // analyse action & its args
544 $actionargn = str_replace(":", "--", $actionargn); //For buggy function parse_url in PHP 4.3.1
545 $acturl = parse_url($actionargn);
546 $actionname = $acturl["path"];
549 $OLD_ZONE_ARGS = $ZONE_ARGS;
550 if (isset($acturl["query"])) {
551 $acturl["query"] = str_replace("--", ":", $acturl["query"]); //For buggy function parse_url in PHP 4.3.1
552 $zargs = explode("&", $acturl["query"]);
553 foreach ($zargs as $k => $v) {
554 if (preg_match("/([^=]*)=(.*)/", $v, $regs)) {
555 // memo zone args for next action execute
556 $ZONE_ARGS[$regs[1]] = urldecode($regs[2]);
561 if ($appname != $this->action->parent->name) {
562 $appl = new Application();
563 $appl->Set($appname, $this->action->parent);
565 $appl = & $this->action->parent;
568 if (($actionname != $this->action->name) || ($OLD_ZONE_ARGS != $ZONE_ARGS)) {
571 if ($act->Exists($actionname, $appl->id)) {
573 $act->Set($actionname, $appl);
575 // it's a no-action zone (no ACL, cannot be call directly by URL)
576 $act->name = $actionname;
578 $res = $act->CompleteSet($appl);
581 $res = $act->execute();
583 $ZONE_ARGS = $OLD_ZONE_ARGS; // restore old zone args
586 return ("Fatal loop : $actionname is called in $actionname");
594 public function set($tag, $val)
596 if (!isUTF8($val)) $val = utf8_encode($val);
597 if (!$this->isXml($val)) {
598 $this->pkey[$tag] = "[$tag]";
599 if (is_array($val)) $val = implode('<text:tab/>', $val);
600 $this->rkey[$tag] = $val;
603 $this->rkeyxml[$tag] = $val;
611 public function eSet($tag, $val)
613 $this->set($tag, $this->xmlEntities($val));
620 static public function xmlEntities($s)
622 return str_replace(array(
637 protected function isXML($val)
640 //return preg_match("/<text:/", $val);
648 public function get($tag)
650 if (isset($this->rkey)) return $this->rkey[$tag];
657 protected function ParseText(&$out = null)
659 $this->template = preg_replace_callback('/\[TEXT(\([^\)]*\))?:([^\]]*)\]/', function ($matches)
662 if ($s == "") return $s;
666 return ___($s, trim($matches[1], '()'));
674 protected function updateManifest()
676 $manifest = new DomDocument();
677 $manifest->loadXML($this->manifest);
679 * @var DOMDocument $manifest_root
681 $manifest_root = null;
682 $items = $manifest->childNodes;
686 foreach ($items as $item) {
687 if ($item->nodeName == 'manifest:manifest') {
688 $manifest_root = $item;
692 if ($manifest_root === null) {
696 $items = $manifest->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0", "file-entry");
697 foreach ($items as $aItem) {
701 $type = $aItem->getAttribute("manifest:media-type");
702 if (substr($type, 0, 6) == "image/") {
703 $file = $aItem->getAttribute("manifest:full-path");
704 if (in_array($file, $this->removed_images)) {
705 $aItem->parentNode->removeChild($aItem);
709 foreach ($this->added_images as $image) {
710 $mime = getSysMimeFile($this->cibledir . '/' . $image);
711 $new = $manifest->createElement("manifest:file-entry");
712 $new->setAttribute("manifest:media-type", $mime);
713 $new->setAttribute("manifest:full-path", $image);
714 $manifest_root->appendChild($new);
717 $this->manifest = $manifest->saveXML();
723 protected function parseHtmlDraw()
725 $draws = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", "frame");
726 foreach ($draws as $draw) {
730 $name = trim($draw->getAttribute('draw:name'));
731 if ($name === "htmlgraphic") {
732 $this->setHtmlDraw($draw);
741 protected function setHtmlDraw(DOMElement & $draw)
744 $imgs = $draw->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", "image");
746 if ($imgs->length > 0) {
750 $img = $imgs->item(0);
752 $href = $img->getAttribute('xlink:href');
753 $fileInfo = new VaultFileInfo();
755 if (preg_match('/^file\/([^\/]+)\/([0-9]+)/', $href, $reg)) {
758 $docimg = new_doc('', $docid, true);
759 if ($docimg->isAlive()) {
760 $err = $docimg->control("view");
762 $fileInfo = \Dcp\VaultManager::getFileInfo($vid);
764 $fileInfo->path = "Images/erreur.png";
767 $fileInfo->path = "Images/noimage.png";
769 } elseif (preg_match('/action=EXPORTFILE.*&docid=([^&]+).*&attrid=([a-z0_9_-]+).*index=([0-9-]+)/i', $href, $reg)) {
773 $index = intval($reg[3]);
775 $docimg = new_doc('', $docid, true);
776 if ($docimg->isAlive()) {
777 $err = $docimg->control("view");
780 $fileValue = $docimg->getRawValue($attrid);
782 $fileValue = $docimg->getMultipleRawValues($attrid, '', $index);
784 $fileInfo = (Object)$docimg->getFileInfo($fileValue);
786 $fileInfo->path = "Images/erreur.png";
789 $fileInfo->path = "Images/noimage.png";
792 if ($fileInfo->path) {
793 $href = sprintf('Pictures/dcp%s', basename($fileInfo->path));
794 $img->setAttribute('xlink:href', $href);
795 $this->added_images[] = $href;
796 if (!is_dir($this->cibledir . '/Pictures')) {
797 mkdir($this->cibledir . '/Pictures');
800 if (!copy($fileInfo->path, $this->cibledir . '/' . $href)) {
801 $err = "setHtmlDraw::file copy fail";
803 // print_r2($this->dom->saveXML());exit;
816 protected function setDraw(DOMElement & $draw, $name, $file)
818 if (strpos($file, '<text:tab') !== false) {
819 return 'muliple values : fail';
821 $imgs = $draw->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", "image");
823 if ($imgs->length > 0) {
827 $img = $imgs->item(0);
828 if (file_exists($file)) {
829 $draw->setAttribute('draw:name', substr($name, 2) . ' ' . uniqid() . mt_rand(1000, 9999));
830 $href = 'Pictures/dcp' . uniqid() . mt_rand(1000000, 9999999) . substr($img->getAttribute('xlink:href') , -9);
831 $img->setAttribute('xlink:href', $href);
832 $this->added_images[] = $href;
833 if (!copy($file, $this->cibledir . '/' . $href)) {
837 if ($err == "") { // need to respect image proportion
838 $width = $draw->getAttribute('svg:width');
839 $size = getimagesize($file);
841 if (preg_match('/[0-9\.]+(.*)$/', $width, $reg)) $unit = $reg[1];
842 $height = sprintf("%.03f%s", (doubleval($width) / $size[0]) * $size[1], $unit);
843 $draw->setAttribute('svg:height', $height);
852 protected function parseDraw()
854 $draws = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", "frame");
856 foreach ($draws as $draw) {
861 $name = trim($draw->getAttribute('draw:name'));
862 if (preg_match('/\[(V_[A-Z0-9_-]+)\]/', $name, $reg)) {
864 if (isset($this->rkey[$key])) {
865 $this->setDraw($draw, $key, $this->rkey[$key]);
874 protected function removeXmlId(&$objNode)
876 $objNodeListNested = $objNode->childNodes;
877 foreach ($objNodeListNested as $objNodeNested) {
881 if ($objNodeNested->nodeType == XML_ELEMENT_NODE) {
882 $objNodeNested->removeAttribute("xml:id");
883 $this->removeXmlId($objNodeNested);
894 protected function replaceNodeText(DOMNode & $objNode, $strOldContent, $strNewContent)
896 if ($strNewContent === null) return;
897 if (is_array($strNewContent)) {
898 throw new Dcp\Exception("node replacement must be a string : array found");
900 $objNodeListNested = & $objNode->childNodes;
901 foreach ($objNodeListNested as $objNodeNested) {
905 if ($objNodeNested->nodeType == XML_TEXT_NODE) {
906 if ($objNodeNested->nodeValue != "") {
907 if (strpos($strNewContent, '<text:p>') !== false) {
908 $strNewContent = str_replace('<', '--Lower.Than--', $strNewContent);
909 $strNewContent = str_replace('>', '--Greater.Than--', $strNewContent);
910 $strNewContent = htmlspecialchars_decode($strNewContent);
912 $objNodeNested->nodeValue = str_replace($strOldContent, $strNewContent, $objNodeNested->nodeValue);
914 } elseif ($objNodeNested->nodeType == XML_ELEMENT_NODE) {
915 if ($objNodeNested->nodeName == 'text:text-input') {
916 $name = $objNodeNested->getAttribute('text:description');
917 if ($name == $strOldContent) {
918 $this->setInputField($objNodeNested, substr($name, 1, -1) , $strNewContent);
920 } elseif ($objNodeNested->nodeName == 'text:drop-down') {
921 $name = $objNodeNested->getAttribute('text:name');
922 if ($name == $strOldContent) {
923 $this->setDropDownField($objNodeNested, substr($name, 1, -1) , $strNewContent);
925 } elseif ($objNodeNested->nodeName == 'draw:frame') {
926 $name = $objNodeNested->getAttribute('draw:name');
927 if (substr($name, 0, strlen($strOldContent)) == $strOldContent) {
928 $this->setDraw($objNodeNested, substr($strOldContent, 1, -1) , $strNewContent);
931 $this->replaceNodeText($objNodeNested, $strOldContent, $strNewContent);
939 protected function parseListItem()
942 $lists = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "list");
943 foreach ($lists as $list) {
947 $items = $list->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "list-item");
948 if ($items->length > 0) {
949 $item = $items->item(0);
950 $skey = implode('|', array_keys($this->arrayMainKeys));
951 if (preg_match_all("/\[($skey)\]/", $this->innerXML($list) , $reg)) {
955 foreach ($reg0 as $k => $v) {
956 $key = substr(trim($v) , 1, -1);
957 $tvkey[$key] = $this->arrayMainKeys[$key];
958 $maxk = max(count($tvkey[$key]) , $maxk);
961 for ($i = 0; $i < $maxk; $i++) {
962 $clone = $item->cloneNode(true);
963 $item->parentNode->appendChild($clone);
964 foreach ($tvkey as $kk => $key) {
965 $this->replaceNodeText($clone, "[$kk]", $key[$i]);
969 $item->parentNode->removeChild($item);
976 private function _section_cmp($k1, $k2)
978 if ($k2 > $k1) return 1;
979 else if ($k2 < $k1) return -1;
985 protected function parseSection()
988 $lists = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "section");
991 // need to inpect section with max depth before to avoid et repeat top level section
996 foreach ($lists as $aSection) {
997 $depth = $this->getNodeDepth($aSection);
998 $section[($depth * 200) + $ks] = $aSection;
1002 uksort($section, array(
1006 foreach ($section as $aSection) {
1010 $skey = implode('|', array_keys($this->arrayMainKeys));
1011 if (preg_match_all("/\\[($skey)\\]/", $this->innerXML($aSection) , $reg)) {
1015 foreach ($reg0 as $k => $v) {
1016 $key = substr(trim($v) , 1, -1);
1017 $tvkey[$key] = $this->arrayMainKeys[$key];
1018 $maxk = max(count($tvkey[$key]) , $maxk);
1021 for ($i = 0; $i < $maxk; $i++) {
1023 * @var DOMElement $clone
1025 $clone = $aSection->cloneNode(true);
1026 $aSection->parentNode->insertBefore($clone, $aSection);
1027 foreach ($tvkey as $kk => $key) {
1028 $this->replaceNodeText($clone, "[$kk]", $key[$i]);
1030 $this->replaceRowIf($clone, array(
1033 $this->replaceRowNode($clone, array(
1035 )); // inspect sub levels
1039 $aSection->parentNode->removeChild($aSection);
1051 protected function setInputField(DomElement & $node, $name, $value)
1053 if (strpos($value, '<text:tab') !== false) {
1054 return 'muliple values : fail';
1057 $node->nodeValue = $value;
1058 $node->setAttribute("text:description", '[PP' . $name . 'PP]');
1069 protected function setDropDownField(DOMElement & $node, $name, $value)
1071 if (strpos($value, '<text:tab') !== false) {
1072 return 'muliple values : fail';
1074 $this->removeAllChilds($node);
1075 $node->setAttribute("text:name", '[PP' . $name . 'PP]');
1076 $value = str_replace(array(
1085 $item = new DOMElement('text:label', '', 'urn:oasis:names:tc:opendocument:xmlns:text:1.0');
1086 $item = $node->appendChild($item);
1090 $item->setAttribute("text:current-selected", 'true');
1091 $item->setAttribute("text:value", $value);
1092 $node->appendChild(new DOMText($value));
1100 protected function removeAllChilds(DOMNode & $objNode)
1102 $objNodeListNested = $objNode->childNodes;
1103 $objNode->nodeValue = '';
1104 if (!empty($objNodeListNested) && $objNodeListNested->length > 0) {
1105 foreach ($objNodeListNested as $objNodeNested) {
1106 $objNode->removeChild($objNodeNested);
1113 protected function parseTableRow()
1116 $lists = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0", "table-row");
1117 $validRow = array();
1119 $skey = implode('|', array_keys($this->arrayMainKeys));
1123 foreach ($lists as $rowItem) {
1124 if (preg_match("/\[($skey)\]/", $this->innerXML($rowItem) , $reg)) {
1125 $validRow[] = $rowItem;
1128 foreach ($validRow as $rowItem) {
1132 if (preg_match_all("/\[($skey)\]/", $this->innerXML($rowItem) , $reg)) {
1135 $maxk = 0; // search values which has the greatest number of values
1136 foreach ($reg0 as $k => $v) {
1137 $key = substr(trim($v) , 1, -1);
1138 $tvkey[$key] = $this->arrayMainKeys[$key];
1139 $maxk = max(count($tvkey[$key]) , $maxk);
1142 for ($i = 0; $i < $maxk; $i++) {
1144 * @var DOMElement $clone
1146 $clone = $rowItem->cloneNode(true);
1148 $rowItem->parentNode->insertBefore($clone, $rowItem);
1149 foreach ($tvkey as $kk => $key) {
1150 $this->replaceNodeText($clone, "[$kk]", $key[$i]);
1152 $this->replaceRowIf($clone, array(
1155 $this->replaceRowNode($clone, array(
1157 )); // inspect sub levels
1162 $rowItem->parentNode->removeChild($rowItem);
1172 private static function getArrayDepth($v)
1175 while (is_array($v)) {
1188 protected function getArrayKeyValue($key, array $levelPath)
1192 if (count($levelPath) == 1) {
1193 if (isset($this->arrayMainKeys[$key])) {
1194 $index = current($levelPath);
1195 return $this->arrayMainKeys[$key][$index];
1198 if (!isset($this->arrayKeys[$key])) return null;
1200 $value = $this->arrayKeys[$key];
1201 foreach ($levelPath as $index) {
1202 $value = $value[$index];
1211 private function fixSpanIf(&$s)
1213 $s = preg_replace('/<text:span ([^>]*)>\s*<\/text:p>/s', "</text:p>", $s);
1214 $s = preg_replace('/<text:p ([^>]*)>\s*<\/text:span>/s', "<text:p \\1>", $s);
1222 protected function replaceRowIf(DOMNode & $row, array $levelPath)
1225 $this->removeXmlId($row);
1227 $inner = $row->ownerDocument->saveXML($row);
1229 $head = '<?xml version="1.0" encoding="UTF-8"?><office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" office:version="1.0">';
1230 $foot = '</office:document-content>';
1233 while ($level < 10) {
1234 $replacement = preg_replace_callback('/(?m)\[IF(NOT)?\s*([^\]]*)\](.*?)\[ENDIF\s*\\2\]/s', function ($matches) use ($levelPath)
1236 return $this->TestIf($matches[2], $matches[3], $matches[1], $levelPath);
1239 if ($inner == $replacement) break;
1240 else $inner = $replacement;
1243 $this->fixSpanIf($replacement);
1245 $dxml = new DomDocument();
1247 $dxml->loadXML($head . $replacement . $foot);
1248 $ot = $dxml->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0", "document-content");
1249 if ($ot->length > 0) {
1250 $newnode = $this->dom->importNode($ot->item(0)->firstChild, true);
1252 // first delete inside
1253 while ($row->firstChild) {
1254 $row->removeChild($row->firstChild);
1257 while ($newnode->firstChild) {
1258 $row->appendChild($newnode->firstChild);
1266 protected function replaceRowNode(DOMElement & $row, array $levelPath)
1268 // Inspect sub tables, rows
1269 $this->replaceRowSomething($row, $levelPath, "table", "table-row", true);
1270 // Inspect list in sub tables
1271 $this->replaceRowSomething($row, $levelPath, "text", "list-item", false);
1272 // Inspect list in subsection
1273 $this->replaceRowSomething($row, $levelPath, "text", "section", true);
1284 protected function replaceRowSomething(DOMElement & $row, array $levelPath, $ns, $tag, $recursive)
1286 if (count($this->arrayKeys) == 0) return; // nothing to do
1288 $subIndex = count($levelPath);
1289 foreach ($this->arrayKeys as $k => $v) {
1290 if ($this->getArrayDepth($v) == $subIndex) $keys[] = $k;
1293 $rowList = $row->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:$ns:1.0", $tag);
1294 if ($rowList->length > 0) {
1295 $skey = implode('|', $keys);
1296 /* print "<h1>$tag</h1>";
1297 print_r2($levelPath);
1300 foreach ($rowList as $item) {
1304 if (preg_match_all("/\\[($skey)\\]/", $this->innerXML($item) , $reg)) {
1307 foreach ($reg[1] as $k => $v) {
1308 $vkey = $this->getArrayKeyValue($v, $levelPath);
1310 $maxk = max(count($tvkey[$v]) , $maxk);
1314 for ($i = 0; $i < $maxk; $i++) {
1316 * @var DOMElement $clone
1318 $clone = $item->cloneNode(true);
1319 $item->parentNode->insertBefore($clone, $item);
1320 foreach ($tvkey as $kk => $key) {
1321 $this->replaceNodeText($clone, "[$kk]", $key[$i]);
1323 $newPath = array_merge($levelPath, array(
1326 $this->replaceRowIf($clone, $newPath);
1327 //if ($recursive) $this->replaceRowSomething($clone,$newPath,$ns,$tag,$recursive);
1328 if ($recursive) $this->replaceRowNode($clone, $newPath);
1331 $item->parentNode->removeChild($item);
1339 protected function parseInput()
1341 $lists = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "text-input");
1342 foreach ($lists as $list) {
1346 $name = $list->getAttribute("text:description");
1347 if (preg_match('/\[(V_[A-Z0-9_-]+)\]/', $name, $reg)) {
1349 if (isset($this->rkey[$key])) {
1350 $this->setInputField($list, $key, $this->rkey[$key]);
1358 protected function parseDropDown()
1360 $lists = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "drop-down");
1361 foreach ($lists as $list) {
1365 $name = $list->getAttribute("text:name");
1366 if (preg_match('/\[(V_[A-Z0-9_-]+)\]/', $name, $reg)) {
1368 if (isset($this->rkey[$key])) {
1369 $this->setDropDownField($list, $key, $this->rkey[$key]);
1377 protected function restoreProtectedValues()
1379 $this->template = preg_replace('/\[PP(V_[A-Z0-9_]+)PP\]/s', '[$1]', $this->template);
1380 $this->template = str_replace('--Lower.Than--', '<', $this->template);
1381 $this->template = str_replace('--Greater.Than--', '>', $this->template);
1386 protected function parseTplSection()
1388 $this->saved_sections = array();
1389 // remove old generated sections
1390 $lists = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "section");
1391 foreach ($lists as $list) {
1395 $name = $list->getAttribute("text:name");
1396 if (substr($name, 0, 5) == '_tpl_') {
1397 $list->parentNode->removeChild($list);
1400 // clone sections and generate them again
1401 $lists = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "section");
1402 foreach ($lists as $list) {
1406 $name = $list->getAttribute("text:name");
1407 if (substr($name, 0, 4) == 'tpl_') {
1408 $this->removeXmlId($list);
1409 // restore original style name of first head
1410 $heads = $list->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "h");
1411 if ($heads->length > 0) {
1415 $firsthead = $heads->item(0);
1416 $firsthead->setAttribute("text:style-name", trim($firsthead->getAttribute('text:style-name') , '_'));
1418 $this->saved_sections[$name] = $list->cloneNode(true);
1422 $originSection = $this->saved_sections[$name];
1423 $list->setAttribute("text:name", '_' . $name);
1424 $list->setAttribute("text:protected", 'true');
1425 $list->setAttribute("text:display", 'true');
1426 // // special treatment to have correct chapter numeration search first header
1427 $heads = $originSection->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "h");
1428 if ($heads->length > 0) {
1432 $firsthead = $heads->item(0);
1433 $styleName = $firsthead->getAttribute("text:style-name");
1435 $styleName = trim($styleName, '_');
1436 $styles = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:style:1.0", "style");
1437 //addLogMsg(array("style"=>$styleName,"length"=>$styles->length));
1438 $tStyleName = array();
1439 foreach ($styles as $style) {
1443 $aStyleName = $style->getAttribute("style:name");
1444 $tStyleName[] = $aStyleName;
1445 if ($aStyleName == $styleName) {
1446 $copyName = '_' . $styleName . '_';
1447 if (!(in_array($copyName, $tStyleName))) {
1451 $cloneStyle = $style->cloneNode(true);
1452 $cloneStyle->setAttribute("style:name", $copyName);
1453 $cloneStyle->setAttribute("style:list-style-name", ""); // unset numeration chapter
1454 $style->parentNode->insertBefore($cloneStyle, $style);
1456 $firsthead->setAttribute("text:style-name", $copyName);
1468 protected function restoreSection()
1471 $inserts_to_do = array();
1473 $lists = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "section");
1474 foreach ($lists as $list) {
1478 $name = $list->getAttribute("text:name");
1479 if (substr($name, 0, 5) == '_tpl_' && isset($this->saved_sections[substr($name, 1) ])) {
1480 $node = $this->dom->importNode($this->saved_sections[substr($name, 1) ], true);
1481 $inserts_to_do[] = array(
1487 foreach ($inserts_to_do as $insert_to_do) {
1488 //$node = $insert_to_do[1]->parentNode->insertBefore($insert_to_do[0], $insert_to_do[1]);
1490 if ($insert_to_do[1]->nextSibling) {
1492 $node = $insert_to_do[1]->parentNode->insertBefore($insert_to_do[0], $insert_to_do[1]->nextSibling);
1495 $node = $insert_to_do[1]->parentNode->appenChild($insert_to_do[0]);
1500 $node->setAttribute("text:protected", 'true');
1501 $node->setAttribute("text:display", 'none');
1509 public function setColumn($key, array $t)
1513 foreach ($t as $v) $ti[$k++] = $v; // delete associative keys
1514 if (is_array(current($t))) $this->setArray($key, $ti);
1515 else $this->arrayMainKeys[$key] = $ti;
1516 //else $this->set($key,implode('<text:tab/>',$t));
1520 protected function setArray($key, array $t)
1522 if (!$key) throw new Dcp\Exception('Key must not be empty');
1523 $this->arrayKeys[$key] = $t;
1530 public function setBlockData($p_nom_block, $data = NULL)
1532 deprecatedFunction();
1533 if ($p_nom_block != "") {
1534 if ($data != null && $this->encoding == "utf-8") {
1535 if (is_array($data)) {
1536 foreach ($data as $k => $v) {
1537 foreach ($v as $kk => $vk) {
1539 $data[$k][$kk] = utf8_encode($vk);
1544 if (!isUTF8($data)) $data = utf8_encode($data);
1547 $this->data[$p_nom_block] = $data;
1548 if (is_array($data)) {
1550 $elem = current($data);
1551 if (isset($elem) && is_array($elem)) {
1553 foreach ($elem as $k => $v) {
1554 if (!isset($this->corresp["$p_nom_block"]["[$k]"])) {
1555 $this->setBlockCorresp($p_nom_block, $k);
1561 $this->setrepeatable($data);
1565 * set array to be use in repeat set like table, list-item or section
1566 * @param array $data the arry to set
1568 public function setrepeatable(array $data)
1572 if (is_array($data)) {
1573 foreach ($data as $k => $v) {
1574 foreach ($v as $ki => $vi) {
1581 foreach ($t as $k => $v) {
1582 if (count($v) > $max) $max = count($v);
1584 foreach ($t as $k => $v) {
1585 if (count($v) < $max) {
1586 $fill = array_fill(0, $max, '');
1587 foreach ($v as $idx => $vi) {
1593 // affect completed columns
1594 foreach ($t as $k => $v) {
1595 $this->setColumn($k, $v);
1599 protected function addHTMLStyle()
1601 $xmldata = '<xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml">' . "</xhtml:html>";
1603 $ddXsl = new DOMDocument();
1604 $ddXsl->load(DEFAULT_PUBDIR . "/CORE/Layout/html2odt.xsl");
1605 $xslt = new xsltProcessor;
1607 $xslt->importStyleSheet($ddXsl);
1609 $ddData = new DOMDocument();
1610 $ddData->loadXML($xmldata);
1611 $xmlout = $xslt->transformToXML($ddData);
1613 $dxml = new DomDocument();
1614 $dxml->loadXML($xmlout);
1615 $ot = $dxml->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0", "automatic-styles");
1616 if ($ot->length <= 0) {
1617 $this->addError("LAY0008", DEFAULT_PUBDIR . "/CORE/Layout/html2odt.xsl");
1620 $ot1 = $ot->item(0);
1621 $ass = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0", "automatic-styles");
1622 if ($ass->length <= 0) {
1623 $outfile = uniqid(getTmpDir() . "/oooKo") . '.xml';
1624 file_put_contents($outfile, $this->template);
1625 $this->addError("LAY0009", $this->file);
1626 $this->exitError($outfile);
1628 $ass0 = $ass->item(0);
1629 foreach ($ot1->childNodes as $ots) {
1630 $c = $this->dom->importNode($ots, true);
1631 $ass0->appendChild($c);
1637 protected function removeOrphanImages()
1639 $imgs = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", "image");
1640 $used_images = array();
1641 foreach ($imgs as $img) {
1645 $href = basename($img->getAttribute('xlink:href'));
1646 if (substr($href, 0, 7) == 'dcp') {
1647 $used_images[] = $href;
1650 $files = glob($this->cibledir . '/Pictures/dcp*');
1651 if (is_array($files)) {
1652 foreach ($files as $file) {
1653 if (!in_array(basename($file) , $used_images)) {
1654 $this->removed_images[] = 'Pictures/' . basename($file);
1661 protected function GenJsRef()
1666 public function GenJsCode($showlog, $onlylog = false)
1671 protected function ParseJs(&$out)
1675 protected function GenCssRef($oldCompatibility = true)
1680 protected function GenCssCode()
1685 protected function ParseCss(&$out)
1691 protected function genStyle()
1694 $this->dom = new DOMDocument();
1696 $this->dom->loadXML($this->style_template);
1698 $this->template = $this->style_template;
1701 $this->template = $this->dom->saveXML();
1703 $this->hideUserFieldSet();
1707 $this->restoreUserFieldSet();
1708 $this->style_template = $this->template;
1714 protected function genMeta()
1716 $this->dom = new DOMDocument();
1718 $this->dom->loadXML($this->meta_template);
1720 $this->template = $this->meta_template;
1726 $this->meta_template = $this->template;
1734 protected function parseHtmlText()
1736 $this->dom->loadXML($this->template);
1737 $lists = $this->dom->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "section");
1738 $htmlSections = array();
1739 $htmlCleanSections = array();
1740 foreach ($lists as $list) {
1744 $aid = $list->getAttribute("aid");
1746 if ($list->parentNode->childNodes->length == 1) {
1747 $htmlSections[] = $list;
1750 $htmlCleanSections[] = $list;
1752 $list->removeAttribute("aid");
1755 foreach ($htmlSections as $htmlSection) {
1759 $pParentHtml = $htmlSection->parentNode->parentNode;
1760 $parentHtml = $htmlSection->parentNode;
1762 if ($parentHtml->nextSibling) {
1763 $pParentHtml->insertBefore($htmlSection, $parentHtml->nextSibling);
1765 $pParentHtml->appendChild($htmlSection);
1767 $pParentHtml->removeChild($parentHtml);
1769 $pParentHtml = $htmlSection->parentNode->parentNode;
1770 $parentHtml = $htmlSection->parentNode;
1772 if (($parentHtml->nodeName == "text:p") && ($parentHtml->childNodes->length == 1)) {
1773 $htmlPs = $htmlSection->getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0", "p");
1775 * @var DOMElement $p
1777 foreach ($htmlPs as $p) {
1778 foreach ($parentHtml->attributes as $attribute) {
1780 $p->setAttribute('text:' . $attribute->name, $attribute->value);
1784 if ($parentHtml->nextSibling) {
1785 $pParentHtml->insertBefore($htmlSection, $parentHtml->nextSibling);
1787 $pParentHtml->appendChild($htmlSection);
1790 $pParentHtml->removeChild($parentHtml);
1792 if (in_array($htmlSection->parentNode->nodeName, array(
1798 $htmlCleanSections[] = $htmlSection;
1799 $attrid = substr($htmlSection->getAttribute("text:name") , 7);
1800 $this->addError("LAY0002", "[V_" . strtoupper($attrid) . "]");
1802 //print "Parent Node is ".$htmlSection->parentNode->nodeName."\n";
1805 if (!in_array($parentHtml->nodeName, array(
1807 'text:text-content',
1808 'text:office-text-content-main',
1812 $htmlCleanSections[] = $htmlSection;
1813 $attrid = substr($htmlSection->getAttribute("text:name") , 7);
1814 $this->addError("LAY0005", "[V_" . strtoupper($attrid) . "]");
1818 foreach ($htmlCleanSections as $htmlSection) {
1823 $attrid = substr($htmlSection->getAttribute("text:name") , 7);
1825 $pp = $this->dom->createElement("text:span");
1826 $pp->nodeValue = "HTML attribute misplaced : " . "[V_" . strtoupper($attrid) . "]";
1827 $htmlSection->parentNode->appendChild($pp);
1830 $this->parseHtmlDraw();
1831 $this->template = $this->dom->saveXML();
1837 public function getErrors()
1840 foreach ($this->errors as $err) {
1841 $s[] = ErrorCode::getError($err["code"], $err["key"]);
1843 return implode("\n", $s);
1852 protected function exitError($outfile = '')
1854 foreach ($this->errors as $err) {
1856 $e = new Dcp\Layout\Exception($err["code"], $err["key"]);
1858 error_log(sprintf("Error {%s}: corrupted temporary file is %s", $err["code"], $outfile));
1859 $e->setCorruptedFile($outfile);
1871 protected function addError($code, $key, $message = '')
1873 $this->errors[] = array(
1876 "message" => $message
1885 protected function changeElementName($node, $name)
1888 $newElement = $this->dom->createElement($name);
1889 // Clone the attributes:
1890 foreach ($node->attributes as $attribute) {
1892 $newElement->setAttribute($attribute->name, $attribute->value);
1894 // Add clones of the old element's children to the replacement
1897 * @var DOMElement $child
1899 foreach ($node->childNodes as $child) {
1901 $newElement->appendChild($child->cloneNode(true));
1903 // Replace the old node
1904 $node->parentNode->replaceChild($newElement, $node);
1910 protected function genContent()
1913 $this->dom = new DOMDocument();
1915 $this->dom->loadXML($this->content_template);
1917 $this->template = $this->content_template;
1919 $this->parseTplSection();
1920 //header('Content-type: text/xml; charset=utf-8');print $this->dom->saveXML();exit;
1921 $this->hideUserFieldSet();
1922 $this->parseTableRow();
1924 $this->parseSection();
1925 $this->parseListItem();
1928 $this->parseInput();
1929 $this->parseDropDown();
1931 $this->addHTMLStyle();
1932 $this->template = $this->dom->saveXML();
1934 $this->ParseBlock();
1936 //$this->ParseKeyXml();
1937 //$this->template=$this->dom->saveXML();
1938 // print $this->template;exit;
1942 $this->restoreUserFieldSet();
1944 $this->restoreProtectedValues();
1946 $this->ParseHtmlText();
1948 $this->template = \Dcp\Utils\htmlclean::cleanXMLUTF8($this->template);
1949 $this->dom = new DOMDocument();
1950 if ($this->dom->loadXML($this->template)) {
1951 $this->restoreSection();
1952 // not remove images because delete images defined in style.xml
1953 //$this->removeOrphanImages();
1954 $this->template = $this->dom->saveXML();
1956 $this->content_template = $this->template;
1958 $outfile = uniqid(getTmpDir() . "/oooKo") . '.xml';
1959 file_put_contents($outfile, $this->template);
1960 $this->addError("LAY0004", $this->file);
1961 $this->exitError($outfile);
1964 $this->addError("LAY0001", $this->file);
1974 public function gen()
1977 $this->addError("LAY0001", $this->template);
1980 // if used in an app , set the app params
1981 if (is_object($this->action)) {
1982 $list = $this->action->parent->GetAllParam();
1983 foreach ($list as $k => $v) {
1984 $v = str_replace(array(
1989 ) , '<text:line-break/>', $v);
1993 // $this->rif=&$this->rkey;
1994 // $this->ParseIf($out);
1995 // Parse IMG: and LAY: tags
1996 $this->genContent();
1999 $this->updateManifest();
2000 $outfile = uniqid(getTmpDir() . "/odf") . '.odt';
2001 $this->content2odf($outfile);
2003 if (!empty($this->errors)) {
2004 //error_log(sprintf("Error {LAY0001}: corrupted temporary file is %s", $outfile));
2005 //throw new Dcp\Layout\Exception("LAY0001", $this->getErrors() , $outfile);
2006 $this->exitError($outfile);
2008 //print_r2($this->content_template);
Layout is a template generator.