Merge branch 'develop' into patch-1

This commit is contained in:
troosan 2019-09-01 21:57:27 +02:00 committed by GitHub
commit 18664fb955
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 109 additions and 49 deletions

View File

@ -19,7 +19,7 @@ matrix:
env: COVERAGE=1 env: COVERAGE=1
- php: 5.3 - php: 5.3
dist: precise dist: precise
env: COMPOSER_MEMORY_LIMIT=2G env: COMPOSER_MEMORY_LIMIT=3G
- php: 7.3 - php: 7.3
env: DEPENDENCIES="--ignore-platform-reqs" env: DEPENDENCIES="--ignore-platform-reqs"
exclude: exclude:
@ -38,6 +38,7 @@ env:
before_install: before_install:
## Packages ## Packages
- sudo rm -f /etc/apt/sources.list.d/mongodb.list # Makes apt crash on Precise, and we don't need MongoDB
- sudo apt-get update -qq - sudo apt-get update -qq
- sudo apt-get install -y graphviz - sudo apt-get install -y graphviz

View File

@ -17,7 +17,7 @@ Develop:
PHPWord is a library written in pure PHP that provides a set of classes to write to and read from different document file formats. The current version of PHPWord supports Microsoft [Office Open XML](http://en.wikipedia.org/wiki/Office_Open_XML) (OOXML or OpenXML), OASIS [Open Document Format for Office Applications](http://en.wikipedia.org/wiki/OpenDocument) (OpenDocument or ODF), [Rich Text Format](http://en.wikipedia.org/wiki/Rich_Text_Format) (RTF), HTML, and PDF. PHPWord is a library written in pure PHP that provides a set of classes to write to and read from different document file formats. The current version of PHPWord supports Microsoft [Office Open XML](http://en.wikipedia.org/wiki/Office_Open_XML) (OOXML or OpenXML), OASIS [Open Document Format for Office Applications](http://en.wikipedia.org/wiki/OpenDocument) (OpenDocument or ODF), [Rich Text Format](http://en.wikipedia.org/wiki/Rich_Text_Format) (RTF), HTML, and PDF.
PHPWord is an open source project licensed under the terms of [LGPL version 3](https://github.com/PHPOffice/PHPWord/blob/develop/COPYING.LESSER). PHPWord is aimed to be a high quality software product by incorporating [continuous integration](https://travis-ci.org/PHPOffice/PHPWord) and [unit testing](http://phpoffice.github.io/PHPWord/coverage/develop/). You can learn more about PHPWord by reading the [Developers' Documentation](http://phpword.readthedocs.org/). PHPWord is an open source project licensed under the terms of [LGPL version 3](COPYING.LESSER). PHPWord is aimed to be a high quality software product by incorporating [continuous integration](https://travis-ci.org/PHPOffice/PHPWord) and [unit testing](http://phpoffice.github.io/PHPWord/coverage/develop/). You can learn more about PHPWord by reading the [Developers' Documentation](http://phpword.readthedocs.org/).
If you have any questions, please ask on [StackOverFlow](https://stackoverflow.com/questions/tagged/phpword) If you have any questions, please ask on [StackOverFlow](https://stackoverflow.com/questions/tagged/phpword)
@ -174,7 +174,7 @@ You can also read the [Developers' Documentation](http://phpword.readthedocs.org
We welcome everyone to contribute to PHPWord. Below are some of the things that you can do to contribute. We welcome everyone to contribute to PHPWord. Below are some of the things that you can do to contribute.
- Read [our contributing guide](https://github.com/PHPOffice/PHPWord/blob/master/CONTRIBUTING.md). - Read [our contributing guide](CONTRIBUTING.md).
- [Fork us](https://github.com/PHPOffice/PHPWord/fork) and [request a pull](https://github.com/PHPOffice/PHPWord/pulls) to the [develop](https://github.com/PHPOffice/PHPWord/tree/develop) branch. - [Fork us](https://github.com/PHPOffice/PHPWord/fork) and [request a pull](https://github.com/PHPOffice/PHPWord/pulls) to the [develop](https://github.com/PHPOffice/PHPWord/tree/develop) branch.
- Submit [bug reports or feature requests](https://github.com/PHPOffice/PHPWord/issues) to GitHub. - Submit [bug reports or feature requests](https://github.com/PHPOffice/PHPWord/issues) to GitHub.
- Follow [@PHPWord](https://twitter.com/PHPWord) and [@PHPOffice](https://twitter.com/PHPOffice) on Twitter. - Follow [@PHPWord](https://twitter.com/PHPWord) and [@PHPOffice](https://twitter.com/PHPOffice) on Twitter.

View File

@ -19,7 +19,7 @@
<rule ref="rulesets/design.xml/CouplingBetweenObjects"> <rule ref="rulesets/design.xml/CouplingBetweenObjects">
<!-- AbstractContainer needs more coupling (default: 13) --> <!-- AbstractContainer needs more coupling (default: 13) -->
<properties> <properties>
<property name="minimum" value="20" /> <property name="maximum" value="20" />
</properties> </properties>
</rule> </rule>
<rule ref="rulesets/design.xml/NumberOfChildren"> <rule ref="rulesets/design.xml/NumberOfChildren">

View File

@ -254,7 +254,7 @@ abstract class AbstractContainer extends AbstractElement
// Special condition, e.g. preservetext can only exists in cell when // Special condition, e.g. preservetext can only exists in cell when
// the cell is located in header or footer // the cell is located in header or footer
$validSubcontainers = array( $validSubcontainers = array(
'PreserveText' => array(array('Cell'), array('Header', 'Footer')), 'PreserveText' => array(array('Cell'), array('Header', 'Footer', 'Section')),
'Footnote' => array(array('Cell', 'TextRun'), array('Section')), 'Footnote' => array(array('Cell', 'TextRun'), array('Section')),
'Endnote' => array(array('Cell', 'TextRun'), array('Section')), 'Endnote' => array(array('Cell', 'TextRun'), array('Section')),
); );

View File

@ -32,9 +32,9 @@ use PhpOffice\PhpWord\Style\Paragraph;
*/ */
class Html class Html
{ {
private static $listIndex = 0; protected static $listIndex = 0;
private static $xpath; protected static $xpath;
private static $options; protected static $options;
/** /**
* Add HTML parts. * Add HTML parts.
@ -203,7 +203,7 @@ class Html
* @param array $styles * @param array $styles
* @param array $data * @param array $data
*/ */
private static function parseChildNodes($node, $element, $styles, $data) protected static function parseChildNodes($node, $element, $styles, $data)
{ {
if ('li' != $node->nodeName) { if ('li' != $node->nodeName) {
$cNodes = $node->childNodes; $cNodes = $node->childNodes;
@ -225,7 +225,7 @@ class Html
* @param array &$styles * @param array &$styles
* @return \PhpOffice\PhpWord\Element\TextRun * @return \PhpOffice\PhpWord\Element\TextRun
*/ */
private static function parseParagraph($node, $element, &$styles) protected static function parseParagraph($node, $element, &$styles)
{ {
$styles['paragraph'] = self::recursiveParseStylesInHierarchy($node, $styles['paragraph']); $styles['paragraph'] = self::recursiveParseStylesInHierarchy($node, $styles['paragraph']);
$newElement = $element->addTextRun($styles['paragraph']); $newElement = $element->addTextRun($styles['paragraph']);
@ -244,7 +244,7 @@ class Html
* @todo Think of a clever way of defining header styles, now it is only based on the assumption, that * @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 * Heading1 - Heading6 are already defined somewhere
*/ */
private static function parseHeading($element, &$styles, $argument1) protected static function parseHeading($element, &$styles, $argument1)
{ {
$styles['paragraph'] = $argument1; $styles['paragraph'] = $argument1;
$newElement = $element->addTextRun($styles['paragraph']); $newElement = $element->addTextRun($styles['paragraph']);
@ -259,7 +259,7 @@ class Html
* @param \PhpOffice\PhpWord\Element\AbstractContainer $element * @param \PhpOffice\PhpWord\Element\AbstractContainer $element
* @param array &$styles * @param array &$styles
*/ */
private static function parseText($node, $element, &$styles) protected static function parseText($node, $element, &$styles)
{ {
$styles['font'] = self::recursiveParseStylesInHierarchy($node, $styles['font']); $styles['font'] = self::recursiveParseStylesInHierarchy($node, $styles['font']);
@ -280,7 +280,7 @@ class Html
* @param string $argument1 Style name * @param string $argument1 Style name
* @param string $argument2 Style value * @param string $argument2 Style value
*/ */
private static function parseProperty(&$styles, $argument1, $argument2) protected static function parseProperty(&$styles, $argument1, $argument2)
{ {
$styles['font'][$argument1] = $argument2; $styles['font'][$argument1] = $argument2;
} }
@ -291,7 +291,7 @@ class Html
* @param \DOMNode $node * @param \DOMNode $node
* @param array &$styles * @param array &$styles
*/ */
private static function parseSpan($node, &$styles) protected static function parseSpan($node, &$styles)
{ {
self::parseInlineStyle($node, $styles['font']); self::parseInlineStyle($node, $styles['font']);
} }
@ -306,7 +306,7 @@ class Html
* *
* @todo As soon as TableItem, RowItem and CellItem support relative width and height * @todo As soon as TableItem, RowItem and CellItem support relative width and height
*/ */
private static function parseTable($node, $element, &$styles) protected static function parseTable($node, $element, &$styles)
{ {
$elementStyles = self::parseInlineStyle($node, $styles['table']); $elementStyles = self::parseInlineStyle($node, $styles['table']);
@ -335,7 +335,7 @@ class Html
* @param array &$styles * @param array &$styles
* @return Row $element * @return Row $element
*/ */
private static function parseRow($node, $element, &$styles) protected static function parseRow($node, $element, &$styles)
{ {
$rowStyles = self::parseInlineStyle($node, $styles['row']); $rowStyles = self::parseInlineStyle($node, $styles['row']);
if ($node->parentNode->nodeName == 'thead') { if ($node->parentNode->nodeName == 'thead') {
@ -353,7 +353,7 @@ class Html
* @param array &$styles * @param array &$styles
* @return \PhpOffice\PhpWord\Element\Cell|\PhpOffice\PhpWord\Element\TextRun $element * @return \PhpOffice\PhpWord\Element\Cell|\PhpOffice\PhpWord\Element\TextRun $element
*/ */
private static function parseCell($node, $element, &$styles) protected static function parseCell($node, $element, &$styles)
{ {
$cellStyles = self::recursiveParseStylesInHierarchy($node, $styles['cell']); $cellStyles = self::recursiveParseStylesInHierarchy($node, $styles['cell']);
@ -376,7 +376,7 @@ class Html
* @param \DOMNode $node * @param \DOMNode $node
* @return bool Returns true if the node contains an HTML element that cannot be added to TextRun * @return bool Returns true if the node contains an HTML element that cannot be added to TextRun
*/ */
private static function shouldAddTextRun(\DOMNode $node) protected static function shouldAddTextRun(\DOMNode $node)
{ {
$containsBlockElement = self::$xpath->query('.//table|./p|./ul|./ol', $node)->length > 0; $containsBlockElement = self::$xpath->query('.//table|./p|./ul|./ol', $node)->length > 0;
if ($containsBlockElement) { if ($containsBlockElement) {
@ -393,7 +393,7 @@ class Html
* @param \DOMNode $node * @param \DOMNode $node
* @param array &$styles * @param array &$styles
*/ */
private static function recursiveParseStylesInHierarchy(\DOMNode $node, array $style) protected static function recursiveParseStylesInHierarchy(\DOMNode $node, array $style)
{ {
$parentStyle = self::parseInlineStyle($node, array()); $parentStyle = self::parseInlineStyle($node, array());
$style = array_merge($parentStyle, $style); $style = array_merge($parentStyle, $style);
@ -412,7 +412,7 @@ class Html
* @param array &$styles * @param array &$styles
* @param array &$data * @param array &$data
*/ */
private static function parseList($node, $element, &$styles, &$data) protected static function parseList($node, $element, &$styles, &$data)
{ {
$isOrderedList = $node->nodeName === 'ol'; $isOrderedList = $node->nodeName === 'ol';
if (isset($data['listdepth'])) { if (isset($data['listdepth'])) {
@ -431,7 +431,7 @@ class Html
* @param bool $isOrderedList * @param bool $isOrderedList
* @return array * @return array
*/ */
private static function getListStyle($isOrderedList) protected static function getListStyle($isOrderedList)
{ {
if ($isOrderedList) { if ($isOrderedList) {
return array( return array(
@ -477,7 +477,7 @@ class Html
* @todo This function is almost the same like `parseChildNodes`. Merged? * @todo This function is almost the same like `parseChildNodes`. Merged?
* @todo As soon as ListItem inherits from AbstractContainer or TextRun delete parsing part of childNodes * @todo As soon as ListItem inherits from AbstractContainer or TextRun delete parsing part of childNodes
*/ */
private static function parseListItem($node, $element, &$styles, $data) protected static function parseListItem($node, $element, &$styles, $data)
{ {
$cNodes = $node->childNodes; $cNodes = $node->childNodes;
if (!empty($cNodes)) { if (!empty($cNodes)) {
@ -495,7 +495,7 @@ class Html
* @param array $styles * @param array $styles
* @return array * @return array
*/ */
private static function parseStyle($attribute, $styles) protected static function parseStyle($attribute, $styles)
{ {
$properties = explode(';', trim($attribute->value, " \t\n\r\0\x0B;")); $properties = explode(';', trim($attribute->value, " \t\n\r\0\x0B;"));
@ -623,7 +623,7 @@ class Html
* *
* @return \PhpOffice\PhpWord\Element\Image * @return \PhpOffice\PhpWord\Element\Image
**/ **/
private static function parseImage($node, $element) protected static function parseImage($node, $element)
{ {
$style = array(); $style = array();
$src = null; $src = null;
@ -726,7 +726,7 @@ class Html
* @param string $cssBorderStyle * @param string $cssBorderStyle
* @return null|string * @return null|string
*/ */
private static function mapBorderStyle($cssBorderStyle) protected static function mapBorderStyle($cssBorderStyle)
{ {
switch ($cssBorderStyle) { switch ($cssBorderStyle) {
case 'none': case 'none':
@ -739,7 +739,7 @@ class Html
} }
} }
private static function mapBorderColor(&$styles, $cssBorderColor) protected static function mapBorderColor(&$styles, $cssBorderColor)
{ {
$numColors = substr_count($cssBorderColor, '#'); $numColors = substr_count($cssBorderColor, '#');
if ($numColors === 1) { if ($numColors === 1) {
@ -759,7 +759,7 @@ class Html
* @param string $cssAlignment * @param string $cssAlignment
* @return string|null * @return string|null
*/ */
private static function mapAlign($cssAlignment) protected static function mapAlign($cssAlignment)
{ {
switch ($cssAlignment) { switch ($cssAlignment) {
case 'right': case 'right':
@ -778,7 +778,7 @@ class Html
* *
* @param \PhpOffice\PhpWord\Element\AbstractContainer $element * @param \PhpOffice\PhpWord\Element\AbstractContainer $element
*/ */
private static function parseLineBreak($element) protected static function parseLineBreak($element)
{ {
$element->addTextBreak(); $element->addTextBreak();
} }
@ -790,7 +790,7 @@ class Html
* @param \PhpOffice\PhpWord\Element\AbstractContainer $element * @param \PhpOffice\PhpWord\Element\AbstractContainer $element
* @param array $styles * @param array $styles
*/ */
private static function parseLink($node, $element, &$styles) protected static function parseLink($node, $element, &$styles)
{ {
$target = null; $target = null;
foreach ($node->attributes as $attribute) { foreach ($node->attributes as $attribute) {

View File

@ -139,6 +139,16 @@ class ListItem extends AbstractStyle
return $this->numId; return $this->numId;
} }
/**
* Set numbering Id. Same numId means same list
* @param mixed $numInt
*/
public function setNumId($numInt)
{
$this->numId = $numInt;
$this->getListTypeStyle();
}
/** /**
* Get legacy numbering definition * Get legacy numbering definition
* *
@ -148,7 +158,12 @@ class ListItem extends AbstractStyle
private function getListTypeStyle() private function getListTypeStyle()
{ {
// Check if legacy style already registered in global Style collection // Check if legacy style already registered in global Style collection
$numStyle = "PHPWordList{$this->listType}"; $numStyle = 'PHPWordListType' . $this->listType;
if ($this->numId) {
$numStyle .= 'NumId' . $this->numId;
}
if (Style::getStyle($numStyle) !== null) { if (Style::getStyle($numStyle) !== null) {
$this->setNumStyle($numStyle); $this->setNumStyle($numStyle);

View File

@ -17,6 +17,7 @@
namespace PhpOffice\PhpWord\Writer\Word2007\Element; namespace PhpOffice\PhpWord\Writer\Word2007\Element;
use PhpOffice\PhpWord\Element\ListItemRun as ListItemRunElement;
use PhpOffice\PhpWord\Writer\Word2007\Style\Paragraph as ParagraphStyleWriter; use PhpOffice\PhpWord\Writer\Word2007\Style\Paragraph as ParagraphStyleWriter;
/** /**
@ -31,34 +32,56 @@ class ListItemRun extends AbstractElement
*/ */
public function write() public function write()
{ {
$xmlWriter = $this->getXmlWriter();
$element = $this->getElement(); $element = $this->getElement();
if (!$element instanceof \PhpOffice\PhpWord\Element\ListItemRun) {
if (!$element instanceof ListItemRunElement) {
return; return;
} }
$this->writeParagraph($element);
}
private function writeParagraph(ListItemRunElement $element)
{
$xmlWriter = $this->getXmlWriter();
$xmlWriter->startElement('w:p'); $xmlWriter->startElement('w:p');
$xmlWriter->startElement('w:pPr'); $this->writeParagraphProperties($element);
$paragraphStyle = $element->getParagraphStyle();
$styleWriter = new ParagraphStyleWriter($xmlWriter, $paragraphStyle);
$styleWriter->setIsInline(true);
$styleWriter->write();
$xmlWriter->startElement('w:numPr');
$xmlWriter->startElement('w:ilvl');
$xmlWriter->writeAttribute('w:val', $element->getDepth());
$xmlWriter->endElement(); // w:ilvl
$xmlWriter->startElement('w:numId');
$xmlWriter->writeAttribute('w:val', $element->getStyle()->getNumId());
$xmlWriter->endElement(); // w:numId
$xmlWriter->endElement(); // w:numPr
$xmlWriter->endElement(); // w:pPr
$containerWriter = new Container($xmlWriter, $element); $containerWriter = new Container($xmlWriter, $element);
$containerWriter->write(); $containerWriter->write();
$xmlWriter->endElement(); // w:p $xmlWriter->endElement(); // w:p
} }
private function writeParagraphProperties(ListItemRunElement $element)
{
$xmlWriter = $this->getXmlWriter();
$xmlWriter->startElement('w:pPr');
$styleWriter = new ParagraphStyleWriter($xmlWriter, $element->getParagraphStyle());
$styleWriter->setIsInline(true);
$styleWriter->setWithoutPPR(true);
$styleWriter->write();
$this->writeParagraphPropertiesNumbering($element);
$xmlWriter->endElement(); // w:pPr
}
private function writeParagraphPropertiesNumbering(ListItemRunElement $element)
{
$xmlWriter = $this->getXmlWriter();
$xmlWriter->startElement('w:numPr');
$xmlWriter->writeElementBlock('w:ilvl', array(
'w:val' => $element->getDepth(),
));
$xmlWriter->writeElementBlock('w:numId', array(
'w:val' => $element->getStyle()->getNumId(),
));
$xmlWriter->endElement(); // w:numPr
}
} }

View File

@ -233,7 +233,7 @@ class CellTest extends AbstractWebServerEmbeddedTest
public function testAddPreserveTextException() public function testAddPreserveTextException()
{ {
$oCell = new Cell(); $oCell = new Cell();
$oCell->setDocPart('Section', 1); $oCell->setDocPart('TextRun', 1);
$oCell->addPreserveText('text'); $oCell->addPreserveText('text');
} }

View File

@ -510,4 +510,25 @@ class ElementTest extends \PHPUnit\Framework\TestCase
$this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:t')); $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:t'));
$this->assertEquals('this text contains an & (ampersant)', $doc->getElement('/w:document/w:body/w:p/w:r/w:t')->nodeValue); $this->assertEquals('this text contains an & (ampersant)', $doc->getElement('/w:document/w:body/w:p/w:r/w:t')->nodeValue);
} }
/**
* Test ListItemRun paragraph style writing
*/
public function testListItemRunStyleWriting()
{
$phpWord = new PhpWord();
$phpWord->addParagraphStyle('MyParagraphStyle', array('spaceBefore' => 400));
$section = $phpWord->addSection();
$listItemRun = $section->addListItemRun(0, null, 'MyParagraphStyle');
$listItemRun->addText('List item');
$listItemRun->addText(' in bold', array('bold' => true));
$doc = TestHelperDOCX::getDocument($phpWord);
$this->assertFalse($doc->elementExists('/w:document/w:body/w:p/w:pPr/w:pPr'));
$this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:pPr/w:pStyle'));
$this->assertEquals('List item', $doc->getElement('/w:document/w:body/w:p/w:r[1]/w:t')->nodeValue);
$this->assertEquals(' in bold', $doc->getElement('/w:document/w:body/w:p/w:r[2]/w:t')->nodeValue);
$this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r[2]/w:rPr/w:b'));
}
} }