Word2007 parsing title formatting (#1297)
* Improve Title parsing - Title should be able to contain TextRun - Style 'Title' should be treated the same with as Heading - Add tests for Heading/Title reader * update the documentation and the changelog * PHP 7.2 build should not fail anymore * reduce dependencies versions * fix parsing of footnotes and endnotes * add method to remove an element from a section
This commit is contained in:
parent
740e66acf5
commit
30b224b3d0
|
|
@ -1,3 +1,8 @@
|
||||||
|
build:
|
||||||
|
nodes:
|
||||||
|
analysis:
|
||||||
|
tests:
|
||||||
|
override: [php-scrutinizer-run]
|
||||||
filter:
|
filter:
|
||||||
excluded_paths: [ 'vendor/*', 'tests/*', 'samples/*', 'src/PhpWord/Shared/PCLZip/*' ]
|
excluded_paths: [ 'vendor/*', 'tests/*', 'samples/*', 'src/PhpWord/Shared/PCLZip/*' ]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,9 @@ matrix:
|
||||||
include:
|
include:
|
||||||
- php: 5.6
|
- php: 5.6
|
||||||
env: COVERAGE=1
|
env: COVERAGE=1
|
||||||
allow_failures:
|
|
||||||
- php: 7.2
|
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- vendor
|
|
||||||
- $HOME/.composer/cache
|
- $HOME/.composer/cache
|
||||||
- .php-cs.cache
|
- .php-cs.cache
|
||||||
|
|
||||||
|
|
@ -38,7 +35,7 @@ before_script:
|
||||||
- if [ -z "$COVERAGE" ]; then phpenv config-rm xdebug.ini ; fi
|
- if [ -z "$COVERAGE" ]; then phpenv config-rm xdebug.ini ; fi
|
||||||
## Composer
|
## Composer
|
||||||
- composer self-update
|
- composer self-update
|
||||||
- composer install --prefer-source
|
- travis_wait composer install --prefer-source
|
||||||
## PHPDocumentor
|
## PHPDocumentor
|
||||||
- mkdir -p build/docs
|
- mkdir -p build/docs
|
||||||
- mkdir -p build/coverage
|
- mkdir -p build/coverage
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ v0.15.0 (?? ??? 2018)
|
||||||
- Fix parsing of `<w:br/>` tag. @troosan #1274
|
- Fix parsing of `<w:br/>` tag. @troosan #1274
|
||||||
- Bookmark are not writton as internal link in html writer @troosan #1263
|
- Bookmark are not writton as internal link in html writer @troosan #1263
|
||||||
- It should be possible to add a Footnote in a ListItemRun @troosan #1287 #1287
|
- It should be possible to add a Footnote in a ListItemRun @troosan #1287 #1287
|
||||||
|
- Fix parsing of Heading and Title formating @troosan @gthomas2 #465
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Remove zend-stdlib dependency @Trainmaster #1284
|
- Remove zend-stdlib dependency @Trainmaster #1284
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ Titles
|
||||||
|
|
||||||
If you want to structure your document or build table of contents, you need titles or headings.
|
If you want to structure your document or build table of contents, you need titles or headings.
|
||||||
To add a title to the document, use the ``addTitleStyle`` and ``addTitle`` method.
|
To add a title to the document, use the ``addTitleStyle`` and ``addTitle`` method.
|
||||||
|
If `depth` is 0, a Title will be inserted, otherwise a Heading1, Heading2, ...
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
|
|
@ -98,7 +99,7 @@ To add a title to the document, use the ``addTitleStyle`` and ``addTitle`` metho
|
||||||
- ``depth``.
|
- ``depth``.
|
||||||
- ``$fontStyle``. See :ref:`font-style`.
|
- ``$fontStyle``. See :ref:`font-style`.
|
||||||
- ``$paragraphStyle``. See :ref:`paragraph-style`.
|
- ``$paragraphStyle``. See :ref:`paragraph-style`.
|
||||||
- ``$text``. Text to be displayed in the document.
|
- ``$text``. Text to be displayed in the document. This can be `string` or a `\PhpOffice\PhpWord\Element\TextRun`
|
||||||
|
|
||||||
It's necessary to add a title style to your document because otherwise the title won't be detected as a real title.
|
It's necessary to add a title style to your document because otherwise the title won't be detected as a real title.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,14 @@ $section = $phpWord->addSection();
|
||||||
// Define styles
|
// Define styles
|
||||||
$fontStyle12 = array('spaceAfter' => 60, 'size' => 12);
|
$fontStyle12 = array('spaceAfter' => 60, 'size' => 12);
|
||||||
$fontStyle10 = array('size' => 10);
|
$fontStyle10 = array('size' => 10);
|
||||||
|
$phpWord->addTitleStyle(null, array('size' => 22, 'bold' => true));
|
||||||
$phpWord->addTitleStyle(1, array('size' => 20, 'color' => '333333', 'bold' => true));
|
$phpWord->addTitleStyle(1, array('size' => 20, 'color' => '333333', 'bold' => true));
|
||||||
$phpWord->addTitleStyle(2, array('size' => 16, 'color' => '666666'));
|
$phpWord->addTitleStyle(2, array('size' => 16, 'color' => '666666'));
|
||||||
$phpWord->addTitleStyle(3, array('size' => 14, 'italic' => true));
|
$phpWord->addTitleStyle(3, array('size' => 14, 'italic' => true));
|
||||||
$phpWord->addTitleStyle(4, array('size' => 12));
|
$phpWord->addTitleStyle(4, array('size' => 12));
|
||||||
|
|
||||||
// Add text elements
|
// Add text elements
|
||||||
$section->addText('Table of contents 1');
|
$section->addTitle('Table of contents 1', 0);
|
||||||
$section->addTextBreak(2);
|
$section->addTextBreak(2);
|
||||||
|
|
||||||
// Add TOC #1
|
// Add TOC #1
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,14 @@ abstract class AbstractCollection
|
||||||
/**
|
/**
|
||||||
* Items
|
* Items
|
||||||
*
|
*
|
||||||
* @var array
|
* @var \PhpOffice\PhpWord\Element\AbstractContainer[]
|
||||||
*/
|
*/
|
||||||
private $items = array();
|
private $items = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get items
|
* Get items
|
||||||
*
|
*
|
||||||
* @return array
|
* @return \PhpOffice\PhpWord\Element\AbstractContainer[]
|
||||||
*/
|
*/
|
||||||
public function getItems()
|
public function getItems()
|
||||||
{
|
{
|
||||||
|
|
@ -45,7 +45,7 @@ abstract class AbstractCollection
|
||||||
* Get item by index
|
* Get item by index
|
||||||
*
|
*
|
||||||
* @param int $index
|
* @param int $index
|
||||||
* @return mixed
|
* @return \PhpOffice\PhpWord\Element\AbstractContainer
|
||||||
*/
|
*/
|
||||||
public function getItem($index)
|
public function getItem($index)
|
||||||
{
|
{
|
||||||
|
|
@ -60,7 +60,7 @@ abstract class AbstractCollection
|
||||||
* Set item.
|
* Set item.
|
||||||
*
|
*
|
||||||
* @param int $index
|
* @param int $index
|
||||||
* @param mixed $item
|
* @param \PhpOffice\PhpWord\Element\AbstractContainer $item
|
||||||
*/
|
*/
|
||||||
public function setItem($index, $item)
|
public function setItem($index, $item)
|
||||||
{
|
{
|
||||||
|
|
@ -72,7 +72,7 @@ abstract class AbstractCollection
|
||||||
/**
|
/**
|
||||||
* Add new item
|
* Add new item
|
||||||
*
|
*
|
||||||
* @param mixed $item
|
* @param \PhpOffice\PhpWord\Element\AbstractContainer $item
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function addItem($item)
|
public function addItem($item)
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ abstract class AbstractContainer extends AbstractElement
|
||||||
/**
|
/**
|
||||||
* Elements collection
|
* Elements collection
|
||||||
*
|
*
|
||||||
* @var array
|
* @var \PhpOffice\PhpWord\Element\AbstractElement[]
|
||||||
*/
|
*/
|
||||||
protected $elements = array();
|
protected $elements = array();
|
||||||
|
|
||||||
|
|
@ -164,6 +164,41 @@ abstract class AbstractContainer extends AbstractElement
|
||||||
return $this->elements;
|
return $this->elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the element at the requested position
|
||||||
|
*
|
||||||
|
* @param int $index
|
||||||
|
* @return \PhpOffice\PhpWord\Element\AbstractElement|null
|
||||||
|
*/
|
||||||
|
public function getElement($index)
|
||||||
|
{
|
||||||
|
if (array_key_exists($index, $this->elements)) {
|
||||||
|
return $this->elements[$index];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the element at requested index
|
||||||
|
*
|
||||||
|
* @param int|\PhpOffice\PhpWord\Element\AbstractElement $toRemove
|
||||||
|
*/
|
||||||
|
public function removeElement($toRemove)
|
||||||
|
{
|
||||||
|
if (is_int($toRemove) && array_key_exists($toRemove, $this->elements)) {
|
||||||
|
unset($this->elements[$toRemove]);
|
||||||
|
} elseif ($toRemove instanceof \PhpOffice\PhpWord\Element\AbstractElement) {
|
||||||
|
foreach ($this->elements as $key => $element) {
|
||||||
|
if ($element->getElementId() === $toRemove->getElementId()) {
|
||||||
|
unset($this->elements[$key]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count elements
|
* Count elements
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class Bookmark extends AbstractElement
|
||||||
*
|
*
|
||||||
* @param string $name
|
* @param string $name
|
||||||
*/
|
*/
|
||||||
public function __construct($name)
|
public function __construct($name = '')
|
||||||
{
|
{
|
||||||
$this->name = CommonText::toUTF8($name);
|
$this->name = CommonText::toUTF8($name);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ class ListItem extends AbstractElement
|
||||||
|
|
||||||
// Version >= 0.10.0 will pass numbering style name. Older version will use old method
|
// Version >= 0.10.0 will pass numbering style name. Older version will use old method
|
||||||
if (!is_null($listStyle) && is_string($listStyle)) {
|
if (!is_null($listStyle) && is_string($listStyle)) {
|
||||||
$this->style = new ListItemStyle($listStyle);
|
$this->style = new ListItemStyle($listStyle); // @codeCoverageIgnore
|
||||||
} else {
|
} else {
|
||||||
$this->style = $this->setNewStyle(new ListItemStyle(), $listStyle, true);
|
$this->style = $this->setNewStyle(new ListItemStyle(), $listStyle, true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class Title extends AbstractElement
|
||||||
/**
|
/**
|
||||||
* Title Text content
|
* Title Text content
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string|TextRun
|
||||||
*/
|
*/
|
||||||
private $text;
|
private $text;
|
||||||
|
|
||||||
|
|
@ -56,15 +56,25 @@ class Title extends AbstractElement
|
||||||
/**
|
/**
|
||||||
* Create a new Title Element
|
* Create a new Title Element
|
||||||
*
|
*
|
||||||
* @param string $text
|
* @param string|TextRun $text
|
||||||
* @param int $depth
|
* @param int $depth
|
||||||
*/
|
*/
|
||||||
public function __construct($text, $depth = 1)
|
public function __construct($text, $depth = 1)
|
||||||
{
|
{
|
||||||
|
if (isset($text)) {
|
||||||
|
if (is_string($text)) {
|
||||||
$this->text = CommonText::toUTF8($text);
|
$this->text = CommonText::toUTF8($text);
|
||||||
|
} elseif ($text instanceof TextRun) {
|
||||||
|
$this->text = $text;
|
||||||
|
} else {
|
||||||
|
throw new \InvalidArgumentException('Invalid text, should be a string or a TextRun');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->depth = $depth;
|
$this->depth = $depth;
|
||||||
if (array_key_exists("Heading_{$this->depth}", Style::getStyles())) {
|
$styleName = $depth === 0 ? 'Title' : "Heading_{$this->depth}";
|
||||||
$this->style = "Heading{$this->depth}";
|
if (array_key_exists($styleName, Style::getStyles())) {
|
||||||
|
$this->style = str_replace('_', '', $styleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,21 @@ class PhpWord
|
||||||
return $this->sections;
|
return $this->sections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the section at the requested position
|
||||||
|
*
|
||||||
|
* @param int $index
|
||||||
|
* @return \PhpOffice\PhpWord\Element\Section|null
|
||||||
|
*/
|
||||||
|
public function getSection($index)
|
||||||
|
{
|
||||||
|
if (array_key_exists($index, $this->sections)) {
|
||||||
|
return $this->sections[$index];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new section
|
* Create new section
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
namespace PhpOffice\PhpWord\Reader\Word2007;
|
namespace PhpOffice\PhpWord\Reader\Word2007;
|
||||||
|
|
||||||
use PhpOffice\Common\XMLReader;
|
use PhpOffice\Common\XMLReader;
|
||||||
|
use PhpOffice\PhpWord\Element\TextRun;
|
||||||
use PhpOffice\PhpWord\Element\TrackChange;
|
use PhpOffice\PhpWord\Element\TrackChange;
|
||||||
use PhpOffice\PhpWord\PhpWord;
|
use PhpOffice\PhpWord\PhpWord;
|
||||||
|
|
||||||
|
|
@ -103,12 +104,10 @@ abstract class AbstractPart
|
||||||
{
|
{
|
||||||
// Paragraph style
|
// Paragraph style
|
||||||
$paragraphStyle = null;
|
$paragraphStyle = null;
|
||||||
$headingMatches = array();
|
$headingDepth = null;
|
||||||
if ($xmlReader->elementExists('w:pPr', $domNode)) {
|
if ($xmlReader->elementExists('w:pPr', $domNode)) {
|
||||||
$paragraphStyle = $this->readParagraphStyle($xmlReader, $domNode);
|
$paragraphStyle = $this->readParagraphStyle($xmlReader, $domNode);
|
||||||
if (is_array($paragraphStyle) && isset($paragraphStyle['styleName'])) {
|
$headingDepth = $this->getHeadingDepth($paragraphStyle);
|
||||||
preg_match('/Heading(\d)/', $paragraphStyle['styleName'], $headingMatches);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PreserveText
|
// PreserveText
|
||||||
|
|
@ -147,14 +146,19 @@ abstract class AbstractPart
|
||||||
foreach ($nodes as $node) {
|
foreach ($nodes as $node) {
|
||||||
$this->readRun($xmlReader, $node, $listItemRun, $docPart, $paragraphStyle);
|
$this->readRun($xmlReader, $node, $listItemRun, $docPart, $paragraphStyle);
|
||||||
}
|
}
|
||||||
} elseif (!empty($headingMatches)) {
|
} elseif ($headingDepth !== null) {
|
||||||
// Heading
|
// Heading or Title
|
||||||
$textContent = '';
|
$textContent = null;
|
||||||
$nodes = $xmlReader->getElements('w:r', $domNode);
|
$nodes = $xmlReader->getElements('w:r', $domNode);
|
||||||
|
if ($nodes->length === 1) {
|
||||||
|
$textContent = $xmlReader->getValue('w:t', $nodes->item(0));
|
||||||
|
} else {
|
||||||
|
$textContent = new TextRun($paragraphStyle);
|
||||||
foreach ($nodes as $node) {
|
foreach ($nodes as $node) {
|
||||||
$textContent .= $xmlReader->getValue('w:t', $node);
|
$this->readRun($xmlReader, $node, $textContent, $docPart, $paragraphStyle);
|
||||||
}
|
}
|
||||||
$parent->addTitle($textContent, $headingMatches[1]);
|
}
|
||||||
|
$parent->addTitle($textContent, $headingDepth);
|
||||||
} else {
|
} else {
|
||||||
// Text and TextRun
|
// Text and TextRun
|
||||||
$runCount = $xmlReader->countElements('w:r', $domNode);
|
$runCount = $xmlReader->countElements('w:r', $domNode);
|
||||||
|
|
@ -176,6 +180,29 @@ abstract class AbstractPart
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the depth of the Heading, returns 0 for a Title
|
||||||
|
*
|
||||||
|
* @param array $paragraphStyle
|
||||||
|
* @return number|null
|
||||||
|
*/
|
||||||
|
private function getHeadingDepth(array $paragraphStyle = null)
|
||||||
|
{
|
||||||
|
if (is_array($paragraphStyle) && isset($paragraphStyle['styleName'])) {
|
||||||
|
if ('Title' === $paragraphStyle['styleName']) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$headingMatches = array();
|
||||||
|
preg_match('/Heading(\d)/', $paragraphStyle['styleName'], $headingMatches);
|
||||||
|
if (!empty($headingMatches)) {
|
||||||
|
return $headingMatches[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read w:r.
|
* Read w:r.
|
||||||
*
|
*
|
||||||
|
|
@ -212,10 +239,14 @@ abstract class AbstractPart
|
||||||
} else {
|
} else {
|
||||||
if ($xmlReader->elementExists('w:footnoteReference', $domNode)) {
|
if ($xmlReader->elementExists('w:footnoteReference', $domNode)) {
|
||||||
// Footnote
|
// Footnote
|
||||||
$parent->addFootnote();
|
$wId = $xmlReader->getAttribute('w:id', $domNode, 'w:footnoteReference');
|
||||||
|
$footnote = $parent->addFootnote();
|
||||||
|
$footnote->setRelationId($wId);
|
||||||
} elseif ($xmlReader->elementExists('w:endnoteReference', $domNode)) {
|
} elseif ($xmlReader->elementExists('w:endnoteReference', $domNode)) {
|
||||||
// Endnote
|
// Endnote
|
||||||
$parent->addEndnote();
|
$wId = $xmlReader->getAttribute('w:id', $domNode, 'w:endnoteReference');
|
||||||
|
$endnote = $parent->addEndnote();
|
||||||
|
$endnote->setRelationId($wId);
|
||||||
} elseif ($xmlReader->elementExists('w:pict', $domNode)) {
|
} elseif ($xmlReader->elementExists('w:pict', $domNode)) {
|
||||||
// Image
|
// Image
|
||||||
$rId = $xmlReader->getAttribute('r:id', $domNode, 'w:pict/v:shape/v:imagedata');
|
$rId = $xmlReader->getAttribute('r:id', $domNode, 'w:pict/v:shape/v:imagedata');
|
||||||
|
|
@ -496,11 +527,9 @@ abstract class AbstractPart
|
||||||
return $possibleAttribute;
|
return $possibleAttribute;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return $attributes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return $attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -578,7 +607,7 @@ abstract class AbstractPart
|
||||||
*/
|
*/
|
||||||
private function isOn($value = null)
|
private function isOn($value = null)
|
||||||
{
|
{
|
||||||
return $value == null || $value == '1' || $value == 'true' || $value == 'on';
|
return $value === null || $value === '1' || $value === 'true' || $value === 'on';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -48,9 +48,6 @@ class Footnotes extends AbstractPart
|
||||||
*/
|
*/
|
||||||
public function read(PhpWord $phpWord)
|
public function read(PhpWord $phpWord)
|
||||||
{
|
{
|
||||||
$getMethod = "get{$this->collection}";
|
|
||||||
$collection = $phpWord->$getMethod()->getItems();
|
|
||||||
|
|
||||||
$xmlReader = new XMLReader();
|
$xmlReader = new XMLReader();
|
||||||
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
|
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
|
||||||
$nodes = $xmlReader->getElements('*');
|
$nodes = $xmlReader->getElements('*');
|
||||||
|
|
@ -60,9 +57,10 @@ class Footnotes extends AbstractPart
|
||||||
$type = $xmlReader->getAttribute('w:type', $node);
|
$type = $xmlReader->getAttribute('w:type', $node);
|
||||||
|
|
||||||
// Avoid w:type "separator" and "continuationSeparator"
|
// Avoid w:type "separator" and "continuationSeparator"
|
||||||
// Only look for <footnote> or <endnote> without w:type attribute
|
// Only look for <footnote> or <endnote> without w:type attribute, or with w:type = normal
|
||||||
if (is_null($type) && isset($collection[$id])) {
|
if ((is_null($type) || $type === 'normal')) {
|
||||||
$element = $collection[$id];
|
$element = $this->getElement($phpWord, $id);
|
||||||
|
if ($element !== null) {
|
||||||
$pNodes = $xmlReader->getElements('w:p/*', $node);
|
$pNodes = $xmlReader->getElements('w:p/*', $node);
|
||||||
foreach ($pNodes as $pNode) {
|
foreach ($pNodes as $pNode) {
|
||||||
$this->readRun($xmlReader, $pNode, $element, $this->collection);
|
$this->readRun($xmlReader, $pNode, $element, $this->collection);
|
||||||
|
|
@ -74,3 +72,26 @@ class Footnotes extends AbstractPart
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for the element with the given relationId
|
||||||
|
*
|
||||||
|
* @param PhpWord $phpWord
|
||||||
|
* @param int $relationId
|
||||||
|
* @return \PhpOffice\PhpWord\Element\AbstractContainer|null
|
||||||
|
*/
|
||||||
|
private function getElement(PhpWord $phpWord, $relationId)
|
||||||
|
{
|
||||||
|
$getMethod = "get{$this->collection}";
|
||||||
|
$collection = $phpWord->$getMethod()->getItems();
|
||||||
|
|
||||||
|
//not found by key, looping to search by relationId
|
||||||
|
foreach ($collection as $collectionElement) {
|
||||||
|
if ($collectionElement->getRelationId() == $relationId) {
|
||||||
|
return $collectionElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,13 @@ class Style
|
||||||
*/
|
*/
|
||||||
public static function addTitleStyle($depth, $fontStyle, $paragraphStyle = null)
|
public static function addTitleStyle($depth, $fontStyle, $paragraphStyle = null)
|
||||||
{
|
{
|
||||||
return self::setStyleValues("Heading_{$depth}", new Font('title', $paragraphStyle), $fontStyle);
|
if ($depth == null) {
|
||||||
|
$styleName = 'Title';
|
||||||
|
} else {
|
||||||
|
$styleName = "Heading_{$depth}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::setStyleValues($styleName, new Font('title', $paragraphStyle), $fontStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ class Title extends AbstractElement
|
||||||
$xmlWriter->endElement();
|
$xmlWriter->endElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($element->getDepth() !== 0) {
|
||||||
$rId = $element->getRelationId();
|
$rId = $element->getRelationId();
|
||||||
$bookmarkRId = $element->getPhpWord()->addBookmark();
|
$bookmarkRId = $element->getPhpWord()->addBookmark();
|
||||||
|
|
||||||
|
|
@ -54,20 +55,28 @@ class Title extends AbstractElement
|
||||||
$xmlWriter->startElement('w:bookmarkStart');
|
$xmlWriter->startElement('w:bookmarkStart');
|
||||||
$xmlWriter->writeAttribute('w:id', $bookmarkRId);
|
$xmlWriter->writeAttribute('w:id', $bookmarkRId);
|
||||||
$xmlWriter->writeAttribute('w:name', "_Toc{$rId}");
|
$xmlWriter->writeAttribute('w:name', "_Toc{$rId}");
|
||||||
$xmlWriter->endElement();
|
$xmlWriter->endElement(); //w:bookmarkStart
|
||||||
|
}
|
||||||
|
|
||||||
// Actual text
|
// Actual text
|
||||||
|
$text = $element->getText();
|
||||||
|
if (is_string($text)) {
|
||||||
$xmlWriter->startElement('w:r');
|
$xmlWriter->startElement('w:r');
|
||||||
$xmlWriter->startElement('w:t');
|
$xmlWriter->startElement('w:t');
|
||||||
$this->writeText($this->getText($element->getText()));
|
$this->writeText($text);
|
||||||
$xmlWriter->endElement(); // w:t
|
$xmlWriter->endElement(); // w:t
|
||||||
$xmlWriter->endElement(); // w:r
|
$xmlWriter->endElement(); // w:r
|
||||||
|
} elseif ($text instanceof \PhpOffice\PhpWord\Element\AbstractContainer) {
|
||||||
|
$containerWriter = new Container($xmlWriter, $text);
|
||||||
|
$containerWriter->write();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($element->getDepth() !== 0) {
|
||||||
// Bookmark end
|
// Bookmark end
|
||||||
$xmlWriter->startElement('w:bookmarkEnd');
|
$xmlWriter->startElement('w:bookmarkEnd');
|
||||||
$xmlWriter->writeAttribute('w:id', $bookmarkRId);
|
$xmlWriter->writeAttribute('w:id', $bookmarkRId);
|
||||||
$xmlWriter->endElement();
|
$xmlWriter->endElement(); //w:bookmarkEnd
|
||||||
|
}
|
||||||
$xmlWriter->endElement();
|
$xmlWriter->endElement(); //w:p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -180,9 +180,15 @@ class Styles extends AbstractPart
|
||||||
// Heading style
|
// Heading style
|
||||||
if ($styleType == 'title') {
|
if ($styleType == 'title') {
|
||||||
$arrStyle = explode('_', $styleName);
|
$arrStyle = explode('_', $styleName);
|
||||||
|
if (count($arrStyle) > 1) {
|
||||||
$styleId = 'Heading' . $arrStyle[1];
|
$styleId = 'Heading' . $arrStyle[1];
|
||||||
$styleName = 'heading ' . $arrStyle[1];
|
$styleName = 'heading ' . $arrStyle[1];
|
||||||
$styleLink = 'Heading' . $arrStyle[1] . 'Char';
|
$styleLink = 'Heading' . $arrStyle[1] . 'Char';
|
||||||
|
} else {
|
||||||
|
$styleId = $styleName;
|
||||||
|
$styleName = strtolower($styleName);
|
||||||
|
$styleLink = $styleName . 'Char';
|
||||||
|
}
|
||||||
$xmlWriter->writeAttribute('w:styleId', $styleId);
|
$xmlWriter->writeAttribute('w:styleId', $styleId);
|
||||||
|
|
||||||
$xmlWriter->startElement('w:link');
|
$xmlWriter->startElement('w:link');
|
||||||
|
|
|
||||||
|
|
@ -162,4 +162,35 @@ class SectionTest extends \PHPUnit\Framework\TestCase
|
||||||
$object = new Section(1);
|
$object = new Section(1);
|
||||||
$object->addHeader('ODD');
|
$object->addHeader('ODD');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \PhpOffice\PhpWord\Element\AbstractContainer::removeElement
|
||||||
|
*/
|
||||||
|
public function testRemoveElementByIndex()
|
||||||
|
{
|
||||||
|
$section = new Section(1);
|
||||||
|
$section->addText('firstText');
|
||||||
|
$section->addText('secondText');
|
||||||
|
|
||||||
|
$this->assertEquals(2, $section->countElements());
|
||||||
|
$section->removeElement(1);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $section->countElements());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \PhpOffice\PhpWord\Element\AbstractContainer::removeElement
|
||||||
|
*/
|
||||||
|
public function testRemoveElementByElement()
|
||||||
|
{
|
||||||
|
$section = new Section(1);
|
||||||
|
$fistText = $section->addText('firstText');
|
||||||
|
$secondText = $section->addText('secondText');
|
||||||
|
|
||||||
|
$this->assertEquals(2, $section->countElements());
|
||||||
|
$section->removeElement($fistText);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $section->countElements());
|
||||||
|
$this->assertEquals($secondText->getElementId(), $section->getElement(1)->getElementId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,4 +45,25 @@ class TitleTest extends \PHPUnit\Framework\TestCase
|
||||||
|
|
||||||
$this->assertNull($oTitle->getStyle());
|
$this->assertNull($oTitle->getStyle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new instance with TextRun
|
||||||
|
*/
|
||||||
|
public function testConstructWithTextRun()
|
||||||
|
{
|
||||||
|
$oTextRun = new TextRun();
|
||||||
|
$oTextRun->addText('text');
|
||||||
|
$oTitle = new Title($oTextRun);
|
||||||
|
|
||||||
|
$this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $oTitle->getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testConstructWithInvalidArgument()
|
||||||
|
{
|
||||||
|
$oPageBreak = new PageBreak();
|
||||||
|
new Title($oPageBreak);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,9 @@ class ElementTest extends AbstractTestReader
|
||||||
</w:r>
|
</w:r>
|
||||||
</w:p>';
|
</w:p>';
|
||||||
|
|
||||||
$phpWord = $this->getDocumentFromString($documentXml);
|
$phpWord = $this->getDocumentFromString(array('document' => $documentXml));
|
||||||
|
|
||||||
$elements = $this->get($phpWord->getSections(), 0)->getElements();
|
$elements = $phpWord->getSection(0)->getElements();
|
||||||
$this->assertInstanceOf('PhpOffice\PhpWord\Element\TextBreak', $elements[0]);
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\TextBreak', $elements[0]);
|
||||||
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $elements[1]);
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $elements[1]);
|
||||||
$this->assertEquals('test string', $elements[1]->getText());
|
$this->assertEquals('test string', $elements[1]->getText());
|
||||||
|
|
@ -70,17 +70,73 @@ class ElementTest extends AbstractTestReader
|
||||||
</w:r>
|
</w:r>
|
||||||
</w:p>';
|
</w:p>';
|
||||||
|
|
||||||
$phpWord = $this->getDocumentFromString($documentXml);
|
$phpWord = $this->getDocumentFromString(array('document' => $documentXml));
|
||||||
|
|
||||||
$elements = $this->get($phpWord->getSections(), 0)->getElements();
|
$sections = $phpWord->getSection(0);
|
||||||
$this->assertInstanceOf('PhpOffice\PhpWord\Element\ListItemRun', $elements[0]);
|
$this->assertNull($sections->getElement(999));
|
||||||
$this->assertEquals(0, $elements[0]->getDepth());
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\ListItemRun', $sections->getElement(0));
|
||||||
|
$this->assertEquals(0, $sections->getElement(0)->getDepth());
|
||||||
|
|
||||||
$listElements = $this->get($elements, 0)->getElements();
|
$listElements = $sections->getElement(0)->getElements();
|
||||||
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $listElements[0]);
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $listElements[0]);
|
||||||
$this->assertEquals('Two', $listElements[0]->getText());
|
$this->assertEquals('Two', $listElements[0]->getText());
|
||||||
$this->assertEquals(' with ', $listElements[1]->getText());
|
$this->assertEquals(' with ', $listElements[1]->getText());
|
||||||
$this->assertEquals('bold', $listElements[2]->getText());
|
$this->assertEquals('bold', $listElements[2]->getText());
|
||||||
$this->assertTrue($listElements[2]->getFontStyle()->getBold());
|
$this->assertTrue($listElements[2]->getFontStyle()->getBold());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test reading Title style
|
||||||
|
*/
|
||||||
|
public function testReadTitleStyle()
|
||||||
|
{
|
||||||
|
$documentXml = '<w:p>
|
||||||
|
<w:pPr>
|
||||||
|
<w:pStyle w:val="Title"/>
|
||||||
|
</w:pPr>
|
||||||
|
<w:r>
|
||||||
|
<w:t>This is a non formatted title</w:t>
|
||||||
|
</w:r>
|
||||||
|
</w:p>
|
||||||
|
<w:p>
|
||||||
|
<w:pPr>
|
||||||
|
<w:pStyle w:val="Title"/>
|
||||||
|
</w:pPr>
|
||||||
|
<w:r>
|
||||||
|
<w:t>This is a </w:t>
|
||||||
|
</w:r>
|
||||||
|
<w:r>
|
||||||
|
<w:rPr>
|
||||||
|
<w:b/>
|
||||||
|
</w:rPr>
|
||||||
|
<w:t>bold</w:t>
|
||||||
|
</w:r>
|
||||||
|
<w:r>
|
||||||
|
<w:t> title</w:t>
|
||||||
|
</w:r>
|
||||||
|
</w:p>';
|
||||||
|
|
||||||
|
$stylesXml = '<w:style w:type="paragraph" w:styleId="Title">
|
||||||
|
<w:name w:val="Title"/>
|
||||||
|
<w:link w:val="TitleChar"/>
|
||||||
|
<w:rPr>
|
||||||
|
<w:i/>
|
||||||
|
</w:rPr>
|
||||||
|
</w:style>';
|
||||||
|
|
||||||
|
$phpWord = $this->getDocumentFromString(array('document' => $documentXml, 'styles' => $stylesXml));
|
||||||
|
|
||||||
|
$elements = $phpWord->getSection(0)->getElements();
|
||||||
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Title', $elements[0]);
|
||||||
|
/** @var \PhpOffice\PhpWord\Element\Title $title */
|
||||||
|
$title = $elements[0];
|
||||||
|
$this->assertEquals('Title', $title->getStyle());
|
||||||
|
$this->assertEquals('This is a non formatted title', $title->getText());
|
||||||
|
|
||||||
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Title', $elements[1]);
|
||||||
|
/** @var \PhpOffice\PhpWord\Element\Title $formattedTitle */
|
||||||
|
$formattedTitle = $elements[1];
|
||||||
|
$this->assertEquals('Title', $formattedTitle->getStyle());
|
||||||
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $formattedTitle->getText());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,163 @@
|
||||||
|
<?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.
|
||||||
|
*
|
||||||
|
* @see https://github.com/PHPOffice/PHPWord
|
||||||
|
* @copyright 2010-2017 PHPWord contributors
|
||||||
|
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpWord\Reader\Word2007;
|
||||||
|
|
||||||
|
use PhpOffice\PhpWord\AbstractTestReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for PhpOffice\PhpWord\Reader\Word2007 subnamespace
|
||||||
|
*/
|
||||||
|
class PartTest extends AbstractTestReader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Test reading Footnotes
|
||||||
|
*/
|
||||||
|
public function testReadFootnote()
|
||||||
|
{
|
||||||
|
$documentXml = '<w:p>
|
||||||
|
<w:r>
|
||||||
|
<w:t>This is a test</w:t>
|
||||||
|
</w:r>
|
||||||
|
<w:r>
|
||||||
|
<w:rPr>
|
||||||
|
<w:rStyle w:val="FootnoteReference"/>
|
||||||
|
</w:rPr>
|
||||||
|
<w:footnoteReference w:id="1"/>
|
||||||
|
</w:r>
|
||||||
|
</w:p>
|
||||||
|
<w:p>
|
||||||
|
<w:r>
|
||||||
|
<w:t>And another one</w:t>
|
||||||
|
</w:r>
|
||||||
|
<w:r>
|
||||||
|
<w:rPr>
|
||||||
|
<w:rStyle w:val="EndnoteReference"/>
|
||||||
|
</w:rPr>
|
||||||
|
<w:endnoteReference w:id="2"/>
|
||||||
|
</w:r>
|
||||||
|
</w:p>';
|
||||||
|
|
||||||
|
$footnotesXml = '<w:footnote w:type="separator" w:id="-1">
|
||||||
|
<w:p>
|
||||||
|
<w:r>
|
||||||
|
<w:separator/>
|
||||||
|
</w:r>
|
||||||
|
</w:p>
|
||||||
|
</w:footnote>
|
||||||
|
<w:footnote w:id="1">
|
||||||
|
<w:p>
|
||||||
|
<w:pPr>
|
||||||
|
<w:pStyle w:val="FootnoteText"/>
|
||||||
|
</w:pPr>
|
||||||
|
<w:r>
|
||||||
|
<w:rPr>
|
||||||
|
<w:rStyle w:val="FootnoteReference"/>
|
||||||
|
</w:rPr>
|
||||||
|
<w:footnoteRef/>
|
||||||
|
</w:r>
|
||||||
|
<w:r>
|
||||||
|
<w:rPr>
|
||||||
|
<w:lang w:val="nl-NL"/>
|
||||||
|
</w:rPr>
|
||||||
|
<w:t>footnote text</w:t>
|
||||||
|
</w:r>
|
||||||
|
</w:p>
|
||||||
|
</w:footnote>';
|
||||||
|
|
||||||
|
$endnotesXml = '<w:endnote w:type="separator" w:id="-1">
|
||||||
|
<w:p>
|
||||||
|
<w:r>
|
||||||
|
<w:separator/>
|
||||||
|
</w:r>
|
||||||
|
</w:p>
|
||||||
|
</w:endnote>
|
||||||
|
<w:endnote w:type="continuationNotice" w:id="1">
|
||||||
|
<w:p>
|
||||||
|
<w:r>
|
||||||
|
<w:separator/>
|
||||||
|
</w:r>
|
||||||
|
</w:p>
|
||||||
|
</w:endnote>
|
||||||
|
<w:endnote w:id="2">
|
||||||
|
<w:p>
|
||||||
|
<w:pPr>
|
||||||
|
<w:pStyle w:val="EndnoteText"/>
|
||||||
|
</w:pPr>
|
||||||
|
<w:r>
|
||||||
|
<w:rPr>
|
||||||
|
<w:rStyle w:val="EndnoteReference"/>
|
||||||
|
</w:rPr>
|
||||||
|
<w:endnoteRef/>
|
||||||
|
</w:r>
|
||||||
|
<w:r>
|
||||||
|
<w:rPr>
|
||||||
|
<w:lang w:val="nl-NL"/>
|
||||||
|
</w:rPr>
|
||||||
|
<w:t>This is an endnote</w:t>
|
||||||
|
</w:r>
|
||||||
|
</w:p>
|
||||||
|
</w:endnote>';
|
||||||
|
|
||||||
|
$phpWord = $this->getDocumentFromString(array('document' => $documentXml, 'footnotes' => $footnotesXml, 'endnotes' => $endnotesXml));
|
||||||
|
|
||||||
|
$elements = $phpWord->getSection(0)->getElements();
|
||||||
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]);
|
||||||
|
/** @var \PhpOffice\PhpWord\Element\TextRun $textRun */
|
||||||
|
$textRun = $elements[0];
|
||||||
|
|
||||||
|
//test the text in the first paragraph
|
||||||
|
/** @var \PhpOffice\PhpWord\Element\Text $text */
|
||||||
|
$text = $elements[0]->getElement(0);
|
||||||
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $text);
|
||||||
|
$this->assertEquals('This is a test', $text->getText());
|
||||||
|
|
||||||
|
//test the presence of the footnote in the document.xml
|
||||||
|
/** @var \PhpOffice\PhpWord\Element\Footnote $footnote */
|
||||||
|
$documentFootnote = $textRun->getElement(1);
|
||||||
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Footnote', $documentFootnote);
|
||||||
|
$this->assertEquals(1, $documentFootnote->getRelationId());
|
||||||
|
|
||||||
|
//test the presence of the footnote in the footnote.xml
|
||||||
|
/** @var \PhpOffice\PhpWord\Element\Footnote $footnote */
|
||||||
|
$footnote = $phpWord->getFootnotes()->getItem(1);
|
||||||
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Footnote', $footnote);
|
||||||
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $footnote->getElement(0));
|
||||||
|
$this->assertEquals('footnote text', $footnote->getElement(0)->getText());
|
||||||
|
$this->assertEquals(1, $footnote->getRelationId());
|
||||||
|
|
||||||
|
//test the text in the second paragraph
|
||||||
|
/** @var \PhpOffice\PhpWord\Element\Text $text */
|
||||||
|
$text = $elements[1]->getElement(0);
|
||||||
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $text);
|
||||||
|
$this->assertEquals('And another one', $text->getText());
|
||||||
|
|
||||||
|
//test the presence of the endnote in the document.xml
|
||||||
|
/** @var \PhpOffice\PhpWord\Element\Endnote $endnote */
|
||||||
|
$documentEndnote = $elements[1]->getElement(1);
|
||||||
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Endnote', $documentEndnote);
|
||||||
|
$this->assertEquals(2, $documentEndnote->getRelationId());
|
||||||
|
|
||||||
|
//test the presence of the endnote in the endnote.xml
|
||||||
|
/** @var \PhpOffice\PhpWord\Element\Endnote $endnote */
|
||||||
|
$endnote = $phpWord->getEndnotes()->getItem(1);
|
||||||
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Endnote', $endnote);
|
||||||
|
$this->assertEquals(2, $endnote->getRelationId());
|
||||||
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $endnote->getElement(0));
|
||||||
|
$this->assertEquals('This is an endnote', $endnote->getElement(0)->getText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -37,9 +37,9 @@ class StyleTest extends AbstractTestReader
|
||||||
</w:tblPr>
|
</w:tblPr>
|
||||||
</w:tbl>';
|
</w:tbl>';
|
||||||
|
|
||||||
$phpWord = $this->getDocumentFromString($documentXml);
|
$phpWord = $this->getDocumentFromString(array('document' => $documentXml));
|
||||||
|
|
||||||
$elements = $this->get($phpWord->getSections(), 0)->getElements();
|
$elements = $phpWord->getSection(0)->getElements();
|
||||||
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]);
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]);
|
||||||
$this->assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle());
|
$this->assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle());
|
||||||
$this->assertEquals(Table::LAYOUT_FIXED, $elements[0]->getStyle()->getLayout());
|
$this->assertEquals(Table::LAYOUT_FIXED, $elements[0]->getStyle()->getLayout());
|
||||||
|
|
@ -56,9 +56,9 @@ class StyleTest extends AbstractTestReader
|
||||||
</w:tblPr>
|
</w:tblPr>
|
||||||
</w:tbl>';
|
</w:tbl>';
|
||||||
|
|
||||||
$phpWord = $this->getDocumentFromString($documentXml);
|
$phpWord = $this->getDocumentFromString(array('document' => $documentXml));
|
||||||
|
|
||||||
$elements = $this->get($phpWord->getSections(), 0)->getElements();
|
$elements = $phpWord->getSection(0)->getElements();
|
||||||
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]);
|
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]);
|
||||||
$this->assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle());
|
$this->assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle());
|
||||||
$this->assertEquals(TblWidth::AUTO, $elements[0]->getStyle()->getUnit());
|
$this->assertEquals(TblWidth::AUTO, $elements[0]->getStyle()->getUnit());
|
||||||
|
|
|
||||||
|
|
@ -447,6 +447,9 @@ class ElementTest extends \PHPUnit\Framework\TestCase
|
||||||
$this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:commentReference'));
|
$this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:commentReference'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test Track changes
|
||||||
|
*/
|
||||||
public function testTrackChange()
|
public function testTrackChange()
|
||||||
{
|
{
|
||||||
$phpWord = new PhpWord();
|
$phpWord = new PhpWord();
|
||||||
|
|
@ -462,4 +465,30 @@ class ElementTest extends \PHPUnit\Framework\TestCase
|
||||||
$this->assertEquals('author name', $doc->getElementAttribute('/w:document/w:body/w:p/w:ins', 'w:author'));
|
$this->assertEquals('author name', $doc->getElementAttribute('/w:document/w:body/w:p/w:ins', 'w:author'));
|
||||||
$this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:del/w:r/w:delText'));
|
$this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:del/w:r/w:delText'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test Title and Headings
|
||||||
|
*/
|
||||||
|
public function testTitleAndHeading()
|
||||||
|
{
|
||||||
|
$phpWord = new PhpWord();
|
||||||
|
$phpWord->addTitleStyle(0, array('size' => 14, 'italic' => true));
|
||||||
|
$phpWord->addTitleStyle(1, array('size' => 20, 'color' => '333333', 'bold' => true));
|
||||||
|
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$section->addTitle('This is a title', 0);
|
||||||
|
$section->addTitle('Heading 1', 1);
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord);
|
||||||
|
|
||||||
|
$this->assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:r/w:t'));
|
||||||
|
$this->assertEquals('This is a title', $doc->getElement('/w:document/w:body/w:p[1]/w:r/w:t')->textContent);
|
||||||
|
$this->assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr/w:pStyle'));
|
||||||
|
$this->assertEquals('Title', $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:pPr/w:pStyle', 'w:val'));
|
||||||
|
|
||||||
|
$this->assertTrue($doc->elementExists('/w:document/w:body/w:p[2]/w:r/w:t'));
|
||||||
|
$this->assertEquals('Heading 1', $doc->getElement('/w:document/w:body/w:p[2]/w:r/w:t')->textContent);
|
||||||
|
$this->assertTrue($doc->elementExists('/w:document/w:body/w:p[2]/w:pPr/w:pStyle'));
|
||||||
|
$this->assertEquals('Heading1', $doc->getElementAttribute('/w:document/w:body/w:p[2]/w:pPr/w:pStyle', 'w:val'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ use PhpOffice\PhpWord\SimpleType\Jc;
|
||||||
use PhpOffice\PhpWord\SimpleType\NumberFormat;
|
use PhpOffice\PhpWord\SimpleType\NumberFormat;
|
||||||
use PhpOffice\PhpWord\Style\Cell;
|
use PhpOffice\PhpWord\Style\Cell;
|
||||||
use PhpOffice\PhpWord\Style\Font;
|
use PhpOffice\PhpWord\Style\Font;
|
||||||
use PhpOffice\PhpWord\Style\Paragraph;
|
|
||||||
use PhpOffice\PhpWord\TestHelperDOCX;
|
use PhpOffice\PhpWord\TestHelperDOCX;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -17,43 +17,48 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpWord;
|
namespace PhpOffice\PhpWord;
|
||||||
|
|
||||||
use PhpOffice\PhpWord\Reader\Word2007\Document;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for Word2007 reader tests
|
* Base class for Word2007 reader tests
|
||||||
*/
|
*/
|
||||||
abstract class AbstractTestReader extends \PHPUnit\Framework\TestCase
|
abstract class AbstractTestReader extends \PHPUnit\Framework\TestCase
|
||||||
{
|
{
|
||||||
|
private $parts = array(
|
||||||
|
'styles' => array('class' => 'PhpOffice\PhpWord\Reader\Word2007\Styles', 'xml' => '<w:styles xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:docDefaults><w:rPrDefault><w:rPr><w:sz w:val="24"/></w:rPr></w:rPrDefault></w:docDefaults>{toReplace}</w:styles>'),
|
||||||
|
'document' => array('class' => 'PhpOffice\PhpWord\Reader\Word2007\Document', 'xml' => '<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:body>{toReplace}</w:body></w:document>'),
|
||||||
|
'footnotes' => array('class' => 'PhpOffice\PhpWord\Reader\Word2007\Footnotes', 'xml' => '<w:footnotes xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">{toReplace}</w:footnotes>'),
|
||||||
|
'endnotes' => array('class' => 'PhpOffice\PhpWord\Reader\Word2007\Endnotes', 'xml' => '<w:endnotes xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">{toReplace}</w:endnotes>'),
|
||||||
|
'settings' => array('class' => 'PhpOffice\PhpWord\Reader\Word2007\Settings', 'xml' => '<w:comments xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">{toReplace}</w:comments>'),
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a PhpWord instance based on the xml passed
|
* Builds a PhpWord instance based on the xml passed
|
||||||
*
|
*
|
||||||
* @param string $documentXml
|
* @param string $documentXml
|
||||||
|
* @param null|string $stylesXml
|
||||||
* @return \PhpOffice\PhpWord\PhpWord
|
* @return \PhpOffice\PhpWord\PhpWord
|
||||||
*/
|
*/
|
||||||
protected function getDocumentFromString($documentXml)
|
protected function getDocumentFromString(array $partXmls = array())
|
||||||
{
|
{
|
||||||
$phpWord = new PhpWord();
|
|
||||||
$file = __DIR__ . '/../_files/temp.docx';
|
$file = __DIR__ . '/../_files/temp.docx';
|
||||||
$zip = new \ZipArchive();
|
$zip = new \ZipArchive();
|
||||||
$zip->open($file, \ZipArchive::CREATE);
|
$zip->open($file, \ZipArchive::CREATE);
|
||||||
$zip->addFromString('document.xml', '<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:body>' . $documentXml . '</w:body></w:document>');
|
foreach ($this->parts as $partName => $part) {
|
||||||
|
if (array_key_exists($partName, $partXmls)) {
|
||||||
|
$zip->addFromString("{$partName}.xml", str_replace('{toReplace}', $partXmls[$partName], $this->parts[$partName]['xml']));
|
||||||
|
}
|
||||||
|
}
|
||||||
$zip->close();
|
$zip->close();
|
||||||
$documentReader = new Document($file, 'document.xml');
|
|
||||||
$documentReader->read($phpWord);
|
$phpWord = new PhpWord();
|
||||||
|
foreach ($this->parts as $partName => $part) {
|
||||||
|
if (array_key_exists($partName, $partXmls)) {
|
||||||
|
$className = $this->parts[$partName]['class'];
|
||||||
|
$reader = new $className($file, "{$partName}.xml");
|
||||||
|
$reader->read($phpWord);
|
||||||
|
}
|
||||||
|
}
|
||||||
unlink($file);
|
unlink($file);
|
||||||
|
|
||||||
return $phpWord;
|
return $phpWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the element at position $index in the array
|
|
||||||
*
|
|
||||||
* @param array $array
|
|
||||||
* @param number $index
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
protected function get(array $array, $index = 0)
|
|
||||||
{
|
|
||||||
return $array[$index];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue