_debug = Debug::getInstance(); $this->_phpdocxconfig = PhpdocxUtilities::parseConfig(); $this->_background = ''; $this->_backgroundColor = 'FFFFFF'; $this->_baseTemplateFilesPath; if ($baseTemplatePath == 'docm') { $this->_baseTemplatePath = PHPDOCX_BASE_FOLDER.'phpdocxBaseTemplate.docm'; $this->_docm = true; $this->_defaultTemplate = true; $this->_extension = 'docm'; } else if($baseTemplatePath == 'docx') { $this->_baseTemplatePath = PHPDOCX_BASE_FOLDER.'phpdocxBaseTemplate.docx'; $this->_docm = false; $this->_defaultTemplate = true; $this->_extension = 'docx'; } else { if ($baseTemplatePath == PHPDOCX_BASE_TEMPLATE) { $this->_defaultTemplate = true; } else { $this->_defaultTemplate = false; } $this->_baseTemplatePath = $baseTemplatePath; $extensionArray = explode('.', $this->_baseTemplatePath); $extension = array_pop($extensionArray); $this->_extension = $extension; if ($extension == 'docm') { $this->_docm = true; } else if ($extension == 'docx') { $this->_docm = false; } else { PhpdocxLogger::logger('Invalid base template extension', 'fatal'); } } $this->_baseTemplateZip = new ZipArchive(); $this->_bookmarksIds = array(); $this->_idRels = array(); $this->_idWords = array(); $this->_idImgHeader = 1; $this->_idRels = 1; self::$intIdWord = rand(9999999,99999999); self::$_encodeUTF = 0; $this->_language = 'en-US'; $this->_markAsFinal = 0; $this->graphicTemplate = array(); $this->fileGraphicTemplate = array(); $this->_zipDocx = new ZipArchive(); if ($this->_phpdocxconfig['settings']['temp_path']) { $this->_tempDir = $this->_phpdocxconfig['settings']['temp_path']; } else { $this->_tempDir = self::getTempDir(); } $this->_tempFile = tempnam($this->_tempDir, 'document'); $this->_templateNumberings; $this->_zipDocx->open($this->_tempFile, ZipArchive::OVERWRITE); $this->_compatibilityMode = false; PhpdocxLogger::logger('Create a temp file to use as initial ZIP file. ' . 'DOCX is a ZIP file.', 'info'); // sign is set false as default $this->_sign = false; $this->_relsRelsC = ''; $this->_relsRelsT = ''; $this->_contentTypeC = ''; $this->_contentTypeT = NULL; $this->_defaultFont = ''; $this->_docPropsAppC = ''; $this->_docPropsAppT = ''; $this->_docPropsCoreC = ''; $this->_docPropsCoreT = ''; $this->_docPropsCustomC = ''; $this->_docPropsCustomT = ''; $this->_macro = 0; $this->_relsHeader = array(); $this->_relsFooter = array(); $this->_parsedStyles = array(); $this->_relsHeaderFooterImage = array(); $this->_relsHeaderFooterImageExternal = array(); $this->_relsHeaderFooterLink = array(); $this->_sectPr = NULL; $this->_tempFileXLSX = array(); $this->_uniqid = 'phpdocx_'.uniqid(); $this->_wordDocumentT = ''; $this->_wordDocumentC = ''; $this->_wordDocumentStyles = ''; $this->_wordEndnotesC = ''; $this->_wordEndnotesT = ''; $this->_wordFontTableT = ''; $this->_wordFontTableC = ''; $this->_wordFooterC = array(); $this->_wordFooterT = array(); $this->_wordFootnotesC = ''; $this->_wordFootnotesT = ''; $this->_wordHeaderC = array(); $this->_wordHeaderT = array(); $this->_wordNumberingC; $this->_wordNumberingT; $this->_wordRelsDocumentRelsC = ''; $this->_wordRelsDocumentRelsT = NULL; $this->_wordRelsHeaderRelsC = array(); $this->_wordRelsHeaderRelsT = array(); $this->_wordRelsFooterRelsC = array(); $this->_wordRelsFooterRelsT = array(); $this->_wordSettingsT = ''; $this->_wordSettingsC = ''; $this->_wordStylesT = ''; $this->_wordStylesC = ''; $this->_wordThemeThemeT = ''; $this->_wordThemeThemeC = ''; $this->_wordWebSettingsT = ''; $this->_wordWebSettingsC = ''; $this->_defaultPHPDOCXStyles = array('Default Paragraph Font PHPDOCX', //This is the default paragraph font style used in multiple places 'List Paragraph PHPDOCX', //This is the style used for the defolt ordered and unorderd lists 'Title PHPDOCX', //This style is used by the addTitle method 'Subtitle PHPDOCX', //This style is used by the addTitle method 'Normal Table PHPDOCX', //This style is used for the basic table 'Table Grid PHPDOCX', //This style is for basic tables and is also used to embed HTML tables with border="1" 'footnote text PHPDOCX', //This style is used for default footnotes 'footnote text Car PHPDOCX', //The character style for footnotes 'footnote reference PHPDOCX', // The style for the footnote 'endnote text PHPDOCX', //This style is used for default endnotes 'endnote text Car PHPDOCX', //The character style for endnotes 'endnote reference PHPDOCX'); // The style for the endnote //Some variables to control that some v2.4 keep working $this->footerAdded = false; $this->headerAdded = false; self::$PHPDOCXStyles = ' '; self::$unorderedListStyle = ' '; self::$orderedListStyle =' '; //We now try to open the zip file defined as base template try { $openBaseTemplate = $this->_baseTemplateZip->open($this->_baseTemplatePath); if ($openBaseTemplate !== true) { throw new Exception('Error while opening the Base Template: please, check the path'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } //We now extract the contents of the base template into a temp dir for further manipulation try { $this->_baseTemplateFilesPath = $this->_tempDir.'/'.uniqid(true); $extractBaseTemplate =$this->_baseTemplateZip->extractTo($this->_baseTemplateFilesPath); if ($extractBaseTemplate !== true) { throw new Exception('Error while extracting the Base Template: there may be problems writing in the default tmp folder'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } //We should now check if there is any structured content as front page to include it in the resulting document try{ $baseTemplateDocumentT = $this->_baseTemplateZip->getFromName('word/document.xml'); if ($baseTemplateDocumentT == '') { throw new Exception('Error while extracting the document.xml file from the base template'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } $baseDocument = new DOMDocument(); $baseDocument->loadXML($baseTemplateDocumentT); $docXpath = new DOMXPath($baseDocument); $docXpath->registerNamespace('w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'); $queryDoc = '//w:body/w:sdt'; $docNodes = $docXpath->query($queryDoc); if ($docNodes->length > 0){ if($docNodes->item(0)->nodeName == 'w:sdt'){ $tempDoc = new DomDocument(); $sdt =$tempDoc->importNode($docNodes->item(0), true); $newNode = $tempDoc->appendChild($sdt); $frontPage = $tempDoc->saveXML($newNode); $this->_wordDocumentC .= $frontPage; } } //Let us extract now the section information to include it at the end of the document.xml file $sectPr = $baseDocument->getElementsByTagName('sectPr')->item(0); $this->_sectPr = new DOMDocument(); $sectNode = $this->_sectPr->importNode($sectPr, true); $this->_sectPr->appendChild($sectNode); //Let us extract the contents of the [Content_Types].xml file for further manipulation try { $baseTemplateContentTypeT = $this->_baseTemplateZip->getFromName('[Content_Types].xml'); if ($baseTemplateContentTypeT == '') { throw new Exception('Error while extracting the [Content_Types].xml file from the base template'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } $this->_contentTypeT = new DOMDocument(); $this->_contentTypeT->loadXML($baseTemplateContentTypeT); //We are going to include the standard image defaults $this->generateDEFAULT('gif', 'image/gif'); $this->generateDEFAULT('jpg', 'image/jpg'); $this->generateDEFAULT('png', 'image/png'); $this->generateDEFAULT('jpeg', 'image/jpeg'); $this->generateDEFAULT('bmp', 'image/bmp'); //Let us extract the document.xml.rels for further manipulation try { $baseTemplateDocumentRelsT = $this->_baseTemplateZip->getFromName('word/_rels/document.xml.rels'); if ($baseTemplateDocumentRelsT == '') { throw new Exception('Error while extracting the document.xml.rels file from the base template'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } $this->_wordRelsDocumentRelsT = new DOMDocument(); $this->_wordRelsDocumentRelsT->loadXML($baseTemplateDocumentRelsT); $relationships = $this->_wordRelsDocumentRelsT->getElementsByTagName('Relationship'); //Now we have to take care of the case that the template used is not one of the default preprocessed templates if ($this->_defaultTemplate) { self::$numUL = 1; self::$numOL = rand(9999, 999999999); //Let's get the original template numbering.xml file as a DOMdocument try { $this->_wordNumberingT = $this->_baseTemplateZip->getFromName('word/numbering.xml'); if ($this->_wordNumberingT == '') { throw new Exception('Error while extracting the numbering file from the base template'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } } else { //We should do now some cleaning of the files from the base template zip //Let us first look at the document.xml.rels file to analyze the contents //Let us analyze its structure //In order to do that we should parse word/_rels/document.xml.rels $counter = $relationships->length -1; for ($j=$counter; $j > -1; $j--) { $completeType = $relationships->item($j)->getAttribute('Type'); $target = $relationships->item($j)->getAttribute('Target'); $tempArray = explode('/', $completeType); $type = array_pop($tempArray); //This array holds the data that has to be changed in settings.xml $arrayCleaner = array(); switch($type){ case 'header': //TODO: this should be changed if we use default templates with headers array_push($this->_relsHeader,$target); break; case 'footer': //TODO: this should be changed if we use default templates with footers array_push($this->_relsFooter,$target); break; case 'chart': $this->recursiveDelete($this->_baseTemplateFilesPath.'/word/charts'); $this->_wordRelsDocumentRelsT->documentElement->removeChild($relationships->item($j)); break; case 'embeddings': $this->recursiveDelete($this->_baseTemplateFilesPath.'/word/embeddings'); $this->_wordRelsDocumentRelsT->documentElement->removeChild($relationships->item($j)); break; } } //Let us now manage the numbering.xml and style.xml files // We are going to use some default styles, for example, in the creation of lists, footnotes, titles, ... // So we should make sure that it is included in the styles.xml document $this->importStyles(PHPDOCX_BASE_TEMPLATE, 'merge', $this->_defaultPHPDOCXStyles); //Let us first check if the base template file has a numbering.xml file $numRef = rand(9999999, 99999999); self::$numUL = $numRef; self::$numOL = $numRef +1; if(file_exists($this->_baseTemplateFilesPath.'/word/numbering.xml')) { //Let's get the original template numbering.xml file as a DOMdocument try { $this->_wordNumberingT = $this->_baseTemplateZip->getFromName('word/numbering.xml'); if ($this->_wordNumberingT == '') { throw new Exception('Error while extracting the numbering file from the base template'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } $this->_wordNumberingT = $this->importSingleNumbering($this->_wordNumberingT, self::$unorderedListStyle, self::$numUL); $this->_wordNumberingT = $this->importSingleNumbering($this->_wordNumberingT, self::$orderedListStyle, self::$numOL); }else{ $this->_wordNumberingT = $this->generateBaseWordNumbering(); $this->_wordNumberingT = $this->importSingleNumbering($this->_wordNumberingT, self::$unorderedListStyle, self::$numUL); $this->_wordNumberingT = $this->importSingleNumbering($this->_wordNumberingT, self::$orderedListStyle, self::$numOL); //Now we should include the corresponding relationshipand Override $this->_wordRelsDocumentRelsC .= $this->generateRELATIONSHIP( 'rId' . rand(99999999, 999999999), 'numbering', 'numbering.xml' ); $this->generateOVERRIDE('/word/numbering.xml','application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml'); } //Let us now make sure that there are the corresponding xmls, with all their relationships for endnotes and footnotes if(!file_exists($this->_baseTemplateFilesPath.'/word/endnotes.xml') || !file_exists($this->_baseTemplateFilesPath.'/word/footnotes.xml')){ $notesZip = new ZipArchive(); try { $openNotesZip = $notesZip->open(PHPDOCX_BASE_TEMPLATE); if ($openNotesZip !== true){ throw new Exception('Error while opening the standard base template to extract the word/footnotes.xml and word/endnotes.xml file'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } $arraySettings = array(); if(!file_exists($this->_baseTemplateFilesPath.'/word/footnotes.xml')){ $notesZip->extractTo($this->_baseTemplateFilesPath, 'word/footnotes.xml'); //Now we should include the corresponding relationshipand Override $this->_wordRelsDocumentRelsC .= $this->generateRELATIONSHIP( 'rId' . rand(99999999, 999999999), 'footnotes', 'footnotes.xml' ); $this->generateOVERRIDE('/word/footnotes.xml','application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml'); array_push($arraySettings, ''); } if(!file_exists($this->_baseTemplateFilesPath.'/word/endnotes.xml')){ $notesZip->extractTo($this->_baseTemplateFilesPath, 'word/endnotes.xml'); //Now we should include the corresponding relationshipand Override $this->_wordRelsDocumentRelsC .= $this->generateRELATIONSHIP( 'rId' . rand(99999999, 999999999), 'endnotes', 'endnotes.xml' ); $this->generateOVERRIDE('/word/endnotes.xml','application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml'); array_push($arraySettings,''); } //$this->includeSettings($arraySettings) } } $this->setLanguage($this->_phpdocxconfig['settings']['language']); } /** * Destruct * * @access public */ public function __destruct() { } /** * Magic method, returns current word XML * * @access public * @return string Return current word */ public function __toString() { $this->generateTemplateWordDocument(); PhpdocxLogger::logger('Get document template content.', 'debug'); return $this->_wordDocumentT; } /** * Setter * * @access public */ public function setExtension($extension) { $this->_extension = $extension; } /** * Getter * * @access public */ public function getExtension() { return $this->_extension; } /** * Setter * * @access public */ public function setTemporaryDirectory($tempDir) { $this->_tempDir = $tempDir; } /** * Getter * * @access public */ public function getTemporaryDirectory() { return $this->_tempDir; } /** * Setter * * @access public */ public function setXmlContentTypes($xmlContentTypes) { $this->_contentTypeC = $xmlContentTypes; } /** * Getter * * @access public */ public function getXmlContentTypes() { return $this->_contentTypeC; } /** * Setter * * @access public */ public function setXmlRelsRels($xmlRelsRels) { $this->_relsRelsC = $xmlRelsRels; } /** * Getter * * @access public */ public function getXmlRelsRels() { return $this->_relsRelsC; } /** * Setter * * @access public */ public function setXmlDocPropsApp($xmlDocPropsApp) { $this->_docPropsAppC = $xmlDocPropsApp; } /** * Getter * * @access public */ public function getXmlDocPropsApp() { return $this->_docPropsAppC; } /** * Setter * * @access public */ public function setXmlDocPropsCore($xmlDocPropsCore) { $this->_docPropsCoreC = $xmlDocPropsCore; } /** * Getter * * @access public */ public function getXmlDocPropsCore() { return $this->_docPropsCoreC; } /** * Setter * * @access public */ public function setXmlDocPropsCustom($xmlDocPropsCustom) { $this->_docPropsCustomC = $xmlDocPropsCustom; } /** * Getter * * @access public */ public function getXmlDocPropsCustom() { return $this->_docPropsCustomC; } /** * Setter * * @access public */ public function setXmlWordDocument($xmlWordDocument) { $this->_wordDocumentC = $xmlWordDocument; } /** * Getter * * @access public */ public function getXmlWordDocumentContent() { return $this->_wordDocumentC; } /** * Setter * * @access public */ public function setXmlWordDocumentStyles($xmlWordDocumentStyles) { $this->_wordDocumentStyles = $xmlWordDocumentStyles; } /** * Getter * * @access public */ public function getXmlWordDocumentStyles() { return $this->_wordDocumentStyles; } /** * Setter * * @access public */ public function setXmlWordEndnotes($xmlWordEndnotes) { $this->_wordEndnotesC = $xmlWordEndnotes; } /** * Getter * * @access public */ public function getXmlWordEndnotes() { return $this->_wordEndnotesC; } /** * Setter * * @access public */ public function setXmlWordFontTable($xmlWordFontTable) { $this->_wordFontTableC = $xmlWordFontTable; } /** * Getter * * @access public */ public function getXmlWordFontTable() { return $this->_wordFontTableC; } /** * Setter * * @access public */ public function setXmlWordFooter1($xmlWordFooter) { $this->_wordFooterC = $xmlWordFooter; } /** * Getter * * @access public */ public function getXmlWordFooter1() { return $this->_wordFooterC; } /** * Setter * * @access public */ public function setXmlWordHeader1($xmlWordHeader) { $this->_wordHeaderC = $xmlWordHeader; } /** * Getter * * @access public */ public function getXmlWordHeader1() { return $this->_wordHeaderC; } /** * Setter * * @access public */ public function setXmlWordRelsDocumentRels($xmlWordRelsDocumentRels) { $this->_wordRelsDocumentRelsC = $xmlWordRelsDocumentRels; } /** * Getter * * @access public */ public function getXmlWordRelsDocumentRels() { return $this->_wordRelsDocumentRelsC; } /** * Setter * * @access public */ public function setXmlWordSettings($xmlWordSettings) { $this->_wordSettingsC = $xmlWordSettings; } /** * Getter * * @access public */ public function getXmlWordSettings() { return $this->_wordSettingsC; } /** * Setter * * @access public */ public function setXmlWordStyles($xmlWordStyles) { $this->_wordStylesC = $xmlWordStyles; } /** * Getter * * @access public */ public function getXmlWordStyles() { return $this->_wordStylesC; } /** * Setter * * @access public */ public function setXmlWordThemeTheme1($xmlWordThemeTheme) { $this->_wordThemeThemeC = $xmlWordThemeTheme; } /** * Getter * * @access public */ public function getXmlWordThemeTheme1() { return $this->_wordThemeThemeC; } /** * Setter * * @access public */ public function setXmlWordWebSettings($xmlWordWebSettings) { $this->_wordWebSettingsC = $xmlWordWebSettings; } /** * Setter * * @access public */ public function getXml_Word_WebSettings() { return $this->_wordWebSettingsC; } /** * Add a break * * @access public * @example ../examples/easy/PageBreak.php * @param string $options * Values: * 'type' (line, page, column) */ public function addBreak($options = array('type' => 'line')) { $break = CreatePage::getInstance(); $break->generatePageBreak($options['type']); PhpdocxLogger::logger('Add break to word document.', 'info'); $this->_wordDocumentC .= (string) $break; } /** * Add a chart * * @access public * @example ../examples/easy/Chart.php * @example ../examples/easy/Chart_bar.php * @param array $options * Values: 'color' (1, 2, 3...) color scheme, * 'perspective' (20, 30...), * 'rotX' (20, 30...), * 'rotY' (20, 30...), * 'data' (array of values), * 'float' (left, right, center) floating image. It only applies if textWrap is not inline (default value). * 'font' (Arial, Times New Roman...), * 'groupBar' (clustered, stacked, percentStacked), * 'horizontalOffset' (int) given in emus (1cm = 360000 emus) * 'jc' (center, left, right), * 'showPercent' (0, 1), * 'sizeX' (10, 11, 12...), * 'sizeY' (10, 11, 12...), * 'textWrap' (0 (inline), 1 (square), 2 (front), 3 (back), 4 (up and bottom)), * 'verticalOffset' (int) given in emus (1cm = 360000 emus) * 'title', * 'type' (barChart, pieChart) * 'legendPos' (r, l, t, b, none), * 'legendOverlay' (0, 1), * 'border' (0, 1), * 'haxLabel' horizontal axis label, * 'vaxLabel' vertical axis label, * 'showtable' (0, 1) shows the table of values, * 'vaxLabelDisplay' (rotated, vertical, horizontal), * 'haxLabelDisplay' (rotated, vertical, horizontal), * 'hgrid' (0, 1, 2, 3), * 'vgrid' (0, 1, 2, 3), * 'style' this work only in radar charts. * 'gapWidth' distance between the pie and the second chart(ofpiechart) * 'secondPieSize' : size of the second chart(ofpiechart) * 'splitType' how decide to split the values :auto(Default Split), cust(Custom Split), percent(Split by Percentage), pos(Split by Position), val(Split by Value) * 'splitPos' split position , integer or float * 'custSplit' array of index to split * 'subtype' type of the second chart pie or bar * 'explosion' distance between the diferents values * 'holeSize' size of the hole in doughnut type * 'symbol' array of symbols(scatter chart) * 'symbolSize' the size of the simbols * 'smooth' smooth the line (scatter chart) * 'wireframe' boolean(surface chart)to remove content color and only leave the border colors * 'showValue' (0,1) shows the values inside the chart * 'showCategory' (0,1) shows the category inside the chart */ public function addChart($options = array()) { PhpdocxLogger::logger('Create chart.', 'debug'); try { if (isset($options['data']) && isset($options['type'])) { self::$intIdWord++; PhpdocxLogger::logger('New ID ' . self::$intIdWord . ' . Chart.', 'debug'); $type = $options['type']; if(strpos($type, 'Chart') === false) $type .= 'Chart'; $graphic = CreateChartFactory::createObject($type); if ($graphic->createGraphic(self::$intIdWord, $options) != false) { PhpdocxLogger::logger('Add chart word/charts/chart' . self::$intIdWord . '.xml to DOCX.', 'info'); $this->_zipDocx->addFromString( 'word/charts/chart' . self::$intIdWord . '.xml', $graphic->getXmlChart() ); $this->_wordRelsDocumentRelsC .= $this->generateRELATIONSHIP( 'rId' . self::$intIdWord, 'chart', 'charts/chart' . self::$intIdWord . '.xml' ); $this->generateDEFAULT('xlsx', 'application/octet-stream'); $this->generateOVERRIDE( '/word/charts/chart' . self::$intIdWord . '.xml', 'application/vnd.openxmlformats-officedocument.' . 'drawingml.chart+xml' ); } else { throw new Exception( 'There was an error related to the chart.' ); } $excel = $graphic->getXlsxType(); $this->_tempFileXLSX[self::$intIdWord] = tempnam($this->_tempDir, 'documentxlsx'); if ( $excel->createXlsx( $this->_tempFileXLSX[self::$intIdWord], $options['data'] ) != false ) { $this->_zipDocx->addFile( $this->_tempFileXLSX[self::$intIdWord], 'word/embeddings/datos' . self::$intIdWord . '.xlsx' ); $chartRels = CreateChartRels::getInstance(); $chartRels->createRelationship(self::$intIdWord); $this->_zipDocx->addFromString( 'word/charts/_rels/chart' . self::$intIdWord . '.xml.rels', (string) $chartRels ); } $this->_wordDocumentC .= (string) $graphic; } else { throw new Exception( 'Images must have "data" and "type" values.' ); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } } /** * Add an image * * @access public * @example ../examples/easy/Image.php * @param array $data * Values: * 'border'(int) 1, 2, 3... * 'borderDiscontinuous' (0, 1) * 'float' (left, right, center) floating image. It only applies if textWrap is not inline (default value). * 'font' (string) Arial, Times New Roman... * 'horizontalOffset' (int) given in emus (1cm = 360000 emus). Only applies if there is the image is not floating * 'jc' (center, left, right, inside, outside) * 'name' (string) path to a local image * 'scaling' (int) 50, 100, .. * 'sizeX' (int) 10, 11, 12... * 'sizeY' (int) 10, 11, 12... * 'dpi' (int) dots per inch * 'spacingTop' (int) 10, 11... * 'spacingBottom' (int) 10, 11... * 'spacingLeft' (int) 10, 11... * 'spacingRight' (int) 10, 11... * 'textWrap' 0 (inline), 1 (square), 2 (front), 3 (back), 4 (up and bottom)) * 'target' (string): document (default value), defaultHeader, firstHeader, evenHeader, defaultFooter, firstFooter, evenFooter * 'verticalOffset' (int) given in emus (1cm = 360000 emus) */ public function addImage($data = '') { if(!isset($data['target'])){ $data['target'] = 'document'; } PhpdocxLogger::logger('Create image.', 'debug'); try { if (isset($data['name']) && file_exists($data['name']) == 'true') { $attrImage = getimagesize($data['name']); try { if ($attrImage['mime'] == 'image/jpg' || $attrImage['mime'] == 'image/jpeg' || $attrImage['mime'] == 'image/png' || $attrImage['mime'] == 'image/gif' ) { self::$intIdWord++; PhpdocxLogger::logger('New ID rId' . self::$intIdWord . ' . Image.', 'debug'); $image = CreateImage::getInstance(); $data['rId'] = self::$intIdWord; $image->createImage($data); $dir = $this->parsePath($data['name']); PhpdocxLogger::logger('Add image word/media/imgrId' . self::$intIdWord . '.' . $dir['extension'] . '.xml to DOCX.', 'info'); $this->_zipDocx->addFile( $data['name'], 'word/media/imgrId' . self::$intIdWord . '.' . $dir['extension'] ); $this->generateDEFAULT( $dir['extension'], $attrImage['mime'] ); if ((string) $image != ''){ //Here we consider the case where the image will be included in a header or footer if($data['target'] == 'defaultHeader' || $data['target'] == 'firstHeader' || $data['target'] == 'evenHeader' || $data['target'] == 'defaultFooter' || $data['target'] == 'firstFooter' || $data['target'] == 'evenFooter'){ $this->_relsHeaderFooterImage[$data['target']][] = array('rId' => 'rId' . self::$intIdWord, 'extension' => $dir['extension']); }else{ $this->_wordRelsDocumentRelsC .= $this->generateRELATIONSHIP( 'rId' . self::$intIdWord, 'image', 'media/imgrId' . self::$intIdWord . '.' . $dir['extension'] ); } } $this->_wordDocumentC .= (string) $image; } else { throw new Exception('Image format is not supported.'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } } else { throw new Exception('Image does not exist.'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } } /** * Add a link * * @access public * @example ../examples/easy/Link.php * @param array $options * @see addText * additional parameter: * 'url' (string) URL or #bookmarkName * */ public function addLink($text, $options = array('url' => '', 'font' => '', 'sz' => '', 'color' => '0000ff', 'u' => 'single', )) { if(substr($options['url'], 0, 1) == '#'){ $url = 'HYPERLINK \l "' . substr($options['url'], 1) . '"'; }else{ $url = 'HYPERLINK "' . $options['url'] . '"'; } if ($text == '') { PhpdocxLogger::logger('The linked text is missing', 'fatal'); } else if($options['url'] == '') { PhpdocxLogger::logger('The URL is missing', 'fatal'); } if (isset($options['color'])) { $color = $options['color']; } else { $color = '0000ff'; } if (isset($options['u'])) { $u = $options['u']; } else { $u = 'single'; } $textOptions = $options; $textLink = CreateText::getInstance(); $textLink->createText($text, $textOptions); $link = (string) $textLink; $link = preg_replace('/__[A-Z]+__/', '', $link); $startNodes =' '.$url.' '; if(strstr($link, '')){ $link = preg_replace('/<\/w:pPr>/', ''.$startNodes, $link); }else{ $link = preg_replace('//', ''.$startNodes, $link); } $endNode = ''; $link = preg_replace('/<\/w:p>/', $endNode . '', $link); PhpdocxLogger::logger('Add link to word document.', 'info'); $this->_wordDocumentC .= (string) $link; } /** * Add a list * * @access public * @example ../examples/easy/List.php * @param array $data Values of the list * @param array $options * Values: * 'font' (string), Arial, Times New Roman, ... * 'val' (int), 0 (clear), 1 (inordinate), 2(numerical) * 'bullets' (array) 1 (), 2 (o), 3 () */ public function addList($data, $options = array()) { $list = CreateList::getInstance(); if ($options['val'] == 2){ self::$numOL++; $this->_wordNumberingT = $this->importSingleNumbering($this->_wordNumberingT, self::$orderedListStyle, self::$numOL); } $list->createList($data, $options); PhpdocxLogger::logger('Add list to word document.', 'info'); $this->_wordDocumentC .= (string) $list; if (!empty($options['bullets']) && is_array($options['bullets']) && $options['val'] == 1 ) { for ($i = 0; $i <= CreateList::MAXDEPTH; $i++) { $bullets = $options['bullets']; if (isset($bullets[$i])) { $styleId = $bullets[$i]; } else { $styleId = $i; } $list->createListStyles($i, $styleId); PhpdocxLogger::logger('Add list styles to word document.', 'info'); $this->_wordDocumentStyles .= (string) $list; } } } /** * Add a raw WordML * * @access public * @param string $wml WordML to add * @deprecated See addWordML */ public function addRawWordML($wml) { PhpdocxLogger::logger('Add raw WordML.', 'info'); $this->_wordDocumentC .= $wml; } /** * Add a table. * * @access public * @example ../examples/easy/Table.php * @param array $tableData an array of arrays with the table data organized by rows * Each cell content may be a string or array. * If the cell contents are in the form of an array its keys and posible values are: * 'value' (string) * 'rowspan' (int) * 'colspan' (int) * 'width' (int) in twentieths of a point * 'border' (none, single, double, dashed, threeDEngrave, threeDEmboss, outset, inset) * 'border_color' (ffffff, ff0000) * 'border_spacing' (0, 1, 2...) * 'border_sz' (10, 11...) in eights of a point * 'border_' (none, single, double, dashed, threeDEngrave, threeDEmboss, outset, inset) where the side may be: top, left, right or bottom * 'border__color' (ffffff, ff0000) * 'border__spacing' (0, 1, 2...) * 'border__sz' (10, 11...) * 'background_color' (ffffff, ff0000) * 'noWrap' (boolean) * 'cellMargin' (mixed) an integer value or an array: * 'top' (int) in twentieths of a point * 'right' (int) in twentieths of a point * 'bottom' (int) in twentieths of a point * 'left' (int) in twentieths of a point * 'textDirection' (string) available values are: tbRl and btLr * 'fitText' (boolean) if true fits the text to the size of the cell * 'vAlign' (string) vertical align of text: top, center, both or bottom * * @param array $tableProperties Parameters to use * Values: * 'border' (none, single, double, dashed, threeDEngrave, threeDEmboss, outset, inset) * 'border_color' (ffffff, ff0000) * 'border_spacing' (0, 1, 2...) * 'border_sz' (10, 11...) in eights of a point * 'border_settings' (all, outside, inside) if all (default value) the border styles apply to all table borders. * If the value is set to outside or inside the border styles will only apply to the outside or inside boreders respectively. * 'cantSplitRows' (boolean) set global row split properties (can be overriden by rowProperties) * 'cellMargin' (array) the keys are top, right, bottom and left and the values is given in twips (twentieths of a point) * 'cellSpacing' (int) given in twips (twentieths of a point) * 'float' (array) with the following keys and values: * 'textMargin_top' (int) in twentieths of a point * 'textMargin_right' (int) in twentieths of a point * 'textMargin_bottom' (int) in twentieths of a point * 'textMargin_left' (int) in twentieths of a point * 'align' (string) posible values are: left, center, right, outside, inside * 'font' (Arial, Times New Roman...) * 'indent' (int) given in twips (twentieths of a point) * 'jc' (center, left, right) * 'decimalTab' * 'size_col': column width fix (int) * column width variable (array) * 'tableWidth' (array) its posible keys and values are: * 'type' (pct, dxa) pct if the value refers to percentage and dxa if the value is given in twentieths of a point (twips) * 'value' (int) * 'TBLSTYLEval' (string) Word table style * * @param array $rowProperties (array) a cero based array. Each entry is an array with keys and values: * 'cantSplit' (boolean) * 'minHeight' (int) in twentieths of a point * 'height' (int) in twentieths of a point * 'tblHeader' (boolean) if true this row repeats at the beguinning of each new page */ public function addTable($tableData, $tableProperties= array(), $rowProperties = array()) { $table = CreateTable::getInstance(); $table->createTable($tableData, $tableProperties, $rowProperties); PhpdocxLogger::logger('Add table to Word document.', 'info'); $this->_wordDocumentC .= (string) $table; } /** * Add a text * * @access public * @example ../examples/easy/Text.php * @example ../examples/easy/Text_cursive.php * @param mixed $textParams if a string just the text to be included, if an * array is or an array of arrays with each element containing * the text to be inserted and their formatting properties * Array values: * 'text' (string) the run of text to be inserted * 'b' (on, off) * 'caps' (on, off) display text in capital letters * 'color' (ffffff, ff0000...) * 'columnBreak' (before, after, both) inserts a column break before, after or both, a run of text * 'font' (Arial, Times New Roman...) * 'i' (on, off) * 'lineBreak' (before, after, both) inserts a line break before, after or both, a run of text * 'sz' (1, 2, 3...) * 'tab' (boolean) inserts a tab. Default value is false * 'spaces': number of spaces at the beguinning of the run of text * 'u' (none, dash, dotted, double, single, wave, words) * @param array $paragraphParams Style options to apply to the whole paragraph * Values: * 'pStyle' (string) Word style to be used. Run parseStyles() to check all available paragraph styles * 'b' (on, off) * 'caps' (on, off) display text in capital letters * 'color' (ffffff, ff0000...) * 'contextualSpacing' (on, off) ignore spacing above and below when using identical styles * 'font' (Arial, Times New Roman...) * 'i' (on, off) * 'indent_left' 100..., * 'indent_right' 100... * 'jc' (both, center, distribute, left, right) * 'keepLines' (on, off) keep all paragraph lines on the same page * 'keepNext' (on, off) keep in the same page the current paragraph with next paragraph * 'lineSpacing' 120, 240 (standard), 360, 480, ... * 'pageBreakBefore' (on, off) * 'spacingBottom' (int) bottom margin in twentieths of a point * 'spacingTop' (int) top margin in twentieths of a point * 'sz' (8, 9, 10, ...) size in points * 'tabPositions' (array) each entry is an associative array with the following keys and values * 'type' (string) can be clear, left (default), center, right, decimal, bar and num * 'leader' (string) can be none (default), dot, hyphen, underscore, heavy and middleDot * 'position' (int) given in twentieths of a point * if there is a tab and the tabPositions array is not defined the standard tab position (default of 708) will be used * 'textDirection' (lrTb, tbRl, btLr, lrTbV, tbRlV, tbLrV) text flow direction * 'u' (none, dash, dotted, double, single, wave, words) * 'widowControl' (on, off) */ public function addText($textParams, $paragraphParams = array()) { $text = CreateText::getInstance(); $text->createText($textParams, $paragraphParams); PhpdocxLogger::logger('Add text to word document.', 'info'); $this->_wordDocumentC .= (string) $text; } /** * Generate a new DOCX file * * @access public * @example ../examples/easy/Text.php * @param string $args[0] File name * @param string $args[1] Page style * Values: 'bottom' (4000, 4001...), 'columns' (1, 2, 3), 'left' (4000, 4001...), * 'orient' (landscape), 'right' (4000, 4001), 'titlePage' (1), * 'top' (4000, 4001) */ public function createDocx() { $args = func_get_args(); if (!empty($args[0])) { $fileName = $args[0]; } else { $fileName = 'document'; } PhpdocxLogger::logger('Set DOCX name to: ' . $fileName . '.', 'info'); PhpdocxLogger::logger('DOCX is a new file, not a template.', 'debug'); //We copy the rels content into the respective file $relsHandler = fopen($this->_baseTemplateFilesPath.'/word/_rels/document.xml.rels', "w+"); fwrite($relsHandler, $this->_wordRelsDocumentRelsT->saveXML()); fclose($relsHandler); //We also copy the contents of the [Content_types].xml file $contentTypesHandler = fopen($this->_baseTemplateFilesPath.'/[Content_Types].xml', "w+"); fwrite($contentTypesHandler, $this->_contentTypeT->saveXML()); fclose($contentTypesHandler); $arrArgsPage = array(); $this->generateTemplateWordDocument($arrArgsPage); if ($this->_debug->getActive() == 1) { PhpdocxLogger::logger('Debug is active, add messages to objDebug.', 'debug'); libxml_use_internal_errors(true); simplexml_load_string( $this->_wordDocumentT, 'SimpleXMLElement', LIBXML_NOWARNING ); $xmlErrors = libxml_get_errors(); if (is_array($xmlErrors)) { $this->_debug->addMessage($xmlErrors); libxml_clear_errors(); } } PhpdocxLogger::logger('Add word/document.xml content to DOCX file.', 'info'); $documentHandler = fopen($this->_baseTemplateFilesPath.'/word/document.xml', "w+"); if (self::$_encodeUTF) { $contentDocumentXML = utf8_encode($this->_wordDocumentT); //TODO: sot out encoding problems fwrite($documentHandler, utf8_encode($this->_wordDocumentT)); } else { if ($this->_phpdocxconfig['settings']['encode_to_UTF8'] == 'true' && !PhpdocxUtilities::isUtf8($this->_wordDocumentT)) { $contentDocumentXML = utf8_encode($this->_wordDocumentT); } else { $contentDocumentXML = $this->_wordDocumentT; } fwrite($documentHandler, $this->_wordDocumentT); } fclose($documentHandler); if($this->_wordFootnotesC != ''){ PhpdocxLogger::logger('Add word/footnote.xml content to DOCX file.', 'info'); $footnoteHandler = fopen($this->_baseTemplateFilesPath.'/word/footnote.xml', "w+"); if (self::$_encodeUTF) { //TODO: sot out encoding problems fwrite($footnoteHandler, utf8_encode($this->_wordFootnotesT)); } else { if ($this->_phpdocxconfig['settings']['encode_to_UTF8'] == 'true') { if (!PhpdocxUtilities::isUtf8($this->_wordFootnotesT)) { $this->_wordFootnotesT = utf8_encode($this->_wordFootnotesT); } } fwrite($footnoteHandler, $this->_wordFootnotesT); } fclose($documentHandler); } $numberingHandler = fopen($this->_baseTemplateFilesPath.'/word/numbering.xml', "w+"); fwrite($numberingHandler, $this->_wordNumberingT); fclose($numberingHandler); PhpdocxLogger::logger('Close ZIP file', 'info'); $this->recursiveInsert($this->_zipDocx, $this->_baseTemplateFilesPath, $this->_baseTemplateFilesPath); //Lets now insert the photos inserted by the embedHTML method if (is_dir($this->_baseTemplateFilesPath.'/word/mediaTemplate')){ $contentsDir = scandir($this->_baseTemplateFilesPath.'/word/mediaTemplate'); $predefinedExtensions = explode(',', PHPDOCX_ALLOWED_IMAGE_EXT); foreach($contentsDir as $element){ $arrayExtension = explode('.', $element); $extension = strtolower(array_pop($arrayExtension)); if (in_array($extension, $predefinedExtensions)){ $this->_zipDocx->addFile($this->_baseTemplateFilesPath.'/word/mediaTemplate/'.$element, 'word/media/'.$element); } //Now we remove the image from the mediaTemplate folder $this->_zipDocx->deleteName('word/mediaTemplate/'.$element); } //And now we delete the mediaTemplate folder $deleteMediaTemplate = $this->_zipDocx->deleteName('word/mediaTemplate/'); } //Check if there are openbookmars and if so throw an error if (count($this->_bookmarksIds) > 0) { PhpdocxLogger::logger('There are unclosed bookmarks. Please, check that all open bookmarks tags are properly closed.', 'fatal'); } $this->_zipDocx->close(); $arrpathFile = pathinfo($fileName); PhpdocxLogger::logger('Copy DOCX file using a new name.', 'info'); copy( $this->_tempFile, $fileName . '.' . $this->_extension ); if ($this->_debug->getActive() == 1) { PhpdocxLogger::logger('Debug is active, show messages.', 'debug'); echo $this->_debug; } // delete temp file if (is_file($this->_tempFile) && is_writable($this->_tempFile)) { unlink($this->_tempFile); } } /** * * Transform a word document to a text file * * @example ../examples/easy/Docx2Text.php * @param string $path. Path to the docx from which we wish to import the content * @param string $path. Path to the text file output * @param array styles. * keys: table => true/false,list => true/false, paragraph => true/false, footnote => true/false, endnote => true/false, chart => (0=false,1=array,2=table) */ public static function docx2txt($from, $to, $options = array()) { $text = new Docx2Text($options); $text->setDocx($from); $text->extract($to); } /** * Imports an existing style sheet from an existing docx document. * * @access private * @param string $path. Must be a valid path to an existing .docx, .dotx o .docm document * @param string $type. You may choose 'replace' (overwrites the current styles) or 'merge' (adds the selected styles) * @param array $myStyles. A list of specific styles to be merged. If it is empty or the choosen type is 'replace' it will be ignored. */ private function importStyles($path, $type= 'replace', $myStyles= array(), $styleIdentifier = 'styleName') { $zipStyles = new ZipArchive(); try { $openStyle = $zipStyles->open($path); if ($openStyle !== true) { throw new Exception('Error while opening the Style Template: please, check the path'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } if ($type == 'replace') { //Now we overwrite the original styles file try { $extractingStyleFile = $zipStyles->extractTo($this->_baseTemplateFilesPath.'/','word/styles.xml'); if (!$extractingStyleFile) { throw new Exception('Error while trying to overwrite the styles.xml of the base template'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } //In order not to loose certain styles needed for certain PHPDOCX methods we should merge them $this->importStyles(PHPDOCX_BASE_TEMPLATE, 'merge', $this->_defaultPHPDOCXStyles); } else { //We will first extract the new styles from the external docx try { $newStyles = $zipStyles->getFromName('word/styles.xml'); if ($newStyles == '') { throw new Exception('Error while extracting the styles from the external docx'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } //let's parse the different styles via XPath $newStylesDoc = new DOMDocument(); $newStylesDoc->loadXML($newStyles); $stylesXpath = new DOMXPath($newStylesDoc); $stylesXpath->registerNamespace('w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'); $queryStyle = '//w:style'; $styleNodes = $stylesXpath->query($queryStyle); //Let's get the original styles as a DOMdocument try{ $styleHandler = fopen($this->_baseTemplateFilesPath.'/word/styles.xml', 'r'); $styleXML = fread($styleHandler, filesize($this->_baseTemplateFilesPath.'/word/styles.xml')); fclose($styleHandler); $this->_wordStylesT = $styleXML; if ($styleXML == '') { throw new Exception('Error while extracting the style file from the base template'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } $stylesDocument = new DomDocument(); $stylesDocument->loadXML($this->_wordStylesT); $baseNode = $stylesDocument->documentElement; $stylesDocumentXPath = new DOMXPath($stylesDocument); $stylesDocumentXPath->registerNamespace('w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'); $query = '//w:style'; $originalNodes = $stylesDocumentXPath->query($query); //Now we start to insert the new styles at the end of the styles.xml foreach($styleNodes as $node){ // in order to avoid duplicated Ids we first remove from the // original styles.xml any duplicity with the new ones // TODO: check performance foreach($originalNodes as $oldNode){ if($styleIdentifier == 'styleID'){ if($oldNode->getAttribute('w:styleId') == $node->getAttribute('w:styleId') && in_array($oldNode->getAttribute('w:styleId'), $myStyles)){ $oldNode->parentNode->removeChild($oldNode); } }else{ $oldName = $oldNode->getElementsByTagName('w:name'); if($oldNode->getAttribute('w:styleId') == $node->getAttribute('w:styleId') && in_array($oldName, $myStyles)){ $oldNode->parentNode->removeChild($oldNode); } } } if(count($myStyles)>0){ //Lets insert the selected styles if($styleIdentifier == 'styleID'){ if(in_array($node->getAttribute('w:styleId'), $myStyles)){ $insertNode = $stylesDocument->importNode($node, true); $baseNode->appendChild($insertNode); } }else{ $nodeChilds = $node->childNodes; foreach($nodeChilds as $child){ if ($child->nodeName == 'w:name'){ $styleName = $child->getAttribute('w:val'); if(in_array($styleName, $myStyles)){ $insertNode = $stylesDocument->importNode($node, true); $baseNode->appendChild($insertNode); } } } } }else{ $insertNode = $stylesDocument->importNode($node, true); $baseNode->appendChild($insertNode); } } $this->_wordStylesT = $stylesDocument->saveXML(); try { $stylesFile=fopen($this->_baseTemplateFilesPath.'/word/styles.xml', 'w'); if ($stylesFile == false) { throw new Exception('Error while opening the base template styles.xml file'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } try { $writeStyles = fwrite($stylesFile,$this->_wordStylesT); if ($writeStyles == 0) { throw new Exception('There were no new styles written'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } } PhpdocxLogger::logger('Importing styles from an external docx.', 'info'); } /** * Imports an existing theme from an existing docx document. * * @access private * @param string $path. Must be a valid path to an existing .docx, .dotx o .docm document */ private function importThemeXML($path){ try { $zipTheme = new ZipArchive(); $extractingThemeFile = $zipTheme->extractTo($this->_baseTemplateFilesPath.'/','word/theme/theme1.xml'); if (!$extractingThemeFile) { throw new Exception('Error while trying to overwrite the theme1.xml of the base template'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } } /** * Imports an existing webSettings.xml file from an existing docx document. * * @access private * @param string $path. Must be a valid path to an existing .docx, .dotx o .docm document */ private function importWebSettingsXML($path){ try { $zipWebSettings = new ZipArchive(); $extractingWebSettingsFile = $zipTheme->extractTo($this->_baseTemplateFilesPath.'/','word/webSettings.xml'); if (!$extractingWebSettingsFile) { throw new Exception('Error while trying to overwrite the webSettings.xml of the base template'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } } /** * Imports an existing settings.xml file from an existing docx document. * * @access private * @param string $path. Must be a valid path to an existing .docx, .dotx o .docm document */ private function importSettingsXML($path){ try { $zipSettings = new ZipArchive(); $extractingSettingsFile = $zipTheme->extractTo($this->_baseTemplateFilesPath.'/','word/settings.xml'); if (!$extractingSettingsFile) { throw new Exception('Error while trying to overwrite the settings.xml of the base template'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } } /** * Imports an existing fontTable.xml file from an existing docx document. * * @access private * @param string $path. Must be a valid path to an existing .docx, .dotx o .docm document */ private function importFontTableXML($path){ try { $zipFontTable = new ZipArchive(); $extractingFontTableFile = $zipTheme->extractTo($this->_baseTemplateFilesPath.'/','word/fontTable.xml'); if (!$extractingFontTableFile) { throw new Exception('Error while trying to overwrite the fontTable.xml of the base template'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } } /** * Transform to UTF-8 charset * * @access public */ public function setEncodeUTF8() { self::$_encodeUTF = 1; } /** * Change default language. * @example ../examples/easy/Language.php * @param $lang Locale: en-US, es-ES... * @access public */ public function setLanguage($lang = null) { if (!$lang) { $lang = 'en-US'; } //Let's get the original styles as a DOMdocument try{ $styleHandler = fopen($this->_baseTemplateFilesPath.'/word/styles.xml', 'r'); $styleXML = fread($styleHandler, 10000000); fclose($styleHandler); $this->_wordStylesT = $styleXML; if ($styleXML == '') { throw new Exception('Error while extracting the style file from the base template to stablish default language'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } $stylesDocument = new DomDocument(); $stylesDocument->loadXML($this->_wordStylesT); $langNode = $stylesDocument->getElementsByTagName('lang'); $langNode->item(0)->setAttribute('w:val', $lang); $langNode->item(0)->setAttribute('w:eastAsia', $lang); $this->_wordStylesT = $stylesDocument->saveXML(); try { $stylesFile=fopen($this->_baseTemplateFilesPath.'/word/styles.xml', 'w'); if ($stylesFile == false) { throw new Exception('Error while opening the base template styles.xml file'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } try { $writeStyles = fwrite($stylesFile,$this->_wordStylesT ); if ($writeStyles == 0) { throw new Exception('There was an error while trying to set the default language'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } PhpdocxLogger::logger('Set language.', 'info'); } /** * Add style * * @param string lang Language * @access private */ private function addStyle($lang = 'en-US') { $style = CreateStyle::getInstance(); $style->createStyle($lang); PhpdocxLogger::logger('Add styles to styles document.', 'info'); $this->_wordStylesC .= (string) $style; } /** * Imports styles into the template stylesheet. * * @access private * @param string $templateStyles * @param DOMDocument $importedStylesheet */ private function addStylesTemplate($templateStyles, $importedStylesheet) { $templateStylesheet = new DomDocument(); $templateStylesheet->loadXML($templateStyles); //let's parse the different styles via XPath $stylesXpath = new DOMXPath($importedStylesheet); $stylesXpath->registerNamespace('w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'); $queryStyle = '//w:style'; $styleNodes = $stylesXpath->query($queryStyle); //Let's get the original styles as a DOMNode $stylesDocument = new DomDocument(); $stylesDocument->loadXML($templateStyles); $baseNode = $stylesDocument->documentElement; //Now we start to insert the new styles at the end of the styles.xml foreach ($styleNodes as $node) { // in order to avoid duplicated Ids we first remove from the // original styles any duplicity with the new ones $originalNodes = $stylesDocument->childNodes; foreach($originalNodes as $oldNode) { if ($oldNode->getAttribute('w:styleId') == $node->getAttribute('w:styleId')) { $oldNode->parent->removeChild($oldNode); } } $insertNode = $stylesDocument->importNode($node, true); $baseNode->appendChild($insertNode); } PhpdocxLogger::logger('Importing styles into the template stylesheet.', 'info'); return $stylesDocument->saveXML(); } /** * Generate content type * * @access private */ private function generateContentType() { $this->generateDEFAULT( 'rels', 'application/vnd.openxmlformats-package.relationships+xml' ); $this->generateDEFAULT('xml', 'application/xml'); $this->generateDEFAULT('htm', 'application/xhtml+xml'); $this->generateDEFAULT('rtf', 'application/rtf'); $this->generateDEFAULT('zip', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml'); $this->generateDEFAULT('mht', 'message/rfc822'); $this->generateDEFAULT('wml', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml'); $this->generateOVERRIDE( '/word/numbering.xml', 'application/vnd.openxmlformats-officedocument.wordprocessingml.' . 'numbering+xml' ); $this->generateOVERRIDE( '/word/styles.xml', 'application/vnd.openxmlformats-officedocument.wordprocessingml' . '.styles+xml' ); $this->generateOVERRIDE( '/docProps/app.xml', 'application/vnd.openxmlformats-officedocument.extended-' . 'properties+xml' ); $this->generateOVERRIDE( '/docProps/custom.xml', 'application/vnd.openxmlformats-officedocument.' . 'custom-properties+xml' ); $this->generateOVERRIDE( '/word/settings.xml', 'application/' . 'vnd.openxmlformats-officedocument.wordprocessingml.settings+xml' ); $this->generateOVERRIDE( '/word/theme/theme1.xml', 'application/vnd.openxmlformats-officedocument.theme+xml' ); $this->generateOVERRIDE( '/word/fontTable.xml', 'application/vnd.openxmlformats-officedocument.wordprocessingml.' . 'fontTable+xml' ); $this->generateOVERRIDE( '/word/webSettings.xml', 'application/vnd.openxmlformats-officedocument.wordprocessingml' . '.webSettings+xml' ); if ($this->_wordFooterC != '' || $this->_wordHeaderC != '') { $this->generateOVERRIDE( '/word/header.xml', 'application/vnd.openxmlformats-officedocument.' . 'wordprocessingml.header+xml' ); $this->generateOVERRIDE( '/word/footer.xml', 'application/vnd.openxmlformats-officedocument.' . 'wordprocessingml.footer+xml' ); $this->generateOVERRIDE( '/word/footnotes.xml', 'application/vnd.openxmlformats-officedocument.' . 'wordprocessingml.footnotes+xml' ); $this->generateOVERRIDE( '/word/endnotes.xml', 'application/vnd.openxmlformats-officedocument.' . 'wordprocessingml.endnotes+xml' ); } $this->generateOVERRIDE( '/docProps/core.xml', 'application/vnd.openxmlformats-package.core-properties+xml' ); } /** * Generate DEFAULT * * @access private */ private function generateDEFAULT($extension, $contentType) { $strContent = $this->_contentTypeT->saveXML(); if ( strpos($strContent, 'Extension="' . $extension) === false ) { $strContentTypes = ' '; $tempNode = $this->_contentTypeT->createDocumentFragment(); $tempNode->appendXML($strContentTypes); $this->_contentTypeT->documentElement->appendChild($tempNode); } } /** * * * @access private */ private function generateDefaultFonts() { $font = array( 'name' => 'Calibri', 'pitch' => 'variable', 'usb0' => 'A00002EF', 'usb1' => '4000207B', 'usb2' => '00000000', 'usb3' => '00000000', 'csb0' => '0000009F', 'csb1' => '00000000', 'family' => 'swiss', 'charset' => '00', 'panose1' => '020F0502020204030204' ); $this->addFont($font); $font = array( 'name' => 'Times New Roman', 'pitch' => 'variable', 'usb0' => 'E0002AEF', 'usb1' => 'C0007841', 'usb2' => '00000009', 'usb3' => '00000000', 'csb0' => '000001FF', 'csb1' => '00000000', 'family' => 'roman', 'charset' => '00', 'panose1' => '02020603050405020304' ); $this->addFont($font); $font = array( 'name' => 'Cambria', 'pitch' => 'variable', 'usb0' => 'A00002EF', 'usb1' => '4000004B', 'usb2' => '00000000', 'usb3' => '00000000', 'csb0' => '0000009F', 'csb1' => '00000000', 'family' => 'roman', 'charset' => '00', 'panose1' => '02040503050406030204' ); $this->addFont($font); } /** * Generate DefaultWordRels * * @access private */ private function generateDefaultWordRels() { self::$intIdWord++; PhpdocxLogger::logger('New ID ' . self::$intIdWord . ' . numbering.xml.', 'debug'); $this->_wordRelsDocumentRelsC .= $this->generateRELATIONSHIP( 'rId' . self::$intIdWord, 'numbering', 'numbering.xml' ); self::$intIdWord++; PhpdocxLogger::logger('New ID ' . self::$intIdWord . ' . theme/theme1.xml.', 'debug'); $this->_wordRelsDocumentRelsC .= $this->generateRELATIONSHIP( 'rId' . self::$intIdWord, 'theme', 'theme/theme1.xml' ); self::$intIdWord++; PhpdocxLogger::logger('New ID ' . self::$intIdWord . ' . numbering.xml.', 'debug'); $this->_wordRelsDocumentRelsC .= $this->generateRELATIONSHIP( 'rId' . self::$intIdWord, 'webSettings', 'webSettings.xml' ); self::$intIdWord++; PhpdocxLogger::logger('New ID ' . self::$intIdWord . ' . webSettings.xml.', 'debug'); $this->_wordRelsDocumentRelsC .= $this->generateRELATIONSHIP( 'rId' . self::$intIdWord, 'fontTable', 'fontTable.xml' ); self::$intIdWord++; PhpdocxLogger::logger('New ID ' . self::$intIdWord . ' . fontTable.xml.', 'debug'); $this->_wordRelsDocumentRelsC .= $this->generateRELATIONSHIP( 'rId' . self::$intIdWord, 'settings', 'settings.xml' ); self::$intIdWord++; PhpdocxLogger::logger('New ID ' . self::$intIdWord . ' . settings.xml.', 'debug'); $this->_wordRelsDocumentRelsC .= $this->generateRELATIONSHIP( 'rId' . self::$intIdWord, 'styles', 'styles.xml' ); } /** * Generate OVERRIDE * * @access private * @param string $partName * @param string $contentType */ private function generateOVERRIDE($partName, $contentType) { $strContent = $this->_contentTypeT->saveXML(); if ( strpos($strContent, 'PartName="' . $partName . '"') === false ) { $strContentTypes = ''; $tempNode = $this->_contentTypeT->createDocumentFragment(); $tempNode->appendXML($strContentTypes); $this->_contentTypeT->documentElement->appendChild($tempNode); } } /** * Generate RELATIONSHIP * * @access private */ private function generateRELATIONSHIP() { $arrArgs = func_get_args(); if ($arrArgs[1] == 'vbaProject') { $type = 'http://schemas.microsoft.com/office/2006/relationships/vbaProject'; } else { $type = 'http://schemas.openxmlformats.org/officeDocument/2006/' . 'relationships/' . $arrArgs[1]; } if (!isset($arrArgs[3])) { $nodeWML = ''; } else { $nodeWML = ''; } $relsNode = $this->_wordRelsDocumentRelsT->createDocumentFragment(); $relsNode->appendXML($nodeWML); $this->_wordRelsDocumentRelsT->documentElement->appendChild($relsNode); } /** * Gnerate RELATIONSHIP * * @access private */ private function generateRELATIONSHIPTemplate() { $arrArgs = func_get_args(); if ($arrArgs[1] == 'vbaProject') { $type = 'http://schemas.microsoft.com/office/2006/relationships/vbaProject'; } else { $type = 'http://schemas.openxmlformats.org/officeDocument/2006/' . 'relationships/' . $arrArgs[1]; } if (!isset($arrArgs[3])) { $nodeWML = ''; } else { $nodeWML = ''; } return $nodeWML; } /** * Generate SECTPR * * @access private * @param array $args Section style */ private function generateSECTPR($args = '') { $page = CreatePage::getInstance(); $page->createSECTPR($args); $this->_wordDocumentC .= (string) $page; } /** * Generates an element in settings.xml * * @access private */ private function generateSetting($tag) { if((!in_array($tag, self::$settings))){ self::$log->fatal('Incorrect setting tag'); } $settingIndex = array_search($tag, self::$settings); try{ $settings = fopen($this->_baseTemplateFilesPath.'/word/settings.xml', "r"); $baseTemplateSettingsT = fread($settings, 1000000); fclose($settings); if ($baseTemplateSettingsT == '') { throw new Exception('Error while extracting settings.xml file from the base template to insert the selected element'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } $this->_wordSettingsT = new DOMDocument(); $this->_wordSettingsT->loadXML($baseTemplateSettingsT); $selectedElements = $this->_wordSettingsT->documentElement->getElementsByTagName($tag); if($selectedElements->length == 0){ $settingsElement = $this->_wordSettingsT->createDocumentFragment(); $settingsElement->appendXML('<' . $tag . ' xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" />'); $childNodes = $this->_wordSettingsT->documentElement->childNodes; $index = false; foreach($childNodes as $node){ $name = $node->nodeName; $index = array_search($node->nodeName, self::$settings); if($index > $settingIndex){ $node->parentNode->insertBefore($settingsElement, $node); break; } } //in case no node was found (pretty unlikely)we should append the node if (!$index) { $this->_wordSettingsT->documentElement->appendChild($settingsElement); } $newSettings = $this->_wordSettingsT->saveXML(); $settingsHandle = fopen($this->_baseTemplateFilesPath.'/word/settings.xml', "w+"); $contents = fwrite($settingsHandle, $newSettings); fclose($settingsHandle); } } /** * Generate ContentType XML template * * @access private */ private function generateTemplateContentType() { $this->_wordContentTypeT = '' . '' . $this->_contentTypeC . ''; } /** * Generate DocPropsApp XML template * * @access private */ private function generateTemplateDocPropsApp() { $this->_docPropsAppT = '' . '' . '0111' . 'Microsoft Office Word' . '411' . 'false'; if ($this->_docPropsAppC) { $this->_docPropsAppT .= $this->_docPropsAppC; } else { $this->_docPropsAppT .= 'Company'; } $this->_docPropsAppT .= 'false' . '1' . 'falsefalse' . '12.0000'; } /** * Generate DocPropsCore XML template * * @access private */ private function generateTemplateDocPropsCore() { date_default_timezone_set('UTC'); if ($this->_markAsFinal) { $this->_docPropsCoreT = '' . 'Title' . 'Subject2mdc' . 'Description' . 'user1' . '' . date('c') . '' . date('c') . 'Final' . ''; } else { $this->_docPropsCoreT = ' ' . '' . 'TitleSubject' . '2mdcDescription' . 'user' . '1' . '' . date('c') . '' . date('c') . ''; } } /** * Generate DocPropsCustom XML template * * @access private */ private function generateTemplateDocPropsCustom() { $this->_docPropsCustomT = '' . '' . 'true' . ''; } /** * Generate RelsRels XML template * * @access private */ private function generateTemplateRelsRels() { $this->_relsRelsT = '' . '' . $this->generateRELATIONSHIP( 'rId3', 'extended-properties', 'docProps/app.xml' ) . '' . $this->generateRELATIONSHIP( 'rId1', 'officeDocument', 'word/document.xml' ); if ($this->_markAsFinal) { $this->_relsRelsT .= ''; } $this->_relsRelsT .= ''; } /** * Generate WordDocument XML template * * @access private */ private function generateTemplateWordDocument() { $arrArgs = func_get_args(); //$this->generateSECTPR($arrArgs[0]); $this->_wordDocumentC .= $this->_sectPr->saveXML($this->_sectPr->documentElement);//FIXME: I am insertying by hand the sections of the base template if (!empty($this->_wordHeaderC)) { $this->_wordDocumentC = str_replace( '__GENERATEHEADERREFERENCE__', '<' . CreateDocx::NAMESPACEWORD . ':headerReference ' . CreateDocx::NAMESPACEWORD . ':type="default" r:id="rId' . $this->_idWords['header'] . '">', $this->_wordDocumentC ); } if (!empty($this->_wordFooterC)) { $this->_wordDocumentC = str_replace( '__GENERATEFOOTERREFERENCE__', '<' . CreateDocx::NAMESPACEWORD . ':footerReference ' . CreateDocx::NAMESPACEWORD . ':type="default" r:id="rId' . $this->_idWords['footer'] . '">', $this->_wordDocumentC ); } $this->_wordDocumentT = '' . '<' . CreateDocx::NAMESPACEWORD . ':document xmlns:ve=' . '"http://schemas.openxmlformats.org/markup-compatibility/2006" ' . 'xmlns:o="urn:schemas-microsoft-com:office:office"' . ' xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006' . '/relationships" xmlns:m="http://schemas.openxmlformats.org/' . 'officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml"'. ' xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/' . 'wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:' . 'office:word" xmlns:w="http://schemas.openxmlformats.org/' . 'wordprocessingml/2006/main" xmlns:wne="http://schemas' . '.microsoft.com/office/word/2006/wordml">' . $this->_background. '<' . CreateDocx::NAMESPACEWORD . ':body>' . $this->_wordDocumentC . '' . ''; } /** * Generate WordEndnotes XML template * * @access private */ private function generateTemplateWordEndnotes() { $this->_wordEndnotesT = '' . '<' . CreateDocx::NAMESPACEWORD . ':endnotes xmlns:ve' . '="http://schemas.openxmlformats.org/markup-compatibility/2006" ' . 'xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="' . 'http://schemas.openxmlformats.org/officeDocument/2006/' . 'relationships" xmlns:m="http://schemas.openxmlformats.org/' . 'officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:' . 'vml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006' . '/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:' . 'office:word" xmlns:w="http://schemas.openxmlformats.org/' . 'wordprocessingml/2006/main" xmlns:wne="http://schemas' . '.microsoft.com/office/word/2006/wordml">' . $this->_wordEndnotesC . ''; self::$intIdWord++; PhpdocxLogger::logger('New ID ' . self::$intIdWord . ' . Endnotes.', 'debug'); $this->_wordRelsDocumentRelsC .= $this->generateRELATIONSHIP( 'rId' . self::$intIdWord, 'endnotes', 'endnotes.xml' ); $this->generateOVERRIDE( '/word/endnotes.xml', 'application/vnd.openxmlformats-officedocument.wordprocessingml' . '.endnotes+xml' ); } /** * Generate WordFontTable XML template * * @access private */ private function generateTemplateWordFontTable() { $this->_wordFontTableT = '' . '<' . CreateDocx::NAMESPACEWORD . ':fonts xmlns:r="http://' . 'schemas.openxmlformats.org/officeDocument/2006/' . 'relationships" xmlns:w="http://schemas.openxmlformats.org/' . 'wordprocessingml/2006/main">' . $this->_wordFontTableC . ''; } /** * Generate WordFooter XML template * * @access private */ private function generateTemplateWordFooter() { self::$intIdWord++; PhpdocxLogger::logger('New ID ' . self::$intIdWord . ' . Footer.', 'debug'); $this->_idWords['footer'] = self::$intIdWord; $this->_wordFooterT = ' <' . CreateDocx::NAMESPACEWORD . ':ftr xmlns:ve' . '="http://schemas.openxmlformats.org/markup-compatibility/' . '2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns' . ':r="http://schemas.openxmlformats.org/officeDocument/2006/' . 'relationships" xmlns:m="http://schemas.openxmlformats.org/' . 'officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml' . '" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/' . 'wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:' . 'office:word" xmlns:w="http://schemas.openxmlformats.org/' . 'wordprocessingml/2006/main" xmlns:wne="http://schemas' . '.microsoft.com/office/word/2006/wordml">' . $this->_wordFooterC . ''; $this->_wordRelsDocumentRelsC .= $this->generateRELATIONSHIP( 'rId' . self::$intIdWord, 'footer', 'footer.xml' ); return 'rId' . self::$intIdWord; } /** * Generate WordFootnotes XML template * * @access private */ private function generateTemplateWordFootnotes() { $this->_wordFootnotesT = '' . '<' . CreateDocx::NAMESPACEWORD . ':footnotes xmlns:ve="' . 'http://schemas.openxmlformats.org/markup-compatibility/2006" ' . 'xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="' . 'http://schemas.openxmlformats.org/officeDocument/2006/' . 'relationships" xmlns:m="http://schemas.openxmlformats.org/' . 'officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:' . 'vml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006' . '/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:' . 'office:word" xmlns:w="http://schemas.openxmlformats.org/' . 'wordprocessingml/2006/main" xmlns:wne="http://schemas.microsoft' . '.com/office/word/2006/wordml">' . $this->_wordFootnotesC . ''; self::$intIdWord++; PhpdocxLogger::logger('New ID ' . self::$intIdWord . ' . Footnotes.', 'debug'); $this->_wordRelsDocumentRelsC .= $this->generateRELATIONSHIP( 'rId' . self::$intIdWord, 'footnotes', 'footnotes.xml' ); $this->generateOVERRIDE( '/word/footnotes.xml', 'application/vnd.openxmlformats-officedocument.wordprocessingml' . '.footnotes+xml' ); } /** * Generate WordHeader XML template * * @access private */ private function generateTemplateWordHeader() { self::$intIdWord++; PhpdocxLogger::logger('New ID ' . self::$intIdWord . ' . Header.', 'debug'); $this->_idWords['header'] = self::$intIdWord; $this->_wordHeaderT = '' . '<' . CreateDocx::NAMESPACEWORD . ':hdr xmlns:ve="http://schemas.openxmlformats.org/markup' . '-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:' . 'office:office" xmlns:r="http://schemas.openxmlformats.org/' . 'officeDocument/2006/relationships" xmlns:m="http://schemas' . '.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:' . 'schemas-microsoft-com:vml" xmlns:wp="http://schemas' . '.openxmlformats.org/drawingml/2006/wordprocessingDrawing" ' . 'xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="' . 'http://schemas.openxmlformats.org/wordprocessingml/2006/' . 'main" xmlns:wne="http://schemas.microsoft.com/office/word/' . '2006/wordml"> ' . $this->_wordHeaderC . ''; $this->_wordRelsDocumentRelsC .= $this->generateRELATIONSHIP( 'rId' . self::$intIdWord, 'header', 'header.xml' ); return 'rId' . self::$intIdWord; } /** * Generate WordNumbering XML template * * @access private */ private function generateTemplateWordNumbering() { $this->_wordNumberingT = '' . '' . '' . '' . '' . '' . ' ' . '' . '' . '' . '' . '' . '' . '' . '' . '' . '' . '' . ''; } /** * Generate WordNumbering XML template * * @access private */ private function generateTemplateWordNumberingStyles() { $this->_wordNumberingT = '' . '' . $this->_wordDocumentStyles . '' . ''; } /** * Generate WordRelsDocumentRels XML template * * @access private */ private function generateTemplateWordRelsDocumentRels() { $this->_wordRelsDocumentRelsT = '' . '' . $this->_wordRelsDocumentRelsC . ''; } /** * Generate WordRelsFooterRels XML template * * @access private */ private function generateTemplateWordRelsFooterRels() { $this->_wordRelsFooterRelsT = '' . '' . $this->_wordRelsFooterRelsC . ''; } /** * Generate WordRelsHeaderRels XML template * * @access private */ private function generateTemplateWordRelsHeaderRels() { $this->_wordRelsHeaderRelsT = '' . '' . $this->_wordRelsHeaderRelsC . ''; } /** * Generate WordSettings XML template * * @access private */ private function generateTemplateWordSettings() { $this->_wordSettingsT = $this->_wordSettingsC; } /** * Generate WordStyles XML template * * @access private */ private function generateTemplateWordStyles() { $this->_wordStylesT = '<' . CreateDocx::NAMESPACEWORD . ':styles xmlns:r="http://' . 'schemas.openxmlformats.org/officeDocument/2006/relationships' . '" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/' . '2006/main">' . $this->_wordStylesC . ''; } /** * Generate WordThemeTheme1 XML template * * @access private */ private function generateTemplateWordThemeTheme1() { $this->addTheme($this->_defaultFont); $this->_wordThemeThemeT = '<' . CreateTheme1::NAMESPACEWORD . ':theme xmlns:a="http://' . 'schemas.openxmlformats.org/drawingml/2006/main" name="' . 'Tema de Office">' . $this->_wordThemeThemeC . ''; } /** * Generate WordWebSettings XML template * * @access private */ private function generateTemplateWordWebSettings() { $this->_wordWebSettingsT = $this->_wordWebSettingsC; } /** * Generates a TitlePg element in SectPr * * @access private */ private function generateTitlePg() { $foundNodes = $this->_sectPr->documentElement->getElementsByTagName('w:TitlePg'); if($foundNodes->length == 0){ $newSectNode = ''; $sectNode = $this->_sectPr->createDocumentFragment(); $sectNode->appendXML($newSectNode); $refNode =$this->_sectPr->documentElement->appendChild($sectNode); } } /** * To add support of sys_get_temp_dir for PHP versions under 5.2.1 * * @access private * @return string */ public static function getTempDir() { if ( !function_exists('sys_get_temp_dir')) { function sys_get_temp_dir() { if ($temp = getenv('TMP')) { return $temp; } if ($temp = getenv('TEMP')) { return $temp; } if ($temp = getenv('TMPDIR')) { return $temp; } $temp = tempnam(__FILE__,''); if (file_exists($temp)) { unlink($temp); return dirname($temp); } return null; } } else { return sys_get_temp_dir(); } } /** * Parse path dir * * @access private * @param string $dir Directory path */ private function parsePath($dir) { $slash = 0; $path = ''; if (($slash = strrpos($dir, '/')) !== false) { $slash += 1; $path = substr($dir, 0, $slash); } $punto = strpos(substr($dir, $slash), '.'); $nombre = substr($dir, $slash, $punto); $extension = substr($dir, $punto + $slash + 1); return array( 'path' => $path, 'nombre' => $nombre, 'extension' => $extension ); } /** * Delete a file or recursively delete a directory * * @param string $str path to file or directory */ private function recursiveDelete($str){ if(is_file($str)){ return @unlink($str); } elseif(is_dir($str)){ $scan = glob(rtrim($str,'/').'/*'); foreach($scan as $index=>$path){ $this->recursiveDelete($path); } return @rmdir($str); } } /** * * Adds directory contents recursively into a zip. * * @param string $fileName. The path to the dir to add. * * @param string $myZip. The zip where the contents of the dir should be added. * */ private function recursiveInsert($myZip, $fileName, $basePath){ $length = strlen($basePath); if(is_dir($fileName)){ $contentsDir = scandir($fileName); foreach($contentsDir as $element){ if($element != "." && $element !=".."){ $this->recursiveInsert($myZip, $fileName."/".$element, $basePath); } } }else{ $newName = substr($fileName, $length + 1); $myZip->addFile($fileName, $newName); } } /** * * Includes data in the setting.xml file. * * @param array $settings. The string with the nodes that should be included in the settings.xml file. * */ private function includeSettings($data){ try{ $baseSettings = $this->_baseTemplateZip->getFromName('word/settings.xml'); if ($baseSettings == '') { throw new Exception('Error while extracting the settings.xml file from the base template'); } } catch (Exception $e) { PhpdocxLogger::logger($e->getMessage(), 'fatal'); } $settingsDoc = new DOMDocument(); $settingsDoc->loadXML($baseSettings); $settings = $settingsDoc->documentElement; foreach($data as $key => $value){ $newNode = $settingsDoc->createDocumentFragment(); $newNode->appendXML($value); $settings->appendChild($newNode); } $settingsHandler = fopen($this->_baseTemplateFilesPath.'/word/settings.xml', "w+"); fwrite($settingsHandler, $settingsDoc->saveXML()); fclose($documentHandler); } }