Merge branch '#231-basjan' into develop
This commit is contained in:
commit
c82f0ac1fc
|
|
@ -5,6 +5,15 @@ before_commands:
|
|||
- "composer install --prefer-source --dev"
|
||||
|
||||
tools:
|
||||
php_code_sniffer:
|
||||
enabled: true
|
||||
config:
|
||||
standard: PSR2
|
||||
php_cpd: true
|
||||
php_mess_detector:
|
||||
enabled: true
|
||||
config:
|
||||
ruleset: phpmd.xml.dist
|
||||
external_code_coverage:
|
||||
enabled: true
|
||||
timeout: 900
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ script:
|
|||
## PHP Copy/Paste Detector
|
||||
- php phpcpd.phar src/ tests/ --verbose
|
||||
## PHP Mess Detector
|
||||
- phpmd src/,tests/ text unusedcode,naming,design,controversial --exclude pclzip.lib.php
|
||||
- phpmd src/,tests/ text ./phpmd.xml.dist --exclude pclzip.lib.php
|
||||
## PHPLOC
|
||||
#- php phploc.phar src/
|
||||
## PHPUnit
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ This release changed PHPWord license from LGPL 2.1 to LGPL 3.
|
|||
- Image: Ability to define relative and absolute positioning - @basjan GH-217
|
||||
- Footer: Conform footer with header by adding firstPage, evenPage and by inheritance - @basjan @ivanlanin GH-219
|
||||
- TextBox: Ability to add textbox in section, header, and footer - @basjan @ivanlanin GH-228
|
||||
- TextBox: Ability to add textbox in table - @basjan GH-231
|
||||
- HTML: Ability to add elements to PHPWord object via html - @basjan GH-231
|
||||
|
||||
### Bugfixes
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<ruleset name="PHPWord PHP Mess Detector Rule Set"
|
||||
xmlns="http://pmd.sf.net/ruleset/1.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
|
||||
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
|
||||
<rule ref="rulesets/naming.xml"/>
|
||||
<rule ref="rulesets/design.xml/ExitExpression" />
|
||||
<rule ref="rulesets/design.xml/EvalExpression" />
|
||||
<rule ref="rulesets/design.xml/GotoStatement" />
|
||||
<rule ref="rulesets/design.xml/NumberOfChildren" />
|
||||
<rule ref="rulesets/design.xml/DepthOfInheritance" />
|
||||
<rule ref="rulesets/design.xml/CouplingBetweenObjects">
|
||||
<properties>
|
||||
<property name="minimum" value="15" />
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="rulesets/unusedcode.xml" />
|
||||
<rule ref="rulesets/controversial.xml" />
|
||||
</ruleset>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
include_once 'Sample_Header.php';
|
||||
|
||||
// New Word Document
|
||||
echo date('H:i:s') , ' Create new PhpWord object' , EOL;
|
||||
$phpWord = new \PhpOffice\PhpWord\PhpWord();
|
||||
|
||||
$section = $phpWord->addSection();
|
||||
$html = '<h1>Adding element via HTML</h1>';
|
||||
$html .= '<p>Some well formed HTML snippet needs to be used</p>';
|
||||
$html .= '<p>With for example <strong>some <em>inline</em> formatting</strong></p>';
|
||||
|
||||
\PhpOffice\PhpWord\Shared\Html::addHtml($section, $html);
|
||||
|
||||
// Save file
|
||||
echo write($phpWord, basename(__FILE__, '.php'), $writers);
|
||||
if (!CLI) {
|
||||
include_once 'Sample_Footer.php';
|
||||
}
|
||||
|
|
@ -66,6 +66,31 @@ abstract class AbstractContainer extends AbstractElement
|
|||
return count($this->elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add generic element with style
|
||||
*
|
||||
* This is how all elements should be added with dependency injection: with
|
||||
* just one simple $style. Currently this function supports TextRun, Table,
|
||||
* and TextBox since all other elements have different arguments
|
||||
*
|
||||
* @todo Change the function name into something better?
|
||||
*
|
||||
* @param string $elementName
|
||||
* @param mixed $style
|
||||
* @return \PhpOffice\PhpWord\Element\AbstractElement
|
||||
*/
|
||||
private function addGenericElement($elementName, $style)
|
||||
{
|
||||
$elementClass = __NAMESPACE__ . '\\' . $elementName;
|
||||
|
||||
$this->checkValidity($elementName);
|
||||
$element = new $elementClass($style);
|
||||
$element->setDocPart($this->getDocPart(), $this->getDocPartId());
|
||||
$this->addElement($element);
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add text/preservetext element
|
||||
*
|
||||
|
|
@ -100,13 +125,7 @@ abstract class AbstractContainer extends AbstractElement
|
|||
*/
|
||||
public function addTextRun($paragraphStyle = null)
|
||||
{
|
||||
$this->checkValidity('TextRun');
|
||||
|
||||
$element = new TextRun($paragraphStyle);
|
||||
$element->setDocPart($this->getDocPart(), $this->getDocPartId());
|
||||
$this->addElement($element);
|
||||
|
||||
return $element;
|
||||
return $this->addGenericElement('TextRun', $paragraphStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -186,6 +205,18 @@ abstract class AbstractContainer extends AbstractElement
|
|||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add table element
|
||||
*
|
||||
* @param mixed $style
|
||||
* @return \PhpOffice\PhpWord\Element\Table
|
||||
* @todo Merge with the same function on Footer
|
||||
*/
|
||||
public function addTable($style = null)
|
||||
{
|
||||
return $this->addGenericElement('Table', $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add image element
|
||||
*
|
||||
|
|
@ -302,13 +333,7 @@ abstract class AbstractContainer extends AbstractElement
|
|||
*/
|
||||
public function addTextBox($style = null)
|
||||
{
|
||||
$this->checkValidity('TextBox');
|
||||
|
||||
$textbox = new TextBox($style);
|
||||
$textbox->setDocPart($this->getDocPart(), $this->getDocPartId());
|
||||
$this->addElement($textbox);
|
||||
|
||||
return $textbox;
|
||||
return $this->addGenericElement('TextBox', $style);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -329,6 +354,7 @@ abstract class AbstractContainer extends AbstractElement
|
|||
'Object' => $allContainers,
|
||||
'TextRun' => array('section', 'header', 'footer', 'cell', 'textbox'),
|
||||
'ListItem' => array('section', 'header', 'footer', 'cell', 'textbox'),
|
||||
'Table' => array('section', 'header', 'footer', 'textbox'),
|
||||
'CheckBox' => array('section', 'header', 'footer', 'cell'),
|
||||
'TextBox' => array('section', 'header', 'footer', 'cell'),
|
||||
'Footnote' => array('section', 'textrun', 'cell'),
|
||||
|
|
|
|||
|
|
@ -114,19 +114,4 @@ class Footer extends AbstractContainer
|
|||
{
|
||||
return $this->type = self::EVEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add table element
|
||||
*
|
||||
* @param mixed $style
|
||||
* @return \PhpOffice\PhpWord\Element\Table
|
||||
* @todo Merge with the same function on Section
|
||||
*/
|
||||
public function addTable($style = null)
|
||||
{
|
||||
$table = new Table($this->getDocPart(), $this->getDocPartId(), $style);
|
||||
$this->addElement($table);
|
||||
|
||||
return $table;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,21 +117,6 @@ class Section extends AbstractContainer
|
|||
$this->addElement(new PageBreak());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add table element
|
||||
*
|
||||
* @param mixed $style
|
||||
* @return \PhpOffice\PhpWord\Element\Table
|
||||
* @todo Merge with the same function on Footer
|
||||
*/
|
||||
public function addTable($style = null)
|
||||
{
|
||||
$table = new Table($this->getDocPart(), $this->getDocPartId(), $style);
|
||||
$this->addElement($table);
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Table-of-Contents Element
|
||||
*
|
||||
|
|
|
|||
|
|
@ -53,9 +53,8 @@ class Table extends AbstractElement
|
|||
* @param integer $docPartId
|
||||
* @param mixed $style
|
||||
*/
|
||||
public function __construct($docPart, $docPartId, $style = null)
|
||||
public function __construct($style = null)
|
||||
{
|
||||
$this->setDocPart($docPart, $docPartId);
|
||||
$this->style = $this->setStyle(new TableStyle(), $style);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,229 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of PHPWord - A pure PHP library for reading and writing
|
||||
* word processing documents.
|
||||
*
|
||||
* PHPWord is free software distributed under the terms of the GNU Lesser
|
||||
* General Public License version 3 as published by the Free Software Foundation.
|
||||
*
|
||||
* For the full copyright and license information, please read the LICENSE
|
||||
* file that was distributed with this source code. For the full list of
|
||||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
|
||||
*
|
||||
* @link https://github.com/PHPOffice/PHPWord
|
||||
* @copyright 2010-2014 PHPWord contributors
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
||||
*/
|
||||
|
||||
namespace PhpOffice\PhpWord\Shared;
|
||||
|
||||
/**
|
||||
* Common Html functions
|
||||
*/
|
||||
class Html
|
||||
{
|
||||
/**
|
||||
* Add HTML parts
|
||||
*
|
||||
* Note: $stylesheet parameter is removed to avoid PHPMD error for unused parameter
|
||||
*
|
||||
* @param \PhpOffice\PhpWord\Element\AbstractElement $object Where the parts need to be added
|
||||
* @param string $html the code to parse
|
||||
*
|
||||
*/
|
||||
public static function addHtml($object, $html)
|
||||
{
|
||||
/*
|
||||
* @todo parse $stylesheet for default styles. Should result in an array based on id, class and element,
|
||||
* which could be applied when such an element occurs in the parseNode function.
|
||||
*/
|
||||
$html = str_replace(array("\n","\r"), '', $html);
|
||||
|
||||
$dom = new \DOMDocument();
|
||||
$dom->preserveWhiteSpace = true;
|
||||
$dom->loadXML('<body>' . html_entity_decode($html) . '</body>');
|
||||
|
||||
$node = $dom->getElementsByTagName('body');
|
||||
|
||||
self::parseNode($node->item(0), $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* parse Inline style of a node
|
||||
*
|
||||
* @param $node node to check on attributes and to compile a style array
|
||||
* @param $style is supplied, the inline style attributes are added to the already existing style
|
||||
*
|
||||
*/
|
||||
protected static function parseInlineStyle($node, $style = array())
|
||||
{
|
||||
if ($node->nodeType == XML_ELEMENT_NODE) {
|
||||
$attributes = $node->attributes; // get all the attributes(eg: id, class)
|
||||
|
||||
foreach ($attributes as $attribute) {
|
||||
switch ($attribute->name) {
|
||||
case 'style':
|
||||
$properties = explode(';', trim($attribute->value, " \t\n\r\0\x0B;"));
|
||||
foreach ($properties as $property) {
|
||||
list ($cKey, $cValue) = explode(':', $property, 2);
|
||||
$cValue = trim($cValue);
|
||||
switch (trim($cKey)) {
|
||||
case 'text-decoration':
|
||||
switch ($cValue) {
|
||||
case 'underline':
|
||||
$style['underline'] = 'single';
|
||||
break;
|
||||
case 'line-through':
|
||||
$style['strikethrough'] = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'text-align':
|
||||
$style['align'] = $cValue;
|
||||
break;
|
||||
case 'color':
|
||||
$style['color'] = trim($cValue, "#");
|
||||
break;
|
||||
case 'background-color':
|
||||
$style['bgColor'] = trim($cValue, "#");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $style;
|
||||
}
|
||||
|
||||
/**
|
||||
* parse a node and add a corresponding element to the object
|
||||
*
|
||||
* @param $node node to parse
|
||||
* @param $object object to add an element corresponding with the node
|
||||
* @param $styles array with all styles
|
||||
* @param $data array to transport data to a next level in the DOM tree, for example level of listitems
|
||||
*
|
||||
*/
|
||||
protected static function parseNode($node, $object, $styles = array('fontStyle' => array(), 'paragraphStyle' => array(), 'listStyle' => array()), $data = array())
|
||||
{
|
||||
$newobject = null;
|
||||
switch ($node->nodeName) {
|
||||
case 'p':
|
||||
$styles['paragraphStyle'] = self::parseInlineStyle($node, $styles['paragraphStyle']);
|
||||
$newobject = $object->addTextRun($styles['paragraphStyle']);
|
||||
break;
|
||||
|
||||
/**
|
||||
* @todo Think of a clever way of defining header styles, now it is only based on the assumption, that
|
||||
* Heading1 - Heading6 are already defined somewhere
|
||||
*/
|
||||
case 'h1':
|
||||
$styles['paragraphStyle'] = 'Heading1';
|
||||
$newobject = $object->addTextRun($styles['paragraphStyle']);
|
||||
break;
|
||||
case 'h2':
|
||||
$styles['paragraphStyle'] = 'Heading2';
|
||||
$newobject = $object->addTextRun($styles['paragraphStyle']);
|
||||
break;
|
||||
case 'h3':
|
||||
$styles['paragraphStyle'] = 'Heading3';
|
||||
$newobject = $object->addTextRun($styles['paragraphStyle']);
|
||||
break;
|
||||
case 'h4':
|
||||
$styles['paragraphStyle'] = 'Heading4';
|
||||
$newobject = $object->addTextRun($styles['paragraphStyle']);
|
||||
break;
|
||||
case 'h5':
|
||||
$styles['paragraphStyle'] = 'Heading5';
|
||||
$newobject = $object->addTextRun($styles['paragraphStyle']);
|
||||
break;
|
||||
case 'h6':
|
||||
$styles['paragraphStyle'] = 'Heading6';
|
||||
$newobject = $object->addTextRun($styles['paragraphStyle']);
|
||||
break;
|
||||
case '#text':
|
||||
$styles['fontStyle'] = self::parseInlineStyle($node, $styles['fontStyle']);
|
||||
$object->AddText($node->nodeValue, $styles['fontStyle'], $styles['paragraphStyle']);
|
||||
break;
|
||||
case 'strong':
|
||||
$styles['fontStyle']['bold'] = true;
|
||||
break;
|
||||
case 'em':
|
||||
$styles['fontStyle']['italic'] = true;
|
||||
break;
|
||||
case 'sup':
|
||||
$styles['fontStyle']['superScript'] = true;
|
||||
break;
|
||||
case 'sub':
|
||||
$styles['fontStyle']['subScript'] = true;
|
||||
break;
|
||||
|
||||
/**
|
||||
* @todo As soon as TableItem, RowItem and CellItem support relative width and height
|
||||
*/
|
||||
case 'table':
|
||||
$styles['paragraphStyle'] = self::parseInlineStyle($node, $styles['paragraphStyle']);
|
||||
$newobject = $object->addTable();
|
||||
// if ($attributes->getNamedItem('width') !== null)$newobject->setWidth($attributes->getNamedItem('width')->value);
|
||||
break;
|
||||
case 'tr':
|
||||
$styles['paragraphStyle'] = self::parseInlineStyle($node, $styles['paragraphStyle']);
|
||||
$newobject = $object->addRow();
|
||||
// if ($attributes->getNamedItem('height') !== null)$newobject->setHeight($attributes->getNamedItem('height')->value);
|
||||
break;
|
||||
case 'td':
|
||||
$styles['paragraphStyle'] = self::parseInlineStyle($node, $styles['paragraphStyle']);
|
||||
// if ($attributes->getNamedItem('width') !== null)$newobject=$object->addCell($width=$attributes->getNamedItem('width')->value);
|
||||
// else $newobject=$object->addCell();
|
||||
$newobject = $object->addCell();
|
||||
break;
|
||||
case 'ul':
|
||||
if (isset($data['listdepth'])) {
|
||||
$data['listdepth'] ++;
|
||||
} else {
|
||||
$data['listdepth'] = 0;
|
||||
}
|
||||
$styles['listStyle']['listType'] = 3; // TYPE_BULLET_FILLED = 3;
|
||||
break;
|
||||
case 'ol':
|
||||
if (isset($data['listdepth'])) {
|
||||
$data['listdepth'] ++;
|
||||
} else {
|
||||
$data['listdepth'] = 0;
|
||||
}
|
||||
$styles['listStyle']['listType'] = 7; // TYPE_NUMBER = 7;
|
||||
break;
|
||||
|
||||
/**
|
||||
* @todo As soon as ListItem inherits from AbstractContainer or TextRun delete parsing part of childNodes
|
||||
*/
|
||||
case 'li':
|
||||
$cNodes = $node->childNodes;
|
||||
if (count($cNodes) > 0) {
|
||||
foreach ($cNodes as $cNode) {
|
||||
if ($cNode->nodeName == '#text') {
|
||||
$text = $cNode->nodeValue;
|
||||
}
|
||||
}
|
||||
$object->addListItem($text, $data['listdepth'], $styles['fontStyle'], $styles['listStyle'], $styles['paragraphStyle']);
|
||||
}
|
||||
}
|
||||
|
||||
if ($newobject === null) {
|
||||
$newobject = $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo As soon as ListItem inherits from AbstractContainer or TextRun delete condition
|
||||
*/
|
||||
if ($node->nodeName != 'li') {
|
||||
$cNodes = $node->childNodes;
|
||||
if (count($cNodes) > 0) {
|
||||
foreach ($cNodes as $cNode) {
|
||||
self::parseNode($cNode, $newobject, $styles, $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue