vorlage_kurzbz, $oe_kurzbz, $version); * $doc->setFilename($filename); * $doc->addDataXML($data); * $doc->addImage($imagepath, $imagename, $imagecontenttype); * $doc->create($outputformat); * $doc->output(true); * $doc->close(); * * New: * $xml_data = $this->documentexportlib->getDataXML($data); * $images = [[ * 'path' => $imagepath, * 'name' => $imagename, * 'contenttype' => $imagecontenttype * ]]; */ class DocumentExportLib { private $_ci; /** * Constructor */ public function __construct() { // Gets CI instance $this->_ci =& get_instance(); // Load phrases $this->_ci->load->library('PhrasesLib', ['document_export', null], 'DocumentExportPhrases'); // Load libraries $this->_ci->load->library('DocumentLib'); $this->_ci->load->library('SignatureLib'); } /** * Laedt die XML Daten fuer die XSL Transformation anhand eines Arrays * * @param array $data Array mit Daten * @param string $root Bezeichnung des Root Nodes * * @return DOMDocument */ public function getDataArray($data, $root) { $xml_data = new DOMDocument(); $xml_data->loadXML($this->convertArrayToXML($data, $root)); return $xml_data; } /** * XML Daten fuer die XSL Transformation * * @param string $xml * * @return DOMDocument */ public function getDataXML($xml) { $xml_data = new DOMDocument(); $xml_data->loadXML($xml); return $xml_data; } /** * URL zu XML Datei die fuer XSLTransformation verwendet werden soll * * @param string $xml URL to XML * @param string $params GET parameter * * @return stdClass */ public function getDataURL($xml, $params) { $xml_found = false; $aktive_addons = array_filter(array_map('trim', explode(";", ACTIVE_ADDONS))); foreach($aktive_addons as $addon) { $xmlfile = DOC_ROOT . 'addons/' . $addon . '/rdf/' . $xml; if (file_exists($xmlfile)) { $xml_found = true; $xml_url = XML_ROOT . '../addons/' . $addon . '/rdf/' . $xml . '?' . $params; break; } } if (!$xml_found) $xml_url = XML_ROOT . $xml . '?' . $params; // Load the XML source $xml_data = new DOMDocument; if (!$xml_data->load($xml_url)) return error($this->_ci->DocumentExportPhrases->t("document_export", "error_xml_load", [ "url" => $xml_url, "xml" => $xml, "params" => $params ])); return success($xml_data); } /** * Adds a XML Tag for signatur to the document * * @param DomDocument $xml_data * * @return void */ protected function addSignToData($xml_data) { $signblock = $xml_data->createElement("signed", "true"); $xml_data->documentElement->appendChild($signblock); } /** * Adds a XML Tag for archive to the document * * @param DomDocument $xml_data * * @return void */ public function addArchiveToData($xml_data) { $archiv = $xml_data->createElement("archivierbar", "true"); $xml_data->documentElement->appendChild($archiv); } /** * Get the contents of a Document * * @param stdClass $vorlage A db entry from tbl_vorlage * @param DomDocument $xml_data * @param string $oe_kurzbz * @param integer|null $version (optional) * @param string $outputformat (optional) * @param string $sign_user (optional) Must be a valid uid * @param string $sign_profile (optional) Signatureprofile for signing * @param array $images (optional) Each element should have a property path, name & contenttype which are all strings * * @return stdClass */ public function getContent( $vorlage, $xml_data, $oe_kurzbz, $version = null, $outputformat = null, $sign_user = null, $sign_profile = null, $images = [] ) { $source_folder = getcwd(); $temp_folder = sys_get_temp_dir() . '/fhcunoconv-' . uniqid(); $outputformat = $this->getDefaultOutputFormat($outputformat, $vorlage->mimetype); $createResult = $this->createAndSignContent( $temp_folder, $outputformat, $vorlage, $oe_kurzbz, $version, $xml_data, $images, $sign_user, $sign_profile ); if (isError($createResult)) { $this->close($temp_folder, $source_folder); return $createResult; } $temp_filename = getData($createResult); $fsize = filesize($temp_filename); $handle = fopen($temp_filename, 'r'); if (!$handle) return error($this->_ci->DocumentExportPhrases->t("document_export", "error_file_load")); $fileContentResult = fread($handle, $fsize); fclose($handle); $this->close($temp_folder, $source_folder); return success($fileContentResult); } /** * Helper function for getContent * Creates the temp folder and calls create and sign functions. * * @param string $temp_folder * @param string $outputformat * @param stdClass $vorlage * @param string $oe_kurzbz * @param integer $version * @param DomDocument $xml_data * @param array $images Each element should have a property path, name and contenttype which are all strings * @param string $sign_user Must be a valid uid * @param string $sign_profile Signatureprofile for signing * * @return stdClass */ protected function createAndSignContent( $temp_folder, $outputformat, $vorlage, $oe_kurzbz, $version, $xml_data, $images, $sign_user, $sign_profile ) { mkdir($temp_folder); chdir($temp_folder); $this->_ci->load->model('system/Vorlagestudiengang_model', 'VorlagestudiengangModel'); $result = $this->_ci->VorlagestudiengangModel->getCurrent($vorlage->vorlage_kurzbz, $oe_kurzbz, $version); if (isError($result)) return $result; if (!hasData($result)) return error($this->_ci->DocumentExportPhrases->t("document_export", "error_template_missing")); $vorlage_stg = current(getData($result)); foreach ($vorlage_stg as $k => $v) $vorlage->$k = $v; if ($sign_user) { $this->addSignToData($xml_data); } $result = $this->create($temp_folder, $outputformat, $vorlage, $xml_data, $images); if (isError($result)) return $result; $temp_filename = getData($result); if ($sign_user) { $result = $this->sign($temp_folder, $temp_filename, $outputformat, $sign_user, $sign_profile); if (isError($result)) return $result; $temp_filename = getData($result); } return success($temp_filename); } /** * Helper function for createAndSignContent. * Creates the files in the temp folder. * * @param string $temp_folder * @param string $outputformat * @param stdClass $vorlage * @param DomDocument $xml_data * @param array $images Each element should have a property path, name and contenttype which are all strings * * @return stdClass */ protected function create($temp_folder, $outputformat, $vorlage, $xml_data, $images) { $content_xsl = new DOMDocument(); if (!$content_xsl->loadXML($vorlage->text)) return error($this->_ci->DocumentExportPhrases->t("document_export", "error_xsl_load")); $proc = new XSLTProcessor(); $proc->importStyleSheet($content_xsl); $contentbuffer = $proc->transformToXml($xml_data); file_put_contents($temp_folder . '/content.xml', $contentbuffer); if ($xml_data->firstChild->tagName == 'error') return error($xml_data->firstChild->textContent); $styles_xsl = null; // styles.xml erstellen if ($vorlage->style) { $styles_xsl = new DOMDocument(); if (!$styles_xsl->loadXML($vorlage->style)) return error($this->_ci->DocumentExportPhrases->t("document_export", "error_styles_load")); $style_proc = new XSLTProcessor(); $style_proc->importStyleSheet($styles_xsl); $stylesbuffer = $style_proc->transformToXml($xml_data); file_put_contents($temp_folder . '/styles.xml', $stylesbuffer); } // Template holen $vorlage_found = false; $vorlage_filename = $vorlage->vorlage_kurzbz . ($vorlage->mimetype == 'application/vnd.oasis.opendocument.spreadsheet' ? '.ods' : '.odt'); $aktive_addons = array_filter(array_map('trim', explode(";", ACTIVE_ADDONS))); foreach($aktive_addons as $addon) { $zipfile = DOC_ROOT . 'addons/' . $addon . '/system/vorlage_zip/' . $vorlage_filename; if (file_exists($zipfile)) { $vorlage_found = true; break; } } if (!$vorlage_found) $zipfile = DOC_ROOT . 'system/vorlage_zip/' . $vorlage_filename; $tempname_zip = $temp_folder . '/out.zip'; if (!copy($zipfile, $tempname_zip)) return error($this->_ci->DocumentExportPhrases->t("document_export", "error_file_copy")); exec("zip $tempname_zip content.xml"); if (!is_null($styles_xsl)) exec("zip $tempname_zip styles.xml"); // bilder hinzufuegen if (count($images) > 0) { // Unterordner fuer die Bilder erstellen mkdir('Pictures'); // Manifest Datei holen exec('unzip ' . $tempname_zip . ' META-INF/manifest.xml'); // Bild zur Manifest Datei hinzufuegen $manifest = file_get_contents('META-INF/manifest.xml'); $manifest_xml = new DOMDocument; if (!$manifest_xml->loadXML($manifest)) return error($this->_ci->DocumentExportPhrases->t("document_export", "error_manifest")); //root-node holen $root = $manifest_xml->getElementsByTagName('manifest')->item(0); foreach ($images as $bild) { copy($bild['path'], 'Pictures/' . $bild['name']); //Neues Element unterhalb des Root Nodes anlegen $node = $manifest_xml->createElement("manifest:file-entry"); $node->setAttribute("manifest:full-path", 'Pictures/' . $bild['name']); $node->setAttribute("manifest:media-type", $bild['contenttype']); $root->appendChild($node); } $out = $manifest_xml->saveXML(); //geaenderte Manifest Datei speichern und wieder ins Zip packen file_put_contents('META-INF/manifest.xml', $out); exec('zip ' . $tempname_zip . ' META-INF/*'); // Bilder zum ZIP-File hinzufuegen exec('zip ' . $tempname_zip . ' Pictures/*'); } clearstatcache(); $temp_filename = $temp_folder . '/out.' . $outputformat; switch ($outputformat) { case 'pdf': case 'doc': $converResult = $this->_ci->documentlib->convert($tempname_zip, $temp_filename, $outputformat); if (isError($converResult)) return error($this->_ci->DocumentExportPhrases->t('document_export', 'error_conv_timeout')); break; case 'odt': } return success($temp_filename); } /** * Helper function for createAndSignContent. * Signs the main file in the temp folder. * * @param string $temp_folder * @param string $temp_filename * @param string $outputformat * @param string $user Must be a valid uid * @param string $profile Signatureprofile for signing * * @return stdClass */ protected function sign($temp_folder, $temp_filename, $outputformat, $user, $profile) { if ($outputformat != 'pdf') return error($this->_ci->DocumentExportPhrases->t('document_export', 'error_sign_pdf')); $signed_filename = $this->_ci->signaturelib->sign($temp_folder, $temp_filename, $user, $profile); // If fine then return it if (isSuccess($signed_filename)) return $signed_filename; // Otherwise it is an error return error($this->_ci->DocumentExportPhrases->t('global', 'unknown_error', ['error' => getError($signed_filename)])); } /** * Deletes all files in the $temp_folder and changes back to the source_folder * * @param string $temp_folder * @param string $source_folder * * @return void */ protected function close($temp_folder, $source_folder) { $files = glob($temp_folder . '/*'); // get all file names foreach ($files as $file) if (is_file($file)) unlink($file); chdir($source_folder); rmdir($temp_folder); } /** * Convert an array to XML * * @param array $data * @param string $root * @param SimpleXMLElement $xml_data * * @return string|boolean */ private function convertArrayToXML($data, $root = null, $xml_data = null) { $_xml_data = $xml_data; if ($_xml_data === null) $_xml_data = new SimpleXMLElement($root !== null ? '<' . $root . ' />' : ''); foreach ($data as $key => $value) { if (is_array($value)) { if (is_numeric($key)) { $key = 'item' . $key; // dealing with <0/>.. issues $this->convertArrayToXML($value, null, $_xml_data); } else { $subnode = $_xml_data->addChild($key); $this->convertArrayToXML($value, null, $subnode); } } else { // Remove UTF8 Control Characters (breaking XML) $value = preg_replace('/[\x00-\x1F\x7F]/u', '', $value); $_xml_data->addChild((string)$key, htmlspecialchars("$value")); } } return $_xml_data->asXML(); } /** * Get default outputformat from mimetype if its not set * * @param string $outputformat * @param string $mimetype * * @return string */ private function getDefaultOutputFormat($outputformat, $mimetype) { if ($outputformat) return $outputformat; if ($mimetype == 'application/vnd.oasis.opendocument.spreadsheet') return 'ods'; if ($mimetype == 'application/vnd.oasis.opendocument.text') return 'odt'; return 'pdf'; } }