Example #1
0
 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;
         }
     }
 }