mirror of
https://github.com/zamentur/libreto.git
synced 2025-11-14 17:48:36 +05:30
update readme and embed html2document as submodule
This commit is contained in:
parent
da13fb7f55
commit
4e20e43e40
12 changed files with 1 additions and 1676 deletions
8
assets/html2opendocument/.gitignore
vendored
8
assets/html2opendocument/.gitignore
vendored
|
|
@ -1,8 +0,0 @@
|
||||||
composer.phar
|
|
||||||
composer.lock
|
|
||||||
/vendor/
|
|
||||||
.idea
|
|
||||||
|
|
||||||
# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file
|
|
||||||
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
|
|
||||||
# composer.lock
|
|
||||||
|
|
@ -1,195 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @link https://github.com/CatoTH/html2opendocument
|
|
||||||
* @author Tobias Hößl <tobias@hoessl.eu>
|
|
||||||
* @license https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace CatoTH\HTML2OpenDocument;
|
|
||||||
|
|
||||||
abstract class Base
|
|
||||||
{
|
|
||||||
const NS_OFFICE = 'urn:oasis:names:tc:opendocument:xmlns:office:1.0';
|
|
||||||
const NS_TEXT = 'urn:oasis:names:tc:opendocument:xmlns:text:1.0';
|
|
||||||
const NS_FO = 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0';
|
|
||||||
const NS_STYLE = 'urn:oasis:names:tc:opendocument:xmlns:style:1.0';
|
|
||||||
const NS_TABLE = 'urn:oasis:names:tc:opendocument:xmlns:table:1.0';
|
|
||||||
const NS_CALCTEXT = 'urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0';
|
|
||||||
const NS_XLINK = 'http://www.w3.org/1999/xlink';
|
|
||||||
|
|
||||||
|
|
||||||
/** @var \DOMDocument */
|
|
||||||
protected $doc = null;
|
|
||||||
|
|
||||||
/** @var bool */
|
|
||||||
protected $DEBUG = false;
|
|
||||||
protected $trustHtml = false;
|
|
||||||
|
|
||||||
/** @var string */
|
|
||||||
protected $tmpPath = '/tmp/';
|
|
||||||
|
|
||||||
/** @var \ZipArchive */
|
|
||||||
private $zip;
|
|
||||||
|
|
||||||
/** @var @string */
|
|
||||||
private $tmpZipFile;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $templateFile
|
|
||||||
* @param array $options
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function __construct($templateFile, $options = [])
|
|
||||||
{
|
|
||||||
$template = file_get_contents($templateFile);
|
|
||||||
if (isset($options['tmpPath']) && $options['tmpPath'] != '') {
|
|
||||||
$this->tmpPath = $options['tmpPath'];
|
|
||||||
}
|
|
||||||
if (isset($options['trustHtml'])) {
|
|
||||||
$this->trustHtml = ($options['trustHtml'] == true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!file_exists($this->tmpPath)){
|
|
||||||
mkdir($this->tmpPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->tmpZipFile = $this->tmpPath . uniqid('zip-');
|
|
||||||
file_put_contents($this->tmpZipFile, $template);
|
|
||||||
|
|
||||||
$this->zip = new \ZipArchive();
|
|
||||||
if ($this->zip->open($this->tmpZipFile) !== true) {
|
|
||||||
throw new \Exception("cannot open <$this->tmpZipFile>\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
$content = $this->zip->getFromName('content.xml');
|
|
||||||
|
|
||||||
$this->doc = new \DOMDocument();
|
|
||||||
$this->doc->loadXML($content);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function finishAndGetDocument()
|
|
||||||
{
|
|
||||||
$content = $this->create();
|
|
||||||
|
|
||||||
$this->zip->deleteName('content.xml');
|
|
||||||
$this->zip->addFromString('content.xml', $content);
|
|
||||||
$this->zip->close();
|
|
||||||
|
|
||||||
$content = file_get_contents($this->tmpZipFile);
|
|
||||||
unlink($this->tmpZipFile);
|
|
||||||
return $content;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
abstract function create();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $html
|
|
||||||
* @param array $config
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function purifyHTML($html, $config)
|
|
||||||
{
|
|
||||||
$configInstance = \HTMLPurifier_Config::create($config);
|
|
||||||
$configInstance->autoFinalize = false;
|
|
||||||
$purifier = \HTMLPurifier::instance($configInstance);
|
|
||||||
$purifier->config->set('Cache.SerializerPath', $this->tmpPath);
|
|
||||||
|
|
||||||
return $purifier->purify($html);
|
|
||||||
return $html;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $html
|
|
||||||
* @return \DOMNode
|
|
||||||
*/
|
|
||||||
public function html2DOM($html)
|
|
||||||
{
|
|
||||||
if (!$this->trustHtml) {
|
|
||||||
$html = $this->purifyHTML(
|
|
||||||
$html,
|
|
||||||
[
|
|
||||||
'HTML.Doctype' => 'HTML 4.01 Transitional',
|
|
||||||
'HTML.Trusted' => true,
|
|
||||||
'CSS.Trusted' => true,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$src_doc = new \DOMDocument();
|
|
||||||
$src_doc->loadHTML('<html><head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
|
||||||
</head><body>' . $html . "</body></html>");
|
|
||||||
$bodies = $src_doc->getElementsByTagName('body');
|
|
||||||
|
|
||||||
return $bodies->item(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* @param bool $debug
|
|
||||||
*/
|
|
||||||
public function setDebug($debug)
|
|
||||||
{
|
|
||||||
$this->DEBUG = $debug;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
public function debugOutput()
|
|
||||||
{
|
|
||||||
$this->doc->preserveWhiteSpace = false;
|
|
||||||
$this->doc->formatOutput = true;
|
|
||||||
echo htmlentities($this->doc->saveXML(), ENT_COMPAT, 'UTF-8');
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $styleName
|
|
||||||
* @param string $family
|
|
||||||
* @param string $element
|
|
||||||
* @param string[] $attributes
|
|
||||||
*/
|
|
||||||
protected function appendStyleNode($styleName, $family, $element, $attributes)
|
|
||||||
{
|
|
||||||
$node = $this->doc->createElementNS(static::NS_STYLE, 'style');
|
|
||||||
$node->setAttribute('style:name', $styleName);
|
|
||||||
$node->setAttribute('style:family', $family);
|
|
||||||
|
|
||||||
$style = $this->doc->createElementNS(static::NS_STYLE, $element);
|
|
||||||
foreach ($attributes as $att_name => $att_val) {
|
|
||||||
$style->setAttribute($att_name, $att_val);
|
|
||||||
}
|
|
||||||
$node->appendChild($style);
|
|
||||||
|
|
||||||
foreach ($this->doc->getElementsByTagNameNS(static::NS_OFFICE, 'automatic-styles') as $element) {
|
|
||||||
/** @var \DOMElement $element */
|
|
||||||
$element->appendChild($node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $styleName
|
|
||||||
* @param array $attributes
|
|
||||||
*/
|
|
||||||
protected function appendTextStyleNode($styleName, $attributes)
|
|
||||||
{
|
|
||||||
$this->appendStyleNode($styleName, 'text', 'text-properties', $attributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $styleName
|
|
||||||
* @param array $attributes
|
|
||||||
*/
|
|
||||||
protected function appendParagraphStyleNode($styleName, $attributes)
|
|
||||||
{
|
|
||||||
$this->appendStyleNode($styleName, 'paragraph', 'paragraph-properties', $attributes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2016 Tobias Hößl
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
||||||
This is a simple PHP-library to create create OpenDocument Text- and Spreadsheet-files (ODT / ODS) from HTML-formatted text.
|
|
||||||
|
|
||||||
It does not support formulae / calculations in spreadsheets. The focus lies on formatted text.
|
|
||||||
|
|
||||||
|
|
||||||
## Example Scripts
|
|
||||||
|
|
||||||
A demo script for the OpenDocument Text converter using the default template:
|
|
||||||
|
|
||||||
```php
|
|
||||||
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php');
|
|
||||||
|
|
||||||
$html = '<p>This is a demo for the converter.</p>
|
|
||||||
<p>The converter supports the following styles:</p>
|
|
||||||
<ul>
|
|
||||||
<li>Lists (UL / OL)</li>
|
|
||||||
<li><strong>STRONG</strong></li>
|
|
||||||
<li><u>U</u> (underlined)</li>
|
|
||||||
<li><s>S</s> (strike-through)</li>
|
|
||||||
<li><em>EM</em> (emphasis / italic)</li>
|
|
||||||
<li><ins>INS</ins> (Inserted text)</li>
|
|
||||||
<li><del>DEL</del> (Deleted text)</li>
|
|
||||||
<li>Line<br>breaks with BR</li>
|
|
||||||
</ul>
|
|
||||||
<blockquote>You can also use BLOCKQUOTE, though it lacks specific styling for now</blockquote>';
|
|
||||||
|
|
||||||
$html2 = '<p>You might be interested<br>in the fact that this converter<br>
|
|
||||||
also supports<br>line numbering<br>for selected paragraphs</p>
|
|
||||||
<p>Dummy Line<br>Dummy Line<br>Dummy Line<br>
|
|
||||||
Dummy Line<br>Dummy Line</p>';
|
|
||||||
|
|
||||||
$odt = new \CatoTH\HTML2OpenDocument\Text();
|
|
||||||
$odt->addHtmlTextBlock('<h1>Test Page</h1>');
|
|
||||||
$odt->addHtmlTextBlock($html, false);
|
|
||||||
$odt->addHtmlTextBlock('<h2>Line Numbering</h2>');
|
|
||||||
$odt->addHtmlTextBlock($html2, true);
|
|
||||||
$odt->finishAndOutputOdt('demo.odt');
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
A demo script for the OpenDocument Spreadsheet converter using the default template:
|
|
||||||
|
|
||||||
```php
|
|
||||||
use CatoTH\HTML2OpenDocument\Spreadsheet;
|
|
||||||
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php');
|
|
||||||
|
|
||||||
$ods = new \CatoTH\HTML2OpenDocument\Spreadsheet();
|
|
||||||
|
|
||||||
// Plain text
|
|
||||||
$ods->setCell(0, 0, Spreadsheet::TYPE_TEXT, 'Plain text with native formatting');
|
|
||||||
$ods->setCellStyle(0, 0, [], ['fo:font-weight' => 'bold']);
|
|
||||||
|
|
||||||
// Print a number as an actual number, just a little bit bigger
|
|
||||||
$ods->setCell(1, 0, Spreadsheet::TYPE_NUMBER, 23);
|
|
||||||
$ods->setCellStyle(1, 0, [], [
|
|
||||||
'fo:font-size' => '16pt',
|
|
||||||
'fo:font-weight' => 'bold',
|
|
||||||
]);
|
|
||||||
$ods->setMinRowHeight(1, 1.5);
|
|
||||||
|
|
||||||
// Print a number as text
|
|
||||||
$ods->setCell(2, 0, Spreadsheet::TYPE_TEXT, '42');
|
|
||||||
|
|
||||||
// Draw a border around two of the cells
|
|
||||||
$ods->drawBorder(1, 0, 2, 0, 1);
|
|
||||||
|
|
||||||
|
|
||||||
// Now we use HTML, and we need a bit more space for that
|
|
||||||
$html = '<p>The converter supports the following styles:</p>
|
|
||||||
<ul>
|
|
||||||
<li><strong>STRONG</strong></li>
|
|
||||||
<li><u>U</u> (underlined)</li>
|
|
||||||
<li><s>S</s> (strike-through)</li>
|
|
||||||
<li><em>EM</em> (emphasis / italic)</li>
|
|
||||||
<li><ins>Inserted text</ins></li>
|
|
||||||
<li><del>Deleted text</del></li>
|
|
||||||
<li>Line<br>breaks with BR</li>
|
|
||||||
<li>Lists (UL / OL) cannot be displayed as lists, but will be flattened to paragraphs</li>
|
|
||||||
</ul>
|
|
||||||
<blockquote>You can also use BLOCKQUOTE, though it lacks specific styling for now</blockquote>';
|
|
||||||
|
|
||||||
$ods->setMinRowHeight(3, 10);
|
|
||||||
$ods->setColumnWidth(1, 20);
|
|
||||||
$ods->setCell(3, 1, Spreadsheet::TYPE_HTML, $html);
|
|
||||||
|
|
||||||
|
|
||||||
$ods->finishAndOutputOds('demo.ods');
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This library is licensed under the [MIT license](http://opensource.org/licenses/MIT)
|
|
||||||
|
|
@ -1,694 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @link https://github.com/CatoTH/html2opendocument
|
|
||||||
* @author Tobias Hößl <tobias@hoessl.eu>
|
|
||||||
* @license https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace CatoTH\HTML2OpenDocument;
|
|
||||||
|
|
||||||
class Spreadsheet extends Base
|
|
||||||
{
|
|
||||||
const TYPE_TEXT = 0;
|
|
||||||
const TYPE_NUMBER = 1;
|
|
||||||
const TYPE_HTML = 2;
|
|
||||||
const TYPE_LINK = 3;
|
|
||||||
|
|
||||||
const FORMAT_LINEBREAK = 0;
|
|
||||||
const FORMAT_BOLD = 1;
|
|
||||||
const FORMAT_ITALIC = 2;
|
|
||||||
const FORMAT_UNDERLINED = 3;
|
|
||||||
const FORMAT_STRIKE = 4;
|
|
||||||
const FORMAT_INS = 5;
|
|
||||||
const FORMAT_DEL = 6;
|
|
||||||
const FORMAT_LINK = 7;
|
|
||||||
const FORMAT_INDENTED = 8;
|
|
||||||
const FORMAT_SUP = 9;
|
|
||||||
const FORMAT_SUB = 10;
|
|
||||||
|
|
||||||
public static $FORMAT_NAMES = [
|
|
||||||
0 => 'linebreak',
|
|
||||||
1 => 'bold',
|
|
||||||
2 => 'italic',
|
|
||||||
3 => 'underlined',
|
|
||||||
4 => 'strike',
|
|
||||||
5 => 'ins',
|
|
||||||
6 => 'del',
|
|
||||||
7 => 'link',
|
|
||||||
8 => 'indented',
|
|
||||||
9 => 'sup',
|
|
||||||
10 => 'sub',
|
|
||||||
];
|
|
||||||
|
|
||||||
/** @var \DOMDocument */
|
|
||||||
protected $doc = null;
|
|
||||||
|
|
||||||
/** @var \DOMElement */
|
|
||||||
protected $domTable;
|
|
||||||
|
|
||||||
protected $matrix = [];
|
|
||||||
protected $matrixRows = 0;
|
|
||||||
protected $matrixCols = 0;
|
|
||||||
protected $matrixColWidths = [];
|
|
||||||
protected $matrixRowHeights = [];
|
|
||||||
|
|
||||||
protected $rowNodes = [];
|
|
||||||
protected $cellNodeMatrix = [];
|
|
||||||
protected $cellStylesMatrix = [];
|
|
||||||
|
|
||||||
protected $classCache = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $options
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function __construct($options = [])
|
|
||||||
{
|
|
||||||
if (isset($options['templateFile']) && $options['templateFile'] != '') {
|
|
||||||
$templateFile = $options['templateFile'];
|
|
||||||
} else {
|
|
||||||
$templateFile = __DIR__ . DIRECTORY_SEPARATOR . 'default-template.ods';
|
|
||||||
}
|
|
||||||
parent::__construct($templateFile, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $filename
|
|
||||||
*/
|
|
||||||
public function finishAndOutputOds($filename = '')
|
|
||||||
{
|
|
||||||
header('Content-Type: application/vnd.oasis.opendocument.spreadsheet');
|
|
||||||
if ($filename != '') {
|
|
||||||
header('Content-disposition: attachment;filename="' . addslashes($filename) . '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
echo $this->finishAndGetDocument();
|
|
||||||
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $styleName
|
|
||||||
* @param array $cellAttributes
|
|
||||||
* @param array $textAttributes
|
|
||||||
*/
|
|
||||||
protected function appendCellStyleNode($styleName, $cellAttributes, $textAttributes)
|
|
||||||
{
|
|
||||||
$node = $this->doc->createElementNS(static::NS_STYLE, "style");
|
|
||||||
$node->setAttribute("style:name", $styleName);
|
|
||||||
$node->setAttribute("style:family", 'table-cell');
|
|
||||||
$node->setAttribute("style:parent-style-name", "Default");
|
|
||||||
|
|
||||||
if (count($cellAttributes) > 0) {
|
|
||||||
$style = $this->doc->createElementNS(static::NS_STYLE, 'table-cell-properties');
|
|
||||||
foreach ($cellAttributes as $att_name => $att_val) {
|
|
||||||
$style->setAttribute($att_name, $att_val);
|
|
||||||
}
|
|
||||||
$node->appendChild($style);
|
|
||||||
}
|
|
||||||
if (count($textAttributes) > 0) {
|
|
||||||
$style = $this->doc->createElementNS(static::NS_STYLE, 'text-properties');
|
|
||||||
foreach ($textAttributes as $att_name => $att_val) {
|
|
||||||
$style->setAttribute($att_name, $att_val);
|
|
||||||
}
|
|
||||||
$node->appendChild($style);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($this->doc->getElementsByTagNameNS(static::NS_OFFICE, 'automatic-styles') as $element) {
|
|
||||||
/** @var \DOMElement $element */
|
|
||||||
$element->appendChild($node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $styleName
|
|
||||||
* @param array $attributes
|
|
||||||
*/
|
|
||||||
protected function appendColStyleNode($styleName, $attributes)
|
|
||||||
{
|
|
||||||
$this->appendStyleNode($styleName, 'table-column', 'table-column-properties', $attributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $styleName
|
|
||||||
* @param array $attributes
|
|
||||||
*/
|
|
||||||
protected function appendRowStyleNode($styleName, $attributes)
|
|
||||||
{
|
|
||||||
$this->appendStyleNode($styleName, 'table-row', 'table-row-properties', $attributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $row
|
|
||||||
*/
|
|
||||||
protected function initRow($row)
|
|
||||||
{
|
|
||||||
if (!isset($this->matrix[$row])) {
|
|
||||||
$this->matrix[$row] = [];
|
|
||||||
}
|
|
||||||
if ($row > $this->matrixRows) {
|
|
||||||
$this->matrixRows = $row;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $row
|
|
||||||
* @param string $col
|
|
||||||
* @param int $contentType
|
|
||||||
* @param string $content
|
|
||||||
* @param null|string $cssClass
|
|
||||||
* @param null|string $styles
|
|
||||||
*/
|
|
||||||
public function setCell($row, $col, $contentType, $content, $cssClass = null, $styles = null)
|
|
||||||
{
|
|
||||||
$this->initRow($row);
|
|
||||||
if ($col > $this->matrixCols) {
|
|
||||||
$this->matrixCols = $col;
|
|
||||||
}
|
|
||||||
$this->matrix[$row][$col] = [
|
|
||||||
'type' => $contentType,
|
|
||||||
'content' => $content,
|
|
||||||
'class' => $cssClass,
|
|
||||||
'styles' => $styles,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $col
|
|
||||||
* @param float $widthInCm
|
|
||||||
*/
|
|
||||||
public function setColumnWidth($col, $widthInCm)
|
|
||||||
{
|
|
||||||
$this->matrixColWidths[$col] = $widthInCm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $row
|
|
||||||
* @param float $minHeightInCm
|
|
||||||
*/
|
|
||||||
public function setMinRowHeight($row, $minHeightInCm)
|
|
||||||
{
|
|
||||||
$this->initRow($row);
|
|
||||||
$rowHeight = (isset($this->matrixRowHeights[$row]) ? $this->matrixRowHeights[$row] : 1);
|
|
||||||
if ($minHeightInCm > $rowHeight) {
|
|
||||||
$rowHeight = $minHeightInCm;
|
|
||||||
}
|
|
||||||
$this->matrixRowHeights[$row] = $rowHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return \DOMElement
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
protected function getCleanDomTable()
|
|
||||||
{
|
|
||||||
$domTables = $this->doc->getElementsByTagNameNS(static::NS_TABLE, 'table');
|
|
||||||
if ($domTables->length != 1) {
|
|
||||||
throw new \Exception('Could not parse ODS template');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->domTable = $domTables->item(0);
|
|
||||||
|
|
||||||
$children = $this->domTable->childNodes;
|
|
||||||
for ($i = $children->length - 1; $i >= 0; $i--) {
|
|
||||||
$this->domTable->removeChild($children->item($i));
|
|
||||||
}
|
|
||||||
return $this->domTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
protected function setColStyles()
|
|
||||||
{
|
|
||||||
for ($col = 0; $col <= $this->matrixCols; $col++) {
|
|
||||||
$element = $this->doc->createElementNS(static::NS_TABLE, 'table-column');
|
|
||||||
if (isset($this->matrixColWidths[$col])) {
|
|
||||||
$element->setAttribute('table:style-name', 'Antragsgruen_col_' . $col);
|
|
||||||
$this->appendColStyleNode('Antragsgruen_col_' . $col, [
|
|
||||||
'style:column-width' => $this->matrixColWidths[$col] . 'cm',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
$this->domTable->appendChild($element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
protected function setCellContent()
|
|
||||||
{
|
|
||||||
for ($row = 0; $row <= $this->matrixRows; $row++) {
|
|
||||||
$this->cellNodeMatrix[$row] = [];
|
|
||||||
$currentRow = $this->doc->createElementNS(static::NS_TABLE, 'table-row');
|
|
||||||
for ($col = 0; $col <= $this->matrixCols; $col++) {
|
|
||||||
$this->cellNodeMatrix[$row][$col] = [];
|
|
||||||
$currentCell = $this->doc->createElementNS(static::NS_TABLE, 'table-cell');
|
|
||||||
if (isset($this->matrix[$row][$col])) {
|
|
||||||
$cell = $this->matrix[$row][$col];
|
|
||||||
switch ($cell["type"]) {
|
|
||||||
case static::TYPE_TEXT:
|
|
||||||
$elementP = $this->doc->createElementNS(static::NS_TEXT, 'p');
|
|
||||||
$elementP->textContent = $cell['content'];
|
|
||||||
$currentCell->appendChild($elementP);
|
|
||||||
break;
|
|
||||||
case static::TYPE_NUMBER:
|
|
||||||
$elementP = $this->doc->createElementNS(static::NS_TEXT, 'p');
|
|
||||||
$elementP->textContent = $cell['content'];
|
|
||||||
$currentCell->appendChild($elementP);
|
|
||||||
$currentCell->setAttribute('calcext:value-type', 'float');
|
|
||||||
$currentCell->setAttribute('office:value-type', 'float');
|
|
||||||
$currentCell->setAttribute('office:value', (string)$cell['content']);
|
|
||||||
break;
|
|
||||||
case static::TYPE_LINK:
|
|
||||||
$elementP = $this->doc->createElementNS(static::NS_TEXT, 'p');
|
|
||||||
$elementA = $this->doc->createElementNS(static::NS_TEXT, 'a');
|
|
||||||
$elementA->setAttributeNS(static::NS_XLINK, 'xlink:href', $cell['content']['href']);
|
|
||||||
$textNode = $this->doc->createTextNode($cell['content']['text']);
|
|
||||||
$elementA->appendChild($textNode);
|
|
||||||
$elementP->appendChild($elementA);
|
|
||||||
$currentCell->appendChild($elementP);
|
|
||||||
break;
|
|
||||||
case static::TYPE_HTML:
|
|
||||||
$nodes = $this->html2OdsNodes($cell['content']);
|
|
||||||
foreach ($nodes as $node) {
|
|
||||||
$currentCell->appendChild($node);
|
|
||||||
}
|
|
||||||
|
|
||||||
//$this->setMinRowHeight($row, count($ps));
|
|
||||||
$styles = $cell['styles'];
|
|
||||||
if (isset($styles['fo:wrap-option']) && $styles['fo:wrap-option'] == 'no-wrap') {
|
|
||||||
$wrap = 'no-wrap';
|
|
||||||
$height = 1;
|
|
||||||
} else {
|
|
||||||
$wrap = 'wrap';
|
|
||||||
$width = (isset($this->matrixColWidths[$col]) ? $this->matrixColWidths[$col] : 2);
|
|
||||||
$height = (mb_strlen(strip_tags($this->matrix[$row][$col]['content'])) / ($width * 6));
|
|
||||||
}
|
|
||||||
$this->setCellStyle($row, $col, [
|
|
||||||
'fo:wrap-option' => $wrap,
|
|
||||||
], [
|
|
||||||
'fo:hyphenate' => 'true',
|
|
||||||
]);
|
|
||||||
$this->setMinRowHeight($row, $height);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$currentRow->appendChild($currentCell);
|
|
||||||
$this->cellNodeMatrix[$row][$col] = $currentCell;
|
|
||||||
}
|
|
||||||
$this->domTable->appendChild($currentRow);
|
|
||||||
$this->rowNodes[$row] = $currentRow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $row
|
|
||||||
* @param int $col
|
|
||||||
* @param null|array $cellAttributes
|
|
||||||
* @param null|array $textAttributes
|
|
||||||
*/
|
|
||||||
public function setCellStyle($row, $col, $cellAttributes, $textAttributes)
|
|
||||||
{
|
|
||||||
if (!isset($this->cellStylesMatrix[$row])) {
|
|
||||||
$this->cellStylesMatrix[$row] = [];
|
|
||||||
}
|
|
||||||
if (!isset($this->cellStylesMatrix[$row][$col])) {
|
|
||||||
$this->cellStylesMatrix[$row][$col] = ['cell' => [], 'text' => []];
|
|
||||||
}
|
|
||||||
if (is_array($cellAttributes)) {
|
|
||||||
foreach ($cellAttributes as $key => $val) {
|
|
||||||
$this->cellStylesMatrix[$row][$col]['cell'][$key] = $val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (is_array($textAttributes)) {
|
|
||||||
foreach ($textAttributes as $key => $val) {
|
|
||||||
$this->cellStylesMatrix[$row][$col]['text'][$key] = $val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
public function setCellStyles()
|
|
||||||
{
|
|
||||||
for ($row = 0; $row <= $this->matrixRows; $row++) {
|
|
||||||
for ($col = 0; $col <= $this->matrixCols; $col++) {
|
|
||||||
if (isset($this->cellStylesMatrix[$row]) && isset($this->cellStylesMatrix[$row][$col])) {
|
|
||||||
$cell = $this->cellStylesMatrix[$row][$col];
|
|
||||||
} else {
|
|
||||||
$cell = ['cell' => [], 'text' => []];
|
|
||||||
}
|
|
||||||
|
|
||||||
$styleId = 'Antragsgruen_cell_' . $row . '_' . $col;
|
|
||||||
$cellStyles = array_merge([
|
|
||||||
'style:vertical-align' => 'top'
|
|
||||||
], $cell['cell']);
|
|
||||||
$this->appendCellStyleNode($styleId, $cellStyles, $cell['text']);
|
|
||||||
/** @var \DOMElement $currentCell */
|
|
||||||
$currentCell = $this->cellNodeMatrix[$row][$col];
|
|
||||||
$currentCell->setAttribute('table:style-name', $styleId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
foreach ($this->cellStylesMatrix as $rowNr => $row) {
|
|
||||||
foreach ($row as $colNr => $cell) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
public function setRowStyles()
|
|
||||||
{
|
|
||||||
foreach ($this->matrixRowHeights as $row => $height) {
|
|
||||||
$styleName = 'Antragsgruen_row_' . $row;
|
|
||||||
$this->appendRowStyleNode($styleName, [
|
|
||||||
'style:row-height' => ($height * 0.45) . 'cm',
|
|
||||||
]);
|
|
||||||
|
|
||||||
/** @var \DOMElement $node */
|
|
||||||
$node = $this->rowNodes[$row];
|
|
||||||
$node->setAttribute('table:style-name', $styleName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $fromRow
|
|
||||||
* @param int $fromCol
|
|
||||||
* @param int $toRow
|
|
||||||
* @param int $toCol
|
|
||||||
* @param float $width
|
|
||||||
*/
|
|
||||||
public function drawBorder($fromRow, $fromCol, $toRow, $toCol, $width)
|
|
||||||
{
|
|
||||||
for ($i = $fromRow; $i <= $toRow; $i++) {
|
|
||||||
$this->setCellStyle($i, $fromCol, [
|
|
||||||
'fo:border-left' => $width . 'pt solid #000000',
|
|
||||||
], []);
|
|
||||||
$this->setCellStyle($i, $toCol, [
|
|
||||||
'fo:border-right' => $width . 'pt solid #000000',
|
|
||||||
], []);
|
|
||||||
}
|
|
||||||
|
|
||||||
for ($i = $fromCol; $i <= $toCol; $i++) {
|
|
||||||
$this->setCellStyle($fromRow, $i, [
|
|
||||||
'fo:border-top' => $width . 'pt solid #000000',
|
|
||||||
], []);
|
|
||||||
$this->setCellStyle($toRow, $i, [
|
|
||||||
'fo:border-bottom' => $width . 'pt solid #000000',
|
|
||||||
], []);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \DOMElement $node
|
|
||||||
* @param array $currentFormats
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function node2Formatting(\DOMElement $node, $currentFormats)
|
|
||||||
{
|
|
||||||
switch ($node->nodeName) {
|
|
||||||
case 'b':
|
|
||||||
case 'strong':
|
|
||||||
$currentFormats[] = static::FORMAT_BOLD;
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
case 'em':
|
|
||||||
$currentFormats[] = static::FORMAT_ITALIC;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
$currentFormats[] = static::FORMAT_STRIKE;
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
$currentFormats[] = static::FORMAT_UNDERLINED;
|
|
||||||
break;
|
|
||||||
case 'sub':
|
|
||||||
$currentFormats[] = static::FORMAT_SUB;
|
|
||||||
break;
|
|
||||||
case 'sup':
|
|
||||||
$currentFormats[] = static::FORMAT_SUP;
|
|
||||||
break;
|
|
||||||
case 'br':
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
case 'div':
|
|
||||||
case 'blockquote':
|
|
||||||
if ($node->hasAttribute('class')) {
|
|
||||||
$classes = explode(' ', $node->getAttribute('class'));
|
|
||||||
if (in_array('underline', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_UNDERLINED;
|
|
||||||
}
|
|
||||||
if (in_array('strike', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_STRIKE;
|
|
||||||
}
|
|
||||||
if (in_array('ins', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_INS;
|
|
||||||
}
|
|
||||||
if (in_array('inserted', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_INS;
|
|
||||||
}
|
|
||||||
if (in_array('del', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_DEL;
|
|
||||||
}
|
|
||||||
if (in_array('deleted', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_DEL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'ul':
|
|
||||||
case 'ol':
|
|
||||||
if ($node->hasAttribute('class')) {
|
|
||||||
$classes = explode(' ', $node->getAttribute('class'));
|
|
||||||
$currentFormats[] = static::FORMAT_INDENTED;
|
|
||||||
if (in_array('ins', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_INS;
|
|
||||||
}
|
|
||||||
if (in_array('inserted', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_INS;
|
|
||||||
}
|
|
||||||
if (in_array('del', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_DEL;
|
|
||||||
}
|
|
||||||
if (in_array('deleted', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_DEL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'li':
|
|
||||||
break;
|
|
||||||
case 'del':
|
|
||||||
$currentFormats[] = static::FORMAT_DEL;
|
|
||||||
break;
|
|
||||||
case 'ins':
|
|
||||||
$currentFormats[] = static::FORMAT_INS;
|
|
||||||
break;
|
|
||||||
case 'h1':
|
|
||||||
case 'h2':
|
|
||||||
case 'h3':
|
|
||||||
case 'h4':
|
|
||||||
case 'h5':
|
|
||||||
case 'h6':
|
|
||||||
$currentFormats[] = static::FORMAT_BOLD;
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
$currentFormats[] = static::FORMAT_LINK;
|
|
||||||
try {
|
|
||||||
$attr = $node->getAttribute('href');
|
|
||||||
if ($attr) {
|
|
||||||
$currentFormats['href'] = $attr;
|
|
||||||
}
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'span':
|
|
||||||
default:
|
|
||||||
if ($node->hasAttribute('class')) {
|
|
||||||
$classes = explode(' ', $node->getAttribute('class'));
|
|
||||||
if (in_array('underline', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_UNDERLINED;
|
|
||||||
}
|
|
||||||
if (in_array('strike', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_STRIKE;
|
|
||||||
}
|
|
||||||
if (in_array('ins', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_INS;
|
|
||||||
}
|
|
||||||
if (in_array('inserted', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_INS;
|
|
||||||
}
|
|
||||||
if (in_array('del', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_DEL;
|
|
||||||
}
|
|
||||||
if (in_array('deleted', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_DEL;
|
|
||||||
}
|
|
||||||
if (in_array('superscript', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_SUP;
|
|
||||||
}
|
|
||||||
if (in_array('subscript', $classes)) {
|
|
||||||
$currentFormats[] = static::FORMAT_SUB;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return $currentFormats;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \DOMNode $node
|
|
||||||
* @param array $currentFormats
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function tokenizeFlattenHtml(\DOMNode $node, $currentFormats)
|
|
||||||
{
|
|
||||||
$return = [];
|
|
||||||
foreach ($node->childNodes as $child) {
|
|
||||||
switch ($child->nodeType) {
|
|
||||||
case XML_ELEMENT_NODE:
|
|
||||||
/** @var \DOMElement $child */
|
|
||||||
$formattings = $this->node2Formatting($child, $currentFormats);
|
|
||||||
$children = $this->tokenizeFlattenHtml($child, $formattings);
|
|
||||||
$return = array_merge($return, $children);
|
|
||||||
if (in_array($child->nodeName, ['br', 'div', 'p', 'li', 'blockquote'])) {
|
|
||||||
$return[] = [
|
|
||||||
'text' => '',
|
|
||||||
'formattings' => [static::FORMAT_LINEBREAK],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
if (in_array($child->nodeName, ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'])) {
|
|
||||||
$return[] = [
|
|
||||||
'text' => '',
|
|
||||||
'formattings' => [static::FORMAT_LINEBREAK, static::FORMAT_BOLD],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case XML_TEXT_NODE:
|
|
||||||
/** @var \DOMText $child */
|
|
||||||
$return[] = [
|
|
||||||
'text' => $child->data,
|
|
||||||
'formattings' => $currentFormats,
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $formats
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function getClassByFormats($formats)
|
|
||||||
{
|
|
||||||
sort($formats);
|
|
||||||
$key = implode('_', $formats);
|
|
||||||
if (!isset($this->classCache[$key])) {
|
|
||||||
$name = 'Antragsgruen';
|
|
||||||
$styles = [];
|
|
||||||
foreach ($formats as $format) {
|
|
||||||
if (!isset(static::$FORMAT_NAMES[$format])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$name .= '_' . static::$FORMAT_NAMES[$format];
|
|
||||||
switch ($format) {
|
|
||||||
case static::FORMAT_INS:
|
|
||||||
$styles['fo:color'] = '#00ff00';
|
|
||||||
$styles['style:text-underline-style'] = 'solid';
|
|
||||||
$styles['style:text-underline-width'] = 'auto';
|
|
||||||
$styles['style:text-underline-color'] = 'font-color';
|
|
||||||
break;
|
|
||||||
case static::FORMAT_DEL:
|
|
||||||
$styles['fo:color'] = '#ff0000';
|
|
||||||
$styles['style:text-line-through-type'] = 'single';
|
|
||||||
break;
|
|
||||||
case static::FORMAT_BOLD:
|
|
||||||
$styles['fo:font-weight'] = 'bold';
|
|
||||||
$styles['style:font-weight-asian'] = 'bold';
|
|
||||||
$styles['style:font-weight-complex'] = 'bold';
|
|
||||||
break;
|
|
||||||
case static::FORMAT_UNDERLINED:
|
|
||||||
$styles['style:text-underline-width'] = 'auto';
|
|
||||||
$styles['style:text-underline-color'] = 'font-color';
|
|
||||||
$styles['style:text-underline-style'] = 'solid';
|
|
||||||
break;
|
|
||||||
case static::FORMAT_STRIKE:
|
|
||||||
$styles['style:text-line-through-type'] = 'single';
|
|
||||||
break;
|
|
||||||
case static::FORMAT_ITALIC:
|
|
||||||
$styles['fo:font-style'] = 'italic';
|
|
||||||
$styles['style:font-style-asian'] = 'italic';
|
|
||||||
$styles['style:font-style-complex'] = 'italic';
|
|
||||||
break;
|
|
||||||
case static::FORMAT_SUP:
|
|
||||||
$styles['fo:font-size'] = '10pt';
|
|
||||||
$styles['style:text-position'] = '31%';
|
|
||||||
break;
|
|
||||||
case static::FORMAT_SUB:
|
|
||||||
$styles['fo:font-size'] = '10pt';
|
|
||||||
$styles['style:text-position'] = '-31%';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->appendTextStyleNode($name, $styles);
|
|
||||||
$this->classCache[$key] = $name;
|
|
||||||
}
|
|
||||||
return $this->classCache[$key];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $html
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function html2OdsNodes($html)
|
|
||||||
{
|
|
||||||
$body = $this->html2DOM($html);
|
|
||||||
$tokens = $this->tokenizeFlattenHtml($body, []);
|
|
||||||
$nodes = [];
|
|
||||||
$currentP = $this->doc->createElementNS(static::NS_TEXT, 'p');
|
|
||||||
foreach ($tokens as $token) {
|
|
||||||
if (trim($token['text']) != '') {
|
|
||||||
$node = $this->doc->createElement('text:span');
|
|
||||||
if (count($token['formattings']) > 0) {
|
|
||||||
$className = $this->getClassByFormats($token['formattings']);
|
|
||||||
$node->setAttribute('text:style-name', $className);
|
|
||||||
}
|
|
||||||
$textNode = $this->doc->createTextNode($token['text']);
|
|
||||||
$node->appendChild($textNode);
|
|
||||||
$currentP->appendChild($node);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_array(static::FORMAT_LINEBREAK, $token['formattings'])) {
|
|
||||||
$nodes[] = $currentP;
|
|
||||||
$currentP = $this->doc->createElementNS(static::NS_TEXT, 'p');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$nodes[] = $currentP;
|
|
||||||
return $nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
$this->getCleanDomTable();
|
|
||||||
$this->setColStyles();
|
|
||||||
$this->setCellContent();
|
|
||||||
$this->setRowStyles();
|
|
||||||
$this->setCellStyles();
|
|
||||||
|
|
||||||
$xml = $this->doc->saveXML();
|
|
||||||
|
|
||||||
$rows = explode("\n", $xml);
|
|
||||||
$rows[0] .= "\n";
|
|
||||||
return implode('', $rows) . "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,583 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @link https://github.com/CatoTH/html2opendocument
|
|
||||||
* @author Tobias Hößl <tobias@hoessl.eu>
|
|
||||||
* @license https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace CatoTH\HTML2OpenDocument;
|
|
||||||
|
|
||||||
class Text extends Base
|
|
||||||
{
|
|
||||||
/** @var null|\DOMElement */
|
|
||||||
private $nodeText = null;
|
|
||||||
|
|
||||||
/** @var bool */
|
|
||||||
private $node_template_1_used = false;
|
|
||||||
|
|
||||||
/** @var string[] */
|
|
||||||
private $replaces = [];
|
|
||||||
|
|
||||||
/** @var array */
|
|
||||||
private $textBlocks = [];
|
|
||||||
|
|
||||||
const STYLE_INS = 'ins';
|
|
||||||
const STYLE_DEL = 'del';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function __construct($options = [])
|
|
||||||
{
|
|
||||||
if (isset($options['templateFile']) && $options['templateFile'] != '') {
|
|
||||||
$templateFile = $options['templateFile'];
|
|
||||||
} else {
|
|
||||||
$templateFile = __DIR__ . DIRECTORY_SEPARATOR . 'default-template.odt';
|
|
||||||
}
|
|
||||||
parent::__construct($templateFile, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $filename
|
|
||||||
*/
|
|
||||||
public function finishAndOutputOdt($filename = '')
|
|
||||||
{
|
|
||||||
header('Content-Type: application/vnd.oasis.opendocument.text');
|
|
||||||
if ($filename != '') {
|
|
||||||
header('Content-disposition: attachment;filename="' . addslashes($filename) . '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
echo $this->finishAndGetDocument();
|
|
||||||
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $search
|
|
||||||
* @param string $replace
|
|
||||||
*/
|
|
||||||
public function addReplace($search, $replace)
|
|
||||||
{
|
|
||||||
$this->replaces[$search] = $replace;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $html
|
|
||||||
* @param bool $lineNumbered
|
|
||||||
*/
|
|
||||||
public function addHtmlTextBlock($html, $lineNumbered = false)
|
|
||||||
{
|
|
||||||
$this->textBlocks[] = ['text' => $html, 'lineNumbered' => $lineNumbered];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \DOMElement $element
|
|
||||||
* @return string[]
|
|
||||||
*/
|
|
||||||
protected static function getCSSClasses(\DOMElement $element)
|
|
||||||
{
|
|
||||||
if ($element->hasAttribute('class')) {
|
|
||||||
return explode(' ', $element->getAttribute('class'));
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \DOMElement $element
|
|
||||||
* @param string[] $parentStyles
|
|
||||||
* @return string[]
|
|
||||||
*/
|
|
||||||
protected static function getChildStyles(\DOMElement $element, $parentStyles = [])
|
|
||||||
{
|
|
||||||
$classes = static::getCSSClasses($element);
|
|
||||||
$childStyles = $parentStyles;
|
|
||||||
if (in_array('ins', $classes)) {
|
|
||||||
$childStyles[] = static::STYLE_INS;
|
|
||||||
}
|
|
||||||
if (in_array('inserted', $classes)) {
|
|
||||||
$childStyles[] = static::STYLE_INS;
|
|
||||||
}
|
|
||||||
if (in_array('del', $classes)) {
|
|
||||||
$childStyles[] = static::STYLE_DEL;
|
|
||||||
}
|
|
||||||
if (in_array('deleted', $classes)) {
|
|
||||||
$childStyles[] = static::STYLE_DEL;
|
|
||||||
}
|
|
||||||
return array_unique($childStyles);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string[] $classes
|
|
||||||
*
|
|
||||||
* @return null|string
|
|
||||||
*/
|
|
||||||
protected static function cssClassesToInternalClass($classes)
|
|
||||||
{
|
|
||||||
if (in_array('underline', $classes)) {
|
|
||||||
return 'AntragsgruenUnderlined';
|
|
||||||
}
|
|
||||||
if (in_array('strike', $classes)) {
|
|
||||||
return 'AntragsgruenStrike';
|
|
||||||
}
|
|
||||||
if (in_array('ins', $classes)) {
|
|
||||||
return 'AntragsgruenIns';
|
|
||||||
}
|
|
||||||
if (in_array('inserted', $classes)) {
|
|
||||||
return 'AntragsgruenIns';
|
|
||||||
}
|
|
||||||
if (in_array('del', $classes)) {
|
|
||||||
return 'AntragsgruenDel';
|
|
||||||
}
|
|
||||||
if (in_array('deleted', $classes)) {
|
|
||||||
return 'AntragsgruenDel';
|
|
||||||
}
|
|
||||||
if (in_array('superscript', $classes)) {
|
|
||||||
return 'AntragsgruenSup';
|
|
||||||
}
|
|
||||||
if (in_array('subscript', $classes)) {
|
|
||||||
return 'AntragsgruenSub';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps all child nodes with text:p nodes, if necessary
|
|
||||||
* (it's not necessary for child nodes that are p's themselves or lists)
|
|
||||||
*
|
|
||||||
* @param \DOMElement $parentEl
|
|
||||||
* @param boolean $lineNumbered
|
|
||||||
*
|
|
||||||
* @return \DOMElement
|
|
||||||
*/
|
|
||||||
protected function wrapChildrenWithP(\DOMElement $parentEl, $lineNumbered)
|
|
||||||
{
|
|
||||||
$childNodes = [];
|
|
||||||
while ($parentEl->childNodes->length > 0) {
|
|
||||||
$el = $parentEl->firstChild;
|
|
||||||
$parentEl->removeChild($el);
|
|
||||||
$childNodes[] = $el;
|
|
||||||
}
|
|
||||||
|
|
||||||
$appendNode = null;
|
|
||||||
foreach ($childNodes as $childNode) {
|
|
||||||
if (in_array(strtolower($childNode->nodeName), ['p', 'list'])) {
|
|
||||||
if ($appendNode) {
|
|
||||||
$parentEl->appendChild($appendNode);
|
|
||||||
$appendNode = null;
|
|
||||||
}
|
|
||||||
$parentEl->appendChild($childNode);
|
|
||||||
} else {
|
|
||||||
if (!$appendNode) {
|
|
||||||
$appendNode = $this->getNextNodeTemplate($lineNumbered);
|
|
||||||
}
|
|
||||||
$appendNode->appendChild($childNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($appendNode) {
|
|
||||||
$parentEl->appendChild($appendNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $parentEl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \DOMNode $srcNode
|
|
||||||
* @param bool $lineNumbered
|
|
||||||
* @param bool $inP
|
|
||||||
* @param string[] $parentStyles
|
|
||||||
*
|
|
||||||
* @return \DOMNode[]
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
protected function html2ooNodeInt($srcNode, $lineNumbered, $inP, $parentStyles = [])
|
|
||||||
{
|
|
||||||
switch ($srcNode->nodeType) {
|
|
||||||
case XML_ELEMENT_NODE:
|
|
||||||
/** @var \DOMElement $srcNode */
|
|
||||||
if ($this->DEBUG) {
|
|
||||||
echo "Element - " . $srcNode->nodeName . " / Children: " . $srcNode->childNodes->length . "<br>";
|
|
||||||
}
|
|
||||||
$needsIntermediateP = false;
|
|
||||||
$childStyles = static::getChildStyles($srcNode, $parentStyles);
|
|
||||||
switch ($srcNode->nodeName) {
|
|
||||||
case 'b':
|
|
||||||
case 'strong':
|
|
||||||
$dstEl = $this->doc->createElementNS(static::NS_TEXT, 'span');
|
|
||||||
$dstEl->setAttribute('text:style-name', 'AntragsgruenBold');
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
case 'em':
|
|
||||||
$dstEl = $this->doc->createElementNS(static::NS_TEXT, 'span');
|
|
||||||
$dstEl->setAttribute('text:style-name', 'AntragsgruenItalic');
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
$dstEl = $this->doc->createElementNS(static::NS_TEXT, 'span');
|
|
||||||
$dstEl->setAttribute('text:style-name', 'AntragsgruenStrike');
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
$dstEl = $this->doc->createElementNS(static::NS_TEXT, 'span');
|
|
||||||
$dstEl->setAttribute('text:style-name', 'AntragsgruenUnderlined');
|
|
||||||
break;
|
|
||||||
case 'sub':
|
|
||||||
$dstEl = $this->doc->createElementNS(static::NS_TEXT, 'span');
|
|
||||||
$dstEl->setAttribute('text:style-name', 'AntragsgruenSub');
|
|
||||||
break;
|
|
||||||
case 'sup':
|
|
||||||
$dstEl = $this->doc->createElementNS(static::NS_TEXT, 'span');
|
|
||||||
$dstEl->setAttribute('text:style-name', 'AntragsgruenSup');
|
|
||||||
break;
|
|
||||||
case 'br':
|
|
||||||
$dstEl = $this->doc->createElementNS(static::NS_TEXT, 'line-break');
|
|
||||||
break;
|
|
||||||
case 'del':
|
|
||||||
$dstEl = $this->doc->createElementNS(static::NS_TEXT, 'span');
|
|
||||||
$dstEl->setAttribute('text:style-name', 'AntragsgruenDel');
|
|
||||||
break;
|
|
||||||
case 'ins':
|
|
||||||
$dstEl = $this->doc->createElementNS(static::NS_TEXT, 'span');
|
|
||||||
$dstEl->setAttribute('text:style-name', 'AntragsgruenIns');
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
$dstEl = $this->doc->createElementNS(static::NS_TEXT, 'a');
|
|
||||||
try {
|
|
||||||
$attr = $srcNode->getAttribute('href');
|
|
||||||
if ($attr) {
|
|
||||||
$dstEl->setAttribute('xlink:href', $attr);
|
|
||||||
}
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
if ($inP) {
|
|
||||||
$dstEl = $this->createNodeWithBaseStyle('span', $lineNumbered);
|
|
||||||
} else {
|
|
||||||
$dstEl = $this->createNodeWithBaseStyle('p', $lineNumbered);
|
|
||||||
}
|
|
||||||
$intClass = static::cssClassesToInternalClass(static::getCSSClasses($srcNode));
|
|
||||||
if ($intClass) {
|
|
||||||
$dstEl->setAttribute('text:style-name', $intClass);
|
|
||||||
}
|
|
||||||
$inP = true;
|
|
||||||
break;
|
|
||||||
case 'div':
|
|
||||||
// We're basically ignoring DIVs here, as there is no corresponding element in OpenDocument
|
|
||||||
// Therefore no support for styles and classes set on DIVs yet.
|
|
||||||
$dstEl = null;
|
|
||||||
break;
|
|
||||||
case 'blockquote':
|
|
||||||
$dstEl = $this->createNodeWithBaseStyle('p', $lineNumbered);
|
|
||||||
$class = ($lineNumbered ? 'Blockquote_Linenumbered' : 'Blockquote');
|
|
||||||
$dstEl->setAttribute('text:style-name', 'Antragsgrün_20_' . $class);
|
|
||||||
if ($srcNode->childNodes->length == 1) {
|
|
||||||
foreach ($srcNode->childNodes as $child) {
|
|
||||||
if ($child->nodeName == 'p') {
|
|
||||||
$srcNode = $child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$inP = true;
|
|
||||||
break;
|
|
||||||
case 'ul':
|
|
||||||
$dstEl = $this->doc->createElementNS(static::NS_TEXT, 'list');
|
|
||||||
break;
|
|
||||||
case 'ol':
|
|
||||||
$dstEl = $this->doc->createElementNS(static::NS_TEXT, 'list');
|
|
||||||
break;
|
|
||||||
case 'li':
|
|
||||||
$dstEl = $this->doc->createElementNS(static::NS_TEXT, 'list-item');
|
|
||||||
$needsIntermediateP = true;
|
|
||||||
$inP = true;
|
|
||||||
break;
|
|
||||||
case 'h1':
|
|
||||||
$dstEl = $this->createNodeWithBaseStyle('p', $lineNumbered);
|
|
||||||
$dstEl->setAttribute('text:style-name', 'Antragsgrün_20_H1');
|
|
||||||
$inP = true;
|
|
||||||
break;
|
|
||||||
case 'h2':
|
|
||||||
$dstEl = $this->createNodeWithBaseStyle('p', $lineNumbered);
|
|
||||||
$dstEl->setAttribute('text:style-name', 'Antragsgrün_20_H2');
|
|
||||||
$inP = true;
|
|
||||||
break;
|
|
||||||
case 'h3':
|
|
||||||
$dstEl = $this->createNodeWithBaseStyle('p', $lineNumbered);
|
|
||||||
$dstEl->setAttribute('text:style-name', 'Antragsgrün_20_H3');
|
|
||||||
$inP = true;
|
|
||||||
break;
|
|
||||||
case 'h4':
|
|
||||||
case 'h5':
|
|
||||||
case 'h6':
|
|
||||||
$dstEl = $this->createNodeWithBaseStyle('p', $lineNumbered);
|
|
||||||
$dstEl->setAttribute('text:style-name', 'Antragsgrün_20_H4');
|
|
||||||
$inP = true;
|
|
||||||
break;
|
|
||||||
case 'span':
|
|
||||||
default:
|
|
||||||
$dstEl = $this->doc->createElementNS(static::NS_TEXT, 'span');
|
|
||||||
$intClass = static::cssClassesToInternalClass(static::getCSSClasses($srcNode));
|
|
||||||
if ($intClass) {
|
|
||||||
$dstEl->setAttribute('text:style-name', $intClass);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ($dstEl === null) {
|
|
||||||
$ret = [];
|
|
||||||
foreach ($srcNode->childNodes as $child) {
|
|
||||||
/** @var \DOMNode $child */
|
|
||||||
if ($this->DEBUG) {
|
|
||||||
echo "CHILD<br>" . $child->nodeType . "<br>";
|
|
||||||
}
|
|
||||||
|
|
||||||
$dstNodes = $this->html2ooNodeInt($child, $lineNumbered, $inP, $childStyles);
|
|
||||||
foreach ($dstNodes as $dstNode) {
|
|
||||||
$ret[] = $dstNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($srcNode->childNodes as $child) {
|
|
||||||
/** @var \DOMNode $child */
|
|
||||||
if ($this->DEBUG) {
|
|
||||||
echo "CHILD<br>" . $child->nodeType . "<br>";
|
|
||||||
}
|
|
||||||
|
|
||||||
$dstNodes = $this->html2ooNodeInt($child, $lineNumbered, $inP, $childStyles);
|
|
||||||
foreach ($dstNodes as $dstNode) {
|
|
||||||
$dstEl->appendChild($dstNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($needsIntermediateP && $dstEl->childNodes->length > 0) {
|
|
||||||
$dstEl = static::wrapChildrenWithP($dstEl, $lineNumbered);
|
|
||||||
}
|
|
||||||
return [$dstEl];
|
|
||||||
case XML_TEXT_NODE:
|
|
||||||
/** @var \DOMText $srcNode */
|
|
||||||
$textnode = new \DOMText();
|
|
||||||
$textnode->data = $srcNode->data;
|
|
||||||
if ($this->DEBUG) {
|
|
||||||
echo 'Text<br>';
|
|
||||||
}
|
|
||||||
if (in_array(static::STYLE_DEL, $parentStyles)) {
|
|
||||||
$dstEl = $this->createNodeWithBaseStyle('span', $lineNumbered);
|
|
||||||
$dstEl->setAttribute('text:style-name', 'AntragsgruenDel');
|
|
||||||
$dstEl->appendChild($textnode);
|
|
||||||
$textnode = $dstEl;
|
|
||||||
}
|
|
||||||
if (in_array(static::STYLE_INS, $parentStyles)) {
|
|
||||||
$dstEl = $this->createNodeWithBaseStyle('span', $lineNumbered);
|
|
||||||
$dstEl->setAttribute('text:style-name', 'AntragsgruenIns');
|
|
||||||
$dstEl->appendChild($textnode);
|
|
||||||
$textnode = $dstEl;
|
|
||||||
}
|
|
||||||
return [$textnode];
|
|
||||||
break;
|
|
||||||
case XML_DOCUMENT_TYPE_NODE:
|
|
||||||
if ($this->DEBUG) {
|
|
||||||
echo 'Type Node<br>';
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
default:
|
|
||||||
if ($this->DEBUG) {
|
|
||||||
echo 'Unknown Node: ' . $srcNode->nodeType . '<br>';
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $html
|
|
||||||
* @param bool $lineNumbered
|
|
||||||
*
|
|
||||||
* @return \DOMNode[]
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
protected function html2ooNodes($html, $lineNumbered)
|
|
||||||
{
|
|
||||||
if (!is_string($html)) {
|
|
||||||
echo print_r($html, true);
|
|
||||||
echo print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), true);
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
|
|
||||||
$body = $this->html2DOM($html);
|
|
||||||
|
|
||||||
$retNodes = [];
|
|
||||||
for ($i = 0; $i < $body->childNodes->length; $i++) {
|
|
||||||
$child = $body->childNodes->item($i);
|
|
||||||
|
|
||||||
/** @var \DOMNode $child */
|
|
||||||
if ($child->nodeName == 'ul') {
|
|
||||||
// Alle anderen Nodes dieses Aufrufs werden ignoriert
|
|
||||||
if ($this->DEBUG) {
|
|
||||||
echo 'LIST<br>';
|
|
||||||
}
|
|
||||||
$recNewNodes = $this->html2ooNodeInt($child, $lineNumbered, false);
|
|
||||||
} else {
|
|
||||||
if ($child->nodeType == XML_TEXT_NODE) {
|
|
||||||
$new_node = $this->getNextNodeTemplate($lineNumbered);
|
|
||||||
/** @var \DOMText $child */
|
|
||||||
if ($this->DEBUG) {
|
|
||||||
echo $child->nodeName . ' - ' . htmlentities($child->data, ENT_COMPAT, 'UTF-8') . '<br>';
|
|
||||||
}
|
|
||||||
$text = new \DOMText();
|
|
||||||
$text->data = $child->data;
|
|
||||||
$new_node->appendChild($text);
|
|
||||||
$recNewNodes = [$new_node];
|
|
||||||
} else {
|
|
||||||
if ($this->DEBUG) {
|
|
||||||
echo $child->nodeName . '!!!!!!!!!!!!<br>';
|
|
||||||
}
|
|
||||||
$recNewNodes = $this->html2ooNodeInt($child, $lineNumbered, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach ($recNewNodes as $recNewNode) {
|
|
||||||
$retNodes[] = $recNewNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $retNodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
$this->appendTextStyleNode('AntragsgruenBold', [
|
|
||||||
'fo:font-weight' => 'bold',
|
|
||||||
'style:font-weight-asian' => 'bold',
|
|
||||||
'style:font-weight-complex' => 'bold',
|
|
||||||
]);
|
|
||||||
$this->appendTextStyleNode('AntragsgruenItalic', [
|
|
||||||
'fo:font-style' => 'italic',
|
|
||||||
'style:font-style-asian' => 'italic',
|
|
||||||
'style:font-style-complex' => 'italic',
|
|
||||||
]);
|
|
||||||
$this->appendTextStyleNode('AntragsgruenUnderlined', [
|
|
||||||
'style:text-underline-width' => 'auto',
|
|
||||||
'style:text-underline-color' => 'font-color',
|
|
||||||
'style:text-underline-style' => 'solid',
|
|
||||||
]);
|
|
||||||
$this->appendTextStyleNode('AntragsgruenStrike', [
|
|
||||||
'style:text-line-through-style' => 'solid',
|
|
||||||
'style:text-line-through-type' => 'single',
|
|
||||||
]);
|
|
||||||
$this->appendTextStyleNode('AntragsgruenIns', [
|
|
||||||
'fo:color' => '#008800',
|
|
||||||
'style:text-underline-style' => 'solid',
|
|
||||||
'style:text-underline-width' => 'auto',
|
|
||||||
'style:text-underline-color' => 'font-color',
|
|
||||||
'fo:font-weight' => 'bold',
|
|
||||||
'style:font-weight-asian' => 'bold',
|
|
||||||
'style:font-weight-complex' => 'bold',
|
|
||||||
]);
|
|
||||||
$this->appendTextStyleNode('AntragsgruenDel', [
|
|
||||||
'fo:color' => '#880000',
|
|
||||||
'style:text-line-through-style' => 'solid',
|
|
||||||
'style:text-line-through-type' => 'single',
|
|
||||||
'fo:font-style' => 'italic',
|
|
||||||
'style:font-style-asian' => 'italic',
|
|
||||||
'style:font-style-complex' => 'italic',
|
|
||||||
]);
|
|
||||||
$this->appendTextStyleNode('AntragsgruenSub', [
|
|
||||||
'style:text-position' => 'sub 58%',
|
|
||||||
]);
|
|
||||||
$this->appendTextStyleNode('AntragsgruenSup', [
|
|
||||||
'style:text-position' => 'super 58%',
|
|
||||||
]);
|
|
||||||
|
|
||||||
/** @var \DOMNode[] $nodes */
|
|
||||||
$nodes = [];
|
|
||||||
foreach ($this->doc->getElementsByTagNameNS(static::NS_TEXT, 'span') as $element) {
|
|
||||||
$nodes[] = $element;
|
|
||||||
}
|
|
||||||
foreach ($this->doc->getElementsByTagNameNS(static::NS_TEXT, 'p') as $element) {
|
|
||||||
$nodes[] = $element;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$searchFor = array_keys($this->replaces);
|
|
||||||
$replaceWith = array_values($this->replaces);
|
|
||||||
foreach ($nodes as $node) {
|
|
||||||
$children = $node->childNodes;
|
|
||||||
foreach ($children as $child) {
|
|
||||||
if ($child->nodeType == XML_TEXT_NODE) {
|
|
||||||
/** @var \DOMText $child */
|
|
||||||
$child->data = preg_replace($searchFor, $replaceWith, $child->data);
|
|
||||||
|
|
||||||
if (preg_match("/\{\{ANTRAGSGRUEN:DUMMY\}\}/siu", $child->data)) {
|
|
||||||
$node->parentNode->removeChild($node);
|
|
||||||
}
|
|
||||||
if (preg_match("/\{\{ANTRAGSGRUEN:TEXT\}\}/siu", $child->data)) {
|
|
||||||
$this->nodeText = $node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($this->textBlocks as $textBlock) {
|
|
||||||
$newNodes = $this->html2ooNodes($textBlock['text'], $textBlock['lineNumbered']);
|
|
||||||
foreach ($newNodes as $newNode) {
|
|
||||||
$this->nodeText->parentNode->insertBefore($newNode, $this->nodeText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->nodeText->parentNode->removeChild($this->nodeText);
|
|
||||||
|
|
||||||
return $this->doc->saveXML();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param bool $lineNumbers
|
|
||||||
*
|
|
||||||
* @return \DOMNode
|
|
||||||
*/
|
|
||||||
protected function getNextNodeTemplate($lineNumbers)
|
|
||||||
{
|
|
||||||
$node = $this->nodeText->cloneNode();
|
|
||||||
/** @var \DOMElement $node */
|
|
||||||
if ($lineNumbers) {
|
|
||||||
if ($this->node_template_1_used) {
|
|
||||||
$node->setAttribute('text:style-name', 'Antragsgrün_20_LineNumbered_20_Standard');
|
|
||||||
} else {
|
|
||||||
$this->node_template_1_used = true;
|
|
||||||
$node->setAttribute('text:style-name', 'Antragsgrün_20_LineNumbered_20_First');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$node->setAttribute('text:style-name', 'Antragsgrün_20_Standard');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $nodeType
|
|
||||||
* @param bool $lineNumbers
|
|
||||||
*
|
|
||||||
* @return \DOMElement|\DOMNode
|
|
||||||
*/
|
|
||||||
protected function createNodeWithBaseStyle($nodeType, $lineNumbers)
|
|
||||||
{
|
|
||||||
$node = $this->doc->createElementNS(static::NS_TEXT, $nodeType);
|
|
||||||
if ($lineNumbers) {
|
|
||||||
if ($this->node_template_1_used) {
|
|
||||||
$node->setAttribute('text:style-name', 'Antragsgrün_20_LineNumbered_20_Standard');
|
|
||||||
} else {
|
|
||||||
$this->node_template_1_used = true;
|
|
||||||
$node->setAttribute('text:style-name', 'Antragsgrün_20_LineNumbered_20_First');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$node->setAttribute('text:style-name', 'Antragsgrün_20_Standard');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
{
|
|
||||||
"name": "catoth/html2opendocument",
|
|
||||||
"description": "Converting simple HTML to Opendocument Text (ODT) or Spreadsheets (ODS)",
|
|
||||||
"type": "library",
|
|
||||||
"minimum-stability": "stable",
|
|
||||||
"license": "MIT",
|
|
||||||
"keywords": [
|
|
||||||
"opendocument",
|
|
||||||
"html",
|
|
||||||
"odt",
|
|
||||||
"ods"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Tobias Hößl",
|
|
||||||
"email": "tobias@hoessl.eu"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.5.0",
|
|
||||||
"ext-zip": "*",
|
|
||||||
"ext-dom": "*",
|
|
||||||
"ezyang/htmlpurifier": "*"
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"CatoTH\\HTML2OpenDocument\\": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,50 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use CatoTH\HTML2OpenDocument\Spreadsheet;
|
|
||||||
|
|
||||||
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'vendor/autoload.php');
|
|
||||||
|
|
||||||
|
|
||||||
$ods = new \CatoTH\HTML2OpenDocument\Spreadsheet();
|
|
||||||
|
|
||||||
// Plain text
|
|
||||||
$ods->setCell(0, 0, Spreadsheet::TYPE_TEXT, 'Plain text with native formatting');
|
|
||||||
$ods->setCellStyle(0, 0, [], ['fo:font-weight' => 'bold']);
|
|
||||||
|
|
||||||
// Print a number as an actual number, just a little bit bigger
|
|
||||||
$ods->setCell(1, 0, Spreadsheet::TYPE_NUMBER, 23);
|
|
||||||
$ods->setCellStyle(1, 0, [], [
|
|
||||||
'fo:font-size' => '16pt',
|
|
||||||
'fo:font-weight' => 'bold',
|
|
||||||
]);
|
|
||||||
$ods->setMinRowHeight(1, 1.5);
|
|
||||||
|
|
||||||
// Print a number as text
|
|
||||||
$ods->setCell(2, 0, Spreadsheet::TYPE_TEXT, '42');
|
|
||||||
|
|
||||||
// Draw a border around two of the cells
|
|
||||||
$ods->drawBorder(1, 0, 2, 0, 1);
|
|
||||||
|
|
||||||
|
|
||||||
// Now we use HTML, and we need a bit more space for that
|
|
||||||
$html = '<p>The converter supports the following styles:</p>
|
|
||||||
<ul>
|
|
||||||
<li><strong>STRONG</strong></li>
|
|
||||||
<li><u>U</u> (underlined)</li>
|
|
||||||
<li><s>S</s> (strike-through)</li>
|
|
||||||
<li><em>EM</em> (emphasis / italic)</li>
|
|
||||||
<li><ins>Inserted text</ins></li>
|
|
||||||
<li><del>Deleted text</del></li>
|
|
||||||
<li>Line<br>breaks with BR</li>
|
|
||||||
<li>Lists (UL / OL) cannot be displayed as lists, but will be flattened to paragraphs</li>
|
|
||||||
</ul>
|
|
||||||
<blockquote>You can also use BLOCKQUOTE, though it lacks specific styling for now</blockquote>';
|
|
||||||
|
|
||||||
$ods->setMinRowHeight(3, 10);
|
|
||||||
$ods->setColumnWidth(1, 20);
|
|
||||||
$ods->setCell(3, 1, Spreadsheet::TYPE_HTML, $html);
|
|
||||||
|
|
||||||
|
|
||||||
$ods->finishAndOutputOds('demo.ods');
|
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#Libreto
|
# Libreto
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue