static function getKeywords($filename, $xml_filenames = NULL) { $res = array(); if (is_null($xml_filenames)) { $xml_filenames = array('content.xml', 'styles.xml'); } foreach ($xml_filenames as $xml_filename) { $txt = ODF_Tools::getXml($filename, $xml_filename); $matches = array(); preg_match_all('/%([a-zA-Z0-9_]*)%/', $txt, $matches); $res = array_unique(array_merge($res, $matches[1])); } return $res; }
static function insertHTML($filename, $html, $placeholder = '%CONTENT%') { if (!strlen($html)) { return FALSE; } $xml = self::getXML($filename); if (!$xml) { trigger_error("Couldn't get Content XML from {$filename}"); return FALSE; } $dom = new DOMDocument(); $dom->loadXML($xml); $dom->preserveWhiteSpace = false; $dom->formatOutput = true; // Find where to insert into the document $insertPoint = NULL; foreach ($dom->getElementsByTagNameNS('urn:oasis:names:tc:opendocument:xmlns:text:1.0', 'p') as $elt) { if (trim($elt->textContent) == $placeholder) { $insertPoint = $elt; break; } } if (NULL === $insertPoint) { trigger_error("Could not find {$placeholder} in a paragraph to insert the new content"); return FALSE; } $paraStyle = $insertPoint->getAttribute('text:style-name'); // ADD STYLES $styleData = array('JethroBold' => array('fo:font-weight' => 'bold'), 'JethroItalic' => array('fo:font-style' => 'italic'), 'JethroUnderline' => array('style:text-underline-style' => 'solid', 'style:text-underline-width' => 'auto', 'style:text-underline-color' => 'font-color'), 'JethroSmall' => array('fo:font-size' => '6pt')); $aStylesElt = $dom->getElementsByTagNameNS('urn:oasis:names:tc:opendocument:xmlns:office:1.0', 'automatic-styles')->item(0); foreach ($styleData as $styleName => $attrs) { $newStyle = $dom->createElement('style:style'); $newStyle->setAttribute('style:name', $styleName); if ($styleName == 'JethroSmall') { $newStyle->setAttribute('style:family', 'paragraph'); $newStyle->setAttribute('style:parent-style-name', $paraStyle); } else { $newStyle->setAttribute('style:family', 'text'); } $aStylesElt->appendChild($newStyle); $newTp = $dom->createElement('style:text-properties'); foreach ($attrs as $key => $val) { $newTp->setAttribute($key, $val); if (0 === strpos('fo:', $key)) { $newTp->setAttribute($key . '-asian', $val); $newTp->setAttribute($key . '-complex', $val); } } $newStyle->appendChild($newTp); } // ADD CONTENT $map = array('p' => array('text:p', array('text:style-name' => $paraStyle)), 'br' => array('text:line-break', array()), 'b' => array('text:span', array('text:style-name' => 'JethroBold')), 'strong' => array('text:span', array('text:style-name' => 'JethroBold')), 'i' => array('text:span', array('text:style-name' => 'JethroItalic')), 'em' => array('text:span', array('text:style-name' => 'JethroItalic')), 'u' => array('text:span', array('text:style-name' => 'JethroUnderline')), 'small' => array('text:p', array('text:style-name' => 'JethroSmall'))); for ($i = 1; $i <= 6; $i++) { $map['h' . $i] = array('text:h', array('text:outline-level' => $i)); } $input = strip_tags($html, '<' . implode('>,<', array_keys($map)) . '>'); $input = preg_replace('#[>]\\s+#', '>', $input); // strip space after tags which would cause funny indents $input = '<body>' . $input . '</body>'; $htmlDom = new DOMDocument(); $htmlDom->preserveWhiteSpace = false; $htmlDom->formatOutput = true; $htmlDom->loadHTML($input); $newTags = array(); foreach ($map as $from => $to) { list($newTag, $newAttrs) = $to; ODF_Tools::renameTags($htmlDom, $from, $newTag, $newAttrs, 'urn:oasis:names:tc:opendocument:xmlns:text:1.0'); $newTags[] = $newTag; } // Now we need to get the result XML text and load it into a real XML DOM, not an HTML one $fragmentXML = $htmlDom->saveXML(); $begin = strpos($fragmentXML, '<body>') + 6; $length = strpos($fragmentXML, '</body>') - $begin; $fragmentXML = '<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" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" office:version="1.2"> ' . substr($fragmentXML, $begin, $length) . '</office:document-content>'; $fragmentDom = new DOMDocument(); $fragmentDom->loadXML($fragmentXML); foreach ($fragmentDom->firstChild->childNodes as $newNode) { $newNew = $dom->importNode($newNode, true); $insertPoint->parentNode->insertBefore($newNew, $insertPoint); } $insertPoint->parentNode->removeChild($insertPoint); return ODF_Tools::setXML($filename, $dom->saveXML()); }
function loadReplacements() { $congs = self::getCongregations(); $this->_keywords = $this->_cong_keywords = array(); if (is_file($this->_filename)) { $this->_keywords = ODF_Tools::getKeywords($this->_filename); } else { if (is_dir($this->_filename)) { foreach (self::getCongregations() as $congid => $cong) { foreach (explode(',', self::EXTENSIONS) as $extn) { $filename = $this->_filename . '/' . $cong['meeting_time'] . '.' . $extn; if (file_exists($filename)) { $this->_cong_keywords[$congid] = array_merge(array_get($this->_cong_keywords, $congid, array()), ODF_Tools::getKeywords($filename)); $this->_keywords = array_merge($this->_keywords, $this->_cong_keywords[$congid]); } } } } else { add_message("Could not find file " . $this->_filename, 'error'); } } $this->_keywords = array_unique($this->_keywords); $congs = self::getCongregations(); foreach ($congs as $congid => $cong) { $service = Service::findByDateAndCong($this->_service_date, $congid); if (empty($service)) { add_message("Could not find service for " . $cong['name'] . " on " . $this->_service_date, 'failure'); unset($congs[$congid]); continue; } $next_service = Service::findByDateAndCong(date('Y-m-d', strtotime($this->_service_date . ' +1 week')), $congid); $list = is_file($this->_filename) ? $this->_keywords : array_get($this->_cong_keywords, $congid, array()); foreach ($list as $keyword) { $keyword = strtoupper($keyword); if (0 === strpos($keyword, 'NAME_OF_')) { $role_title = substr($keyword, strlen('NAME_OF_')); $this->_replacements[$congid][$keyword] = $service->getPersonnelByRoleTitle($role_title); } else { if (0 === strpos($keyword, 'SERVICE_')) { $service_field = strtolower(substr($keyword, strlen('SERVICE_'))); $this->_replacements[$congid][$keyword] = $service->getValue($service_field); if (null === $this->_replacements[$congid][$keyword]) { $this->_replacements[$congid][$keyword] = ''; } if ($service_field == 'date') { // make a friendly date $this->_replacements[$congid][$keyword] = date('j F Y', strtotime($this->_replacements[$congid][$keyword])); } } else { if (0 === strpos($keyword, 'NEXT_SERVICE_')) { if (!empty($next_service)) { $service_field = strtolower(substr($keyword, strlen('NEXT_SERVICE_'))); $this->_replacements[$congid][$keyword] = $next_service->getValue($service_field); if ($service_field == 'date') { // make a short friendly date $this->_replacements[$congid][$keyword] = date('j M', strtotime($this->_replacements[$congid][$keyword])); } } else { $this->_replacements[$congid][$keyword] = ''; add_message('NEXT_SERVICE keyword could not be replaced because no next service was found for ' . $cong['name'], 'warning'); } } else { if (0 === strpos($keyword, 'CONGREGATION_')) { $cong_field = strtolower(substr($keyword, strlen('CONGREGATION_'))); $this->_replacements[$congid][$keyword] = $cong[$cong_field]; } else { $this->_replacements[$congid][$keyword] = ''; } } } } } } }
function mergeODT($source_file, $merged_file) { $xml_filename = 'content.xml'; require_once 'include/odf_tools.class.php'; $content = ODF_Tools::getXML($source_file, $xml_filename); if (empty($content)) { trigger_error('Could not find content within this ' . $extension . ' file'); return; } $HEADER_END = '</text:sequence-decls>'; $FOOTER_START = '</office:text>'; $middle_start_pos = strpos($content, $HEADER_END) + strlen($HEADER_END); $middle_end_pos = strpos($content, $FOOTER_START); if (NULL === $middle_start_pos || NULL === $middle_end_pos) { trigger_error('Cannot locate body content of the file'); return; } $middle_template = substr($content, $middle_start_pos, $middle_end_pos - $middle_start_pos); $header = substr($content, 0, $middle_start_pos); $footer = substr($content, $middle_end_pos); $merged_middle = ''; foreach ($this->getMergeData() as $id => $row) { if (empty($row)) { continue; } $this_middle = $middle_template; foreach ($row as $k => $v) { $this_middle = str_replace('%' . strtoupper($k) . '%', ODF_Tools::odfEntities(trim($v)), $this_middle); } $merged_middle .= $this_middle; } $merged_file = dirname($source_file) . '/jethro_merged_' . time() . session_id(); copy($source_file, $merged_file); ODF_Tools::setXML($merged_file, $header . $merged_middle . $footer, $xml_filename); }
function expandFile($filename) { $pathinfo = pathinfo($filename); $new_dirname = $pathinfo['dirname'] . '/' . $this->_service_date; if (!file_exists($new_dirname)) { mkdir($new_dirname); } if (is_writable($new_dirname)) { chdir($new_dirname); foreach ($this->_congregations as $congid => $cong) { $new_filename = substr($pathinfo['basename'], 0, -(strlen($pathinfo['extension']) + 1)) . '_' . $cong['meeting_time'] . '.' . $pathinfo['extension']; if (file_exists($new_filename)) { if (!unlink($new_filename)) { trigger_error("Could not overwrite " . $new_filename . ' - file open?'); continue; } } copy($filename, $new_filename); ODF_Tools::replaceKeywords($new_filename, array_get($_POST['replacements'], $congid, array())); chmod($new_filename, fileperms($filename)); $this->_generated_files[] = basename($pathinfo['dirname']) . ' / ' . basename($new_dirname) . ' / ' . $new_filename; } } }