Ability to add Endnotes

This commit is contained in:
Ivan Lanin 2014-04-09 21:35:55 +07:00
parent 38418677f8
commit f837381238
25 changed files with 470 additions and 205 deletions

View File

@ -4,7 +4,7 @@ This is the changelog between releases of PHPWord. Releases are listed in revers
## 0.9.2 - Not yet released ## 0.9.2 - Not yet released
This release marked heavy refactorings on internal code structure with the creation of some abstract classes to reduce code duplication. `Element` subnamespace is introduced in this release to replace `Section`. This release marked heavy refactorings on internal code structure with the creation of some abstract classes to reduce code duplication. `Element` subnamespace is introduced in this release to replace `Section`. Word2007 reader capability is greatly enhanced. Endnote is introduced.
### Features ### Features
@ -28,6 +28,7 @@ This release marked heavy refactorings on internal code structure with the creat
- Media: Add `Media::resetElements()` to reset all media data - @juzi GH-19 - Media: Add `Media::resetElements()` to reset all media data - @juzi GH-19
- General: Add `Style::resetStyles()`, `Footnote::resetElements()`, and `TOC::resetTitles()` - @ivanlanin GH-187 - General: Add `Style::resetStyles()`, `Footnote::resetElements()`, and `TOC::resetTitles()` - @ivanlanin GH-187
- Reader: Ability to read header, footer, footnotes, link, preservetext, textbreak, pagebreak, table - @ivanlanin - Reader: Ability to read header, footer, footnotes, link, preservetext, textbreak, pagebreak, table - @ivanlanin
- Endnote: Ability to add endnotes - @ivanlanin
### Bugfixes ### Bugfixes
@ -59,6 +60,7 @@ This release marked heavy refactorings on internal code structure with the creat
- General: Give `Abstract` prefix and `Interface` suffix for all abstract classes and interfaces as per [PHP-FIG recommendation](https://github.com/php-fig/fig-standards/blob/master/bylaws/002-psr-naming-conventions.md) - @ivanlanin GH-187 - General: Give `Abstract` prefix and `Interface` suffix for all abstract classes and interfaces as per [PHP-FIG recommendation](https://github.com/php-fig/fig-standards/blob/master/bylaws/002-psr-naming-conventions.md) - @ivanlanin GH-187
- Style: New `Style\AbstractStyle` abstract class - @ivanlanin GH-187 - Style: New `Style\AbstractStyle` abstract class - @ivanlanin GH-187
- Writer: New 'ODText\Base` class - @ivanlanin GH-187 - Writer: New 'ODText\Base` class - @ivanlanin GH-187
- General: Rename `Footnote` to `Footnotes` to reflect the nature of collection - @ivanlanin
## 0.9.1 - 27 Mar 2014 ## 0.9.1 - 27 Mar 2014

View File

@ -25,6 +25,7 @@ With PHPWord, you can create DOCX, ODT, or RTF documents dynamically using your
* Insert and format table with customized properties for each rows (e.g. repeat as header row) and cells (e.g. background color, rowspan, colspan) * Insert and format table with customized properties for each rows (e.g. repeat as header row) and cells (e.g. background color, rowspan, colspan)
* Insert list items as bulleted, numbered, or multilevel * Insert list items as bulleted, numbered, or multilevel
* Insert hyperlinks * Insert hyperlinks
* Insert footnotes and endnotes
* Create document from templates * Create document from templates
* Use XSL 1.0 style sheets to transform main document part of OOXML template * Use XSL 1.0 style sheets to transform main document part of OOXML template
* ... and many more features on progress * ... and many more features on progress

View File

@ -37,7 +37,9 @@ the containers while the rows lists the elements.
+-----+---------------+---------+--------+--------+------+----------+----------+ +-----+---------------+---------+--------+--------+------+----------+----------+
| 14 | Footnote | v | \- | \- | v\*\*| v\*\* | \- | | 14 | Footnote | v | \- | \- | v\*\*| v\*\* | \- |
+-----+---------------+---------+--------+--------+------+----------+----------+ +-----+---------------+---------+--------+--------+------+----------+----------+
| 15 | CheckBox | v | v | v | v | ? | ? | | 15 | Endnote | v | \- | \- | v\*\*| v\*\* | \- |
+-----+---------------+---------+--------+--------+------+----------+----------+
| 16 | CheckBox | v | v | v | v | ? | ? |
+-----+---------------+---------+--------+--------+------+----------+----------+ +-----+---------------+---------+--------+--------+------+----------+----------+
Legend: Legend:
@ -376,12 +378,13 @@ Options for ``$tocStyle``:
twips. twips.
- ``indent`` The indent factor of the titles in twips. - ``indent`` The indent factor of the titles in twips.
Footnotes Footnotes & endnotes
--------- --------------------
You can create footnotes in texts or textruns, but it's recommended to You can create footnotes with ``addFootnote`` and endnotes with ``addEndnote``
use textrun to have better layout. You can use ``addText``, ``addLink``, in texts or textruns, but it's recommended to use textrun to have better layout.
and ``addTextBreak`` on a footnote. You can use ``addText``, ``addLink``, ``addTextBreak``, ``addImage``,
``addObject`` on footnotes and endnotes.
On textrun: On textrun:
@ -396,6 +399,8 @@ On textrun:
$footnote->addTextBreak(); $footnote->addTextBreak();
$footnote->addText('And text break.'); $footnote->addText('And text break.');
$textrun->addText('Trailing text.'); $textrun->addText('Trailing text.');
$endnote = $textrun->addEndnote();
$endnote->addText('Endnote put at the end');
On text: On text:

View File

@ -48,6 +48,7 @@ Features
rowspan, colspan) rowspan, colspan)
- Insert list items as bulleted, numbered, or multilevel - Insert list items as bulleted, numbered, or multilevel
- Insert hyperlinks - Insert hyperlinks
- Insert footnotes and endnotes
- Create document from templates - Create document from templates
- Use XSL 1.0 style sheets to transform main document part of OOXML - Use XSL 1.0 style sheets to transform main document part of OOXML
template template
@ -90,8 +91,6 @@ Writers
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Image | ✓ | | | | | Image | ✓ | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | MemoryImage | ✓ | | |
+ +-----------------------+--------+-------+-------+
| | Object | ✓ | | | | | Object | ✓ | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Watermark | ✓ | | | | | Watermark | ✓ | | |
@ -103,6 +102,8 @@ Writers
| | Footer | ✓ | | | | | Footer | ✓ | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Footnote | ✓ | | | | | Footnote | ✓ | | |
+ +-----------------------+--------+-------+-------+
| | Endnote | ✓ | | |
+-------------------------+-----------------------+--------+-------+-------+ +-------------------------+-----------------------+--------+-------+-------+
| **Graphs** | 2D basic graphs | | | | | **Graphs** | 2D basic graphs | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
@ -126,11 +127,11 @@ Readers
+-------------------------------------------------+--------+-------+-------+ +-------------------------------------------------+--------+-------+-------+
| Features | DOCX | ODT | RTF | | Features | DOCX | ODT | RTF |
+=========================+=======================+========+=======+=======+ +=========================+=======================+========+=======+=======+
| **Document Properties** | Standard | | | | | **Document Properties** | Standard | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Extended | | | | | | Extended | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | UserDefined | | | | | | UserDefined | | | |
+-------------------------+-----------------------+--------+-------+-------+ +-------------------------+-----------------------+--------+-------+-------+
| **Element Type** | Text | ✓ | | | | **Element Type** | Text | ✓ | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
@ -138,33 +139,33 @@ Readers
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Title | | | | | | Title | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Link | | | | | | Link | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Preserve Text | | | | | | Preserve Text | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Text Break | ✓ | | | | | Text Break | ✓ | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Page Break | | | | | | Page Break | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | List | | | | | | List | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Table | | | | | | Table | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Image | | | | | | Image | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | MemoryImage | | | |
+ +-----------------------+--------+-------+-------+
| | Object | | | | | | Object | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Watermark | | | | | | Watermark | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Table of Contents | | | | | | Table of Contents | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Header | | | | | | Header | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Footer | | | | | | Footer | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+
| | Footnote | | | | | | Footnote | ✓ | | |
+ +-----------------------+--------+-------+-------+
| | Endnote | ✓ | | |
+-------------------------+-----------------------+--------+-------+-------+ +-------------------------+-----------------------+--------+-------+-------+
| **Graphs** | 2D basic graphs | | | | | **Graphs** | 2D basic graphs | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+

View File

@ -13,7 +13,8 @@ use PhpOffice\PhpWord\Exception\InvalidObjectException;
use PhpOffice\PhpWord\Media; use PhpOffice\PhpWord\Media;
use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\TOC; use PhpOffice\PhpWord\TOC;
use PhpOffice\PhpWord\Footnote as FootnoteCollection; use PhpOffice\PhpWord\Footnotes;
use PhpOffice\PhpWord\Endnotes;
use PhpOffice\PhpWord\Shared\String; use PhpOffice\PhpWord\Shared\String;
use PhpOffice\PhpWord\Element\Element; use PhpOffice\PhpWord\Element\Element;
use PhpOffice\PhpWord\Element\Text; use PhpOffice\PhpWord\Element\Text;
@ -27,6 +28,7 @@ use PhpOffice\PhpWord\Element\Table;
use PhpOffice\PhpWord\Element\Image; use PhpOffice\PhpWord\Element\Image;
use PhpOffice\PhpWord\Element\Object; use PhpOffice\PhpWord\Element\Object;
use PhpOffice\PhpWord\Element\Footnote as FootnoteElement; use PhpOffice\PhpWord\Element\Footnote as FootnoteElement;
use PhpOffice\PhpWord\Element\Endnote;
use PhpOffice\PhpWord\Element\CheckBox; use PhpOffice\PhpWord\Element\CheckBox;
/** /**
@ -37,7 +39,7 @@ use PhpOffice\PhpWord\Element\CheckBox;
abstract class AbstractElement abstract class AbstractElement
{ {
/** /**
* Container type section|header|footer|cell|textrun|footnote * Container type section|header|footer|cell|textrun|footnote|endnote
* *
* @var string * @var string
*/ */
@ -99,7 +101,7 @@ abstract class AbstractElement
$this->checkValidity('text'); $this->checkValidity('text');
// Reset paragraph style for footnote and textrun. They have their own // Reset paragraph style for footnote and textrun. They have their own
if (in_array($this->container, array('footnote', 'textrun'))) { if (in_array($this->container, array('textrun', 'footnote', 'endnote'))) {
$paragraphStyle = null; $paragraphStyle = null;
} }
@ -323,7 +325,7 @@ abstract class AbstractElement
$this->checkValidity('footnote'); $this->checkValidity('footnote');
$footnote = new FootnoteElement($paragraphStyle); $footnote = new FootnoteElement($paragraphStyle);
$rId = FootnoteCollection::addFootnoteElement($footnote); $rId = Footnotes::addElement($footnote);
$footnote->setDocPart('footnote', $this->getDocPartId()); $footnote->setDocPart('footnote', $this->getDocPartId());
$footnote->setRelationId($rId); $footnote->setRelationId($rId);
@ -332,6 +334,26 @@ abstract class AbstractElement
return $footnote; return $footnote;
} }
/**
* Add endnote element
*
* @param mixed $paragraphStyle
* @return Endnote
*/
public function addEndnote($paragraphStyle = null)
{
$this->checkValidity('endnote');
$endnote = new Endnote($paragraphStyle);
$rId = Endnotes::addElement($endnote);
$endnote->setDocPart('endnote', $this->getDocPartId());
$endnote->setRelationId($rId);
$this->elements[] = $endnote;
return $endnote;
}
/** /**
* Add a CheckBox Element * Add a CheckBox Element
* *
@ -469,7 +491,7 @@ abstract class AbstractElement
private function checkValidity($method) private function checkValidity($method)
{ {
// Valid containers for each element // Valid containers for each element
$allContainers = array('section', 'header', 'footer', 'cell', 'textrun', 'footnote'); $allContainers = array('section', 'header', 'footer', 'cell', 'textrun', 'footnote', 'endnote');
$validContainers = array( $validContainers = array(
'text' => $allContainers, 'text' => $allContainers,
'link' => $allContainers, 'link' => $allContainers,
@ -481,6 +503,7 @@ abstract class AbstractElement
'checkbox' => array('section', 'header', 'footer', 'cell'), 'checkbox' => array('section', 'header', 'footer', 'cell'),
'table' => array('section', 'header', 'footer'), 'table' => array('section', 'header', 'footer'),
'footnote' => array('section', 'textrun', 'cell'), 'footnote' => array('section', 'textrun', 'cell'),
'endnote' => array('section', 'textrun', 'cell'),
'preservetext' => array('header', 'footer', 'cell'), 'preservetext' => array('header', 'footer', 'cell'),
'title' => array('section'), 'title' => array('section'),
); );
@ -489,6 +512,7 @@ abstract class AbstractElement
$validContainerInContainers = array( $validContainerInContainers = array(
'preservetext' => array(array('cell'), array('header', 'footer')), 'preservetext' => array(array('cell'), array('header', 'footer')),
'footnote' => array(array('cell', 'textrun'), array('section')), 'footnote' => array(array('cell', 'textrun'), array('section')),
'endnote' => array(array('cell', 'textrun'), array('section')),
); );
// Check if a method is valid for current container // Check if a method is valid for current container

View File

@ -0,0 +1,31 @@
<?php
/**
* PHPWord
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2014 PHPWord
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
*/
namespace PhpOffice\PhpWord\Element;
use PhpOffice\PhpWord\Style\Paragraph;
/**
* Endnote element
*
* @since 0.9.2
*/
class Endnote extends Footnote
{
/**
* Create new instance
*
* @param string|array|Paragraph $paragraphStyle
*/
public function __construct($paragraphStyle = null)
{
$this->container = 'endnote';
$this->paragraphStyle = $this->setStyle(new Paragraph(), $paragraphStyle);
}
}

View File

@ -21,7 +21,7 @@ class Footnote extends AbstractElement
* *
* @var string|Paragraph * @var string|Paragraph
*/ */
private $paragraphStyle; protected $paragraphStyle;
/** /**
* Create new instance * Create new instance

98
src/PhpWord/Endnotes.php Normal file
View File

@ -0,0 +1,98 @@
<?php
/**
* PHPWord
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2014 PHPWord
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
*/
namespace PhpOffice\PhpWord;
use PhpOffice\PhpWord\Media;
use PhpOffice\PhpWord\Element\Endnote;
/**
* Endnote collection
*
* @since 0.9.2
*/
class Endnotes
{
/**
* Elements
*
* @var array
*/
private static $elements = array();
/**
* Add new element
*
* @param Endnote $element
* @return integer Reference ID
*/
public static function addElement($element)
{
$rId = self::countElements() + 1;
self::$elements[$rId] = $element;
return $rId;
}
/**
* Set element
*
* @param integer $index
* @param Endnote $element
*/
public static function setElement($index, $element)
{
if (array_key_exists($index, self::$elements)) {
self::$elements[$index] = $element;
}
}
/**
* Get element by index
*
* @param integer $index
* @return Endnote
*/
public static function getElement($index)
{
if (array_key_exists($index, self::$elements)) {
return self::$elements[$index];
} else {
return null;
}
}
/**
* Get elements
*
* @return array
*/
public static function getElements()
{
return self::$elements;
}
/**
* Get element count
*
* @return integer
*/
public static function countElements()
{
return count(self::$elements);
}
/**
* Reset elements
*/
public static function resetElements()
{
self::$elements = array();
}
}

View File

@ -10,12 +10,12 @@
namespace PhpOffice\PhpWord; namespace PhpOffice\PhpWord;
use PhpOffice\PhpWord\Media; use PhpOffice\PhpWord\Media;
use PhpOffice\PhpWord\Element\Footnote as FootnoteElement; use PhpOffice\PhpWord\Element\Footnote;
/** /**
* Footnote collection * Footnote collection
*/ */
class Footnote class Footnotes
{ {
/** /**
* Elements * Elements
@ -27,14 +27,14 @@ class Footnote
/** /**
* Add new element * Add new element
* *
* @param FootnoteElement $footnote * @param Footnote $element
* @return integer Reference ID * @return integer Reference ID
* @since 0.9.2 * @since 0.9.2
*/ */
public static function addElement(FootnoteElement $footnote) public static function addElement($element)
{ {
$rId = self::countElements() + 1; $rId = self::countElements() + 1;
self::$elements[$rId] = $footnote; self::$elements[$rId] = $element;
return $rId; return $rId;
} }
@ -43,13 +43,13 @@ class Footnote
* Set element * Set element
* *
* @param integer $index * @param integer $index
* @param FootnoteElement $footnote * @param Footnote $element
* @since 0.9.2 * @since 0.9.2
*/ */
public static function setElement($index, FootnoteElement $footnote) public static function setElement($index, $element)
{ {
if (array_key_exists($index, self::$elements)) { if (array_key_exists($index, self::$elements)) {
self::$elements[$index] = $footnote; self::$elements[$index] = $element;
} }
} }
@ -57,7 +57,7 @@ class Footnote
* Get element by index * Get element by index
* *
* @param integer $index * @param integer $index
* @return FootnoteElement * @return Footnote
* @since 0.9.2 * @since 0.9.2
*/ */
public static function getElement($index) public static function getElement($index)
@ -104,14 +104,14 @@ class Footnote
/** /**
* Add new footnote * Add new footnote
* *
* @param FootnoteElement $footnote * @param Footnote $element
* @return integer Reference ID * @return integer Reference ID
* @deprecated 0.9.2 * @deprecated 0.9.2
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function addFootnoteElement(FootnoteElement $footnote) public static function addFootnoteElement($element)
{ {
return self::addElement($footnote); return self::addElement($element);
} }
/** /**

View File

@ -27,7 +27,7 @@ class Media
/** /**
* Add new media element * Add new media element
* *
* @param string $container section|headerx|footerx|footnote * @param string $container section|headerx|footerx|footnote|endnote
* @param string $mediaType image|object|link * @param string $mediaType image|object|link
* @param string $source * @param string $source
* @param Image $image * @param Image $image
@ -51,28 +51,33 @@ class Media
$target = null; $target = null;
$mediaTypeCount++; $mediaTypeCount++;
// Images switch ($mediaType) {
if ($mediaType == 'image') { // Images
if (is_null($image)) { case 'image':
throw new Exception('Image object not assigned.'); if (is_null($image)) {
} throw new Exception('Image object not assigned.');
$isMemImage = $image->getIsMemImage(); }
$extension = $image->getImageExtension(); $isMemImage = $image->getIsMemImage();
$mediaData['imageExtension'] = $extension; $extension = $image->getImageExtension();
$mediaData['imageType'] = $image->getImageType(); $mediaData['imageExtension'] = $extension;
if ($isMemImage) { $mediaData['imageType'] = $image->getImageType();
$mediaData['isMemImage'] = true; if ($isMemImage) {
$mediaData['createFunction'] = $image->getImageCreateFunction(); $mediaData['isMemImage'] = true;
$mediaData['imageFunction'] = $image->getImageFunction(); $mediaData['createFunction'] = $image->getImageCreateFunction();
} $mediaData['imageFunction'] = $image->getImageFunction();
$target = "media/{$container}_image{$mediaTypeCount}.{$extension}"; }
// Objects $target = "media/{$container}_image{$mediaTypeCount}.{$extension}";
} elseif ($mediaType == 'object') { break;
$file = "oleObject{$mediaTypeCount}.bin";
$target = "embeddings/{$container}_oleObject{$mediaTypeCount}.bin"; // Objects
// Links case 'object':
} elseif ($mediaType == 'link') { $target = "embeddings/{$container}_oleObject{$mediaTypeCount}.bin";
$target = $source; break;
// Links
case 'link':
$target = $source;
break;
} }
$mediaData['source'] = $source; $mediaData['source'] = $source;
@ -89,7 +94,7 @@ class Media
/** /**
* Get media elements count * Get media elements count
* *
* @param string $container section|headerx|footerx|footnote * @param string $container section|headerx|footerx|footnote|endnote
* @param string $mediaType image|object|link * @param string $mediaType image|object|link
* @return integer * @return integer
* @since 0.9.2 * @since 0.9.2
@ -116,7 +121,7 @@ class Media
/** /**
* Get media elements * Get media elements
* *
* @param string $container section|headerx|footerx|footnote * @param string $container section|headerx|footerx|footnote|endnote
* @param string $mediaType image|object|link * @param string $mediaType image|object|link
* @return array * @return array
* @since 0.9.2 * @since 0.9.2

View File

@ -12,8 +12,8 @@ namespace PhpOffice\PhpWord\Reader;
use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Footnote; use PhpOffice\PhpWord\Footnote;
use PhpOffice\PhpWord\Endnotes;
use PhpOffice\PhpWord\DocumentProperties; use PhpOffice\PhpWord\DocumentProperties;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Shared\XMLReader; use PhpOffice\PhpWord\Shared\XMLReader;
use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\Element\Section;
@ -44,7 +44,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
* Loads PhpWord from file * Loads PhpWord from file
* *
* @param string $filename * @param string $filename
* @return PhpWord|null * @return PhpWord
*/ */
public function load($filename) public function load($filename)
{ {
@ -96,7 +96,8 @@ class Word2007 extends AbstractReader implements ReaderInterface
break; break;
case 'footnotes': case 'footnotes':
$this->readFootnotes($filename, $rel['target']); case 'endnotes':
$this->readNotes($filename, $rel['target'], $rel['type']);
break; break;
} }
} }
@ -147,14 +148,13 @@ class Word2007 extends AbstractReader implements ReaderInterface
$nodes = $xmlReader->getElements('*'); $nodes = $xmlReader->getElements('*');
if ($nodes->length > 0) { if ($nodes->length > 0) {
foreach ($nodes as $node) { foreach ($nodes as $node) {
$nodeName = $node->nodeName; if (!array_key_exists($node->nodeName, $mapping)) {
if (!array_key_exists($nodeName, $mapping)) {
continue; continue;
} }
$method = $mapping[$nodeName]; $method = $mapping[$node->nodeName];
$value = $node->nodeValue == '' ? null : $node->nodeValue; $value = $node->nodeValue == '' ? null : $node->nodeValue;
if (array_key_exists($nodeName, $callbacks)) { if (array_key_exists($node->nodeName, $callbacks)) {
$value = $callbacks[$nodeName]($value); $value = $callbacks[$node->nodeName]($value);
} }
if (method_exists($docProps, $method)) { if (method_exists($docProps, $method)) {
$docProps->$method($value); $docProps->$method($value);
@ -253,7 +253,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
if (is_null($name)) { if (is_null($name)) {
$name = $xmlReader->getAttribute('w:val', $node, 'w:name'); $name = $xmlReader->getAttribute('w:val', $node, 'w:name');
} }
$default = ($xmlReader->getAttribute('w:default', $node) == 1); // $default = ($xmlReader->getAttribute('w:default', $node) == 1);
switch ($type) { switch ($type) {
case 'paragraph': case 'paragraph':
$pStyle = $this->readParagraphStyle($xmlReader, $node); $pStyle = $this->readParagraphStyle($xmlReader, $node);
@ -321,14 +321,16 @@ class Word2007 extends AbstractReader implements ReaderInterface
} }
/** /**
* Read footnotes.xml * Read (footnotes|endnotes).xml
* *
* @param string $filename * @param string $filename
* @param string $xmlFile * @param string $xmlFile
*/ */
private function readFootnotes($filename, $xmlFile) private function readNotes($filename, $xmlFile, $notesType = 'footnotes')
{ {
$footnotes = Footnote::getElements(); $notesType = ($notesType == 'endnotes') ? 'endnotes' : 'footnotes';
$collectionClass = 'PhpOffice\\PhpWord\\' . ucfirst($notesType);
$collection = $collectionClass::getElements();
$xmlReader = new XMLReader(); $xmlReader = new XMLReader();
$xmlReader->getDomFromZip($filename, $xmlFile); $xmlReader->getDomFromZip($filename, $xmlFile);
@ -339,14 +341,14 @@ class Word2007 extends AbstractReader implements ReaderInterface
$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> without w:type attribute // Only look for <footnote> or <endnote> without w:type attribute
if (is_null($type) && array_key_exists($id, $footnotes)) { if (is_null($type) && array_key_exists($id, $collection)) {
$footnote = $footnotes[$id]; $element = $collection[$id];
$pNodes = $xmlReader->getElements('w:p/*', $node); $pNodes = $xmlReader->getElements('w:p/*', $node);
foreach ($pNodes as $pNode) { foreach ($pNodes as $pNode) {
$this->readRun($xmlReader, $pNode, $footnote, 'footnotes'); $this->readRun($xmlReader, $pNode, $element, $notesType);
} }
Footnote::setElement($id, $footnote); $collectionClass::setElement($id, $element);
} }
} }
} }
@ -445,6 +447,10 @@ class Word2007 extends AbstractReader implements ReaderInterface
if ($xmlReader->elementExists('w:footnoteReference', $domNode)) { if ($xmlReader->elementExists('w:footnoteReference', $domNode)) {
$parent->addFootnote(); $parent->addFootnote();
// Endnote
} elseif ($xmlReader->elementExists('w:endnoteReference', $domNode)) {
$parent->addEndnote();
// Image // Image
} elseif ($xmlReader->elementExists('w:pict', $domNode)) { } elseif ($xmlReader->elementExists('w:pict', $domNode)) {
$rId = $xmlReader->getAttribute('r:id', $domNode, 'w:pict/v:shape/v:imagedata'); $rId = $xmlReader->getAttribute('r:id', $domNode, 'w:pict/v:shape/v:imagedata');
@ -457,7 +463,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
// Object // Object
} elseif ($xmlReader->elementExists('w:object', $domNode)) { } elseif ($xmlReader->elementExists('w:object', $domNode)) {
$rId = $xmlReader->getAttribute('r:id', $domNode, 'w:object/o:OLEObject'); $rId = $xmlReader->getAttribute('r:id', $domNode, 'w:object/o:OLEObject');
$rIdIcon = $xmlReader->getAttribute('r:id', $domNode, 'w:object/v:shape/v:imagedata'); // $rIdIcon = $xmlReader->getAttribute('r:id', $domNode, 'w:object/v:shape/v:imagedata');
$target = $this->getMediaTarget($docPart, $rId); $target = $this->getMediaTarget($docPart, $rId);
if (!is_null($target)) { if (!is_null($target)) {
$textContent = "<Object: {$target}>"; $textContent = "<Object: {$target}>";
@ -489,7 +495,6 @@ class Word2007 extends AbstractReader implements ReaderInterface
$table = $parent->addTable($tblStyle); $table = $parent->addTable($tblStyle);
$tblNodes = $xmlReader->getElements('*', $domNode); $tblNodes = $xmlReader->getElements('*', $domNode);
foreach ($tblNodes as $tblNode) { foreach ($tblNodes as $tblNode) {
$tblNodeName = $tblNode->nodeName;
if ($tblNode->nodeName == 'w:tblGrid') { // Column if ($tblNode->nodeName == 'w:tblGrid') { // Column
// @todo Do something with table columns // @todo Do something with table columns
@ -745,7 +750,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
if (!array_key_exists($node->nodeName, $mapping)) { if (!array_key_exists($node->nodeName, $mapping)) {
continue; continue;
} }
$property = $mapping[$node->nodeName]; // $property = $mapping[$node->nodeName];
switch ($node->nodeName) { switch ($node->nodeName) {
case 'w:tblCellMar': case 'w:tblCellMar':
foreach ($margins as $side) { foreach ($margins as $side) {

View File

@ -105,7 +105,7 @@ class XMLReader
* @param string $path * @param string $path
* @return string|null * @return string|null
*/ */
public function getAttribute($attribute, \DOMElement $contextNode, $path = null) public function getAttribute($attribute, \DOMNode $contextNode, $path = null)
{ {
if (is_null($path)) { if (is_null($path)) {
$return = $contextNode->getAttribute($attribute); $return = $contextNode->getAttribute($attribute);
@ -154,7 +154,7 @@ class XMLReader
* Element exists * Element exists
* *
* @param string $path * @param string $path
* @return \DOMNodeList * @return boolean
*/ */
public function elementExists($path, \DOMNode $contextNode) public function elementExists($path, \DOMNode $contextNode)
{ {

View File

@ -109,7 +109,7 @@ class Style
/** /**
* Get all styles * Get all styles
* *
* @return Font[] * @return array
*/ */
public static function getStyles() public static function getStyles()
{ {

View File

@ -192,7 +192,6 @@ class Image extends AbstractStyle
break; break;
default: default:
throw new \InvalidArgumentException('Wrapping style does not exists'); throw new \InvalidArgumentException('Wrapping style does not exists');
break;
} }
return $this; return $this;
} }

View File

@ -48,6 +48,7 @@ class ODText extends AbstractWriter implements WriterInterface
* *
* @param string $filename * @param string $filename
* @throws Exception * @throws Exception
* @todo Not in \ZipArchive::CM_STORE mode
*/ */
public function save($filename = null) public function save($filename = null)
{ {
@ -56,20 +57,11 @@ class ODText extends AbstractWriter implements WriterInterface
$objZip = $this->getZipArchive($filename); $objZip = $this->getZipArchive($filename);
// Add mimetype to ZIP file // Add mimetype to ZIP file
//@todo Not in \ZipArchive::CM_STORE mode $objZip->addFromString('mimetype', $this->getWriterPart('mimetype')->writeMimetype());
$objZip->addFromString('mimetype', $this->getWriterPart('mimetype')->writeMimetype($this->phpWord));
// Add content.xml to ZIP file
$objZip->addFromString('content.xml', $this->getWriterPart('content')->writeContent($this->phpWord)); $objZip->addFromString('content.xml', $this->getWriterPart('content')->writeContent($this->phpWord));
// Add meta.xml to ZIP file
$objZip->addFromString('meta.xml', $this->getWriterPart('meta')->writeMeta($this->phpWord)); $objZip->addFromString('meta.xml', $this->getWriterPart('meta')->writeMeta($this->phpWord));
// Add styles.xml to ZIP file
$objZip->addFromString('styles.xml', $this->getWriterPart('styles')->writeStyles($this->phpWord)); $objZip->addFromString('styles.xml', $this->getWriterPart('styles')->writeStyles($this->phpWord));
$objZip->addFromString('META-INF/manifest.xml', $this->getWriterPart('manifest')->writeManifest());
// Add META-INF/manifest.xml
$objZip->addFromString('META-INF/manifest.xml', $this->getWriterPart('manifest')->writeManifest($this->phpWord));
// Close file // Close file
if ($objZip->close() === false) { if ($objZip->close() === false) {

View File

@ -9,8 +9,6 @@
namespace PhpOffice\PhpWord\Writer\ODText; namespace PhpOffice\PhpWord\Writer\ODText;
use PhpOffice\PhpWord\PhpWord;
/** /**
* ODText manifest part writer * ODText manifest part writer
*/ */
@ -19,10 +17,9 @@ class Manifest extends AbstractWriterPart
/** /**
* Write Manifest file to XML format * Write Manifest file to XML format
* *
* @param PhpWord $phpWord
* @return string XML Output * @return string XML Output
*/ */
public function writeManifest(PhpWord $phpWord = null) public function writeManifest()
{ {
// Create XML writer // Create XML writer
$xmlWriter = $this->getXmlWriter(); $xmlWriter = $this->getXmlWriter();

View File

@ -9,8 +9,6 @@
namespace PhpOffice\PhpWord\Writer\ODText; namespace PhpOffice\PhpWord\Writer\ODText;
use PhpOffice\PhpWord\PhpWord;
/** /**
* ODText mimetype part writer * ODText mimetype part writer
*/ */
@ -19,10 +17,9 @@ class Mimetype extends AbstractWriterPart
/** /**
* Write Mimetype to Text format * Write Mimetype to Text format
* *
* @param PhpWord $phpWord
* @return string Text Output * @return string Text Output
*/ */
public function writeMimetype(PhpWord $phpWord = null) public function writeMimetype()
{ {
return 'application/vnd.oasis.opendocument.text'; return 'application/vnd.oasis.opendocument.text';
} }

View File

@ -11,7 +11,6 @@ namespace PhpOffice\PhpWord\Writer;
use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Footnote;
use PhpOffice\PhpWord\Media; use PhpOffice\PhpWord\Media;
use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\Element\Section;
use PhpOffice\PhpWord\Writer\Word2007\ContentTypes; use PhpOffice\PhpWord\Writer\Word2007\ContentTypes;
@ -19,7 +18,7 @@ use PhpOffice\PhpWord\Writer\Word2007\Rels;
use PhpOffice\PhpWord\Writer\Word2007\DocProps; use PhpOffice\PhpWord\Writer\Word2007\DocProps;
use PhpOffice\PhpWord\Writer\Word2007\Document; use PhpOffice\PhpWord\Writer\Word2007\Document;
use PhpOffice\PhpWord\Writer\Word2007\Footer; use PhpOffice\PhpWord\Writer\Word2007\Footer;
use PhpOffice\PhpWord\Writer\Word2007\Footnotes; use PhpOffice\PhpWord\Writer\Word2007\Notes;
use PhpOffice\PhpWord\Writer\Word2007\Header; use PhpOffice\PhpWord\Writer\Word2007\Header;
use PhpOffice\PhpWord\Writer\Word2007\Styles; use PhpOffice\PhpWord\Writer\Word2007\Styles;
@ -60,7 +59,8 @@ class Word2007 extends AbstractWriter implements WriterInterface
$this->writerParts['styles'] = new Styles(); $this->writerParts['styles'] = new Styles();
$this->writerParts['header'] = new Header(); $this->writerParts['header'] = new Header();
$this->writerParts['footer'] = new Footer(); $this->writerParts['footer'] = new Footer();
$this->writerParts['footnotes'] = new Footnotes(); $this->writerParts['footnotes'] = new Notes();
$this->writerParts['endnotes'] = new Notes();
foreach ($this->writerParts as $writer) { foreach ($this->writerParts as $writer) {
$writer->setParentWriter($this); $writer->setParentWriter($this);
} }
@ -105,17 +105,8 @@ class Word2007 extends AbstractWriter implements WriterInterface
$this->addHeaderFooterContent($section, $objZip, 'footer', $rId); $this->addHeaderFooterContent($section, $objZip, 'footer', $rId);
} }
// Add footnotes media files, relations, and contents $this->addNotes($objZip, $rId, 'footnote');
if (Footnote::countFootnoteElements() > 0) { $this->addNotes($objZip, $rId, 'endnote');
$footnoteMedia = Media::getElements('footnote');
$this->addFilesToPackage($objZip, $footnoteMedia);
if (!empty($footnoteMedia)) {
$objZip->addFromString('word/_rels/footnotes.xml.rels', $this->getWriterPart('rels')->writeMediaRels($footnoteMedia));
}
$objZip->addFromString('word/footnotes.xml', $this->getWriterPart('footnotes')->writeFootnotes(Footnote::getFootnoteElements()));
$this->cTypes['override']["/word/footnotes.xml"] = 'footnotes';
$this->docRels[] = array('target' => 'footnotes.xml', 'type' => 'footnotes', 'rID' => ++$rId);
}
// Write dynamic files // Write dynamic files
$objZip->addFromString('[Content_Types].xml', $this->getWriterPart('contenttypes')->writeContentTypes($this->cTypes)); $objZip->addFromString('[Content_Types].xml', $this->getWriterPart('contenttypes')->writeContentTypes($this->cTypes));
@ -199,7 +190,8 @@ class Word2007 extends AbstractWriter implements WriterInterface
if (!empty($media)) { if (!empty($media)) {
$this->addFilesToPackage($objZip, $media); $this->addFilesToPackage($objZip, $media);
} }
$objZip->addFromString("word/_rels/{$file}.xml.rels", $this->getWriterPart('rels')->writeMediaRels($media)); $relsFile = "word/_rels/{$file}.xml.rels";
$objZip->addFromString($relsFile, $this->getWriterPart('rels')->writeMediaRels($media));
} }
} }
} }
@ -227,4 +219,34 @@ class Word2007 extends AbstractWriter implements WriterInterface
$this->docRels[] = array('target' => $elmFile, 'type' => $elmType, 'rID' => $rId); $this->docRels[] = array('target' => $elmFile, 'type' => $elmType, 'rID' => $rId);
} }
} }
/**
* Add footnotes/endnotes
*
* @param mixed $objZip
* @param string $elmType
* @param integer $rId
*/
private function addNotes($objZip, &$rId, $notesType = 'footnote')
{
$notesType = ($notesType == 'endnote') ? 'endnote' : 'footnote';
$notesTypes = "{$notesType}s";
$collection = 'PhpOffice\\PhpWord\\' . ucfirst($notesTypes);
$xmlFile = "{$notesTypes}.xml";
$relsFile = "word/_rels/{$xmlFile}.rels";
$xmlPath = "word/{$xmlFile}";
// Add footnotes media files, relations, and contents
if ($collection::countElements() > 0) {
$media = Media::getElements($notesType);
$elements = $collection::getElements();
$this->addFilesToPackage($objZip, $media);
if (!empty($media)) {
$objZip->addFromString($relsFile, $this->getWriterPart('rels')->writeMediaRels($media));
}
$objZip->addFromString($xmlPath, $this->getWriterPart($notesTypes)->writeNotes($elements, $notesTypes));
$this->cTypes['override']["/{$xmlPath}"] = $notesTypes;
$this->docRels[] = array('target' => $xmlFile, 'type' => $notesTypes, 'rID' => ++$rId);
}
}
} }

View File

@ -23,6 +23,7 @@ use PhpOffice\PhpWord\Element\Table;
use PhpOffice\PhpWord\Element\Image; use PhpOffice\PhpWord\Element\Image;
use PhpOffice\PhpWord\Element\Object; use PhpOffice\PhpWord\Element\Object;
use PhpOffice\PhpWord\Element\Footnote; use PhpOffice\PhpWord\Element\Footnote;
use PhpOffice\PhpWord\Element\Endnote;
use PhpOffice\PhpWord\Element\CheckBox; use PhpOffice\PhpWord\Element\CheckBox;
use PhpOffice\PhpWord\Shared\String; use PhpOffice\PhpWord\Shared\String;
use PhpOffice\PhpWord\Shared\XMLWriter; use PhpOffice\PhpWord\Shared\XMLWriter;
@ -623,6 +624,33 @@ class Base extends AbstractWriterPart
} }
} }
/**
* Write endnote element which links to the actual content in endnotes.xml
*
* @param XMLWriter $xmlWriter
* @param Endnote $endnote
* @param boolean $withoutP
*/
protected function writeEndnote(XMLWriter $xmlWriter, Endnote $endnote, $withoutP = false)
{
if (!$withoutP) {
$xmlWriter->startElement('w:p');
}
$xmlWriter->startElement('w:r');
$xmlWriter->startElement('w:rPr');
$xmlWriter->startElement('w:rStyle');
$xmlWriter->writeAttribute('w:val', 'EndnoteReference');
$xmlWriter->endElement(); // w:rStyle
$xmlWriter->endElement(); // w:rPr
$xmlWriter->startElement('w:endnoteReference');
$xmlWriter->writeAttribute('w:id', $endnote->getRelationId());
$xmlWriter->endElement(); // w:endnoteReference
$xmlWriter->endElement(); // w:r
if (!$withoutP) {
$xmlWriter->endElement(); // w:p
}
}
/** /**
* Write CheckBox * Write CheckBox
* *
@ -1132,9 +1160,10 @@ class Base extends AbstractWriterPart
'Section' => array_merge($elmMainCell, array('Table', 'Footnote', 'Title', 'PageBreak', 'TOC')), 'Section' => array_merge($elmMainCell, array('Table', 'Footnote', 'Title', 'PageBreak', 'TOC')),
'Header' => array_merge($elmMainCell, array('Table', 'PreserveText')), 'Header' => array_merge($elmMainCell, array('Table', 'PreserveText')),
'Footer' => array_merge($elmMainCell, array('Table', 'PreserveText')), 'Footer' => array_merge($elmMainCell, array('Table', 'PreserveText')),
'Cell' => array_merge($elmMainCell, array('PreserveText', 'Footnote')), 'Cell' => array_merge($elmMainCell, array('PreserveText', 'Footnote', 'Endnote')),
'TextRun' => array_merge($elmCommon, array('Footnote')), 'TextRun' => array_merge($elmCommon, array('Footnote', 'Endnote')),
'Footnote' => $elmCommon, 'Footnote' => $elmCommon,
'Endnote' => $elmCommon,
); );
$containerName = get_class($container); $containerName = get_class($container);
$containerName = substr($containerName, strrpos($containerName, '\\') + 1); $containerName = substr($containerName, strrpos($containerName, '\\') + 1);
@ -1158,10 +1187,14 @@ class Base extends AbstractWriterPart
$method = "writeWatermark"; $method = "writeWatermark";
} }
} }
if (in_array($containerName, array('TextRun', 'Footnote'))) { switch ($containerName) {
$this->$method($xmlWriter, $element, true); case 'TextRun':
} else { case 'Footnote':
$this->$method($xmlWriter, $element); case 'Endnote':
$this->$method($xmlWriter, $element, true);
break;
default:
$this->$method($xmlWriter, $element);
} }
} }
} }

View File

@ -10,27 +10,30 @@
namespace PhpOffice\PhpWord\Writer\Word2007; namespace PhpOffice\PhpWord\Writer\Word2007;
use PhpOffice\PhpWord\Element\Footnote; use PhpOffice\PhpWord\Element\Footnote;
use PhpOffice\PhpWord\Element\Endnote;
use PhpOffice\PhpWord\Shared\XMLWriter; use PhpOffice\PhpWord\Shared\XMLWriter;
/** /**
* Word2007 footnotes part writer * Word2007 footnotes part writer
*/ */
class Footnotes extends Base class Notes extends Base
{ {
/** /**
* Write word/footnotes.xml * Write word/(footnotes|endnotes).xml
* *
* @param array $allFootnotesCollection * @param array $elements
* @param string $notesTypes
*/ */
public function writeFootnotes($allFootnotesCollection) public function writeNotes($elements, $notesTypes = 'footnotes')
{ {
// Create XML writer $isFootnote = $notesTypes == 'footnotes';
$rootNode = $isFootnote ? 'w:footnotes' : 'w:endnotes';
$elementNode = $isFootnote ? 'w:footnote' : 'w:endnote';
$xmlWriter = $this->getXmlWriter(); $xmlWriter = $this->getXmlWriter();
// XML header // XML header
$xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); $xmlWriter->startDocument('1.0', 'UTF-8', 'yes');
$xmlWriter->startElement('w:footnotes'); $xmlWriter->startElement($rootNode);
$xmlWriter->writeAttribute('xmlns:ve', 'http://schemas.openxmlformats.org/markup-compatibility/2006'); $xmlWriter->writeAttribute('xmlns:ve', 'http://schemas.openxmlformats.org/markup-compatibility/2006');
$xmlWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office'); $xmlWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office');
$xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); $xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
@ -42,7 +45,7 @@ class Footnotes extends Base
$xmlWriter->writeAttribute('xmlns:wne', 'http://schemas.microsoft.com/office/word/2006/wordml'); $xmlWriter->writeAttribute('xmlns:wne', 'http://schemas.microsoft.com/office/word/2006/wordml');
// Separator and continuation separator // Separator and continuation separator
$xmlWriter->startElement('w:footnote'); $xmlWriter->startElement($elementNode);
$xmlWriter->writeAttribute('w:id', -1); $xmlWriter->writeAttribute('w:id', -1);
$xmlWriter->writeAttribute('w:type', 'separator'); $xmlWriter->writeAttribute('w:type', 'separator');
$xmlWriter->startElement('w:p'); $xmlWriter->startElement('w:p');
@ -51,8 +54,8 @@ class Footnotes extends Base
$xmlWriter->endElement(); // w:separator $xmlWriter->endElement(); // w:separator
$xmlWriter->endElement(); // w:r $xmlWriter->endElement(); // w:r
$xmlWriter->endElement(); // w:p $xmlWriter->endElement(); // w:p
$xmlWriter->endElement(); // w:footnote $xmlWriter->endElement(); // $elementNode
$xmlWriter->startElement('w:footnote'); $xmlWriter->startElement($elementNode);
$xmlWriter->writeAttribute('w:id', 0); $xmlWriter->writeAttribute('w:id', 0);
$xmlWriter->writeAttribute('w:type', 'continuationSeparator'); $xmlWriter->writeAttribute('w:type', 'continuationSeparator');
$xmlWriter->startElement('w:p'); $xmlWriter->startElement('w:p');
@ -61,42 +64,53 @@ class Footnotes extends Base
$xmlWriter->endElement(); // w:continuationSeparator $xmlWriter->endElement(); // w:continuationSeparator
$xmlWriter->endElement(); // w:r $xmlWriter->endElement(); // w:r
$xmlWriter->endElement(); // w:p $xmlWriter->endElement(); // w:p
$xmlWriter->endElement(); // w:footnote $xmlWriter->endElement(); // $elementNode
// Content // Content
foreach ($allFootnotesCollection as $footnote) { foreach ($elements as $element) {
if ($footnote instanceof Footnote) { if ($element instanceof Footnote || $element instanceof Endnote) {
$this->writeFootnote($xmlWriter, $footnote); $this->writeNote($xmlWriter, $element, null, $notesTypes);
} }
} }
$xmlWriter->endElement(); $xmlWriter->endElement();
return $xmlWriter->getData(); return $xmlWriter->getData();
} }
/** /**
* Write footnote content, overrides method in parent class * Write note item
* *
* @param XMLWriter $xmlWriter * @param XMLWriter $xmlWriter
* @param Footnote $footnote * @param Footnote|Endnote $element
* @param boolean $withoutP * @param boolean $withoutP
* @param string $notesTypes
*/ */
protected function writeFootnote(XMLWriter $xmlWriter, Footnote $footnote, $withoutP = false) protected function writeNote(XMLWriter $xmlWriter, $element, $withoutP = false, $notesTypes = 'footnotes')
{ {
$xmlWriter->startElement('w:footnote'); $isFootnote = ($notesTypes == 'footnotes');
$xmlWriter->writeAttribute('w:id', $footnote->getRelationId()); $elementNode = $isFootnote ? 'w:footnote' : 'w:endnote';
$refNode = $isFootnote ? 'w:footnoteRef' : 'w:endnoteRef';
$styleName = $isFootnote ? 'FootnoteReference' : 'EndnoteReference';
$xmlWriter->startElement($elementNode);
$xmlWriter->writeAttribute('w:id', $element->getRelationId());
$xmlWriter->startElement('w:p'); $xmlWriter->startElement('w:p');
// Paragraph style // Paragraph style
$styleParagraph = $footnote->getParagraphStyle(); $styleParagraph = $element->getParagraphStyle();
$this->writeInlineParagraphStyle($xmlWriter, $styleParagraph); $this->writeInlineParagraphStyle($xmlWriter, $styleParagraph);
// Reference symbol // Reference symbol
$xmlWriter->startElement('w:r'); $xmlWriter->startElement('w:r');
$xmlWriter->startElement('w:rPr'); $xmlWriter->startElement('w:rPr');
$xmlWriter->startElement('w:rStyle'); $xmlWriter->startElement('w:rStyle');
$xmlWriter->writeAttribute('w:val', 'FootnoteReference'); $xmlWriter->writeAttribute('w:val', $styleName);
$xmlWriter->endElement(); // w:rStyle $xmlWriter->endElement(); // w:rStyle
$xmlWriter->endElement(); // w:rPr $xmlWriter->endElement(); // w:rPr
$xmlWriter->writeElement('w:footnoteRef'); $xmlWriter->writeElement($refNode);
$xmlWriter->endElement(); // w:r $xmlWriter->endElement(); // w:r
// Empty space after refence symbol // Empty space after refence symbol
$xmlWriter->startElement('w:r'); $xmlWriter->startElement('w:r');
$xmlWriter->startElement('w:t'); $xmlWriter->startElement('w:t');
@ -105,9 +119,9 @@ class Footnotes extends Base
$xmlWriter->endElement(); // w:t $xmlWriter->endElement(); // w:t
$xmlWriter->endElement(); // w:r $xmlWriter->endElement(); // w:r
$this->writeContainerElements($xmlWriter, $footnote); $this->writeContainerElements($xmlWriter, $element);
$xmlWriter->endElement(); // w:p $xmlWriter->endElement(); // w:p
$xmlWriter->endElement(); // w:footnote $xmlWriter->endElement(); // $elementNode
} }
} }

View File

@ -0,0 +1,39 @@
<?php
/**
* PHPWord
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2014 PHPWord
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
*/
namespace PhpOffice\PhpWord\Tests;
use PhpOffice\PhpWord\Endnotes;
/**
* Test class for PhpOffice\PhpWord\Endnotes
*
* @runTestsInSeparateProcesses
*/
class EndnotesTest extends \PHPUnit_Framework_TestCase
{
/**
* Test endnote collection
*/
public function testEndnotes()
{
$endnote1 = new \PhpOffice\PhpWord\Element\Endnote();
$endnote2 = new \PhpOffice\PhpWord\Element\Endnote();
$rId = Endnotes::addElement($endnote1);
Endnotes::setElement(1, $endnote2);
$this->assertEquals(1, $rId);
$this->assertEquals(1, count(Endnotes::getElements()));
$this->assertEquals($endnote2, Endnotes::getElement(1));
$this->assertNull(Endnotes::getElement(2));
Endnotes::resetElements();
$this->assertEquals(0, Endnotes::countElements());
}
}

View File

@ -1,39 +0,0 @@
<?php
/**
* PHPWord
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2014 PHPWord
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
*/
namespace PhpOffice\PhpWord\Tests;
use PhpOffice\PhpWord\Footnote;
/**
* Test class for PhpOffice\PhpWord\Footnote
*
* @runTestsInSeparateProcesses
*/
class FootnoteTest extends \PHPUnit_Framework_TestCase
{
/**
* Test add, get, and count footnote elements and links
*/
public function testFootnote()
{
$footnote1 = new \PhpOffice\PhpWord\Element\Footnote('default');
$footnote2 = new \PhpOffice\PhpWord\Element\Footnote('first');
$rId = Footnote::addElement($footnote1);
Footnote::setElement(1, $footnote2);
$this->assertEquals(1, $rId);
$this->assertEquals(1, count(Footnote::getElements()));
$this->assertEquals($footnote2, Footnote::getElement(1));
$this->assertNull(Footnote::getElement(2));
Footnote::resetElements();
$this->assertEquals(0, Footnote::countElements());
}
}

View File

@ -0,0 +1,39 @@
<?php
/**
* PHPWord
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2014 PHPWord
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
*/
namespace PhpOffice\PhpWord\Tests;
use PhpOffice\PhpWord\Footnotes;
/**
* Test class for PhpOffice\PhpWord\Footnotes
*
* @runTestsInSeparateProcesses
*/
class FootnotesTest extends \PHPUnit_Framework_TestCase
{
/**
* Test footnote collection
*/
public function testFootnotes()
{
$footnote1 = new \PhpOffice\PhpWord\Element\Footnote();
$footnote2 = new \PhpOffice\PhpWord\Element\Footnote();
$rId = Footnotes::addElement($footnote1);
Footnotes::setElement(1, $footnote2);
$this->assertEquals(1, $rId);
$this->assertEquals(1, count(Footnotes::getElements()));
$this->assertEquals($footnote2, Footnotes::getElement(1));
$this->assertNull(Footnotes::getElement(2));
Footnotes::resetElements();
$this->assertEquals(0, Footnotes::countElements());
}
}

View File

@ -12,12 +12,11 @@ use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Tests\TestHelperDOCX; use PhpOffice\PhpWord\Tests\TestHelperDOCX;
/** /**
* Test class for PhpOffice\PhpWord\Writer\Word2007\Footnotes * Test class for PhpOffice\PhpWord\Writer\Word2007\Notes
* *
* @coversDefaultClass \PhpOffice\PhpWord\Writer\Word2007\Footnotes
* @runTestsInSeparateProcesses * @runTestsInSeparateProcesses
*/ */
class FootnotesTest extends \PHPUnit_Framework_TestCase class NotesTest extends \PHPUnit_Framework_TestCase
{ {
/** /**
* Executed before each method of the class * Executed before each method of the class

View File

@ -35,18 +35,19 @@ class Word2007Test extends \PHPUnit_Framework_TestCase
$object = new Word2007(new PhpWord()); $object = new Word2007(new PhpWord());
$writerParts = array( $writerParts = array(
'ContentTypes', 'ContentTypes' => 'ContentTypes',
'Rels', 'Rels' => 'Rels',
'DocProps', 'DocProps' => 'DocProps',
'Document', 'Document' => 'Document',
'Styles', 'Styles' => 'Styles',
'Header', 'Header' => 'Header',
'Footer', 'Footer' => 'Footer',
'Footnotes', 'Footnotes' => 'Notes',
'Endnotes' => 'Notes',
); );
foreach ($writerParts as $part) { foreach ($writerParts as $part => $type) {
$this->assertInstanceOf( $this->assertInstanceOf(
"PhpOffice\\PhpWord\\Writer\\Word2007\\{$part}", "PhpOffice\\PhpWord\\Writer\\Word2007\\{$type}",
$object->getWriterPart($part) $object->getWriterPart($part)
); );
$this->assertInstanceOf( $this->assertInstanceOf(