Merge remote-tracking branch 'origin/develop' into develop

Conflicts:
	src/PhpWord/Element/Section.php
	src/PhpWord/Endnotes.php
	src/PhpWord/Footnotes.php
	src/PhpWord/Media.php
	src/PhpWord/PhpWord.php
	src/PhpWord/Reader/Word2007.php
	src/PhpWord/Writer/AbstractWriter.php
	src/PhpWord/Writer/ODText/Content.php
	src/PhpWord/Writer/Word2007.php
	src/PhpWord/Writer/Word2007/Notes.php
This commit is contained in:
Roman Syroeshko 2014-04-16 17:39:26 +04:00
commit db1d89ab23
97 changed files with 4195 additions and 1116 deletions

View File

@ -18,8 +18,9 @@ before_script:
## Composer ## Composer
# - curl -s http://getcomposer.org/installer | php # - curl -s http://getcomposer.org/installer | php
# - php composer.phar install --prefer-source # - php composer.phar install --prefer-source
- composer self-update
- composer require dompdf/dompdf:0.6.*
- composer install --prefer-source - composer install --prefer-source
- composer selfupdate --quiet
## PHP_CodeSniffer ## PHP_CodeSniffer
- pyrus install pear/PHP_CodeSniffer - pyrus install pear/PHP_CodeSniffer
- phpenv rehash - phpenv rehash

View File

@ -2,9 +2,9 @@
This is the changelog between releases of PHPWord. Releases are listed in reverse chronological order with the latest version listed on top, while additions/changes in each release are listed in chronological order. Changes in each release are divided into three parts: added or change features, bugfixes, and miscellaneous improvements. Each line contains short information about the change made, the person who made it, and the related issue number(s) in GitHub. This is the changelog between releases of PHPWord. Releases are listed in reverse chronological order with the latest version listed on top, while additions/changes in each release are listed in chronological order. Changes in each release are divided into three parts: added or change features, bugfixes, and miscellaneous improvements. Each line contains short information about the change made, the person who made it, and the related issue number(s) in GitHub.
## 0.9.2 - Not yet released ## 0.10.0 - 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`. Word2007 reader capability is greatly enhanced. Endnote is introduced. 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. List numbering is now customizable. Basic HTML and PDF writing support is enabled.
### Features ### Features
@ -27,12 +27,18 @@ This release marked heavy refactorings on internal code structure with the creat
- Object: Ability to add object in header, footer, textrun, and footnote - @ivanlanin GH-187 - Object: Ability to add object in header, footer, textrun, and footnote - @ivanlanin GH-187
- 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 - DOCX Reader: Ability to read header, footer, footnotes, link, preservetext, textbreak, pagebreak, table, list, image - @ivanlanin
- Endnote: Ability to add endnotes - @ivanlanin - Endnote: Ability to add endnotes - @ivanlanin
- ListItem: Ability to create custom list and reset list number - @ivanlanin GH-10 GH-198
- ODT Writer: Basic table writing support - @ivanlanin
- Image: Keep image aspect ratio if only 1 dimension styled - @japonicus GH-194
- HTML Writer: Basic HTML writer: text, textrun, link, title, textbreak, table, image (as Base64), footnote, endnote - @ivanlanin GH-203 GH-67 GH-147
- PDF Writer: Basic PDF writer using DomPDF: All HTML element except image - @ivanlanin GH-68
### Bugfixes ### Bugfixes
- Footnote: Footnote content doesn't show footnote reference number - @ivanlanin GH-170 - Footnote: Footnote content doesn't show footnote reference number - @ivanlanin GH-170
- Documentation : Error in a fonction - @theBeerNut GH-195
### Deprecated ### Deprecated
@ -61,6 +67,8 @@ This release marked heavy refactorings on internal code structure with the creat
- 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 - General: Rename `Footnote` to `Footnotes` to reflect the nature of collection - @ivanlanin
- General: Add some unit tests for Shared & Element (100%!) - @Progi1984
- Test: Add some samples and tests for image wrapping style - @brunocasado GH-59
## 0.9.1 - 27 Mar 2014 ## 0.9.1 - 27 Mar 2014

View File

@ -40,9 +40,10 @@
"phpunit/phpunit": "3.7.*" "phpunit/phpunit": "3.7.*"
}, },
"suggest": { "suggest": {
"ext-gd2": "*", "ext-gd2": "Required to add images",
"ext-xmlwriter": "*", "ext-xmlwriter": "Required to write DOCX and ODT",
"ext-xsl": "*" "ext-xsl": "Required to apply XSL style sheet to template part",
"dompdf/dompdf": "Required to write PDF"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

View File

@ -207,10 +207,14 @@ Lists
To add a list item use the function ``addListItem``. To add a list item use the function ``addListItem``.
Basic usage:
.. code-block:: php .. code-block:: php
$section->addListItem($text, [$depth], [$fontStyle], [$listStyle], [$paragraphStyle]); $section->addListItem($text, [$depth], [$fontStyle], [$listStyle], [$paragraphStyle]);
Parameters:
- ``$text`` Text that appears in the document. - ``$text`` Text that appears in the document.
- ``$depth`` Depth of list item. - ``$depth`` Depth of list item.
- ``$fontStyle`` See "Font style" section. - ``$fontStyle`` See "Font style" section.
@ -219,6 +223,40 @@ To add a list item use the function ``addListItem``.
PHPWord\_Style\_ListItem. PHPWord\_Style\_ListItem.
- ``$paragraphStyle`` See "Paragraph style" section. - ``$paragraphStyle`` See "Paragraph style" section.
Advanced usage:
You can also create your own numbering style by changing the ``$listStyle`` parameter
with the name of your numbering style.
.. code-block:: php
$phpWord->addNumberingStyle(
'multilevel',
array('type' => 'multilevel', 'levels' => array(
array('format' => 'decimal', 'text' => '%1.', 'left' => 360, 'hanging' => 360, 'tabPos' => 360),
array('format' => 'upperLetter', 'text' => '%2.', 'left' => 720, 'hanging' => 360, 'tabPos' => 720),
)
)
);
$section->addListItem('List Item I', 0, null, 'multilevel');
$section->addListItem('List Item I.a', 1, null, 'multilevel');
$section->addListItem('List Item I.b', 1, null, 'multilevel');
$section->addListItem('List Item II', 0, null, 'multilevel');
Level styles:
- ``start`` Starting value
- ``format`` Numbering format bullet|decimal|upperRoman|lowerRoman|upperLetter|lowerLetter
- ``restart`` Restart numbering level symbol
- ``suffix`` Content between numbering symbol and paragraph text tab|space|nothing
- ``text`` Numbering level text e.g. %1 for nonbullet or bullet character
- ``align`` Numbering symbol align left|center|right|both
- ``left`` See paragraph style
- ``hanging`` See paragraph style
- ``tabPos`` See paragraph style
- ``font`` Font name
- ``hint`` See font style
Tables Tables
------ ------

View File

@ -63,9 +63,9 @@ XML Writer compatibility
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
This option sets This option sets
```XMLWriter::setIndent`` <http://www.php.net/manual/en/function.xmlwriter-set-indent.php>`__ `XMLWriter::setIndent <http://www.php.net/manual/en/function.xmlwriter-set-indent.php>`__
and and
```XMLWriter::setIndentString`` <http://www.php.net/manual/en/function.xmlwriter-set-indent-string.php>`__. `XMLWriter::setIndentString <http://www.php.net/manual/en/function.xmlwriter-set-indent-string.php>`__.
The default value of this option is ``true`` (compatible), which is The default value of this option is ``true`` (compatible), which is
`required for OpenOffice <https://github.com/PHPOffice/PHPWord/issues/103>`__ to `required for OpenOffice <https://github.com/PHPOffice/PHPWord/issues/103>`__ to
render OOXML document correctly. You can set this option to ``false`` render OOXML document correctly. You can set this option to ``false``
@ -108,7 +108,7 @@ name. Use the following functions:
.. code-block:: php .. code-block:: php
$properties = $phpWord->getProperties(); $properties = $phpWord->getDocumentProperties();
$properties->setCreator('My name'); $properties->setCreator('My name');
$properties->setCompany('My factory'); $properties->setCompany('My factory');
$properties->setTitle('My title'); $properties->setTitle('My title');

View File

@ -62,63 +62,63 @@ Below are the supported features for each file formats.
Writers Writers
~~~~~~~ ~~~~~~~
+-------------------------------------------------+--------+-------+-------+ +-------------------------------------------------+--------+-------+-------+-------+-------+
| Features | DOCX | ODT | RTF | | Features | DOCX | ODT | RTF | HTML | PDF |
+=========================+=======================+========+=======+=======+ +=========================+=======================+========+=======+=======+=======+=======+
| **Document Properties** | Standard | | | | | **Document Properties** | Standard | ✓ | | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Extended | | | | | | Extended | ✓ | | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | UserDefined | | | | | | UserDefined | ✓ | | | | |
+-------------------------+-----------------------+--------+-------+-------+ +-------------------------+-----------------------+--------+-------+-------+-------+-------+
| **Element Type** | Text | ✓ | ✓ | ✓ | | **Element Type** | Text | ✓ | ✓ | ✓ | ✓ | ✓ |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Text Run | ✓ | ✓ | ✓ | | | Text Run | ✓ | ✓ | ✓ | ✓ | ✓ |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Title | ✓ | | | | | Title | ✓ | | | ✓ | ✓ |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Link | ✓ | | | | | Link | ✓ | | | ✓ | ✓ |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Preserve Text | ✓ | | | | | Preserve Text | ✓ | | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Text Break | ✓ | ✓ | ✓ | | | Text Break | ✓ | ✓ | ✓ | ✓ | ✓ |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Page Break | ✓ | | | | | Page Break | ✓ | | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | List | ✓ | | | | | List | ✓ | | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Table | ✓ | | | | | Table | ✓ | ✓ | | | ✓ |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Image | ✓ | | | | | Image | ✓ | | | ✓ | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Object | ✓ | | | | | Object | ✓ | | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Watermark | ✓ | | | | | Watermark | ✓ | | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Table of Contents | ✓ | | | | | Table of Contents | ✓ | | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Header | ✓ | | | | | Header | ✓ | | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Footer | ✓ | | | | | Footer | ✓ | | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Footnote | ✓ | | | | | Footnote | ✓ | | | ✓ | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Endnote | ✓ | | | | | Endnote | ✓ | | | ✓ | |
+-------------------------+-----------------------+--------+-------+-------+ +-------------------------+-----------------------+--------+-------+-------+-------+-------+
| **Graphs** | 2D basic graphs | | | | | **Graphs** | 2D basic graphs | | | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | 2D advanced graphs | | | | | | 2D advanced graphs | | | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | 3D graphs | | | | | | 3D graphs | | | | | |
+-------------------------+-----------------------+--------+-------+-------+ +-------------------------+-----------------------+--------+-------+-------+-------+-------+
| **Math** | OMML support | | | | | **Math** | OMML support | | | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | MathML support | | | | | | MathML support | | | | | |
+-------------------------+-----------------------+--------+-------+-------+ +-------------------------+-----------------------+--------+-------+-------+-------+-------+
| **Bonus** | Encryption | | | | | **Bonus** | Encryption | | | | | |
+ +-----------------------+--------+-------+-------+ + +-----------------------+--------+-------+-------+-------+-------+
| | Protection | | | | | | Protection | | | | | |
+-------------------------+-----------------------+--------+-------+-------+ +-------------------------+-----------------------+--------+-------+-------+-------+-------+
Readers Readers

View File

@ -45,13 +45,7 @@ $section->addTextBreak();
$section->addImage('resources/_earth.jpg', array('width'=>18, 'height'=>18)); $section->addImage('resources/_earth.jpg', array('width'=>18, 'height'=>18));
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -33,13 +33,7 @@ $section->addText("Left Aligned\tRight Aligned", null, 'rightTab');
$section->addText("\tCenter Aligned", null, 'centerTab'); $section->addText("\tCenter Aligned", null, 'centerTab');
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -26,13 +26,7 @@ $section->addHeader()->addText('Header');
$section->addFooter()->addText('Footer'); $section->addFooter()->addText('Footer');
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -34,13 +34,7 @@ $textrun->addObject('resources/_sheet.xls');
$textrun->addText(' Here is some more text. '); $textrun->addText(' Here is some more text. ');
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -36,13 +36,7 @@ $section = $phpWord->addSection(array('breakType' => 'continuous'));
$section->addText('Normal paragraph again.'); $section->addText('Normal paragraph again.');
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -38,13 +38,7 @@ $footnote = $section->addFootnote();
$footnote->addText('The reference for this is wrapped in its own line'); $footnote->addText('The reference for this is wrapped in its own line');
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -60,4 +60,8 @@ echo date('H:i:s'), " Write to Word2007 format", EOL;
$document->saveAs($name); $document->saveAs($name);
rename($name, "results/{$name}"); rename($name, "results/{$name}");
include_once 'Sample_Footer.php'; $writers = array('Word2007' => 'docx');
echo getEndingNotes($writers);
if (!CLI) {
include_once 'Sample_Footer.php';
}

View File

@ -46,13 +46,7 @@ $section->addText('Paragraph with pageBreakBefore = true (default: false). ' .
null, array('pageBreakBefore' => true)); null, array('pageBreakBefore' => true));
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -85,13 +85,7 @@ $table->addCell(2000, $cellVCentered)->addText('D', null, $cellHCentered);
$table->addCell(null, $cellRowContinue); $table->addCell(null, $cellRowContinue);
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -10,13 +10,7 @@ $header = array('size' => 16, 'bold' => true);
$section->addText('中文楷体样式测试',array('name' => '楷体', 'size' => 16, 'color' => '1B2232')); $section->addText('中文楷体样式测试',array('name' => '楷体', 'size' => 16, 'color' => '1B2232'));
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -7,13 +7,8 @@ $source = "resources/{$name}.docx";
echo date('H:i:s'), " Reading contents from `{$source}`", EOL; echo date('H:i:s'), " Reading contents from `{$source}`", EOL;
$phpWord = \PhpOffice\PhpWord\IOFactory::load($source); $phpWord = \PhpOffice\PhpWord\IOFactory::load($source);
// (Re)write contents // Save file
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
foreach ($writers as $writer => $extension) { if (!CLI) {
echo date('H:i:s'), " Write to {$writer} format", EOL; include_once 'Sample_Footer.php';
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -59,15 +59,8 @@ $sec2Header->addText("All pages in Section 2 will Have this!");
$section2->addTextBreak(); $section2->addTextBreak();
$section2->addText('Some text...'); $section2->addText('Some text...');
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -10,24 +10,29 @@ $section = $phpWord->addSection();
$section->addText('Local image without any styles:'); $section->addText('Local image without any styles:');
$section->addImage('resources/_mars.jpg'); $section->addImage('resources/_mars.jpg');
$section->addTextBreak(2); $section->addTextBreak(2);
//
$section->addText('Local image with styles:'); $section->addText('Local image with styles:');
$section->addImage('resources/_earth.jpg', array('width' => 210, 'height' => 210, 'align' => 'center')); $section->addImage('resources/_earth.jpg', array('width' => 210, 'height' => 210, 'align' => 'center'));
$section->addTextBreak(2); $section->addTextBreak(2);
// Remote image
$source = 'http://php.net/images/logos/php-med-trans-light.gif'; $source = 'http://php.net/images/logos/php-med-trans-light.gif';
$section->addText("Remote image from: {$source}"); $section->addText("Remote image from: {$source}");
$section->addImage($source); $section->addImage($source);
// End code
// Save file //Wrapping style
$name = basename(__FILE__, '.php'); $text = str_repeat('Hello World! ', 15);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); $wrappingStyles = array('inline', 'behind', 'infront', 'square', 'tight');
foreach ($writers as $writer => $extension) { foreach ($wrappingStyles as $wrappingStyle) {
echo date('H:i:s'), " Write to {$writer} format", EOL; $section->addTextBreak(5);
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer); $section->addText('Wrapping style ' . $wrappingStyle);
$xmlWriter->save("{$name}.{$extension}"); $section->addImage('resources/_earth.jpg', array('marginTop' => -1, 'marginLeft' => 1,
rename("{$name}.{$extension}", "results/{$name}.{$extension}"); 'width' => 80, 'height' => 80, 'wrappingStyle' => $wrappingStyle));
$section->addText($text);
} }
include_once 'Sample_Footer.php'; // Save file
echo write($phpWord, basename(__FILE__, '.php'), $writers);
if (!CLI) {
include_once 'Sample_Footer.php';
}

View File

@ -8,50 +8,54 @@ $phpWord = new \PhpOffice\PhpWord\PhpWord();
// Begin code // Begin code
$section = $phpWord->addSection(); $section = $phpWord->addSection();
// Add listitem elements // Style definition
$section->addListItem('List Item 1', 0);
$section->addListItem('List Item 2', 0);
$section->addListItem('List Item 3', 0);
$section->addTextBreak(2);
// Add listitem elements
$section->addListItem('List Item 1', 0);
$section->addListItem('List Item 1.1', 1);
$section->addListItem('List Item 1.2', 1);
$section->addListItem('List Item 1.3 (styled)', 1, array('bold'=>true));
$section->addListItem('List Item 1.3.1', 2);
$section->addListItem('List Item 1.3.2', 2);
$section->addTextBreak(2);
// Add listitem elements
$listStyle = array('listType' => \PhpOffice\PhpWord\Style\ListItem::TYPE_NUMBER);
$section->addListItem('List Item 1', 0, null, $listStyle);
$section->addListItem('List Item 2', 0, null, $listStyle);
$section->addListItem('List Item 3', 0, null, $listStyle);
$section->addTextBreak(2);
// Add listitem elements
$phpWord->addFontStyle('myOwnStyle', array('color'=>'FF0000')); $phpWord->addFontStyle('myOwnStyle', array('color'=>'FF0000'));
$phpWord->addParagraphStyle('P-Style', array('spaceAfter'=>95)); $phpWord->addParagraphStyle('P-Style', array('spaceAfter'=>95));
$listStyle = array('listType' => \PhpOffice\PhpWord\Style\ListItem::TYPE_NUMBER_NESTED); $phpWord->addNumberingStyle(
$section->addListItem('List Item 1', 0, 'myOwnStyle', $listStyle, 'P-Style'); 'multilevel',
$section->addListItem('List Item 2', 0, 'myOwnStyle', $listStyle, 'P-Style'); array('type' => 'multilevel', 'levels' => array(
$section->addListItem('List Item 3', 1, 'myOwnStyle', $listStyle, 'P-Style'); array('format' => 'decimal', 'text' => '%1.', 'left' => 360, 'hanging' => 360, 'tabPos' => 360),
$section->addListItem('List Item 4', 1, 'myOwnStyle', $listStyle, 'P-Style'); array('format' => 'upperLetter', 'text' => '%2.', 'left' => 720, 'hanging' => 360, 'tabPos' => 720),
$section->addListItem('List Item 5', 2, 'myOwnStyle', $listStyle, 'P-Style'); )
$section->addListItem('List Item 6', 1, 'myOwnStyle', $listStyle, 'P-Style'); )
$section->addListItem('List Item 7', 0, 'myOwnStyle', $listStyle, 'P-Style'); );
$predefinedMultilevel = array('listType' => \PhpOffice\PhpWord\Style\ListItem::TYPE_NUMBER_NESTED);
// End code // Lists
$section->addText('Multilevel list.');
$section->addListItem('List Item I', 0, null, 'multilevel');
$section->addListItem('List Item I.a', 1, null, 'multilevel');
$section->addListItem('List Item I.b', 1, null, 'multilevel');
$section->addListItem('List Item II', 0, null, 'multilevel');
$section->addListItem('List Item II.a', 1, null, 'multilevel');
$section->addListItem('List Item III', 0, null, 'multilevel');
$section->addTextBreak(2);
$section->addText('Basic simple bulleted list.');
$section->addListItem('List Item 1');
$section->addListItem('List Item 2');
$section->addListItem('List Item 3');
$section->addTextBreak(2);
$section->addText('Continue from multilevel list above.');
$section->addListItem('List Item IV', 0, null, 'multilevel');
$section->addListItem('List Item IV.a', 1, null, 'multilevel');
$section->addTextBreak(2);
$section->addText('Multilevel predefined list.');
$section->addListItem('List Item 1', 0, 'myOwnStyle', $predefinedMultilevel, 'P-Style');
$section->addListItem('List Item 2', 0, 'myOwnStyle', $predefinedMultilevel, 'P-Style');
$section->addListItem('List Item 3', 1, 'myOwnStyle', $predefinedMultilevel, 'P-Style');
$section->addListItem('List Item 4', 1, 'myOwnStyle', $predefinedMultilevel, 'P-Style');
$section->addListItem('List Item 5', 2, 'myOwnStyle', $predefinedMultilevel, 'P-Style');
$section->addListItem('List Item 6', 1, 'myOwnStyle', $predefinedMultilevel, 'P-Style');
$section->addListItem('List Item 7', 0, 'myOwnStyle', $predefinedMultilevel, 'P-Style');
$section->addTextBreak(2);
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -16,16 +16,8 @@ $phpWord->addLinkStyle('myOwnLinkStyle', array('bold'=>true, 'color'=>'808000'))
$section->addLink('http://www.bing.com', null, 'myOwnLinkStyle'); $section->addLink('http://www.bing.com', null, 'myOwnLinkStyle');
$section->addLink('http://www.yahoo.com', null, 'myOwnLinkStyle'); $section->addLink('http://www.yahoo.com', null, 'myOwnLinkStyle');
// End code
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -11,16 +11,8 @@ $section->addText('You can open this OLE object by double clicking on the icon:'
$section->addTextBreak(2); $section->addTextBreak(2);
$section->addObject('resources/_sheet.xls'); $section->addObject('resources/_sheet.xls');
// End code
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -67,16 +67,9 @@ $section->addTitle('Subtitle 3.1.2', 3);
$section->addText('Text'); $section->addText('Text');
echo date('H:i:s'), " Note: Please refresh TOC manually.", EOL; echo date('H:i:s'), " Note: Please refresh TOC manually.", EOL;
// End code
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -12,16 +12,8 @@ $header = $section->addHeader();
$header->addWatermark('resources/_earth.jpg', array('marginTop' => 200, 'marginLeft' => 55)); $header->addWatermark('resources/_earth.jpg', array('marginTop' => 200, 'marginLeft' => 55));
$section->addText('The header reference to the current section includes a watermark image.'); $section->addText('The header reference to the current section includes a watermark image.');
// End code
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -25,16 +25,8 @@ $section->addText('Text break with inline paragraph style:');
$section->addTextBreak(1, null, $paragraphStyle); $section->addTextBreak(1, null, $paragraphStyle);
$section->addText('Done.'); $section->addText('Done.');
// End code
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -11,13 +11,7 @@ $section->addText("This one uses bgColor and is using hex value (0xfbbb10)", arr
$section->addText("Compatible with font colors", array("color"=>"0000ff", "bgColor" => "fbbb10")); $section->addText("Compatible with font colors", array("color"=>"0000ff", "bgColor" => "fbbb10"));
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -28,13 +28,7 @@ $section->addText("In this example, image is 250px height. Rows are calculated i
$section->addText("So: $"."table2->addRow(3750, array('exactHeight'=>true));"); $section->addText("So: $"."table2->addRow(3750, array('exactHeight'=>true));");
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -15,13 +15,7 @@ $cell = $table->addCell();
$cell->addCheckBox('chkBox2', 'Checkbox 2'); $cell->addCheckBox('chkBox2', 'Checkbox 2');
// Save file // Save file
$name = basename(__FILE__, '.php'); echo write($phpWord, basename(__FILE__, '.php'), $writers);
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); if (!CLI) {
foreach ($writers as $writer => $extension) { include_once 'Sample_Footer.php';
echo date('H:i:s'), " Write to {$writer} format", EOL;
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$name}.{$extension}");
rename("{$name}.{$extension}", "results/{$name}.{$extension}");
} }
include_once 'Sample_Footer.php';

View File

@ -18,4 +18,8 @@ echo date('H:i:s'), " Write to Word2007 format", EOL;
$document->saveAs($name); $document->saveAs($name);
rename($name, "results/{$name}"); rename($name, "results/{$name}");
include_once 'Sample_Footer.php'; $writers = array('Word2007' => 'docx');
echo getEndingNotes($writers);
if (!CLI) {
include_once 'Sample_Footer.php';
}

View File

@ -2,33 +2,10 @@
/** /**
* Footer file * Footer file
*/ */
// Do not show execution time for index
if (!IS_INDEX) {
echo date('H:i:s'), " Done writing file(s)", EOL;
echo date('H:i:s'), " Peak memory usage: ", (memory_get_peak_usage(true) / 1024 / 1024), " MB", EOL;
}
// Show message when executed with CLI, show links when using browsers
if (CLI) {
echo 'The results are stored in the "results" subdirectory.', EOL;
} else {
if (!IS_INDEX) {
$types = array('docx', 'odt', 'rtf');
echo '<p>&nbsp;</p>';
echo '<p>Results: ';
foreach ($types as $type) {
$result = 'results/' . SCRIPT_FILENAME . '.' . $type;
if (file_exists($result)) {
echo "<a href='{$result}' class='btn btn-primary'>{$type}</a> ";
}
}
echo '</p>';
}
?> ?>
</div> </div>
<script src="bootstrap/js/jquery.min.js"></script> <script src="bootstrap/js/jquery.min.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script> <script src="bootstrap/js/bootstrap.min.js"></script>
</body> </body>
</html> </html>
<?php
} // if (CLI)

View File

@ -11,6 +11,17 @@ define('IS_INDEX', SCRIPT_FILENAME == 'index');
require_once '../src/PhpWord/Autoloader.php'; require_once '../src/PhpWord/Autoloader.php';
\PhpOffice\PhpWord\Autoloader::register(); \PhpOffice\PhpWord\Autoloader::register();
// Set writers
$writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf', 'HTML' => 'html', 'PDF' => 'pdf');
// Set PDF renderer
$rendererName = \PhpOffice\PhpWord\Settings::PDF_RENDERER_DOMPDF;
$rendererLibraryPath = ''; // DomPDF library path
if (!\PhpOffice\PhpWord\Settings::setPdfRenderer($rendererName, $rendererLibraryPath)) {
$writers['PDF'] = null;
}
// Return to the caller script when runs by CLI // Return to the caller script when runs by CLI
if (CLI) { if (CLI) {
return; return;
@ -21,6 +32,7 @@ $pageHeading = str_replace('_', ' ', SCRIPT_FILENAME);
$pageTitle = IS_INDEX ? 'Welcome to ' : "{$pageHeading} - "; $pageTitle = IS_INDEX ? 'Welcome to ' : "{$pageHeading} - ";
$pageTitle .= 'PHPWord'; $pageTitle .= 'PHPWord';
$pageHeading = IS_INDEX ? '' : "<h1>{$pageHeading}</h1>"; $pageHeading = IS_INDEX ? '' : "<h1>{$pageHeading}</h1>";
// Populate samples // Populate samples
$files = ''; $files = '';
if ($handle = opendir('.')) { if ($handle = opendir('.')) {
@ -32,6 +44,73 @@ if ($handle = opendir('.')) {
} }
closedir($handle); closedir($handle);
} }
/**
* Write documents
*
* @param \PhpOffice\PhpWord\PhpWord $phpWord
* @param string $filename
* @param array $writers
*/
function write($phpWord, $filename, $writers)
{
$result = '';
// Write documents
foreach ($writers as $writer => $extension) {
$result .= date('H:i:s') . " Write to {$writer} format";
if (!is_null($extension)) {
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$filename}.{$extension}");
rename("{$filename}.{$extension}", "results/{$filename}.{$extension}");
} else {
$result .= ' ... NOT DONE!';
}
$result .= EOL;
}
$result .= getEndingNotes($writers);
return $result;
}
/**
* Get ending notes
*
* @param array $writers
*/
function getEndingNotes($writers)
{
$result = '';
// Do not show execution time for index
if (!IS_INDEX) {
$result .= date('H:i:s') . " Done writing file(s)" . EOL;
$result .= date('H:i:s') . " Peak memory usage: " . (memory_get_peak_usage(true) / 1024 / 1024) . " MB" . EOL;
}
// Return
if (CLI) {
$result .= 'The results are stored in the "results" subdirectory.' . EOL;
} else {
if (!IS_INDEX) {
$types = array_values($writers);
$result .= '<p>&nbsp;</p>';
$result .= '<p>Results: ';
foreach ($types as $type) {
if (!is_null($type)) {
$resultFile = 'results/' . SCRIPT_FILENAME . '.' . $type;
if (file_exists($resultFile)) {
$result .= "<a href='{$resultFile}' class='btn btn-primary'>{$type}</a> ";
}
}
}
$result .= '</p>';
}
}
return $result;
}
?> ?>
<title><?php echo $pageTitle; ?></title> <title><?php echo $pageTitle; ?></title>
<meta charset="utf-8"> <meta charset="utf-8">

View File

@ -24,5 +24,7 @@ foreach ($requirements as $key => $value) {
echo "<li>{$value[0]} ... <span class='{$status}'>{$status}</span></li>"; echo "<li>{$value[0]} ... <span class='{$status}'>{$status}</span></li>";
} }
echo "</ul>"; echo "</ul>";
} // if (!CLI) }
include_once 'Sample_Footer.php'; if (!CLI) {
include_once 'Sample_Footer.php';
}

View File

@ -22,7 +22,7 @@ use PhpOffice\PhpWord\TOC;
/** /**
* Container abstract class * Container abstract class
* *
* @since 0.9.2 * @since 0.10.0
*/ */
abstract class AbstractElement abstract class AbstractElement
{ {
@ -69,6 +69,20 @@ abstract class AbstractElement
*/ */
protected $elements = array(); protected $elements = array();
/**
* Index of element in the elements collection (start with 1)
*
* @var integer
*/
protected $elementIndex = 1;
/**
* Unique Id for element
*
* @var integer
*/
protected $elementId;
/** /**
* Relation Id * Relation Id
* *
@ -96,7 +110,7 @@ abstract class AbstractElement
$text = String::toUTF8($text); $text = String::toUTF8($text);
$textObject = new Text($text, $fontStyle, $paragraphStyle); $textObject = new Text($text, $fontStyle, $paragraphStyle);
$textObject->setDocPart($this->getDocPart(), $this->getDocPartId()); $textObject->setDocPart($this->getDocPart(), $this->getDocPartId());
$this->elements[] = $textObject; $this->addElement($textObject);
return $textObject; return $textObject;
} }
@ -113,7 +127,7 @@ abstract class AbstractElement
$textRun = new TextRun($paragraphStyle); $textRun = new TextRun($paragraphStyle);
$textRun->setDocPart($this->getDocPart(), $this->getDocPartId()); $textRun->setDocPart($this->getDocPart(), $this->getDocPartId());
$this->elements[] = $textRun; $this->addElement($textRun);
return $textRun; return $textRun;
} }
@ -136,7 +150,7 @@ abstract class AbstractElement
$link->setDocPart($this->getDocPart(), $this->getDocPartId()); $link->setDocPart($this->getDocPart(), $this->getDocPartId());
$rId = Media::addElement($elementDocPart, 'link', $linkSrc); $rId = Media::addElement($elementDocPart, 'link', $linkSrc);
$link->setRelationId($rId); $link->setRelationId($rId);
$this->elements[] = $link; $this->addElement($link);
return $link; return $link;
} }
@ -167,7 +181,7 @@ abstract class AbstractElement
$bookmarkId = $data[1]; $bookmarkId = $data[1];
$title->setAnchor($anchor); $title->setAnchor($anchor);
$title->setBookmarkId($bookmarkId); $title->setBookmarkId($bookmarkId);
$this->elements[] = $title; $this->addElement($title);
return $title; return $title;
} }
@ -186,7 +200,7 @@ abstract class AbstractElement
$preserveText = new PreserveText(String::toUTF8($text), $fontStyle, $paragraphStyle); $preserveText = new PreserveText(String::toUTF8($text), $fontStyle, $paragraphStyle);
$preserveText->setDocPart($this->getDocPart(), $this->getDocPartId()); $preserveText->setDocPart($this->getDocPart(), $this->getDocPartId());
$this->elements[] = $preserveText; $this->addElement($preserveText);
return $preserveText; return $preserveText;
} }
@ -205,7 +219,7 @@ abstract class AbstractElement
for ($i = 1; $i <= $count; $i++) { for ($i = 1; $i <= $count; $i++) {
$textBreak = new TextBreak($fontStyle, $paragraphStyle); $textBreak = new TextBreak($fontStyle, $paragraphStyle);
$textBreak->setDocPart($this->getDocPart(), $this->getDocPartId()); $textBreak->setDocPart($this->getDocPart(), $this->getDocPartId());
$this->elements[] = $textBreak; $this->addElement($textBreak);
} }
} }
@ -225,7 +239,7 @@ abstract class AbstractElement
$listItem = new ListItem(String::toUTF8($text), $depth, $fontStyle, $styleList, $paragraphStyle); $listItem = new ListItem(String::toUTF8($text), $depth, $fontStyle, $styleList, $paragraphStyle);
$listItem->setDocPart($this->getDocPart(), $this->getDocPartId()); $listItem->setDocPart($this->getDocPart(), $this->getDocPartId());
$this->elements[] = $listItem; $this->addElement($listItem);
return $listItem; return $listItem;
} }
@ -241,7 +255,7 @@ abstract class AbstractElement
$this->checkValidity('table'); $this->checkValidity('table');
$table = new Table($this->getDocPart(), $this->getDocPartId(), $style); $table = new Table($this->getDocPart(), $this->getDocPartId(), $style);
$this->elements[] = $table; $this->addElement($table);
return $table; return $table;
} }
@ -263,7 +277,8 @@ abstract class AbstractElement
$image->setDocPart($this->getDocPart(), $this->getDocPartId()); $image->setDocPart($this->getDocPart(), $this->getDocPartId());
$rId = Media::addElement($elementDocPart, 'image', $src, $image); $rId = Media::addElement($elementDocPart, 'image', $src, $image);
$image->setRelationId($rId); $image->setRelationId($rId);
$this->elements[] = $image; $this->addElement($image);
return $image; return $image;
} }
@ -296,7 +311,8 @@ abstract class AbstractElement
$object->setRelationId($rId); $object->setRelationId($rId);
$rIdimg = Media::addElement($elementDocPart, 'image', $icon, new Image($icon)); $rIdimg = Media::addElement($elementDocPart, 'image', $icon, new Image($icon));
$object->setImageRelationId($rIdimg); $object->setImageRelationId($rIdimg);
$this->elements[] = $object; $this->addElement($object);
return $object; return $object;
} else { } else {
throw new InvalidObjectException(); throw new InvalidObjectException();
@ -318,7 +334,7 @@ abstract class AbstractElement
$footnote->setDocPart('footnote', $this->getDocPartId()); $footnote->setDocPart('footnote', $this->getDocPartId());
$footnote->setRelationId($rId); $footnote->setRelationId($rId);
$this->elements[] = $footnote; $this->addElement($footnote);
return $footnote; return $footnote;
} }
@ -338,7 +354,7 @@ abstract class AbstractElement
$endnote->setDocPart('endnote', $this->getDocPartId()); $endnote->setDocPart('endnote', $this->getDocPartId());
$endnote->setRelationId($rId); $endnote->setRelationId($rId);
$this->elements[] = $endnote; $this->addElement($endnote);
return $endnote; return $endnote;
} }
@ -358,7 +374,7 @@ abstract class AbstractElement
$checkBox = new CheckBox(String::toUTF8($name), String::toUTF8($text), $fontStyle, $paragraphStyle); $checkBox = new CheckBox(String::toUTF8($name), String::toUTF8($text), $fontStyle, $paragraphStyle);
$checkBox->setDocPart($this->getDocPart(), $this->getDocPartId()); $checkBox->setDocPart($this->getDocPart(), $this->getDocPartId());
$this->elements[] = $checkBox; $this->addElement($checkBox);
return $checkBox; return $checkBox;
} }
@ -405,6 +421,16 @@ abstract class AbstractElement
return $this->docPartId; return $this->docPartId;
} }
/**
* Set element index and unique id, and add element into elements collection
*/
protected function addElement(AbstractElement $element)
{
$element->setElementIndex($this->countElements() + 1);
$element->setElementId();
$this->elements[] = $element;
}
/** /**
* Get all elements * Get all elements
* *
@ -415,6 +441,54 @@ abstract class AbstractElement
return $this->elements; return $this->elements;
} }
/**
* Count elements
*
* @return integer
*/
public function countElements()
{
return count($this->elements);
}
/**
* Get element index
*
* @return int
*/
public function getElementIndex()
{
return $this->elementIndex;
}
/**
* Set element index
*
* @param int $value
*/
public function setElementIndex($value)
{
$this->elementIndex = $value;
}
/**
* Get element unique ID
*
* @return string
*/
public function getElementId()
{
return $this->elementId;
}
/**
* Set element unique ID from 6 first digit of md5
*/
public function setElementId()
{
$this->elementId = substr(md5(rand()), 0, 6);
}
/** /**
* Get relation Id * Get relation Id
* *
@ -458,9 +532,6 @@ abstract class AbstractElement
{ {
if (!is_null($styleValue) && is_array($styleValue)) { if (!is_null($styleValue) && is_array($styleValue)) {
foreach ($styleValue as $key => $value) { foreach ($styleValue as $key => $value) {
if (substr($key, 0, 1) == '_') {
$key = substr($key, 1);
}
$styleObject->setStyleValue($key, $value); $styleObject->setStyleValue($key, $value);
} }
$style = $styleObject; $style = $styleObject;
@ -555,7 +626,7 @@ abstract class AbstractElement
* Create textrun element * Create textrun element
* *
* @param mixed $paragraphStyle * @param mixed $paragraphStyle
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public function createTextRun($paragraphStyle = null) public function createTextRun($paragraphStyle = null)
@ -567,7 +638,7 @@ abstract class AbstractElement
* Create footnote element * Create footnote element
* *
* @param mixed $paragraphStyle * @param mixed $paragraphStyle
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public function createFootnote($paragraphStyle = null) public function createFootnote($paragraphStyle = null)

View File

@ -14,7 +14,7 @@ use PhpOffice\PhpWord\Style\Paragraph;
/** /**
* Endnote element * Endnote element
* *
* @since 0.9.2 * @since 0.10.0
*/ */
class Endnote extends Footnote class Endnote extends Footnote
{ {

View File

@ -44,7 +44,7 @@ class Footer extends AbstractElement
* Set type * Set type
* *
* @param string $value * @param string $value
* @since 0.9.2 * @since 0.10.0
*/ */
public function setType($value = self::AUTO) public function setType($value = self::AUTO)
{ {
@ -55,7 +55,7 @@ class Footer extends AbstractElement
* Get type * Get type
* *
* @return string * @return string
* @since 0.9.2 * @since 0.10.0
*/ */
public function getType() public function getType()
{ {

View File

@ -48,7 +48,7 @@ class Footnote extends AbstractElement
* Get Footnote Reference ID * Get Footnote Reference ID
* *
* @return int * @return int
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public function getReferenceId() public function getReferenceId()
@ -60,7 +60,7 @@ class Footnote extends AbstractElement
* Set Footnote Reference ID * Set Footnote Reference ID
* *
* @param int $rId * @param int $rId
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public function setReferenceId($rId) public function setReferenceId($rId)

View File

@ -64,7 +64,7 @@ class Header extends AbstractElement
* Set header type * Set header type
* *
* @param string $value * @param string $value
* @since 0.9.2 * @since 0.10.0
*/ */
public function setType($value = self::AUTO) public function setType($value = self::AUTO)
{ {

View File

@ -18,6 +18,13 @@ use PhpOffice\PhpWord\Style\Image as ImageStyle;
*/ */
class Image extends AbstractElement class Image extends AbstractElement
{ {
/**
* Image source type constants
*/
const SOURCE_LOCAL = 'local'; // Local images
const SOURCE_GD = 'gd'; // Generated using GD
const SOURCE_ARCHIVE = 'archive'; // Image in archives zip://$archive#$image
/** /**
* Image source * Image source
* *
@ -25,6 +32,13 @@ class Image extends AbstractElement
*/ */
private $source; private $source;
/**
* Source type: local|gd|archive
*
* @var string
*/
private $sourceType;
/** /**
* Image style * Image style
* *
@ -85,57 +99,11 @@ class Image extends AbstractElement
*/ */
public function __construct($source, $style = null, $isWatermark = false) public function __construct($source, $style = null, $isWatermark = false)
{ {
// Detect if it's a memory image, by .php ext or by URL
if (stripos(strrev($source), strrev('.php')) === 0) {
$this->isMemImage = true;
} else {
$this->isMemImage = (filter_var($source, FILTER_VALIDATE_URL) !== false);
}
// Check supported types
if ($this->isMemImage) {
$supportedTypes = array('image/jpeg', 'image/gif', 'image/png');
$imgData = @getimagesize($source);
if (!is_array($imgData)) {
throw new InvalidImageException();
}
$this->imageType = $imgData['mime']; // string
if (!in_array($this->imageType, $supportedTypes)) {
throw new UnsupportedImageTypeException();
}
} else {
$supportedTypes = array(
IMAGETYPE_JPEG, IMAGETYPE_GIF,
IMAGETYPE_PNG, IMAGETYPE_BMP,
IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM
);
if (!file_exists($source)) {
throw new InvalidImageException();
}
$imgData = getimagesize($source);
if (function_exists('exif_imagetype')) {
$this->imageType = exif_imagetype($source);
} else {
// @codeCoverageIgnoreStart
$tmp = getimagesize($source);
$this->imageType = $tmp[2];
// @codeCoverageIgnoreEnd
}
if (!in_array($this->imageType, $supportedTypes)) {
throw new UnsupportedImageTypeException();
}
$this->imageType = image_type_to_mime_type($this->imageType);
}
// Set private properties
$this->source = $source; $this->source = $source;
$this->isWatermark = $isWatermark; $this->setIsWatermark($isWatermark);
$this->style = $this->setStyle(new ImageStyle(), $style, true); $this->style = $this->setStyle(new ImageStyle(), $style, true);
if ($this->style->getWidth() == null && $this->style->getHeight() == null) {
$this->style->setWidth($imgData[0]); $this->checkImage($source);
$this->style->setHeight($imgData[1]);
}
$this->setImageFunctions();
} }
/** /**
@ -158,6 +126,16 @@ class Image extends AbstractElement
return $this->source; return $this->source;
} }
/**
* Get image source type
*
* @return string
*/
public function getSourceType()
{
return $this->sourceType;
}
/** /**
* Get image media ID * Get image media ID
* *
@ -239,9 +217,92 @@ class Image extends AbstractElement
} }
/** /**
* Set image functions * Check memory image, supported type, image functions, and proportional width/height
*
* @param string $source
*/ */
private function setImageFunctions() private function checkImage($source)
{
$this->setSourceType($source);
// Check image data
if ($this->sourceType == self::SOURCE_ARCHIVE) {
$imageData = $this->getArchiveImageSize($source);
} else {
$imageData = @getimagesize($source);
}
if (!is_array($imageData)) {
throw new InvalidImageException();
}
list($actualWidth, $actualHeight, $imageType) = $imageData;
// Check image type support
$supportedTypes = array(IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_PNG);
if ($this->sourceType != self::SOURCE_GD) {
$supportedTypes = array_merge($supportedTypes, array(IMAGETYPE_BMP, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM));
}
if (!in_array($imageType, $supportedTypes)) {
throw new UnsupportedImageTypeException();
}
// Define image functions
$this->imageType = image_type_to_mime_type($imageType);
$this->setFunctions();
$this->setProportionalSize($actualWidth, $actualHeight);
}
/**
* Set source type
*
* @param string $source
*/
private function setSourceType($source)
{
if (stripos(strrev($source), strrev('.php')) === 0) {
$this->isMemImage = true;
$this->sourceType = self::SOURCE_GD;
} elseif (strpos($source, 'zip://') !== false) {
$this->isMemImage = false;
$this->sourceType = self::SOURCE_ARCHIVE;
} else {
$this->isMemImage = (filter_var($source, FILTER_VALIDATE_URL) !== false);
$this->sourceType = $this->isMemImage ? self::SOURCE_GD : self::SOURCE_LOCAL;
}
}
/**
* Get image size from archive
*
* @param string $source
* @return array|null
*/
private function getArchiveImageSize($source)
{
$imageData = null;
$source = substr($source, 6);
list($zipFilename, $imageFilename) = explode('#', $source);
$tempFilename = tempnam(sys_get_temp_dir(), 'PHPWordImage');
$zip = new \ZipArchive();
if ($zip->open($zipFilename) !== false) {
if ($zip->locateName($imageFilename)) {
$imageContent = $zip->getFromName($imageFilename);
if ($imageContent !== false) {
file_put_contents($tempFilename, $imageContent);
$imageData = @getimagesize($tempFilename);
unlink($tempFilename);
}
}
$zip->close();
}
return $imageData;
}
/**
* Set image functions and extensions
*/
private function setFunctions()
{ {
switch ($this->imageType) { switch ($this->imageType) {
case 'image/png': case 'image/png':
@ -260,8 +321,8 @@ class Image extends AbstractElement
$this->imageFunc = 'imagejpeg'; $this->imageFunc = 'imagejpeg';
$this->imageExtension = 'jpg'; $this->imageExtension = 'jpg';
break; break;
case 'image/x-ms-bmp':
case 'image/bmp': case 'image/bmp':
case 'image/x-ms-bmp':
$this->imageType = 'image/bmp'; $this->imageType = 'image/bmp';
$this->imageExtension = 'bmp'; $this->imageExtension = 'bmp';
break; break;
@ -270,4 +331,26 @@ class Image extends AbstractElement
break; break;
} }
} }
/**
* Set proportional width/height if one dimension not available
*
* @param integer $actualWidth
* @param integer $actualHeight
*/
private function setProportionalSize($actualWidth, $actualHeight)
{
$styleWidth = $this->style->getWidth();
$styleHeight = $this->style->getHeight();
if (!($styleWidth && $styleHeight)) {
if ($styleWidth == null && $styleHeight == null) {
$this->style->setWidth($actualWidth);
$this->style->setHeight($actualHeight);
} elseif ($styleWidth) {
$this->style->setHeight($actualHeight * ($styleWidth / $actualWidth));
} else {
$this->style->setWidth($actualWidth * ($styleHeight / $actualHeight));
}
}
}
} }

View File

@ -43,15 +43,21 @@ class ListItem extends AbstractElement
* *
* @param string $text * @param string $text
* @param int $depth * @param int $depth
* @param mixed $styleFont * @param mixed $fontStyle
* @param mixed $styleList * @param array|string|null $listStyle
* @param mixed $styleParagraph * @param mixed $paragraphStyle
*/ */
public function __construct($text, $depth = 0, $styleFont = null, $styleList = null, $styleParagraph = null) public function __construct($text, $depth = 0, $fontStyle = null, $listStyle = null, $paragraphStyle = null)
{ {
$this->textObject = new Text($text, $styleFont, $styleParagraph); $this->textObject = new Text($text, $fontStyle, $paragraphStyle);
$this->depth = $depth; $this->depth = $depth;
$this->style = $this->setStyle(new ListItemStyle(), $styleList, true);
// Version >= 0.10.0 will pass numbering style name. Older version will use old method
if (!is_null($listStyle) && is_string($listStyle)) {
$this->style = new ListItemStyle($listStyle);
} else {
$this->style = $this->setStyle(new ListItemStyle(), $listStyle, true);
}
} }
/** /**

View File

@ -101,7 +101,7 @@ class Object extends AbstractElement
* Get Object ID * Get Object ID
* *
* @return int * @return int
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public function getObjectId() public function getObjectId()
@ -113,7 +113,7 @@ class Object extends AbstractElement
* Set Object ID * Set Object ID
* *
* @param int $objId * @param int $objId
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public function setObjectId($objId) public function setObjectId($objId)

View File

@ -66,9 +66,6 @@ class Section extends AbstractElement
if (is_null($value)) { if (is_null($value)) {
continue; continue;
} }
if (substr($key, 0, 1) == '_') {
$key = substr($key, 1);
}
$this->settings->setSettingValue($key, $value); $this->settings->setSettingValue($key, $value);
} }
} }
@ -113,7 +110,7 @@ class Section extends AbstractElement
* *
* @param string $type * @param string $type
* @return Header * @return Header
* @since 0.9.2 * @since 0.10.0
*/ */
public function addHeader($type = Header::AUTO) public function addHeader($type = Header::AUTO)
{ {
@ -125,7 +122,7 @@ class Section extends AbstractElement
* *
* @param string $type * @param string $type
* @return Footer * @return Footer
* @since 0.9.2 * @since 0.10.0
*/ */
public function addFooter($type = Header::AUTO) public function addFooter($type = Header::AUTO)
{ {
@ -177,7 +174,7 @@ class Section extends AbstractElement
* @param boolean $header * @param boolean $header
* @return Header|Footer * @return Header|Footer
* @throws \PhpOffice\PhpWord\Exception\Exception * @throws \PhpOffice\PhpWord\Exception\Exception
* @since 0.9.2 * @since 0.10.0
*/ */
private function addHeaderFooter($type = Header::AUTO, $header = true) private function addHeaderFooter($type = Header::AUTO, $header = true)
{ {
@ -201,7 +198,7 @@ class Section extends AbstractElement
* Create header * Create header
* *
* @return Header * @return Header
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public function createHeader() public function createHeader()
@ -213,7 +210,7 @@ class Section extends AbstractElement
* Create footer * Create footer
* *
* @return Footer * @return Footer
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public function createFooter() public function createFooter()
@ -225,7 +222,7 @@ class Section extends AbstractElement
* Get footer * Get footer
* *
* @return Footer * @return Footer
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public function getFooter() public function getFooter()

View File

@ -33,7 +33,7 @@ class Table extends AbstractElement
/** /**
* Table width * Table width
* *
* @var int * @var integer
*/ */
private $width = null; private $width = null;
@ -42,7 +42,7 @@ class Table extends AbstractElement
* Create a new table * Create a new table
* *
* @param string $docPart * @param string $docPart
* @param int $docPartId * @param integer $docPartId
* @param mixed $style * @param mixed $style
*/ */
public function __construct($docPart, $docPartId, $style = null) public function __construct($docPart, $docPartId, $style = null)
@ -54,7 +54,7 @@ class Table extends AbstractElement
/** /**
* Add a row * Add a row
* *
* @param int $height * @param integer $height
* @param mixed $style * @param mixed $style
*/ */
public function addRow($height = null, $style = null) public function addRow($height = null, $style = null)
@ -67,7 +67,7 @@ class Table extends AbstractElement
/** /**
* Add a cell * Add a cell
* *
* @param int $width * @param integer $width
* @param mixed $style * @param mixed $style
* @return Cell * @return Cell
*/ */
@ -101,7 +101,7 @@ class Table extends AbstractElement
/** /**
* Set table width * Set table width
* *
* @param int $width * @param integer $width
*/ */
public function setWidth($width) public function setWidth($width)
{ {
@ -111,10 +111,31 @@ class Table extends AbstractElement
/** /**
* Get table width * Get table width
* *
* @return int * @return integer
*/ */
public function getWidth() public function getWidth()
{ {
return $this->width; return $this->width;
} }
/**
* Get column count
*
* @return integer
*/
public function countColumns()
{
$columnCount = 0;
if (is_array($this->rows)) {
$rowCount = count($this->rows);
for ($i = 0; $i < $rowCount; $i++) {
$cellCount = count($this->rows[$i]->getCells());
if ($columnCount < $cellCount) {
$columnCount = $cellCount;
}
}
}
return $columnCount;
}
} }

View File

@ -119,6 +119,16 @@ class Title extends AbstractElement
return $this->text; return $this->text;
} }
/**
* Get depth
*
* @return integer
*/
public function getDepth()
{
return $this->depth;
}
/** /**
* Get Title style * Get Title style
* *

View File

@ -12,7 +12,7 @@ namespace PhpOffice\PhpWord;
/** /**
* Endnote collection * Endnote collection
* *
* @since 0.9.2 * @since 0.10.0
*/ */
class Endnotes class Endnotes
{ {

View File

@ -26,7 +26,7 @@ class Footnotes
* *
* @param \PhpOffice\PhpWord\Element\Footnote $element * @param \PhpOffice\PhpWord\Element\Footnote $element
* @return integer Reference ID * @return integer Reference ID
* @since 0.9.2 * @since 0.10.0
*/ */
public static function addElement($element) public static function addElement($element)
{ {
@ -41,7 +41,7 @@ class Footnotes
* *
* @param integer $index * @param integer $index
* @param \PhpOffice\PhpWord\Element\Footnote $element * @param \PhpOffice\PhpWord\Element\Footnote $element
* @since 0.9.2 * @since 0.10.0
*/ */
public static function setElement($index, $element) public static function setElement($index, $element)
{ {
@ -55,7 +55,7 @@ class Footnotes
* *
* @param integer $index * @param integer $index
* @return \PhpOffice\PhpWord\Element\Footnote * @return \PhpOffice\PhpWord\Element\Footnote
* @since 0.9.2 * @since 0.10.0
*/ */
public static function getElement($index) public static function getElement($index)
{ {
@ -70,7 +70,7 @@ class Footnotes
* Get elements * Get elements
* *
* @return array * @return array
* @since 0.9.2 * @since 0.10.0
*/ */
public static function getElements() public static function getElements()
{ {
@ -81,7 +81,7 @@ class Footnotes
* Get element count * Get element count
* *
* @return integer * @return integer
* @since 0.9.2 * @since 0.10.0
*/ */
public static function countElements() public static function countElements()
{ {
@ -91,7 +91,7 @@ class Footnotes
/** /**
* Reset elements * Reset elements
* *
* @since 0.9.2 * @since 0.10.0
*/ */
public static function resetElements() public static function resetElements()
{ {
@ -103,7 +103,7 @@ class Footnotes
* *
* @param \PhpOffice\PhpWord\Element\Footnote $element * @param \PhpOffice\PhpWord\Element\Footnote $element
* @return integer Reference ID * @return integer Reference ID
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function addFootnoteElement($element) public static function addFootnoteElement($element)
@ -115,7 +115,7 @@ class Footnotes
* Get Footnote Elements * Get Footnote Elements
* *
* @return array * @return array
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function getFootnoteElements() public static function getFootnoteElements()
@ -127,7 +127,7 @@ class Footnotes
* Get Footnote Elements Count * Get Footnote Elements Count
* *
* @return integer * @return integer
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function countFootnoteElements() public static function countFootnoteElements()
@ -140,7 +140,7 @@ class Footnotes
* *
* @param string $linkSrc * @param string $linkSrc
* @return integer Reference ID * @return integer Reference ID
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function addFootnoteLinkElement($linkSrc) public static function addFootnoteLinkElement($linkSrc)
@ -152,7 +152,7 @@ class Footnotes
* Get Footnote Link Elements * Get Footnote Link Elements
* *
* @return array * @return array
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function getFootnoteLinkElements() public static function getFootnoteLinkElements()

View File

@ -26,7 +26,7 @@ abstract class IOFactory
*/ */
public static function createWriter(PhpWord $phpWord, $name = 'Word2007') public static function createWriter(PhpWord $phpWord, $name = 'Word2007')
{ {
if ($name !== 'WriterInterface' && $name !== 'ODText' && $name !== 'RTF' && $name !== 'Word2007') { if (!in_array($name, array('WriterInterface', 'Word2007', 'ODText', 'RTF', 'HTML', 'PDF'))) {
throw new Exception("\"{$name}\" is not a valid writer."); throw new Exception("\"{$name}\" is not a valid writer.");
} }
@ -43,7 +43,7 @@ abstract class IOFactory
*/ */
public static function createReader($name = 'Word2007') public static function createReader($name = 'Word2007')
{ {
if ($name !== 'ReaderInterface' && $name !== 'Word2007') { if (!in_array($name, array('ReaderInterface', 'Word2007'))) {
throw new Exception("\"{$name}\" is not a valid reader."); throw new Exception("\"{$name}\" is not a valid reader.");
} }

View File

@ -34,6 +34,7 @@ class Media
* @return integer * @return integer
* @throws \PhpOffice\PhpWord\Exception\Exception * @throws \PhpOffice\PhpWord\Exception\Exception
* @since 0.9.2 * @since 0.9.2
* @since 0.10.0
*/ */
public static function addElement($container, $mediaType, $source, Image $image = null) public static function addElement($container, $mediaType, $source, Image $image = null)
{ {
@ -98,7 +99,7 @@ class Media
* @param string $container section|headerx|footerx|footnote|endnote * @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.10.0
*/ */
public static function countElements($container, $mediaType = null) public static function countElements($container, $mediaType = null)
{ {
@ -125,7 +126,7 @@ class Media
* @param string $container section|headerx|footerx|footnote|endnote * @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.10.0
*/ */
public static function getElements($container, $mediaType = null) public static function getElements($container, $mediaType = null)
{ {
@ -171,7 +172,7 @@ class Media
* @param string $type * @param string $type
* @param \PhpOffice\PhpWord\Element\Image $image * @param \PhpOffice\PhpWord\Element\Image $image
* @return integer * @return integer
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function addSectionMediaElement($src, $type, Image $image = null) public static function addSectionMediaElement($src, $type, Image $image = null)
@ -184,7 +185,7 @@ class Media
* *
* @param string $linkSrc * @param string $linkSrc
* @return integer * @return integer
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function addSectionLinkElement($linkSrc) public static function addSectionLinkElement($linkSrc)
@ -197,7 +198,7 @@ class Media
* *
* @param string $key * @param string $key
* @return array * @return array
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function getSectionMediaElements($key = null) public static function getSectionMediaElements($key = null)
@ -210,7 +211,7 @@ class Media
* *
* @param string $key * @param string $key
* @return integer * @return integer
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function countSectionMediaElements($key = null) public static function countSectionMediaElements($key = null)
@ -225,7 +226,7 @@ class Media
* @param string $src * @param string $src
* @param \PhpOffice\PhpWord\Element\Image $image * @param \PhpOffice\PhpWord\Element\Image $image
* @return integer * @return integer
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function addHeaderMediaElement($headerCount, $src, Image $image = null) public static function addHeaderMediaElement($headerCount, $src, Image $image = null)
@ -238,7 +239,7 @@ class Media
* *
* @param string $key * @param string $key
* @return integer * @return integer
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function countHeaderMediaElements($key) public static function countHeaderMediaElements($key)
@ -250,7 +251,7 @@ class Media
* Get Header Media Elements * Get Header Media Elements
* *
* @return array * @return array
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function getHeaderMediaElements() public static function getHeaderMediaElements()
@ -265,7 +266,7 @@ class Media
* @param string $src * @param string $src
* @param \PhpOffice\PhpWord\Element\Image $image * @param \PhpOffice\PhpWord\Element\Image $image
* @return integer * @return integer
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function addFooterMediaElement($footerCount, $src, Image $image = null) public static function addFooterMediaElement($footerCount, $src, Image $image = null)
@ -278,7 +279,7 @@ class Media
* *
* @param string $key * @param string $key
* @return integer * @return integer
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function countFooterMediaElements($key) public static function countFooterMediaElements($key)
@ -290,7 +291,7 @@ class Media
* Get Footer Media Elements * Get Footer Media Elements
* *
* @return array * @return array
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function getFooterMediaElements() public static function getFooterMediaElements()

View File

@ -9,9 +9,11 @@
namespace PhpOffice\PhpWord; namespace PhpOffice\PhpWord;
use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\DocumentProperties;
use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Element\Section;
use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Template;
/** /**
* PHPWord main class * PHPWord main class
@ -212,6 +214,17 @@ class PhpWord
Style::addLinkStyle($styleName, $styles); Style::addLinkStyle($styleName, $styles);
} }
/**
* Adds a numbering style
*
* @param string $styleName
* @param mixed $styles
*/
public function addNumberingStyle($styleName, $styles)
{
Style::addNumberingStyle($styleName, $styles);
}
/** /**
* Get all sections * Get all sections
* *
@ -243,7 +256,7 @@ class PhpWord
* *
* @param array $settings * @param array $settings
* @return \PhpOffice\PhpWord\Element\Section * @return \PhpOffice\PhpWord\Element\Section
* @deprecated 0.9.2 * @deprecated 0.10.0
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public function createSection($settings = null) public function createSection($settings = null)

View File

@ -9,16 +9,18 @@
namespace PhpOffice\PhpWord\Reader; namespace PhpOffice\PhpWord\Reader;
use PhpOffice\PhpWord\DocumentProperties;
use PhpOffice\PhpWord\Footnote;
use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Footnote;
use PhpOffice\PhpWord\Endnotes;
use PhpOffice\PhpWord\DocumentProperties;
use PhpOffice\PhpWord\Shared\XMLReader; use PhpOffice\PhpWord\Shared\XMLReader;
use PhpOffice\PhpWord\Element\Section;
/** /**
* Reader for Word2007 * Reader for Word2007
* *
* @since 0.9.2 * @since 0.10.0
* @todo title, list, watermark, checkbox, toc * @todo title, list, watermark, checkbox, toc
* @todo Partly done: image, object * @todo Partly done: image, object
*/ */
@ -38,6 +40,13 @@ class Word2007 extends AbstractReader implements ReaderInterface
*/ */
private $rels = array('main' => array(), 'document' => array()); private $rels = array('main' => array(), 'document' => array());
/**
* Filename
*
* @var string
*/
private $filename;
/** /**
* Loads PhpWord from file * Loads PhpWord from file
* *
@ -48,14 +57,27 @@ class Word2007 extends AbstractReader implements ReaderInterface
{ {
$this->phpWord = new PhpWord(); $this->phpWord = new PhpWord();
$this->readRelationships($filename); $this->filename = $filename;
$this->readRelationships();
// Read styles and numbering first
foreach ($this->rels['document'] as $rId => $rel) {
switch ($rel['type']) {
case 'styles':
$this->readStyles($rel['target']);
break;
case 'numbering':
$this->readNumbering($rel['target']);
break;
}
}
// Read main relationship // Read main relationship
foreach ($this->rels['main'] as $rId => $rel) { foreach ($this->rels['main'] as $rId => $rel) {
switch ($rel['type']) { switch ($rel['type']) {
case 'officeDocument': case 'officeDocument':
$this->readDocument($filename, $rel['target']); $this->readDocument($rel['target']);
break; break;
case 'core-properties': case 'core-properties':
@ -71,31 +93,26 @@ class Word2007 extends AbstractReader implements ReaderInterface
'dcterms:modified' => 'setModified', 'dcterms:modified' => 'setModified',
); );
$callbacks = array('dcterms:created' => 'strtotime', 'dcterms:modified' => 'strtotime'); $callbacks = array('dcterms:created' => 'strtotime', 'dcterms:modified' => 'strtotime');
$this->readDocProps($filename, $rel['target'], $mapping, $callbacks); $this->readDocProps($rel['target'], $mapping, $callbacks);
break; break;
case 'extended-properties': case 'extended-properties':
$mapping = array('Company' => 'setCompany', 'Manager' => 'setManager'); $mapping = array('Company' => 'setCompany', 'Manager' => 'setManager');
$this->readDocProps($filename, $rel['target'], $mapping); $this->readDocProps($rel['target'], $mapping);
break; break;
case 'custom-properties': case 'custom-properties':
$this->readDocPropsCustom($filename, $rel['target']); $this->readDocPropsCustom($rel['target']);
break; break;
} }
} }
// Read document relationships // Read footnotes and endnotes
foreach ($this->rels['document'] as $rId => $rel) { foreach ($this->rels['document'] as $rId => $rel) {
switch ($rel['type']) { switch ($rel['type']) {
case 'styles':
$this->readStyles($filename, $rel['target']);
break;
case 'footnotes': case 'footnotes':
case 'endnotes': case 'endnotes':
$this->readNotes($filename, $rel['target'], $rel['type']); $this->readNotes($rel['target'], $rel['type']);
break; break;
} }
} }
@ -105,24 +122,22 @@ class Word2007 extends AbstractReader implements ReaderInterface
/** /**
* Read all relationship files * Read all relationship files
*
* @param string $filename
*/ */
private function readRelationships($filename) private function readRelationships()
{ {
// _rels/.rels // _rels/.rels
$this->rels['main'] = $this->getRels($filename, '_rels/.rels'); $this->rels['main'] = $this->getRels('_rels/.rels');
// word/_rels/*.xml.rels // word/_rels/*.xml.rels
$wordRelsPath = 'word/_rels/'; $wordRelsPath = 'word/_rels/';
$zipClass = Settings::getZipClass(); $zipClass = Settings::getZipClass();
$zip = new $zipClass(); $zip = new $zipClass();
if ($zip->open($filename) === true) { if ($zip->open($this->filename) === true) {
for ($i = 0; $i < $zip->numFiles; $i++) { for ($i = 0; $i < $zip->numFiles; $i++) {
$xmlFile = $zip->getNameIndex($i); $xmlFile = $zip->getNameIndex($i);
if ((substr($xmlFile, 0, strlen($wordRelsPath))) == $wordRelsPath) { if ((substr($xmlFile, 0, strlen($wordRelsPath))) == $wordRelsPath && (substr($xmlFile, -1)) != '/') {
$docPart = str_replace('.xml.rels', '', str_replace($wordRelsPath, '', $xmlFile)); $docPart = str_replace('.xml.rels', '', str_replace($wordRelsPath, '', $xmlFile));
$this->rels[$docPart] = $this->getRels($filename, $xmlFile, 'word/'); $this->rels[$docPart] = $this->getRels($xmlFile, 'word/');
} }
} }
$zip->close(); $zip->close();
@ -132,15 +147,14 @@ class Word2007 extends AbstractReader implements ReaderInterface
/** /**
* Read core and extended document properties * Read core and extended document properties
* *
* @param string $filename
* @param string $xmlFile * @param string $xmlFile
* @param array $mapping * @param array $mapping
* @param array $callbacks * @param array $callbacks
*/ */
private function readDocProps($filename, $xmlFile, $mapping, $callbacks = array()) private function readDocProps($xmlFile, $mapping, $callbacks = array())
{ {
$xmlReader = new XMLReader(); $xmlReader = new XMLReader();
$xmlReader->getDomFromZip($filename, $xmlFile); $xmlReader->getDomFromZip($this->filename, $xmlFile);
$docProps = $this->phpWord->getDocumentProperties(); $docProps = $this->phpWord->getDocumentProperties();
$nodes = $xmlReader->getElements('*'); $nodes = $xmlReader->getElements('*');
@ -164,19 +178,17 @@ class Word2007 extends AbstractReader implements ReaderInterface
/** /**
* Read custom document properties * Read custom document properties
* *
* @param string $filename
* @param string $xmlFile * @param string $xmlFile
*/ */
private function readDocPropsCustom($filename, $xmlFile) private function readDocPropsCustom($xmlFile)
{ {
$xmlReader = new XMLReader(); $xmlReader = new XMLReader();
$xmlReader->getDomFromZip($filename, $xmlFile); $xmlReader->getDomFromZip($this->filename, $xmlFile);
$docProps = $this->phpWord->getDocumentProperties(); $docProps = $this->phpWord->getDocumentProperties();
$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;
$propertyName = $xmlReader->getAttribute('name', $node); $propertyName = $xmlReader->getAttribute('name', $node);
$attributeNode = $xmlReader->getElement('*', $node); $attributeNode = $xmlReader->getElement('*', $node);
$attributeType = $attributeNode->nodeName; $attributeType = $attributeNode->nodeName;
@ -191,19 +203,19 @@ class Word2007 extends AbstractReader implements ReaderInterface
/** /**
* Read document.xml * Read document.xml
* *
* @param string $filename
* @param string $xmlFile * @param string $xmlFile
*/ */
private function readDocument($filename, $xmlFile) private function readDocument($xmlFile)
{ {
$xmlReader = new XMLReader(); $xmlReader = new XMLReader();
$xmlReader->getDomFromZip($filename, $xmlFile); $xmlReader->getDomFromZip($this->filename, $xmlFile);
$nodes = $xmlReader->getElements('w:body/*'); $nodes = $xmlReader->getElements('w:body/*');
if ($nodes->length > 0) { if ($nodes->length > 0) {
$section = $this->phpWord->addSection(); $section = $this->phpWord->addSection();
foreach ($nodes as $node) { foreach ($nodes as $node) {
switch ($node->nodeName) { switch ($node->nodeName) {
case 'w:p': // Paragraph case 'w:p': // Paragraph
if ($xmlReader->getAttribute('w:type', $node, 'w:r/w:br') == 'page') { if ($xmlReader->getAttribute('w:type', $node, 'w:r/w:br') == 'page') {
$section->addPageBreak(); // PageBreak $section->addPageBreak(); // PageBreak
@ -213,19 +225,27 @@ class Word2007 extends AbstractReader implements ReaderInterface
// Section properties // Section properties
if ($xmlReader->elementExists('w:pPr/w:sectPr', $node)) { if ($xmlReader->elementExists('w:pPr/w:sectPr', $node)) {
$settingsNode = $xmlReader->getElement('w:pPr/w:sectPr', $node); $settingsNode = $xmlReader->getElement('w:pPr/w:sectPr', $node);
$settings = $this->readSectionStyle($xmlReader, $settingsNode); if (!is_null($settingsNode)) {
$section->setSettings($settings); $settings = $this->readSectionStyle($xmlReader, $settingsNode);
$this->readHeaderFooter($filename, $settings, $section); $section->setSettings($settings);
if (!is_null($settings)) {
$this->readHeaderFooter($settings, $section);
}
}
$section = $this->phpWord->addSection(); $section = $this->phpWord->addSection();
} }
break; break;
case 'w:tbl': // Table case 'w:tbl': // Table
$this->readTable($xmlReader, $node, $section, 'document'); $this->readTable($xmlReader, $node, $section, 'document');
break; break;
case 'w:sectPr': // Last section case 'w:sectPr': // Last section
$settings = $this->readSectionStyle($xmlReader, $node); $settings = $this->readSectionStyle($xmlReader, $node);
$section->setSettings($settings); $section->setSettings($settings);
$this->readHeaderFooter($filename, $settings, $section); if (!is_null($settings)) {
$this->readHeaderFooter($settings, $section);
}
break; break;
} }
} }
@ -235,13 +255,12 @@ class Word2007 extends AbstractReader implements ReaderInterface
/** /**
* Read styles.xml * Read styles.xml
* *
* @param string $filename
* @param string $xmlFile * @param string $xmlFile
*/ */
private function readStyles($filename, $xmlFile) private function readStyles($xmlFile)
{ {
$xmlReader = new XMLReader(); $xmlReader = new XMLReader();
$xmlReader->getDomFromZip($filename, $xmlFile); $xmlReader->getDomFromZip($this->filename, $xmlFile);
$nodes = $xmlReader->getElements('w:style'); $nodes = $xmlReader->getElements('w:style');
if ($nodes->length > 0) { if ($nodes->length > 0) {
@ -253,21 +272,26 @@ class Word2007 extends AbstractReader implements ReaderInterface
} }
// $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);
$fStyle = $this->readFontStyle($xmlReader, $node); $fStyle = $this->readFontStyle($xmlReader, $node);
if (empty($fStyle)) { if (empty($fStyle)) {
$this->phpWord->addParagraphStyle($name, $pStyle); if (is_array($pStyle)) {
$this->phpWord->addParagraphStyle($name, $pStyle);
}
} else { } else {
$this->phpWord->addFontStyle($name, $fStyle, $pStyle); $this->phpWord->addFontStyle($name, $fStyle, $pStyle);
} }
break; break;
case 'character': case 'character':
$fStyle = $this->readFontStyle($xmlReader, $node); $fStyle = $this->readFontStyle($xmlReader, $node);
if (!empty($fStyle)) { if (!empty($fStyle)) {
$this->phpWord->addFontStyle($name, $fStyle); $this->phpWord->addFontStyle($name, $fStyle);
} }
break; break;
case 'table': case 'table':
$tStyle = $this->readTableStyle($xmlReader, $node); $tStyle = $this->readTableStyle($xmlReader, $node);
if (!empty($tStyle)) { if (!empty($tStyle)) {
@ -279,14 +303,104 @@ class Word2007 extends AbstractReader implements ReaderInterface
} }
} }
/**
* Read numbering.xml
*
* @param string $xmlFile
*/
private function readNumbering($xmlFile)
{
$abstracts = array();
$numberings = array();
$xmlReader = new XMLReader();
$xmlReader->getDomFromZip($this->filename, $xmlFile);
// Abstract numbering definition
$nodes = $xmlReader->getElements('w:abstractNum');
if ($nodes->length > 0) {
foreach ($nodes as $node) {
$abstractId = $xmlReader->getAttribute('w:abstractNumId', $node);
$abstracts[$abstractId] = array('levels' => array());
$abstract = &$abstracts[$abstractId];
$subnodes = $xmlReader->getElements('*', $node);
foreach ($subnodes as $subnode) {
switch ($subnode->nodeName) {
case 'w:multiLevelType':
$abstract['type'] = $xmlReader->getAttribute('w:val', $subnode);
break;
case 'w:lvl':
$levelId = $xmlReader->getAttribute('w:ilvl', $subnode);
$abstract['levels'][$levelId] = $this->readNumberingLevel($xmlReader, $subnode, $levelId);
break;
}
}
}
}
// Numbering instance definition
$nodes = $xmlReader->getElements('w:num');
if ($nodes->length > 0) {
foreach ($nodes as $node) {
$numId = $xmlReader->getAttribute('w:numId', $node);
$abstractId = $xmlReader->getAttribute('w:val', $node, 'w:abstractNumId');
$numberings[$numId] = $abstracts[$abstractId];
$numberings[$numId]['numId'] = $numId;
$subnodes = $xmlReader->getElements('w:lvlOverride/w:lvl', $node);
foreach ($subnodes as $subnode) {
$levelId = $xmlReader->getAttribute('w:ilvl', $subnode);
$overrides = $this->readNumberingLevel($xmlReader, $subnode, $levelId);
foreach ($overrides as $key => $value) {
$numberings[$numId]['levels'][$levelId][$key] = $value;
}
}
}
}
// Push to Style collection
foreach ($numberings as $numId => $numbering) {
$this->phpWord->addNumberingStyle("PHPWordList{$numId}", $numbering);
}
}
/**
* Read numbering level definition from w:abstractNum and w:num
*
* @param integer $levelId
* @return array
*/
private function readNumberingLevel(XMLReader $xmlReader, \DOMElement $subnode, $levelId)
{
$level = array();
$level['level'] = $levelId;
$level['start'] = $xmlReader->getAttribute('w:val', $subnode, 'w:start');
$level['format'] = $xmlReader->getAttribute('w:val', $subnode, 'w:numFmt');
$level['restart'] = $xmlReader->getAttribute('w:val', $subnode, 'w:lvlRestart');
$level['suffix'] = $xmlReader->getAttribute('w:val', $subnode, 'w:suff');
$level['text'] = $xmlReader->getAttribute('w:val', $subnode, 'w:lvlText');
$level['align'] = $xmlReader->getAttribute('w:val', $subnode, 'w:lvlJc');
$level['tab'] = $xmlReader->getAttribute('w:pos', $subnode, 'w:pPr/w:tabs/w:tab');
$level['left'] = $xmlReader->getAttribute('w:left', $subnode, 'w:pPr/w:ind');
$level['hanging'] = $xmlReader->getAttribute('w:hanging', $subnode, 'w:pPr/w:ind');
$level['font'] = $xmlReader->getAttribute('w:ascii', $subnode, 'w:rPr/w:rFonts');
$level['hint'] = $xmlReader->getAttribute('w:hint', $subnode, 'w:rPr/w:rFonts');
foreach ($level as $key => $value) {
if (is_null($value)) {
unset($level[$key]);
}
}
return $level;
}
/** /**
* Read header footer * Read header footer
* *
* @param string $filename
* @param array $settings * @param array $settings
* @param \PhpOffice\PhpWord\Element\Section $section * @param \PhpOffice\PhpWord\Element\Section $section
*/ */
private function readHeaderFooter($filename, $settings, &$section) private function readHeaderFooter($settings, &$section)
{ {
if (is_array($settings) && array_key_exists('hf', $settings)) { if (is_array($settings) && array_key_exists('hf', $settings)) {
foreach ($settings['hf'] as $rId => $hfSetting) { foreach ($settings['hf'] as $rId => $hfSetting) {
@ -297,7 +411,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
// Read header/footer content // Read header/footer content
$xmlReader = new XMLReader(); $xmlReader = new XMLReader();
$xmlReader->getDomFromZip($filename, $xmlFile); $xmlReader->getDomFromZip($this->filename, $xmlFile);
$nodes = $xmlReader->getElements('*'); $nodes = $xmlReader->getElements('*');
if ($nodes->length > 0) { if ($nodes->length > 0) {
foreach ($nodes as $node) { foreach ($nodes as $node) {
@ -321,17 +435,17 @@ class Word2007 extends AbstractReader implements ReaderInterface
/** /**
* Read (footnotes|endnotes).xml * Read (footnotes|endnotes).xml
* *
* @param string $filename
* @param string $xmlFile * @param string $xmlFile
* @param string $notesType
*/ */
private function readNotes($filename, $xmlFile, $notesType = 'footnotes') private function readNotes($xmlFile, $notesType = 'footnotes')
{ {
$notesType = ($notesType == 'endnotes') ? 'endnotes' : 'footnotes'; $notesType = ($notesType == 'endnotes') ? 'endnotes' : 'footnotes';
$collectionClass = 'PhpOffice\\PhpWord\\' . ucfirst($notesType); $collectionClass = 'PhpOffice\\PhpWord\\' . ucfirst($notesType);
$collection = $collectionClass::getElements(); $collection = $collectionClass::getElements();
$xmlReader = new XMLReader(); $xmlReader = new XMLReader();
$xmlReader->getDomFromZip($filename, $xmlFile); $xmlReader->getDomFromZip($this->filename, $xmlFile);
$nodes = $xmlReader->getElements('*'); $nodes = $xmlReader->getElements('*');
if ($nodes->length > 0) { if ($nodes->length > 0) {
foreach ($nodes as $node) { foreach ($nodes as $node) {
@ -360,7 +474,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
* *
* @todo Get font style for preserve text * @todo Get font style for preserve text
*/ */
private function readParagraph(XMLReader $xmlReader, \DOMNode $domNode, &$parent, $docPart) private function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart)
{ {
// Paragraph style // Paragraph style
$pStyle = null; $pStyle = null;
@ -394,6 +508,17 @@ class Word2007 extends AbstractReader implements ReaderInterface
} }
$parent->addPreserveText($textContent, $fStyle, $pStyle); $parent->addPreserveText($textContent, $fStyle, $pStyle);
// List item
} elseif ($xmlReader->elementExists('w:pPr/w:numPr', $domNode)) {
$textContent = '';
$numId = $xmlReader->getAttribute('w:val', $domNode, 'w:pPr/w:numPr/w:numId');
$levelId = $xmlReader->getAttribute('w:val', $domNode, 'w:pPr/w:numPr/w:ilvl');
$nodes = $xmlReader->getElements('w:r', $domNode);
foreach ($nodes as $node) {
$textContent .= $xmlReader->getValue('w:t', $node);
}
$parent->addListItem($textContent, $levelId, null, "PHPWordList{$numId}", $pStyle);
// Text and TextRun // Text and TextRun
} else { } else {
$runCount = $xmlReader->countElements('w:r', $domNode); $runCount = $xmlReader->countElements('w:r', $domNode);
@ -419,13 +544,15 @@ class Word2007 extends AbstractReader implements ReaderInterface
/** /**
* Read w:r * Read w:r
* *
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @param mixed $parent * @param mixed $parent
* @param string $docPart * @param string $docPart
* @param mixed $pStyle * @param mixed $pStyle
* *
* @todo Footnote paragraph style * @todo Footnote paragraph style
*/ */
private function readRun(XMLReader $xmlReader, \DOMNode $domNode, &$parent, $docPart, $pStyle = null) private function readRun(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart, $pStyle = null)
{ {
if (!in_array($domNode->nodeName, array('w:r', 'w:hyperlink'))) { if (!in_array($domNode->nodeName, array('w:r', 'w:hyperlink'))) {
return; return;
@ -454,8 +581,8 @@ class Word2007 extends AbstractReader implements ReaderInterface
$rId = $xmlReader->getAttribute('r:id', $domNode, 'w:pict/v:shape/v:imagedata'); $rId = $xmlReader->getAttribute('r:id', $domNode, 'w:pict/v:shape/v:imagedata');
$target = $this->getMediaTarget($docPart, $rId); $target = $this->getMediaTarget($docPart, $rId);
if (!is_null($target)) { if (!is_null($target)) {
$textContent = "<Image: {$target}>"; $imageSource = "zip://{$this->filename}#{$target}";
$parent->addText($textContent, $fStyle, $pStyle); $parent->addImage($imageSource);
} }
// Object // Object
@ -482,7 +609,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
* @param mixed $parent * @param mixed $parent
* @param string $docPart * @param string $docPart
*/ */
private function readTable(XMLReader $xmlReader, \DOMNode $domNode, &$parent, $docPart) private function readTable(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart)
{ {
// Table style // Table style
$tblStyle = null; $tblStyle = null;
@ -515,8 +642,9 @@ class Word2007 extends AbstractReader implements ReaderInterface
} elseif ($rowNode->nodeName == 'w:tc') { // Cell } elseif ($rowNode->nodeName == 'w:tc') { // Cell
$cellWidth = $xmlReader->getAttribute('w:w', $rowNode, 'w:tcPr/w:tcW'); $cellWidth = $xmlReader->getAttribute('w:w', $rowNode, 'w:tcPr/w:tcW');
$cellStyle = null; $cellStyle = null;
if ($xmlReader->elementExists('w:tcPr', $rowNode)) { $cellStyleNode = $xmlReader->getElement('w:tcPr', $rowNode);
$cellStyle = $this->readCellStyle($xmlReader, $xmlReader->getElement('w:tcPr', $rowNode)); if (!is_null($cellStyleNode)) {
$cellStyle = $this->readCellStyle($xmlReader, $cellStyleNode);
} }
$cell = $row->addCell($cellWidth, $cellStyle); $cell = $row->addCell($cellWidth, $cellStyle);
@ -537,7 +665,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
* *
* @return array|null * @return array|null
*/ */
private function readSectionStyle(XMLReader $xmlReader, \DOMNode $domNode) private function readSectionStyle(XMLReader $xmlReader, \DOMElement $domNode)
{ {
$ret = null; $ret = null;
$mapping = array( $mapping = array(
@ -552,6 +680,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
} }
$property = $mapping[$node->nodeName]; $property = $mapping[$node->nodeName];
switch ($node->nodeName) { switch ($node->nodeName) {
case 'w:type': case 'w:type':
$ret['breakType'] = $xmlReader->getAttribute('w:val', $node); $ret['breakType'] = $xmlReader->getAttribute('w:val', $node);
break; break;
@ -596,7 +725,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
* *
* @return string|array|null * @return string|array|null
*/ */
private function readParagraphStyle(XMLReader $xmlReader, \DOMNode $domNode) private function readParagraphStyle(XMLReader $xmlReader, \DOMElement $domNode)
{ {
$style = null; $style = null;
if ($xmlReader->elementExists('w:pPr', $domNode)) { if ($xmlReader->elementExists('w:pPr', $domNode)) {
@ -618,6 +747,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
} }
$property = $mapping[$node->nodeName]; $property = $mapping[$node->nodeName];
switch ($node->nodeName) { switch ($node->nodeName) {
case 'w:ind': case 'w:ind':
$style['indent'] = $xmlReader->getAttribute('w:left', $node); $style['indent'] = $xmlReader->getAttribute('w:left', $node);
$style['hanging'] = $xmlReader->getAttribute('w:hanging', $node); $style['hanging'] = $xmlReader->getAttribute('w:hanging', $node);
@ -658,13 +788,16 @@ class Word2007 extends AbstractReader implements ReaderInterface
* *
* @return string|array|null * @return string|array|null
*/ */
private function readFontStyle(XMLReader $xmlReader, \DOMNode $domNode) private function readFontStyle(XMLReader $xmlReader, \DOMElement $domNode)
{ {
$style = null; $style = null;
// Hyperlink has an extra w:r child // Hyperlink has an extra w:r child
if ($domNode->nodeName == 'w:hyperlink') { if ($domNode->nodeName == 'w:hyperlink') {
$domNode = $xmlReader->getElement('w:r', $domNode); $domNode = $xmlReader->getElement('w:r', $domNode);
} }
if (is_null($domNode)) {
return $style;
}
if ($xmlReader->elementExists('w:rPr', $domNode)) { if ($xmlReader->elementExists('w:rPr', $domNode)) {
if ($xmlReader->elementExists('w:rPr/w:rStyle', $domNode)) { if ($xmlReader->elementExists('w:rPr/w:rStyle', $domNode)) {
$style = $xmlReader->getAttribute('w:val', $domNode, 'w:rPr/w:rStyle'); $style = $xmlReader->getAttribute('w:val', $domNode, 'w:rPr/w:rStyle');
@ -684,6 +817,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
} }
$property = $mapping[$node->nodeName]; $property = $mapping[$node->nodeName];
switch ($node->nodeName) { switch ($node->nodeName) {
case 'w:rFonts': case 'w:rFonts':
$style['name'] = $xmlReader->getAttribute('w:ascii', $node); $style['name'] = $xmlReader->getAttribute('w:ascii', $node);
$style['hint'] = $xmlReader->getAttribute('w:hint', $node); $style['hint'] = $xmlReader->getAttribute('w:hint', $node);
@ -728,7 +862,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
* @return string|array|null * @return string|array|null
* @todo Capture w:tblStylePr w:type="firstRow" * @todo Capture w:tblStylePr w:type="firstRow"
*/ */
private function readTableStyle(XMLReader $xmlReader, \DOMNode $domNode) private function readTableStyle(XMLReader $xmlReader, \DOMElement $domNode)
{ {
$style = null; $style = null;
$margins = array('top', 'left', 'bottom', 'right'); $margins = array('top', 'left', 'bottom', 'right');
@ -751,6 +885,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
} }
// $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) {
$ucfSide = ucfirst($side); $ucfSide = ucfirst($side);
@ -778,7 +913,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
* *
* @return array|null * @return array|null
*/ */
private function readCellStyle(XMLReader $xmlReader, \DOMNode $domNode) private function readCellStyle(XMLReader $xmlReader, \DOMElement $domNode)
{ {
$style = null; $style = null;
$mapping = array( $mapping = array(
@ -809,12 +944,11 @@ class Word2007 extends AbstractReader implements ReaderInterface
/** /**
* Get relationship array * Get relationship array
* *
* @param string $filename
* @param string $xmlFile * @param string $xmlFile
* @param string $targetPrefix * @param string $targetPrefix
* @return array * @return array
*/ */
private function getRels($filename, $xmlFile, $targetPrefix = '') private function getRels($xmlFile, $targetPrefix = '')
{ {
$metaPrefix = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/'; $metaPrefix = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/';
$officePrefix = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/'; $officePrefix = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/';
@ -822,7 +956,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
$rels = array(); $rels = array();
$xmlReader = new XMLReader(); $xmlReader = new XMLReader();
$xmlReader->getDomFromZip($filename, $xmlFile); $xmlReader->getDomFromZip($this->filename, $xmlFile);
$nodes = $xmlReader->getElements('*'); $nodes = $xmlReader->getElements('*');
foreach ($nodes as $node) { foreach ($nodes as $node) {
$rId = $xmlReader->getAttribute('Id', $node); $rId = $xmlReader->getAttribute('Id', $node);

View File

@ -14,10 +14,13 @@ namespace PhpOffice\PhpWord;
*/ */
class Settings class Settings
{ {
/** Available Zip library classes */ /** Available Zip library classes */
const PCLZIP = 'PhpOffice\\PhpWord\\Shared\\ZipArchive'; const PCLZIP = 'PhpOffice\\PhpWord\\Shared\\ZipArchive';
const ZIPARCHIVE = 'ZipArchive'; const ZIPARCHIVE = 'ZipArchive';
/** Optional PDF Rendering libraries */
const PDF_RENDERER_DOMPDF = 'DomPDF';
/** /**
* Compatibility option for XMLWriter * Compatibility option for XMLWriter
* *
@ -27,13 +30,32 @@ class Settings
/** /**
* Name of the class used for Zip file management * Name of the class used for Zip file management
* e.g.
* ZipArchive
* *
* @var string * @var string
*/ */
private static $zipClass = self::ZIPARCHIVE; private static $zipClass = self::ZIPARCHIVE;
/**
* Name of the classes used for PDF renderer
*
* @var array
*/
private static $pdfRenderers = array(self::PDF_RENDERER_DOMPDF);
/**
* Name of the external Library used for rendering PDF files
*
* @var string
*/
private static $pdfRendererName = null;
/**
* Directory Path to the external Library used for rendering PDF files
*
* @var string
*/
private static $pdfRendererPath = null;
/** /**
* Set the compatibility option used by the XMLWriter * Set the compatibility option used by the XMLWriter
* *
@ -74,7 +96,7 @@ class Settings
return true; return true;
} }
return false; return false;
} // function setZipClass() }
/** /**
* Return the name of the Zip handler Class that PHPWord is configured to use (PCLZip or ZipArchive) * Return the name of the Zip handler Class that PHPWord is configured to use (PCLZip or ZipArchive)
@ -87,5 +109,71 @@ class Settings
public static function getZipClass() public static function getZipClass()
{ {
return self::$zipClass; return self::$zipClass;
} // function getZipClass() }
/**
* Set details of the external library for rendering PDF files
*
* @param string $libraryName
* @param string $libraryBaseDir
* @return boolean Success or failure
*/
public static function setPdfRenderer($libraryName, $libraryBaseDir)
{
if (!self::setPdfRendererName($libraryName)) {
return false;
}
return self::setPdfRendererPath($libraryBaseDir);
}
/**
* Return the PDF Rendering Library
*/
public static function getPdfRendererName()
{
return self::$pdfRendererName;
}
/**
* Identify the external library to use for rendering PDF files
*
* @param string $libraryName
* @return boolean Success or failure
*/
public static function setPdfRendererName($libraryName)
{
if (!in_array($libraryName, self::$pdfRenderers)) {
return false;
}
self::$pdfRendererName = $libraryName;
return true;
}
/**
* Return the directory path to the PDF Rendering Library
*/
public static function getPdfRendererPath()
{
return self::$pdfRendererPath;
}
/**
* Location of external library to use for rendering PDF files
*
* @param string $libraryBaseDir Directory path to the library's base folder
* @return boolean Success or failure
*/
public static function setPdfRendererPath($libraryBaseDir)
{
if ((file_exists($libraryBaseDir) === false) || (is_readable($libraryBaseDir) === false)) {
return false;
}
self::$pdfRendererPath = $libraryBaseDir;
return true;
}
} }

View File

@ -77,6 +77,23 @@ class String
return $value; return $value;
} }
/**
* Return name without underscore for < 0.10.0 variable name compatibility
*
* @param string $value
* @return string
*/
public static function removeUnderscorePrefix($value)
{
if (!is_null($value)) {
if (substr($value, 0, 1) == '_') {
$value = substr($value, 1);
}
}
return $value;
}
/** /**
* Build control characters array * Build control characters array
*/ */

View File

@ -15,7 +15,7 @@ use PhpOffice\PhpWord\Settings;
/** /**
* XML Reader wrapper * XML Reader wrapper
* *
* @since 0.9.2 * @since 0.10.0
*/ */
class XMLReader class XMLReader
{ {
@ -70,7 +70,7 @@ class XMLReader
* @param string $path * @param string $path
* @return \DOMNodeList * @return \DOMNodeList
*/ */
public function getElements($path, \DOMNode $contextNode = null) public function getElements($path, \DOMElement $contextNode = null)
{ {
if ($this->dom === null) { if ($this->dom === null) {
return array(); return array();
@ -86,9 +86,9 @@ class XMLReader
* Get element * Get element
* *
* @param string $path * @param string $path
* @return \DOMNode|null * @return \DOMElement|null
*/ */
public function getElement($path, \DOMNode $contextNode) public function getElement($path, \DOMElement $contextNode)
{ {
$elements = $this->getElements($path, $contextNode); $elements = $this->getElements($path, $contextNode);
if ($elements->length > 0) { if ($elements->length > 0) {
@ -105,7 +105,7 @@ class XMLReader
* @param string $path * @param string $path
* @return string|null * @return string|null
*/ */
public function getAttribute($attribute, \DOMNode $contextNode, $path = null) public function getAttribute($attribute, \DOMElement $contextNode, $path = null)
{ {
if (is_null($path)) { if (is_null($path)) {
$return = $contextNode->getAttribute($attribute); $return = $contextNode->getAttribute($attribute);
@ -127,7 +127,7 @@ class XMLReader
* @param string $path * @param string $path
* @return string|null * @return string|null
*/ */
public function getValue($path, \DOMNode $contextNode) public function getValue($path, \DOMElement $contextNode)
{ {
$elements = $this->getElements($path, $contextNode); $elements = $this->getElements($path, $contextNode);
if ($elements->length > 0) { if ($elements->length > 0) {
@ -143,7 +143,7 @@ class XMLReader
* @param string $path * @param string $path
* @return integer * @return integer
*/ */
public function countElements($path, \DOMNode $contextNode) public function countElements($path, \DOMElement $contextNode)
{ {
$elements = $this->getElements($path, $contextNode); $elements = $this->getElements($path, $contextNode);
@ -156,7 +156,7 @@ class XMLReader
* @param string $path * @param string $path
* @return boolean * @return boolean
*/ */
public function elementExists($path, \DOMNode $contextNode) public function elementExists($path, \DOMElement $contextNode)
{ {
return $this->getElements($path, $contextNode)->length > 0; return $this->getElements($path, $contextNode)->length > 0;
} }

View File

@ -22,7 +22,7 @@ require_once 'PCLZip/pclzip.lib.php';
/** /**
* PCLZip wrapper * PCLZip wrapper
* *
* @since 0.9.2 * @since 0.10.0
*/ */
class ZipArchive class ZipArchive
{ {
@ -217,8 +217,7 @@ class ZipArchive
public function getNameIndex($index) public function getNameIndex($index)
{ {
$list = $this->zip->listContent(); $list = $this->zip->listContent();
$listCount = count($list); if (isset($list[$index])) {
if ($index <= $listCount) {
return $list[$index]['filename']; return $list[$index]['filename'];
} else { } else {
return false; return false;

View File

@ -12,6 +12,7 @@ namespace PhpOffice\PhpWord;
use PhpOffice\PhpWord\Style\Font; use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Style\Paragraph; use PhpOffice\PhpWord\Style\Paragraph;
use PhpOffice\PhpWord\Style\Table; use PhpOffice\PhpWord\Style\Table;
use PhpOffice\PhpWord\Style\Numbering;
/** /**
* Style collection * Style collection
@ -33,7 +34,7 @@ class Style
*/ */
public static function addParagraphStyle($styleName, $styles) public static function addParagraphStyle($styleName, $styles)
{ {
self::setStyleValues($styleName, $styles, new Paragraph()); self::setStyleValues($styleName, new Paragraph(), $styles);
} }
/** /**
@ -45,7 +46,7 @@ class Style
*/ */
public static function addFontStyle($styleName, $styleFont, $styleParagraph = null) public static function addFontStyle($styleName, $styleFont, $styleParagraph = null)
{ {
self::setStyleValues($styleName, $styleFont, new Font('text', $styleParagraph)); self::setStyleValues($styleName, new Font('text', $styleParagraph), $styleFont);
} }
/** /**
@ -56,7 +57,7 @@ class Style
*/ */
public static function addLinkStyle($styleName, $styles) public static function addLinkStyle($styleName, $styles)
{ {
self::setStyleValues($styleName, $styles, new Font('link')); self::setStyleValues($styleName, new Font('link'), $styles);
} }
/** /**
@ -64,15 +65,11 @@ class Style
* *
* @param string $styleName * @param string $styleName
* @param array $styleTable * @param array $styleTable
* @param array $styleFirstRow * @param array|null $styleFirstRow
*/ */
public static function addTableStyle($styleName, $styleTable, $styleFirstRow = null) public static function addTableStyle($styleName, $styleTable, $styleFirstRow = null)
{ {
if (!array_key_exists($styleName, self::$styles)) { self::setStyleValues($styleName, new Table($styleTable, $styleFirstRow), null);
$style = new Table($styleTable, $styleFirstRow);
self::$styles[$styleName] = $style;
}
} }
/** /**
@ -84,12 +81,36 @@ class Style
*/ */
public static function addTitleStyle($titleCount, $styleFont, $styleParagraph = null) public static function addTitleStyle($titleCount, $styleFont, $styleParagraph = null)
{ {
$styleName = 'Heading_' . $titleCount; self::setStyleValues("Heading_{$titleCount}", new Font('title', $styleParagraph), $styleFont);
self::setStyleValues("Heading_{$titleCount}", $styleFont, new Font('title', $styleParagraph)); }
/**
* Add numbering style
*
* @param string $styleName
* @param array $styleValues
* @return Numbering
* @since 0.10.0
*/
public static function addNumberingStyle($styleName, $styleValues)
{
self::setStyleValues($styleName, new Numbering(), $styleValues);
}
/**
* Count styles
*
* @return integer
* @since 0.10.0
*/
public static function countStyles()
{
return count(self::$styles);
} }
/** /**
* Reset styles * Reset styles
* @since 0.10.0
*/ */
public static function resetStyles() public static function resetStyles()
{ {
@ -120,6 +141,7 @@ class Style
* Get style by name * Get style by name
* *
* @param string $styleName * @param string $styleName
* @return Paragraph|Font|Table|Numbering|null
*/ */
public static function getStyle($styleName) public static function getStyle($styleName)
{ {
@ -131,24 +153,21 @@ class Style
} }
/** /**
* Set style values * Set style values and put it to static style collection
* *
* @param string $styleName * @param string $styleName
* @param array $styleValues * @param Paragraph|Font|Table|Numbering $styleObject
* @param mixed $styleObject * @param array|null $styleValues
*/ */
private static function setStyleValues($styleName, $styleValues, $styleObject) private static function setStyleValues($styleName, $styleObject, $styleValues = null)
{ {
if (!array_key_exists($styleName, self::$styles)) { if (!array_key_exists($styleName, self::$styles)) {
if (is_array($styleValues)) { if (!is_null($styleValues) && is_array($styleValues)) {
foreach ($styleValues as $key => $value) { foreach ($styleValues as $key => $value) {
if (substr($key, 0, 1) == '_') {
$key = substr($key, 1);
}
$styleObject->setStyleValue($key, $value); $styleObject->setStyleValue($key, $value);
} }
} }
$styleObject->setIndex(self::countStyles() + 1); // One based index
self::$styles[$styleName] = $styleObject; self::$styles[$styleName] = $styleObject;
} }
} }

View File

@ -9,35 +9,144 @@
namespace PhpOffice\PhpWord\Style; namespace PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Shared\String;
/** /**
* Abstract style class * Abstract style class
* *
* @since 0.9.2 * @since 0.10.0
*/ */
abstract class AbstractStyle abstract class AbstractStyle
{ {
/**
* Index number in Style collection for named style
*
* This number starts from one and defined in Style::setStyleValues()
*
* @var integer|null
*/
protected $index;
/**
* Get index number
*
* @return integer|null
*/
public function getIndex()
{
return $this->index;
}
/**
* Set index number
*
* @param integer|null $value
*/
public function setIndex($value = null)
{
$this->index = $this->setIntVal($value, $this->index);
return $this;
}
/** /**
* Set style value template method * Set style value template method
* *
* Some child classes have their own specific overrides * Some child classes have their own specific overrides.
* Backward compability check for versions < 0.10.0 which use underscore
* prefix for their private properties.
* Check if the set method is exists. Throws an exception?
* *
* @param string $key * @param string $key
* @param string $value * @param string $value
* * @return self
* @todo Implement type check mechanism, e.g. boolean, integer, enum, defaults
*/ */
public function setStyleValue($key, $value) public function setStyleValue($key, $value)
{ {
// Backward compability check for versions < 0.9.2 which use underscore $method = 'set' . String::removeUnderscorePrefix($key);
// prefix for their private properties
if (substr($key, 0, 1) == '_') {
$key = substr($key, 1);
}
// Check if the set method is exists. Throws an exception?
$method = 'set' . $key;
if (method_exists($this, $method)) { if (method_exists($this, $method)) {
$this->$method($value); $this->$method($value);
} }
return $this;
}
/**
* Set style by using associative array
*
* @param array $styles
* @return self
*/
public function setStyleByArray($styles = array())
{
foreach ($styles as $key => $value) {
$this->setStyleValue($key, $value);
}
return $this;
}
/**
* Set boolean value
*
* @param mixed $value
* @param boolean|null $default
* @return boolean|null
*/
protected function setBoolVal($value, $default = null)
{
if (!is_bool($value)) {
$value = $default;
}
return $value;
}
/**
* Set integer value
*
* @param mixed $value
* @param integer|null $default
* @return integer|null
*/
protected function setIntVal($value, $default = null)
{
if (!is_int($value)) {
$value = $default;
}
return $value;
}
/**
* Set float value
*
* @param mixed $value
* @param float|null $default
* @return float|null
*/
protected function setFloatVal($value, $default = null)
{
if (!is_float($value)) {
$value = $default;
}
return $value;
}
/**
* Set enum value
*
* @param mixed $value
* @param array $enum
* @param mixed $default
*/
protected function setEnumVal($value, $enum, $default = null)
{
if (!in_array($value, $enum)) {
$value = $default;
}
return $value;
} }
} }

View File

@ -9,6 +9,8 @@
namespace PhpOffice\PhpWord\Style; namespace PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Shared\String;
/** /**
* Table cell style * Table cell style
*/ */
@ -145,9 +147,7 @@ class Cell extends AbstractStyle
*/ */
public function setStyleValue($key, $value) public function setStyleValue($key, $value)
{ {
if (substr($key, 0, 1) == '_') { $key = String::removeUnderscorePrefix($key);
$key = substr($key, 1);
}
if ($key == 'borderSize') { if ($key == 'borderSize') {
$this->setBorderSize($value); $this->setBorderSize($value);
} elseif ($key == 'borderColor') { } elseif ($key == 'borderColor') {

View File

@ -193,8 +193,6 @@ class Font extends AbstractStyle
if ($key === 'line-height') { if ($key === 'line-height') {
$this->setLineHeight($value); $this->setLineHeight($value);
null; null;
} elseif (substr($key, 0, 1) == '_') {
$key = substr($key, 1);
} }
$this->setStyleValue($key, $value); $this->setStyleValue($key, $value);
} }

View File

@ -9,46 +9,239 @@
namespace PhpOffice\PhpWord\Style; namespace PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Style;
/** /**
* List item style * List item style
*
* Before version 0.10.0, numbering style is defined statically with $listType.
* After version 0.10.0, numbering style is defined by using Numbering and
* recorded by $numStyle. $listStyle is maintained for backward compatility
*/ */
class ListItem extends AbstractStyle class ListItem extends AbstractStyle
{ {
const TYPE_SQUARE_FILLED = 1;
const TYPE_BULLET_FILLED = 3; // default
const TYPE_BULLET_EMPTY = 5;
const TYPE_NUMBER = 7; const TYPE_NUMBER = 7;
const TYPE_NUMBER_NESTED = 8; const TYPE_NUMBER_NESTED = 8;
const TYPE_ALPHANUM = 9; const TYPE_ALPHANUM = 9;
const TYPE_BULLET_FILLED = 3;
const TYPE_BULLET_EMPTY = 5;
const TYPE_SQUARE_FILLED = 1;
/** /**
* List Type * Legacy list type
*
* @var integer
*/ */
private $listType; private $listType;
/** /**
* Create a new ListItem Style * Numbering style name
*
* @var string
* @since 0.10.0
*/ */
public function __construct() private $numStyle;
{
$this->listType = self::TYPE_BULLET_FILLED;
}
/** /**
* Set List Type * Numbering definition instance ID
* *
* @param int $pValue * @var integer
* @since 0.10.0
*/ */
public function setListType($pValue = self::TYPE_BULLET_FILLED) private $numId;
/**
* Create new instance
*
* @param string $numStyle
*/
public function __construct($numStyle = null)
{ {
$this->listType = $pValue; if (!is_null($numStyle)) {
$this->setNumStyle($numStyle);
} else {
$this->setListType();
}
} }
/** /**
* Get List Type * Get List Type
*
* @return integer
*/ */
public function getListType() public function getListType()
{ {
return $this->listType; return $this->listType;
} }
/**
* Set legacy list type for version < 0.10.0
*
* @param integer $value
*/
public function setListType($value = self::TYPE_BULLET_FILLED)
{
$enum = array(self::TYPE_SQUARE_FILLED, self::TYPE_BULLET_FILLED,
self::TYPE_BULLET_EMPTY, self::TYPE_NUMBER,
self::TYPE_NUMBER_NESTED, self::TYPE_ALPHANUM);
$this->listType = $this->setEnumVal($value, $enum, $this->listType);
$this->getListTypeStyle();
}
/**
* Get numbering style name
*
* @return string
*/
public function getNumStyle()
{
return $this->numStyle;
}
/**
* Set numbering style name
*
* @param string $value
*/
public function setNumStyle($value)
{
$this->numStyle = $value;
$numStyleObject = Style::getStyle($this->numStyle);
if ($numStyleObject instanceof Numbering) {
$this->numId = $numStyleObject->getIndex();
$numStyleObject->setNumId($this->numId);
}
}
/**
* Get numbering Id
*
* @return integer
*/
public function getNumId()
{
return $this->numId;
}
/**
* Get legacy numbering definition
*
* @return array
* @since 0.10.0
*/
private function getListTypeStyle()
{
// Check if legacy style already registered in global Style collection
$numStyle = "PHPWordList{$this->listType}";
if (!is_null(Style::getStyle($numStyle))) {
$this->setNumStyle($numStyle);
return;
}
// Property mapping for numbering level information
$properties = array('start', 'format', 'text', 'align', 'tabPos', 'left', 'hanging', 'font', 'hint');
// Legacy level information
$listTypeStyles = array(
self::TYPE_SQUARE_FILLED => array(
'type' => 'hybridMultilevel',
'levels' => array(
0 => '1, bullet, , left, 720, 720, 360, Wingdings, default',
1 => '1, bullet, o, left, 1440, 1440, 360, Courier New, default',
2 => '1, bullet, , left, 2160, 2160, 360, Wingdings, default',
3 => '1, bullet, , left, 2880, 2880, 360, Symbol, default',
4 => '1, bullet, o, left, 3600, 3600, 360, Courier New, default',
5 => '1, bullet, , left, 4320, 4320, 360, Wingdings, default',
6 => '1, bullet, , left, 5040, 5040, 360, Symbol, default',
7 => '1, bullet, o, left, 5760, 5760, 360, Courier New, default',
8 => '1, bullet, , left, 6480, 6480, 360, Wingdings, default',
),
),
self::TYPE_BULLET_FILLED => array(
'type' => 'hybridMultilevel',
'levels' => array(
0 => '1, bullet, , left, 720, 720, 360, Symbol, default',
1 => '1, bullet, o, left, 1440, 1440, 360, Courier New, default',
2 => '1, bullet, , left, 2160, 2160, 360, Wingdings, default',
3 => '1, bullet, , left, 2880, 2880, 360, Symbol, default',
4 => '1, bullet, o, left, 3600, 3600, 360, Courier New, default',
5 => '1, bullet, , left, 4320, 4320, 360, Wingdings, default',
6 => '1, bullet, , left, 5040, 5040, 360, Symbol, default',
7 => '1, bullet, o, left, 5760, 5760, 360, Courier New, default',
8 => '1, bullet, , left, 6480, 6480, 360, Wingdings, default',
),
),
self::TYPE_BULLET_EMPTY => array(
'type' => 'hybridMultilevel',
'levels' => array(
0 => '1, bullet, o, left, 720, 720, 360, Courier New, default',
1 => '1, bullet, o, left, 1440, 1440, 360, Courier New, default',
2 => '1, bullet, , left, 2160, 2160, 360, Wingdings, default',
3 => '1, bullet, , left, 2880, 2880, 360, Symbol, default',
4 => '1, bullet, o, left, 3600, 3600, 360, Courier New, default',
5 => '1, bullet, , left, 4320, 4320, 360, Wingdings, default',
6 => '1, bullet, , left, 5040, 5040, 360, Symbol, default',
7 => '1, bullet, o, left, 5760, 5760, 360, Courier New, default',
8 => '1, bullet, , left, 6480, 6480, 360, Wingdings, default',
),
),
self::TYPE_NUMBER => array(
'type' => 'hybridMultilevel',
'levels' => array(
0 => '1, decimal, %1., left, 720, 720, 360, , default',
1 => '1, bullet, o, left, 1440, 1440, 360, Courier New, default',
2 => '1, bullet, , left, 2160, 2160, 360, Wingdings, default',
3 => '1, bullet, , left, 2880, 2880, 360, Symbol, default',
4 => '1, bullet, o, left, 3600, 3600, 360, Courier New, default',
5 => '1, bullet, , left, 4320, 4320, 360, Wingdings, default',
6 => '1, bullet, , left, 5040, 5040, 360, Symbol, default',
7 => '1, bullet, o, left, 5760, 5760, 360, Courier New, default',
8 => '1, bullet, , left, 6480, 6480, 360, Wingdings, default',
),
),
self::TYPE_NUMBER_NESTED => array(
'type' => 'multilevel',
'levels' => array(
0 => '1, decimal, %1., left, 360, 360, 360, , ',
1 => '1, decimal, %1.%2., left, 792, 792, 432, , ',
2 => '1, decimal, %1.%2.%3., left, 1224, 1224, 504, , ',
3 => '1, decimal, %1.%2.%3.%4., left, 1800, 1728, 648, , ',
4 => '1, decimal, %1.%2.%3.%4.%5., left, 2520, 2232, 792, , ',
5 => '1, decimal, %1.%2.%3.%4.%5.%6., left, 2880, 2736, 936, , ',
6 => '1, decimal, %1.%2.%3.%4.%5.%6.%7., left, 3600, 3240, 1080, , ',
7 => '1, decimal, %1.%2.%3.%4.%5.%6.%7.%8., left, 3960, 3744, 1224, , ',
8 => '1, decimal, %1.%2.%3.%4.%5.%6.%7.%8.%9., left, 4680, 4320, 1440, , ',
),
),
self::TYPE_ALPHANUM => array(
'type' => 'multilevel',
'levels' => array(
0 => '1, decimal, %1., left, 720, 720, 360, , ',
1 => '1, lowerLetter, %2., left, 1440, 1440, 360, , ',
2 => '1, lowerRoman, %3., right, 2160, 2160, 180, , ',
3 => '1, decimal, %4., left, 2880, 2880, 360, , ',
4 => '1, lowerLetter, %5., left, 3600, 3600, 360, , ',
5 => '1, lowerRoman, %6., right, 4320, 4320, 180, , ',
6 => '1, decimal, %7., left, 5040, 5040, 360, , ',
7 => '1, lowerLetter, %8., left, 5760, 5760, 360, , ',
8 => '1, lowerRoman, %9., right, 6480, 6480, 180, , ',
),
),
);
// Populate style and register to global Style register
$style = $listTypeStyles[$this->listType];
foreach ($style['levels'] as $key => $value) {
$level = array();
$levelProperties = explode(', ', $value);
$level['level'] = $key;
for ($i = 0; $i < count($properties); $i++) {
$property = $properties[$i];
$level[$property] = $levelProperties[$i];
}
$style['levels'][$key] = $level;
}
Style::addNumberingStyle($numStyle, $style);
$this->setNumStyle($numStyle);
}
} }

View File

@ -0,0 +1,123 @@
<?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\Style;
use PhpOffice\PhpWord\Style\NumberingLevel;
/**
* Numbering style
*
* @link http://www.schemacentral.com/sc/ooxml/e-w_numbering.html
* @link http://www.schemacentral.com/sc/ooxml/e-w_abstractNum-1.html
* @link http://www.schemacentral.com/sc/ooxml/e-w_num-1.html
* @since 0.10.0
*/
class Numbering extends AbstractStyle
{
/**
* Numbering definition instance ID
*
* @var int
* @link http://www.schemacentral.com/sc/ooxml/e-w_num-1.html
*/
private $numId;
/**
* Multilevel type singleLevel|multilevel|hybridMultilevel
*
* @var string
* @link http://www.schemacentral.com/sc/ooxml/a-w_val-67.html
*/
private $type;
/**
* Numbering levels
*
* @var NumberingLevel[]
*/
private $levels = array();
/**
* Get Id
*
* @return integer
*/
public function getNumId()
{
return $this->numId;
}
/**
* Set Id
*
* @param integer $value
* @return self
*/
public function setNumId($value)
{
$this->numId = $this->setIntVal($value, $this->numId);
return $this;
}
/**
* Get multilevel type
*
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* Set multilevel type
*
* @param string $value
* @return self
*/
public function setType($value)
{
$enum = array('singleLevel', 'multilevel', 'hybridMultilevel');
$this->type = $this->setEnumVal($value, $enum, $this->type);
return $this;
}
/**
* Get levels
*
* @return NumberingLevel[]
*/
public function getLevels()
{
return $this->levels;
}
/**
* Set multilevel type
*
* @param array $values
* @return self
*/
public function setLevels($values)
{
if (is_array($values)) {
foreach ($values as $key => $value) {
$numberingLevel = new NumberingLevel();
if (is_array($value)) {
$numberingLevel->setStyleByArray($value);
$numberingLevel->setLevel($key);
}
$this->levels[$key] = $numberingLevel;
}
}
return $this;
}
}

View File

@ -0,0 +1,378 @@
<?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\Style;
/**
* Numbering level definition
*
* @link http://www.schemacentral.com/sc/ooxml/e-w_lvl-1.html
* @since 0.10.0
*/
class NumberingLevel extends AbstractStyle
{
/**
* Level number, 0 to 8 (total 9 levels)
*
* @var integer
*/
private $level = 0;
/**
* Starting value w:start
*
* @var integer
* @link http://www.schemacentral.com/sc/ooxml/e-w_start-1.html
*/
private $start = 1;
/**
* Numbering format bullet|decimal|upperRoman|lowerRoman|upperLetter|lowerLetter
*
* @var string
* @link http://www.schemacentral.com/sc/ooxml/t-w_ST_NumberFormat.html
*/
private $format;
/**
* Restart numbering level symbol w:lvlRestart
*
* @var integer
* @link http://www.schemacentral.com/sc/ooxml/e-w_lvlRestart-1.html
*/
private $restart;
/**
* Content between numbering symbol and paragraph text
*
* @var string tab|space|nothing
* @link http://www.schemacentral.com/sc/ooxml/e-w_suff-1.html
*/
private $suffix = 'tab';
/**
* Numbering level text e.g. %1 for nonbullet or bullet character
*
* @var string
* @link http://www.schemacentral.com/sc/ooxml/e-w_lvlText-1.html
*/
private $text;
/**
* Align left|center|right|both
*
* @var string
* @link http://www.schemacentral.com/sc/ooxml/e-w_lvlJc-1.html
*/
private $align;
/**
* Left
*
* @var integer
*/
private $left;
/**
* Hanging
*
* @var integer
*/
private $hanging;
/**
* Tab position
*
* @var integer
*/
private $tabPos;
/**
* Font family
*
* @var string
*/
private $font;
/**
* Hint default|eastAsia|cs
*
* @var string
* @link http://www.schemacentral.com/sc/ooxml/a-w_hint-1.html
*/
private $hint;
/**
* Get level
*
* @return integer
*/
public function getLevel()
{
return $this->level;
}
/**
* Set level
*
* @param integer $value
* @return self
*/
public function setLevel($value)
{
$this->level = $this->setIntVal($value, $this->level);
return $this;
}
/**
* Get start
*
* @return integer
*/
public function getStart()
{
return $this->start;
}
/**
* Set start
*
* @param integer $value
* @return self
*/
public function setStart($value)
{
$this->start = $this->setIntVal($value, $this->start);
return $this;
}
/**
* Get format
*
* @return string
*/
public function getFormat()
{
return $this->format;
}
/**
* Set format
*
* @param string $value
* @return self
*/
public function setFormat($value)
{
$enum = array('bullet', 'decimal', 'upperRoman', 'lowerRoman', 'upperLetter', 'lowerLetter');
$this->format = $this->setEnumVal($value, $enum, $this->format);
return $this;
}
/**
* Get start
*
* @return integer
*/
public function getRestart()
{
return $this->restart;
}
/**
* Set start
*
* @param integer $value
* @return self
*/
public function setRestart($value)
{
$this->restart = $this->setIntVal($value, $this->restart);
return $this;
}
/**
* Get suffix
*
* @return string
*/
public function getSuffix()
{
return $this->suffix;
}
/**
* Set suffix
*
* @param string $value
* @return self
*/
public function setSuffix($value)
{
$enum = array('tab', 'space', 'nothing');
$this->suffix = $this->setEnumVal($value, $enum, $this->suffix);
return $this;
}
/**
* Get text
*
* @return string
*/
public function getText()
{
return $this->text;
}
/**
* Set text
*
* @param string $value
* @return self
*/
public function setText($value)
{
$this->text = $value;
return $this;
}
/**
* Get align
*
* @return string
*/
public function getAlign()
{
return $this->align;
}
/**
* Set align
*
* @param string $value
* @return self
*/
public function setAlign($value)
{
$enum = array('left', 'center', 'right', 'both');
$this->align = $this->setEnumVal($value, $enum, $this->align);
return $this;
}
/**
* Get left
*
* @return integer
*/
public function getLeft()
{
return $this->left;
}
/**
* Set left
*
* @param integer $value
* @return self
*/
public function setLeft($value)
{
$this->left = $this->setIntVal($value, $this->left);
return $this;
}
/**
* Get hanging
*
* @return integer
*/
public function getHanging()
{
return $this->hanging;
}
/**
* Set hanging
*
* @param integer $value
* @return self
*/
public function setHanging($value)
{
$this->hanging = $this->setIntVal($value, $this->hanging);
return $this;
}
/**
* Get tab
*
* @return integer
*/
public function getTabPos()
{
return $this->tabPos;
}
/**
* Set tab
*
* @param integer $value
* @return self
*/
public function setTabPos($value)
{
$this->tabPos = $this->setIntVal($value, $this->tabPos);
return $this;
}
/**
* Get font
*
* @return string
*/
public function getFont()
{
return $this->font;
}
/**
* Set font
*
* @param string $value
* @return self
*/
public function setFont($value)
{
$this->font = $value;
return $this;
}
/**
* Get hint
*
* @return string
*/
public function getHint()
{
return $this->hint;
}
/**
* Set hint
*
* @param string $value
* @return self
*/
public function setHint($value)
{
$enum = array('default', 'eastAsia', 'cs');
$this->hint = $this->setEnumVal($value, $enum, $this->hint);
return $this;
}
}

View File

@ -10,6 +10,7 @@
namespace PhpOffice\PhpWord\Style; namespace PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Exception\InvalidStyleException; use PhpOffice\PhpWord\Exception\InvalidStyleException;
use PhpOffice\PhpWord\Shared\String;
/** /**
* Paragraph style * Paragraph style
@ -127,8 +128,6 @@ class Paragraph extends AbstractStyle
foreach ($style as $key => $value) { foreach ($style as $key => $value) {
if ($key === 'line-height') { if ($key === 'line-height') {
null; null;
} elseif (substr($key, 0, 1) == '_') {
$key = substr($key, 1);
} }
$this->setStyleValue($key, $value); $this->setStyleValue($key, $value);
} }
@ -144,9 +143,7 @@ class Paragraph extends AbstractStyle
*/ */
public function setStyleValue($key, $value) public function setStyleValue($key, $value)
{ {
if (substr($key, 0, 1) == '_') { $key = String::removeUnderscorePrefix($key);
$key = substr($key, 1);
}
if ($key == 'indent' || $key == 'hanging') { if ($key == 'indent' || $key == 'hanging') {
$value = $value * 720; $value = $value * 720;
} elseif ($key == 'spacing') { } elseif ($key == 'spacing') {

View File

@ -45,16 +45,12 @@ class Row extends AbstractStyle
/** /**
* Set tblHeader * Set tblHeader
* *
* @param boolean $pValue * @param boolean $value
* @return $this * @return self
*/ */
public function setTblHeader($pValue = false) public function setTblHeader($value = false)
{ {
if (!is_bool($pValue)) { $this->tblHeader = $this->setBoolVal($value, $this->tblHeader);
$pValue = false;
}
$this->tblHeader = $pValue;
return $this;
} }
/** /**
@ -70,16 +66,12 @@ class Row extends AbstractStyle
/** /**
* Set cantSplit * Set cantSplit
* *
* @param boolean $pValue * @param boolean $value
* @return $this * @return self
*/ */
public function setCantSplit($pValue = false) public function setCantSplit($value = false)
{ {
if (!is_bool($pValue)) { $this->cantSplit = $this->setBoolVal($value, $this->cantSplit);
$pValue = false;
}
$this->cantSplit = $pValue;
return $this;
} }
/** /**
@ -95,15 +87,12 @@ class Row extends AbstractStyle
/** /**
* Set exactHeight * Set exactHeight
* *
* @param bool $pValue * @param bool $value
* @return $this * @return self
*/ */
public function setExactHeight($pValue = false) public function setExactHeight($value = false)
{ {
if (!is_bool($pValue)) { $this->exactHeight = $this->setBoolVal($value, $this->exactHeight);
$pValue = false;
}
$this->exactHeight = $pValue;
return $this; return $this;
} }

View File

@ -9,6 +9,8 @@
namespace PhpOffice\PhpWord\Style; namespace PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Shared\String;
/** /**
* Section settings * Section settings
*/ */
@ -217,9 +219,7 @@ class Section extends AbstractStyle
*/ */
public function setSettingValue($key, $value) public function setSettingValue($key, $value)
{ {
if (substr($key, 0, 1) == '_') { $key = String::removeUnderscorePrefix($key);
$key = substr($key, 1);
}
if ($key == 'orientation' && $value == 'landscape') { if ($key == 'orientation' && $value == 'landscape') {
$this->setLandscape(); $this->setLandscape();
} elseif ($key == 'orientation' && is_null($value)) { } elseif ($key == 'orientation' && is_null($value)) {

View File

@ -110,15 +110,4 @@ class TOC extends AbstractStyle
{ {
$this->indent = $pValue; $this->indent = $pValue;
} }
/**
* Set style value
*
* @param string $key
* @param string $value
*/
public function setStyleValue($key, $value)
{
$this->$key = $value;
}
} }

View File

@ -9,6 +9,8 @@
namespace PhpOffice\PhpWord\Style; namespace PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Shared\String;
/** /**
* Table style * Table style
*/ */
@ -161,18 +163,12 @@ class Table extends AbstractStyle
unset($this->firstRow->borderInsideHColor); unset($this->firstRow->borderInsideHColor);
unset($this->firstRow->borderInsideHSize); unset($this->firstRow->borderInsideHSize);
foreach ($styleFirstRow as $key => $value) { foreach ($styleFirstRow as $key => $value) {
if (substr($key, 0, 1) == '_') {
$key = substr($key, 1);
}
$this->firstRow->setStyleValue($key, $value); $this->firstRow->setStyleValue($key, $value);
} }
} }
if (!is_null($styleTable) && is_array($styleTable)) { if (!is_null($styleTable) && is_array($styleTable)) {
foreach ($styleTable as $key => $value) { foreach ($styleTable as $key => $value) {
if (substr($key, 0, 1) == '_') {
$key = substr($key, 1);
}
$this->setStyleValue($key, $value); $this->setStyleValue($key, $value);
} }
} }
@ -186,9 +182,7 @@ class Table extends AbstractStyle
*/ */
public function setStyleValue($key, $value) public function setStyleValue($key, $value)
{ {
if (substr($key, 0, 1) == '_') { $key = String::removeUnderscorePrefix($key);
$key = substr($key, 1);
}
if ($key == 'borderSize') { if ($key == 'borderSize') {
$this->setBorderSize($value); $this->setBorderSize($value);
} elseif ($key == 'borderColor') { } elseif ($key == 'borderColor') {

View File

@ -82,9 +82,6 @@ class TOC
if (!is_null($styleTOC) && is_array($styleTOC)) { if (!is_null($styleTOC) && is_array($styleTOC)) {
foreach ($styleTOC as $key => $value) { foreach ($styleTOC as $key => $value) {
if (substr($key, 0, 1) == '_') {
$key = substr($key, 1);
}
self::$TOCStyle->setStyleValue($key, $value); self::$TOCStyle->setStyleValue($key, $value);
} }
} }
@ -93,9 +90,6 @@ class TOC
if (is_array($styleFont)) { if (is_array($styleFont)) {
self::$fontStyle = new Font(); self::$fontStyle = new Font();
foreach ($styleFont as $key => $value) { foreach ($styleFont as $key => $value) {
if (substr($key, 0, 1) == '_') {
$key = substr($key, 1);
}
self::$fontStyle->setStyleValue($key, $value); self::$fontStyle->setStyleValue($key, $value);
} }
} else { } else {

View File

@ -420,17 +420,4 @@ class Template
} }
return substr($this->documentXML, $startPosition, ($endPosition - $startPosition)); return substr($this->documentXML, $startPosition, ($endPosition - $startPosition));
} }
/**
* Delete a block of text
*
* @param string $blockname
* @param string $replacement
* @deprecated
* @codeCoverageIgnore
*/
public function deleteTemplateBlock($blockname, $replacement = '')
{
$this->deleteBlock($blockname, $replacement);
}
} }

View File

@ -16,7 +16,7 @@ use PhpOffice\PhpWord\Settings;
/** /**
* Abstract writer class * Abstract writer class
* *
* @since 0.9.2 * @since 0.10.0
*/ */
abstract class AbstractWriter implements WriterInterface abstract class AbstractWriter implements WriterInterface
{ {
@ -48,6 +48,13 @@ abstract class AbstractWriter implements WriterInterface
*/ */
private $diskCachingDirectory = './'; private $diskCachingDirectory = './';
/**
* Temporary directory
*
* @var string
*/
private $tempDir = '';
/** /**
* Original file name * Original file name
* *
@ -81,7 +88,7 @@ abstract class AbstractWriter implements WriterInterface
* Set PhpWord object * Set PhpWord object
* *
* @param \PhpOffice\PhpWord\PhpWord * @param \PhpOffice\PhpWord\PhpWord
* @return $this * @return self
*/ */
public function setPhpWord(PhpWord $phpWord = null) public function setPhpWord(PhpWord $phpWord = null)
{ {
@ -119,7 +126,7 @@ abstract class AbstractWriter implements WriterInterface
* *
* @param boolean $pValue * @param boolean $pValue
* @param string $pDirectory * @param string $pDirectory
* @return $this * @return self
*/ */
public function setUseDiskCaching($pValue = false, $pDirectory = null) public function setUseDiskCaching($pValue = false, $pDirectory = null)
{ {
@ -146,6 +153,32 @@ abstract class AbstractWriter implements WriterInterface
return $this->diskCachingDirectory; return $this->diskCachingDirectory;
} }
/**
* Get temporary directory
*
* @return string
*/
public function getTempDir()
{
return $this->tempDir;
}
/**
* Set temporary directory
*
* @param string $value
* @return self
*/
public function setTempDir($value)
{
if (!is_dir($value)) {
mkdir($value);
}
$this->tempDir = $value;
return $this;
}
/** /**
* Get temporary file name * Get temporary file name
* *
@ -156,6 +189,10 @@ abstract class AbstractWriter implements WriterInterface
*/ */
protected function getTempFile($filename) protected function getTempFile($filename)
{ {
// Temporary directory
$this->setTempDir(sys_get_temp_dir() . '/PHPWordWriter/');
// Temporary file
$this->originalFilename = $filename; $this->originalFilename = $filename;
if (strtolower($filename) == 'php://output' || strtolower($filename) == 'php://stdout') { if (strtolower($filename) == 'php://output' || strtolower($filename) == 'php://stdout') {
$filename = @tempnam(sys_get_temp_dir(), 'phpword_'); $filename = @tempnam(sys_get_temp_dir(), 'phpword_');
@ -170,8 +207,6 @@ abstract class AbstractWriter implements WriterInterface
/** /**
* Cleanup temporary file * Cleanup temporary file
*
* If a temporary file was used, copy it to the correct file stream
*/ */
protected function cleanupTempFile() protected function cleanupTempFile()
{ {
@ -181,6 +216,18 @@ abstract class AbstractWriter implements WriterInterface
} }
@unlink($this->tempFilename); @unlink($this->tempFilename);
} }
$this->clearTempDir();
}
/**
* Clear temporary directory
*/
protected function clearTempDir()
{
if (is_dir($this->tempDir)) {
$this->deleteDir($this->tempDir);
}
} }
/** /**
@ -215,4 +262,24 @@ abstract class AbstractWriter implements WriterInterface
return $objZip; return $objZip;
} }
/**
* Delete directory
*
* @param string $dir
*/
private function deleteDir($dir)
{
foreach (scandir($dir) as $file) {
if ($file === '.' || $file === '..') {
continue;
} elseif (is_file($dir . "/" . $file)) {
unlink($dir . "/" . $file);
} elseif (is_dir($dir . "/" . $file)) {
$this->deleteDir($dir . "/" . $file);
}
}
rmdir($dir);
}
} }

746
src/PhpWord/Writer/HTML.php Normal file
View File

@ -0,0 +1,746 @@
<?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\Writer;
use PhpOffice\PhpWord\Element\Endnote;
use PhpOffice\PhpWord\Element\Footnote;
use PhpOffice\PhpWord\Element\Image;
use PhpOffice\PhpWord\Element\Link;
use PhpOffice\PhpWord\Element\ListItem;
use PhpOffice\PhpWord\Element\Object;
use PhpOffice\PhpWord\Element\PageBreak;
use PhpOffice\PhpWord\Element\PreserveText;
use PhpOffice\PhpWord\Element\Table;
use PhpOffice\PhpWord\Element\Text;
use PhpOffice\PhpWord\Element\TextBreak;
use PhpOffice\PhpWord\Element\TextRun;
use PhpOffice\PhpWord\Element\Title;
use PhpOffice\PhpWord\Endnotes;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Footnotes;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Style\Paragraph;
/**
* HTML writer
*
* @since 0.10.0
*/
class HTML extends AbstractWriter implements WriterInterface
{
/**
* Is the current writer creating PDF?
*
* @var boolean
*/
protected $isPdf = false;
/**
* Footnotes and endnotes collection
*
* @var array
*/
protected $notes = array();
/**
* Create new instance
*/
public function __construct(PhpWord $phpWord = null)
{
$this->setPhpWord($phpWord);
}
/**
* Save PhpWord to file
*
* @param string $filename
* @throws Exception
*/
public function save($filename = null)
{
if (!is_null($this->getPhpWord())) {
$this->setTempDir(sys_get_temp_dir() . '/PHPWordWriter/');
$hFile = fopen($filename, 'w') or die("can't open file");
fwrite($hFile, $this->writeDocument());
fclose($hFile);
$this->clearTempDir();
} else {
throw new Exception("No PHPWord assigned.");
}
}
/**
* Get phpWord data
*
* @return string
*/
public function writeDocument()
{
$html = '';
$html .= '<!DOCTYPE html>' . PHP_EOL;
$html .= '<!-- Generated by PHPWord -->' . PHP_EOL;
$html .= '<html>' . PHP_EOL;
$html .= '<head>' . PHP_EOL;
$html .= $this->writeHTMLHead();
$html .= '</head>' . PHP_EOL;
$html .= '<body>' . PHP_EOL;
$html .= $this->writeHTMLBody();
$html .= $this->writeNotes();
$html .= '</body>' . PHP_EOL;
$html .= '</html>' . PHP_EOL;
return $html;
}
/**
* Generate HTML header
*
* @return string
*/
private function writeHTMLHead()
{
$properties = $this->getPhpWord()->getDocumentProperties();
$propertiesMapping = array(
'creator' => 'author',
'title' => '',
'description' => '',
'subject' => '',
'keywords' => '',
'category' => '',
'company' => '',
'manager' => ''
);
$title = $properties->getTitle();
$title = ($title != '') ? $title : 'PHPWord';
$html = '';
$html .= '<meta charset="UTF-8" />' . PHP_EOL;
$html .= '<title>' . htmlspecialchars($title) . '</title>' . PHP_EOL;
foreach ($propertiesMapping as $key => $value) {
$value = ($value == '') ? $key : $value;
$method = "get" . $key;
if ($properties->$method() != '') {
$html .= '<meta name="' . $value . '" content="' .
htmlspecialchars($properties->$method()) . '" />' . PHP_EOL;
}
}
$html .= $this->writeStyles();
return $html;
}
/**
* Get content
*
* @return string
*/
private function writeHTMLBody()
{
$phpWord = $this->getPhpWord();
$html = '';
$sections = $phpWord->getSections();
$countSections = count($sections);
$pSection = 0;
if ($countSections > 0) {
foreach ($sections as $section) {
$pSection++;
$contents = $section->getElements();
foreach ($contents as $element) {
if ($element instanceof Text) {
$html .= $this->writeText($element);
} elseif ($element instanceof TextRun) {
$html .= $this->writeTextRun($element);
} elseif ($element instanceof Link) {
$html .= $this->writeLink($element);
} elseif ($element instanceof Title) {
$html .= $this->writeTitle($element);
} elseif ($element instanceof PreserveText) {
$html .= $this->writePreserveText($element);
} elseif ($element instanceof TextBreak) {
$html .= $this->writeTextBreak($element);
} elseif ($element instanceof PageBreak) {
$html .= $this->writePageBreak($element);
} elseif ($element instanceof Table) {
$html .= $this->writeTable($element);
} elseif ($element instanceof ListItem) {
$html .= $this->writeListItem($element);
} elseif ($element instanceof Image) {
$html .= $this->writeImage($element);
} elseif ($element instanceof Object) {
$html .= $this->writeObject($element);
} elseif ($element instanceof Endnote) {
$html .= $this->writeEndnote($element);
} elseif ($element instanceof Footnote) {
$html .= $this->writeFootnote($element);
}
}
}
}
return $html;
}
/**
* Write footnote/endnote contents
*/
private function writeNotes()
{
$footnote = Footnotes::getElements();
$endnote = Endnotes::getElements();
$html = '';
if (count($this->notes) > 0) {
$html .= "<hr />";
foreach ($this->notes as $noteId => $noteMark) {
$noteAnchor = "note-{$noteId}";
list($noteType, $noteTypeId) = explode('-', $noteMark);
$collection = $$noteType;
if (array_key_exists($noteTypeId, $collection)) {
$element = $collection[$noteTypeId];
$content = "<a href=\"#{$noteMark}\" class=\"NoteRef\"><sup>{$noteId}</sup></a>" . $this->writeTextRun($element, true);
$html .= "<p><a name=\"{$noteAnchor}\" />{$content}</p>" . PHP_EOL;
}
}
}
return $html;
}
/**
* Get text
*
* @param Text $text
* @param boolean $withoutP
* @return string
*/
private function writeText($text, $withoutP = false)
{
$html = '';
$paragraphStyle = $text->getParagraphStyle();
$spIsObject = ($paragraphStyle instanceof Paragraph);
$fontStyle = $text->getFontStyle();
$sfIsObject = ($fontStyle instanceof Font);
if ($paragraphStyle && !$withoutP) {
$html .= '<p';
if (!$spIsObject) {
$html .= ' class="' . $paragraphStyle . '"';
} else {
$html .= ' style="' . $this->writeParagraphStyle($paragraphStyle) . '"';
}
$html .= '>';
}
if ($fontStyle) {
$html .= '<span';
if (!$sfIsObject) {
$html .= ' class="' . $fontStyle . '"';
} else {
$html .= ' style="' . $this->writeFontStyle($fontStyle) . '"';
}
$html .= '>';
}
$html .= htmlspecialchars($text->getText());
if ($fontStyle) {
$html .= '</span>';
}
if ($paragraphStyle && !$withoutP) {
$html .= '</p>' . PHP_EOL;
}
return $html;
}
/**
* Write text run content
*
* @param TextRun|Footnote|Endnote $textrun
* @return string
*/
private function writeTextRun($textrun, $withoutP = false)
{
$html = '';
$elements = $textrun->getElements();
if (count($elements) > 0) {
$paragraphStyle = $textrun->getParagraphStyle();
$spIsObject = ($paragraphStyle instanceof Paragraph);
$html .= $withoutP ? '<span' : '<p';
if ($paragraphStyle) {
if (!$spIsObject) {
$html .= ' class="' . $paragraphStyle . '"';
} else {
$html .= ' style="' . $this->writeParagraphStyle($paragraphStyle) . '"';
}
}
$html .= '>';
foreach ($elements as $element) {
if ($element instanceof Text) {
$html .= $this->writeText($element, true);
} elseif ($element instanceof Link) {
$html .= $this->writeLink($element, true);
} elseif ($element instanceof TextBreak) {
$html .= $this->writeTextBreak($element, true);
} elseif ($element instanceof Image) {
$html .= $this->writeImage($element, true);
} elseif ($element instanceof Endnote) {
$html .= $this->writeEndnote($element);
} elseif ($element instanceof Footnote) {
$html .= $this->writeFootnote($element);
}
}
$html .= $withoutP ? '</span>' : '</p>';
$html .= PHP_EOL;
}
return $html;
}
/**
* Write link
*
* @param Link $element
* @param boolean $withoutP
* @return string
*/
private function writeLink($element, $withoutP = false)
{
$url = $element->getLinkSrc();
$text = $element->getLinkName();
if ($text == '') {
$text = $url;
}
$html = '';
if (!$withoutP) {
$html .= "<p>" . PHP_EOL;
}
$html .= "<a href=\"{$url}\">{$text}</a>" . PHP_EOL;
if (!$withoutP) {
$html .= "</p>" . PHP_EOL;
}
return $html;
}
/**
* Write heading
*
* @param Title $element
* @return string
*/
private function writeTitle($element)
{
$tag = 'h' . $element->getDepth();
$text = htmlspecialchars($element->getText());
$html = "<{$tag}>{$text}</{$tag}>" . PHP_EOL;
return $html;
}
/**
* Write preserve text
*
* @param PreserveText $element
* @param boolean $withoutP
* @return string
*/
private function writePreserveText($element, $withoutP = false)
{
return $this->writeUnsupportedElement($element, $withoutP);
}
/**
* Get text break
*
* @param TextBreak $element
* @param boolean $withoutP
* @return string
*/
private function writeTextBreak($element, $withoutP = false)
{
if ($withoutP) {
$html = '<br />' . PHP_EOL;
} else {
$html = '<p>&nbsp;</p>' . PHP_EOL;
}
return $html;
}
/**
* Write page break
*
* @param PageBreak $element
* @return string
*/
private function writePageBreak($element)
{
return $this->writeUnsupportedElement($element, false);
}
/**
* Write list item
*
* @param ListItem $element
* @return string
*/
private function writeListItem($element)
{
$text = htmlspecialchars($element->getTextObject()->getText());
$html = '<p>' . $text . '</{$p}>' . PHP_EOL;
return $html;
}
/**
* Write table
*
* @param Table $element
* @return string
*/
private function writeTable($element)
{
$html = '';
$rows = $element->getRows();
$cRows = count($rows);
if ($cRows > 0) {
$html .= "<table>" . PHP_EOL;
foreach ($rows as $row) {
// $height = $row->getHeight();
$rowStyle = $row->getStyle();
$tblHeader = $rowStyle->getTblHeader();
$html .= "<tr>" . PHP_EOL;
foreach ($row->getCells() as $cell) {
$cellTag = $tblHeader ? 'th' : 'td';
$cellContents = $cell->getElements();
$html .= "<{$cellTag}>" . PHP_EOL;
if (count($cellContents) > 0) {
foreach ($cellContents as $content) {
if ($content instanceof Text) {
$html .= $this->writeText($content);
} elseif ($content instanceof TextRun) {
$html .= $this->writeTextRun($content);
} elseif ($content instanceof Link) {
$html .= $this->writeLink($content);
} elseif ($content instanceof PreserveText) {
$html .= $this->writePreserveText($content);
} elseif ($content instanceof TextBreak) {
$html .= $this->writeTextBreak($content);
} elseif ($content instanceof ListItem) {
$html .= $this->writeListItem($content);
} elseif ($content instanceof Image) {
$html .= $this->writeImage($content);
} elseif ($content instanceof Object) {
$html .= $this->writeObject($content);
} elseif ($element instanceof Endnote) {
$html .= $this->writeEndnote($element);
} elseif ($element instanceof Footnote) {
$html .= $this->writeFootnote($element);
}
}
} else {
$html .= $this->writeTextBreak(new TextBreak());
}
$html .= "</td>" . PHP_EOL;
}
$html .= "</tr>" . PHP_EOL;
}
$html .= "</table>" . PHP_EOL;
}
return $html;
}
/**
* Write image
*
* @param Image $element
* @param boolean $withoutP
* @return string
*/
private function writeImage($element, $withoutP = false)
{
$html = $this->writeUnsupportedElement($element, $withoutP);
if (!$this->isPdf) {
$imageData = $this->getBase64ImageData($element);
if (!is_null($imageData)) {
$style = $this->assembleCss(array(
'width' => $element->getStyle()->getWidth() . 'px',
'height' => $element->getStyle()->getHeight() . 'px',
));
$html = "<img border=\"0\" style=\"{$style}\" src=\"{$imageData}\"/>";
if (!$withoutP) {
$html = "<p>{$html}</p>" . PHP_EOL;
}
}
}
return $html;
}
/**
* Write object
*
* @param Object $element
* @param boolean $withoutP
* @return string
*/
private function writeObject($element, $withoutP = false)
{
return $this->writeUnsupportedElement($element, $withoutP);
}
/**
* Write footnote
*
* @param Footnote $element
* @return string
*/
private function writeFootnote($element)
{
return $this->writeNote($element);
}
/**
* Write endnote
*
* @param Endnote $element
* @return string
*/
private function writeEndnote($element)
{
return $this->writeNote($element);
}
/**
* Write footnote/endnote marks
*
* @param Footnote|Endnote $element
* @return string
*/
private function writeNote($element)
{
$index = count($this->notes) + 1;
$prefix = ($element instanceof Endnote) ? 'endnote' : 'footnote';
$noteMark = $prefix . '-' . $element->getRelationId();
$noteAnchor = "note-{$index}";
$this->notes[$index] = $noteMark;
$html = "<a name=\"{$noteMark}\"><a href=\"#{$noteAnchor}\" class=\"NoteRef\"><sup>{$index}</sup></a>";
return $html;
}
/**
* Write unsupported element
*
* @param mixed $element
* @param boolean $withoutP
* @return string
*/
private function writeUnsupportedElement($element, $withoutP = false)
{
$elementClass = get_class($element);
$elementMark = str_replace('PhpOffice\\PhpWord\\Element\\', '', $elementClass);
$elementMark = htmlentities("<{$elementMark}>");
if ($withoutP) {
$html = "<span class=\"other-elm\">{$elementMark}</span>" . PHP_EOL;
} else {
$html = "<p>{$elementMark}</p>" . PHP_EOL;
}
return $html;
}
/**
* Get styles
*
* @return string
*/
private function writeStyles()
{
$css = '<style>' . PHP_EOL;
// Default styles
$defaultStyles = array(
'*' => array(
'font-family' => $this->getPhpWord()->getDefaultFontName(),
'font-size' => $this->getPhpWord()->getDefaultFontSize() . 'pt',
),
'a.NoteRef' => array(
'text-decoration' => 'none',
),
'hr' => array(
'height' => '1px',
'padding' => '0',
'margin' => '1em 0',
'border' => '0',
'border-top' => '1px solid #CCC',
),
);
foreach ($defaultStyles as $selector => $style) {
$css .= $selector . ' ' . $this->assembleCss($style, true) . PHP_EOL;
}
// Custom styles
$customStyles = Style::getStyles();
if (is_array($customStyles)) {
foreach ($customStyles as $name => $style) {
if ($style instanceof Font) {
if ($style->getStyleType() == 'title') {
$name = str_replace('Heading_', 'h', $name);
} else {
$name = '.' . $name;
}
$css .= "{$name} " . $this->writeFontStyle($style, true) . PHP_EOL;
} elseif ($style instanceof Paragraph) {
$name = '.' . $name;
$css .= "{$name} " . $this->writeParagraphStyle($style, true) . PHP_EOL;
}
}
}
$css .= '</style>' . PHP_EOL;
return $css;
}
/**
* Get font style
*
* @param Font $style
* @param boolean $curlyBracket
* @return string
*/
private function writeFontStyle($style, $curlyBracket = false)
{
$css = array();
if (PHPWord::DEFAULT_FONT_NAME != $style->getName()) {
$css['font-family'] = "'" . $style->getName() . "'";
}
if (PHPWord::DEFAULT_FONT_SIZE != $style->getSize()) {
$css['font-size'] = $style->getSize() . 'pt';
}
if (PHPWord::DEFAULT_FONT_COLOR != $style->getColor()) {
$css['color'] = '#' . $style->getColor();
}
$css['background'] = $style->getFgColor();
if ($style->getBold()) {
$css['font-weight'] = 'bold';
}
if ($style->getItalic()) {
$css['font-style'] = 'italic';
}
if ($style->getSuperScript()) {
$css['vertical-align'] = 'super';
} elseif ($style->getSubScript()) {
$css['vertical-align'] = 'sub';
}
$css['text-decoration'] = '';
if ($style->getUnderline() != Font::UNDERLINE_NONE) {
$css['text-decoration'] .= 'underline ';
}
if ($style->getStrikethrough()) {
$css['text-decoration'] .= 'line-through ';
}
return $this->assembleCss($css, $curlyBracket);
}
/**
* Get paragraph style
*
* @param Paragraph $style
* @param boolean $curlyBracket
* @return string
*/
private function writeParagraphStyle($style, $curlyBracket = false)
{
$css = array();
if ($style->getAlign()) {
$css['text-align'] = $style->getAlign();
}
return $this->assembleCss($css, $curlyBracket);
}
/**
* Takes array where of CSS properties / values and converts to CSS string
*
* @param array $css
* @param boolean $curlyBracket
* @return string
*/
private function assembleCss($css, $curlyBracket = false)
{
$pairs = array();
foreach ($css as $key => $value) {
if ($value != '') {
$pairs[] = $key . ': ' . $value;
}
}
$string = implode('; ', $pairs);
if ($curlyBracket) {
$string = '{ ' . $string . ' }';
}
return $string;
}
/**
* Get Base64 image data
*
* @return string|null
*/
private function getBase64ImageData(Image $element)
{
$imageData = null;
$imageBinary = null;
$source = $element->getSource();
$imageType = $element->getImageType();
// Get actual source from archive image
if ($element->getSourceType() == Image::SOURCE_ARCHIVE) {
$source = substr($source, 6);
list($zipFilename, $imageFilename) = explode('#', $source);
$zip = new \ZipArchive();
if ($zip->open($zipFilename) !== false) {
if ($zip->locateName($imageFilename)) {
$zip->extractTo($this->getTempDir(), $imageFilename);
$actualSource = $this->getTempDir() . DIRECTORY_SEPARATOR . $imageFilename;
}
}
$zip->close();
} else {
$actualSource = $source;
}
// Read image binary data and convert into Base64
if ($element->getSourceType() == Image::SOURCE_GD) {
$imageResource = call_user_func($element->getImageCreateFunction(), $actualSource);
ob_start();
call_user_func($element->getImageFunction(), $imageResource);
$imageBinary = ob_get_contents();
ob_end_clean();
} else {
if ($fp = fopen($actualSource, 'rb', false)) {
$imageBinary = fread($fp, filesize($actualSource));
fclose($fp);
}
}
if (!is_null($imageBinary)) {
$base64 = chunk_split(base64_encode($imageBinary));
$imageData = 'data:' . $imageType . ';base64,' . $base64;
}
return $imageData;
}
}

View File

@ -17,7 +17,7 @@ use PhpOffice\PhpWord\Shared\XMLWriter;
/** /**
* ODT base part writer * ODT base part writer
* *
* @since 0.9.2 * @since 0.10.0
*/ */
class Base extends AbstractWriterPart class Base extends AbstractWriterPart
{ {

View File

@ -24,7 +24,6 @@ use PhpOffice\PhpWord\Shared\XMLWriter;
use PhpOffice\PhpWord\Style\Font; use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Style\Paragraph; use PhpOffice\PhpWord\Style\Paragraph;
use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\TOC;
/** /**
* ODText content part writer * ODText content part writer
@ -95,10 +94,311 @@ class Content extends Base
} }
} }
// office:font-face-decls
$this->writeFontFaces($xmlWriter);
// office:automatic-styles $this->writeFontFaces($xmlWriter); // office:font-face-decls
$this->writeAutomaticStyles($xmlWriter); // office:automatic-styles
// Tables
$sections = $phpWord->getSections();
$countSections = count($sections);
if ($countSections > 0) {
$sectionId = 0;
foreach ($sections as $section) {
$sectionId++;
$elements = $section->getElements();
foreach ($elements as $element) {
if ($elements instanceof Table) {
$xmlWriter->startElement('style:style');
$xmlWriter->writeAttribute('style:name', $element->getElementId());
$xmlWriter->writeAttribute('style:family', 'table');
$xmlWriter->startElement('style:table-properties');
//$xmlWriter->writeAttribute('style:width', 'table');
$xmlWriter->writeAttribute('style:rel-width', 100);
$xmlWriter->writeAttribute('table:align', 'center');
$xmlWriter->endElement();
$xmlWriter->endElement();
}
}
}
}
$xmlWriter->endElement();
// office:body
$xmlWriter->startElement('office:body');
// office:text
$xmlWriter->startElement('office:text');
// text:sequence-decls
$xmlWriter->startElement('text:sequence-decls');
// text:sequence-decl
$xmlWriter->startElement('text:sequence-decl');
$xmlWriter->writeAttribute('text:display-outline-level', 0);
$xmlWriter->writeAttribute('text:name', 'Illustration');
$xmlWriter->endElement();
// text:sequence-decl
$xmlWriter->startElement('text:sequence-decl');
$xmlWriter->writeAttribute('text:display-outline-level', 0);
$xmlWriter->writeAttribute('text:name', 'Table');
$xmlWriter->endElement();
// text:sequence-decl
$xmlWriter->startElement('text:sequence-decl');
$xmlWriter->writeAttribute('text:display-outline-level', 0);
$xmlWriter->writeAttribute('text:name', 'Text');
$xmlWriter->endElement();
// text:sequence-decl
$xmlWriter->startElement('text:sequence-decl');
$xmlWriter->writeAttribute('text:display-outline-level', 0);
$xmlWriter->writeAttribute('text:name', 'Drawing');
$xmlWriter->endElement();
$xmlWriter->endElement();
$sections = $phpWord->getSections();
$countSections = count($sections);
if ($countSections > 0) {
foreach ($sections as $section) {
$elements = $section->getElements();
foreach ($elements as $element) {
if ($element instanceof Text) {
$this->writeText($xmlWriter, $element);
} elseif ($element instanceof TextRun) {
$this->writeTextRun($xmlWriter, $element);
} elseif ($element instanceof Link) {
$this->writeLink($xmlWriter, $element);
} elseif ($element instanceof Title) {
$this->writeTitle($xmlWriter, $element);
} elseif ($element instanceof ListItem) {
$this->writeListItem($xmlWriter, $element);
} elseif ($element instanceof TextBreak) {
$this->writeTextBreak($xmlWriter);
} elseif ($element instanceof PageBreak) {
$this->writePageBreak($xmlWriter);
} elseif ($element instanceof Table) {
$this->writeTable($xmlWriter, $element);
} elseif ($element instanceof Image) {
$this->writeImage($xmlWriter, $element);
} elseif ($element instanceof Object) {
$this->writeObject($xmlWriter, $element);
}
}
}
}
$xmlWriter->endElement();
$xmlWriter->endElement();
$xmlWriter->endElement();
// Return
return $xmlWriter->getData();
}
/**
* Write text
*
* @param XMLWriter $xmlWriter
* @param Text $text
* @param bool $withoutP
*/
protected function writeText(XMLWriter $xmlWriter, Text $text, $withoutP = false)
{
$styleFont = $text->getFontStyle();
$styleParagraph = $text->getParagraphStyle();
// @todo Commented for TextRun. Should really checkout this value
// $SfIsObject = ($styleFont instanceof Font) ? true : false;
$SfIsObject = false;
if ($SfIsObject) {
// Don't never be the case, because I browse all sections for cleaning all styles not declared
die('PhpWord : $SfIsObject wouldn\'t be an object');
} else {
if (!$withoutP) {
$xmlWriter->startElement('text:p'); // text:p
}
if (empty($styleFont)) {
if (empty($styleParagraph)) {
$xmlWriter->writeAttribute('text:style-name', 'P1');
} elseif (is_string($styleParagraph)) {
$xmlWriter->writeAttribute('text:style-name', $styleParagraph);
}
$xmlWriter->writeRaw($text->getText());
} else {
if (empty($styleParagraph)) {
$xmlWriter->writeAttribute('text:style-name', 'Standard');
} elseif (is_string($styleParagraph)) {
$xmlWriter->writeAttribute('text:style-name', $styleParagraph);
}
// text:span
$xmlWriter->startElement('text:span');
if (is_string($styleFont)) {
$xmlWriter->writeAttribute('text:style-name', $styleFont);
}
$xmlWriter->writeRaw($text->getText());
$xmlWriter->endElement();
}
if (!$withoutP) {
$xmlWriter->endElement(); // text:p
}
}
}
/**
* Write TextRun section
*
* @param XMLWriter $xmlWriter
* @param TextRun $textrun
* @todo Enable all other section types
*/
protected function writeTextRun(XMLWriter $xmlWriter, TextRun $textrun)
{
$elements = $textrun->getElements();
$xmlWriter->startElement('text:p');
if (count($elements) > 0) {
foreach ($elements as $element) {
if ($element instanceof Text) {
$this->writeText($xmlWriter, $element, true);
}
}
}
$xmlWriter->endElement();
}
/**
* Write link element
*
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
*/
protected function writeLink(XMLWriter $xmlWriter, Link $link)
{
$this->writeUnsupportedElement($xmlWriter, 'Link');
}
/**
* Write title element
*/
protected function writeTitle(XMLWriter $xmlWriter, Title $title)
{
$this->writeUnsupportedElement($xmlWriter, 'Title');
}
/**
* Write preserve text
*/
protected function writePreserveText(XMLWriter $xmlWriter, PreserveText $preservetext)
{
$this->writeUnsupportedElement($xmlWriter, 'PreserveText');
}
/**
* Write list item
*/
protected function writeListItem(XMLWriter $xmlWriter, ListItem $listItem)
{
$this->writeUnsupportedElement($xmlWriter, 'ListItem');
}
/**
* Write text break
*/
protected function writeTextBreak(XMLWriter $xmlWriter)
{
$xmlWriter->startElement('text:p');
$xmlWriter->writeAttribute('text:style-name', 'Standard');
$xmlWriter->endElement();
}
/**
* Write page break
*/
protected function writePageBreak(XMLWriter $xmlWriter)
{
$this->writeUnsupportedElement($xmlWriter, 'PageBreak');
}
/**
* Write table
*/
protected function writeTable(XMLWriter $xmlWriter, Table $table)
{
$rows = $table->getRows();
$rowCount = count($rows);
$colCount = $table->countColumns();
if ($rowCount > 0) {
$xmlWriter->startElement('table:table');
$xmlWriter->writeAttribute('table:name', $table->getElementId());
$xmlWriter->writeAttribute('table:style', $table->getElementId());
$xmlWriter->startElement('table:table-column');
$xmlWriter->writeAttribute('table:number-columns-repeated', $colCount);
$xmlWriter->endElement(); // table:table-column
foreach ($rows as $row) {
$xmlWriter->startElement('table:table-row');
foreach ($row->getCells() as $cell) {
$xmlWriter->startElement('table:table-cell');
$xmlWriter->writeAttribute('office:value-type', 'string');
$elements = $cell->getElements();
if (count($elements) > 0) {
foreach ($elements as $element) {
if ($element instanceof Text) {
$this->writeText($xmlWriter, $element);
} elseif ($element instanceof TextRun) {
$this->writeTextRun($xmlWriter, $element);
} elseif ($element instanceof ListItem) {
$this->writeListItem($xmlWriter, $element);
} elseif ($element instanceof TextBreak) {
$this->writeTextBreak($xmlWriter);
} elseif ($element instanceof Image) {
$this->writeImage($xmlWriter, $element);
} elseif ($element instanceof Object) {
$this->writeObject($xmlWriter, $element);
}
}
} else {
$this->writeTextBreak($xmlWriter);
}
$xmlWriter->endElement(); // table:table-cell
}
$xmlWriter->endElement(); // table:table-row
}
$xmlWriter->endElement(); // table:table
}
}
/**
* Write image
*/
protected function writeImage(XMLWriter $xmlWriter, Image $element)
{
$this->writeUnsupportedElement($xmlWriter, 'Image');
}
/**
* Write object
*/
protected function writeObject(XMLWriter $xmlWriter, Object $element)
{
$this->writeUnsupportedElement($xmlWriter, 'Object');
}
/**
* Write unsupported element
*
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param string $element
*/
private function writeUnsupportedElement(XMLWriter $xmlWriter, $element)
{
$xmlWriter->startElement('text:p');
$xmlWriter->writeRaw($element);
$xmlWriter->endElement();
}
/**
* Write automatic styles
*/
private function writeAutomaticStyles(XMLWriter $xmlWriter)
{
$xmlWriter->startElement('office:automatic-styles'); $xmlWriter->startElement('office:automatic-styles');
$styles = Style::getStyles(); $styles = Style::getStyles();
$numPStyles = 0; $numPStyles = 0;
@ -151,172 +451,5 @@ class Content extends Base
$xmlWriter->endElement(); $xmlWriter->endElement();
} }
} }
$xmlWriter->endElement();
// office:body
$xmlWriter->startElement('office:body');
// office:text
$xmlWriter->startElement('office:text');
// text:sequence-decls
$xmlWriter->startElement('text:sequence-decls');
// text:sequence-decl
$xmlWriter->startElement('text:sequence-decl');
$xmlWriter->writeAttribute('text:display-outline-level', 0);
$xmlWriter->writeAttribute('text:name', 'Illustration');
$xmlWriter->endElement();
// text:sequence-decl
$xmlWriter->startElement('text:sequence-decl');
$xmlWriter->writeAttribute('text:display-outline-level', 0);
$xmlWriter->writeAttribute('text:name', 'Table');
$xmlWriter->endElement();
// text:sequence-decl
$xmlWriter->startElement('text:sequence-decl');
$xmlWriter->writeAttribute('text:display-outline-level', 0);
$xmlWriter->writeAttribute('text:name', 'Text');
$xmlWriter->endElement();
// text:sequence-decl
$xmlWriter->startElement('text:sequence-decl');
$xmlWriter->writeAttribute('text:display-outline-level', 0);
$xmlWriter->writeAttribute('text:name', 'Drawing');
$xmlWriter->endElement();
$xmlWriter->endElement();
$sections = $phpWord->getSections();
$countSections = count($sections);
if ($countSections > 0) {
foreach ($sections as $section) {
$elements = $section->getElements();
foreach ($elements as $element) {
if ($element instanceof Text) {
$this->writeText($xmlWriter, $element);
} elseif ($element instanceof TextRun) {
$this->writeTextRun($xmlWriter, $element);
} elseif ($element instanceof TextBreak) {
$this->writeTextBreak($xmlWriter);
} elseif ($element instanceof Link) {
$this->writeUnsupportedElement($xmlWriter, 'Link');
} elseif ($element instanceof Title) {
$this->writeUnsupportedElement($xmlWriter, 'Title');
} elseif ($element instanceof PageBreak) {
$this->writeUnsupportedElement($xmlWriter, 'Page Break');
} elseif ($element instanceof Table) {
$this->writeUnsupportedElement($xmlWriter, 'Table');
} elseif ($element instanceof ListItem) {
$this->writeUnsupportedElement($xmlWriter, 'List Item');
} elseif ($element instanceof Image) {
$this->writeUnsupportedElement($xmlWriter, 'Image');
} elseif ($element instanceof Object) {
$this->writeUnsupportedElement($xmlWriter, 'Object');
} elseif ($element instanceof TOC) {
$this->writeUnsupportedElement($xmlWriter, 'TOC');
} else {
$this->writeUnsupportedElement($xmlWriter, 'Element');
}
}
}
}
$xmlWriter->endElement();
$xmlWriter->endElement();
$xmlWriter->endElement();
// Return
return $xmlWriter->getData();
}
/**
* Write text
*
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\Text $text
* @param bool $withoutP
*/
protected function writeText(XMLWriter $xmlWriter, Text $text, $withoutP = false)
{
$styleFont = $text->getFontStyle();
$styleParagraph = $text->getParagraphStyle();
// @todo Commented for TextRun. Should really checkout this value
// $SfIsObject = ($styleFont instanceof Font) ? true : false;
$SfIsObject = false;
if ($SfIsObject) {
// Don't never be the case, because I browse all sections for cleaning all styles not declared
die('PhpWord : $SfIsObject wouldn\'t be an object');
} else {
if (!$withoutP) {
$xmlWriter->startElement('text:p'); // text:p
}
if (empty($styleFont)) {
if (empty($styleParagraph)) {
$xmlWriter->writeAttribute('text:style-name', 'P1');
} elseif (is_string($styleParagraph)) {
$xmlWriter->writeAttribute('text:style-name', $styleParagraph);
}
$xmlWriter->writeRaw($text->getText());
} else {
if (empty($styleParagraph)) {
$xmlWriter->writeAttribute('text:style-name', 'Standard');
} elseif (is_string($styleParagraph)) {
$xmlWriter->writeAttribute('text:style-name', $styleParagraph);
}
// text:span
$xmlWriter->startElement('text:span');
if (is_string($styleFont)) {
$xmlWriter->writeAttribute('text:style-name', $styleFont);
}
$xmlWriter->writeRaw($text->getText());
$xmlWriter->endElement();
}
if (!$withoutP) {
$xmlWriter->endElement(); // text:p
}
}
}
/**
* Write TextRun section
*
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\TextRun $textrun
* @todo Enable all other section types
*/
protected function writeTextRun(XMLWriter $xmlWriter, TextRun $textrun)
{
$elements = $textrun->getElements();
$xmlWriter->startElement('text:p');
if (count($elements) > 0) {
foreach ($elements as $element) {
if ($element instanceof Text) {
$this->writeText($xmlWriter, $element, true);
}
}
}
$xmlWriter->endElement();
}
/**
* Write TextBreak
*
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
*/
protected function writeTextBreak(XMLWriter $xmlWriter)
{
$xmlWriter->startElement('text:p');
$xmlWriter->writeAttribute('text:style-name', 'Standard');
$xmlWriter->endElement();
}
/**
* Write unsupported element
*
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param string $element
*/
private function writeUnsupportedElement($xmlWriter, $element)
{
$xmlWriter->startElement('text:p');
$xmlWriter->writeRaw($element);
$xmlWriter->endElement();
} }
} }

View File

@ -0,0 +1,66 @@
<?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\Writer;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings;
/**
* PDF Writer
*/
class PDF
{
/**
* The wrapper for the requested PDF rendering engine
*
* @var \PhpOffice\PhpWord\Writer\PDF\AbstractRenderer
*/
private $renderer = null;
/**
* Instantiate a new renderer of the configured type within this container class
*
* @param \PhpOffice\PhpWord\PhpWord $phpWord
*/
public function __construct(PhpWord $phpWord)
{
$pdfLibraryName = Settings::getPdfRendererName();
$pdfLibraryPath = Settings::getPdfRendererPath();
if (is_null($pdfLibraryName) || is_null($pdfLibraryPath)) {
throw new Exception("PDF rendering library or library path has not been defined.");
}
$includePath = str_replace('\\', '/', get_include_path());
$rendererPath = str_replace('\\', '/', $pdfLibraryPath);
if (strpos($rendererPath, $includePath) === false) {
set_include_path(get_include_path() . PATH_SEPARATOR . $pdfLibraryPath);
}
$rendererName = 'PhpOffice\\PhpWord\\Writer\\PDF\\' . $pdfLibraryName;
$this->renderer = new $rendererName($phpWord);
}
/**
* Magic method to handle direct calls to the configured PDF renderer wrapper class.
*
* @param string $name Renderer library method name
* @param mixed[] $arguments Array of arguments to pass to the renderer method
* @return mixed Returned data from the PDF renderer wrapper method
*/
public function __call($name, $arguments)
{
if ($this->renderer === null) {
throw new Exception("PDF Rendering library has not been defined.");
}
return call_user_func_array(array($this->renderer, $name), $arguments);
}
}

View File

@ -0,0 +1,170 @@
<?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\Writer\PDF;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\PhpWord;
/**
* Abstract PDF renderer
*/
abstract class AbstractRenderer extends \PhpOffice\PhpWord\Writer\HTML
{
/**
* Temporary storage directory
*
* @var string
*/
protected $tempDir = '';
/**
* Font
*
* @var string
*/
protected $font;
/**
* Paper size
*
* @var int
*/
protected $paperSize = null;
/**
* Orientation
*
* @var string
*/
protected $orientation = null;
/**
* Temporary storage for Save Array Return type
*
* @var string
*/
private $saveArrayReturnType;
/**
* Paper Sizes xRef List
*
* @var array
*/
protected static $paperSizes = array(
9 => 'A4', // (210 mm by 297 mm)
);
/**
* Create new instance
*
* @param PhpWord $phpWord PhpWord object
*/
public function __construct(PhpWord $phpWord)
{
parent::__construct($phpWord);
}
/**
* Get Font
*
* @return string
*/
public function getFont()
{
return $this->font;
}
/**
* Set font. Examples:
* 'arialunicid0-chinese-simplified'
* 'arialunicid0-chinese-traditional'
* 'arialunicid0-korean'
* 'arialunicid0-japanese'
*
* @param string $fontName
*/
public function setFont($fontName)
{
$this->font = $fontName;
return $this;
}
/**
* Get Paper Size
*
* @return int
*/
public function getPaperSize()
{
return $this->paperSize;
}
/**
* Set Paper Size
*
* @param string $pValue Paper size = PAPERSIZE_A4
* @return self
*/
public function setPaperSize($pValue = 9)
{
$this->paperSize = $pValue;
return $this;
}
/**
* Get Orientation
*
* @return string
*/
public function getOrientation()
{
return $this->orientation;
}
/**
* Set Orientation
*
* @param string $pValue Page orientation ORIENTATION_DEFAULT
* @return self
*/
public function setOrientation($pValue = 'default')
{
$this->orientation = $pValue;
return $this;
}
/**
* Save PhpWord to PDF file, pre-save
*
* @param string $pFilename Name of the file to save as
* @return resource
*/
protected function prepareForSave($pFilename = null)
{
$fileHandle = fopen($pFilename, 'w');
if ($fileHandle === false) {
throw new Exception("Could not open file $pFilename for writing.");
}
$this->isPdf = true;
return $fileHandle;
}
/**
* Save PhpWord to PDF file, post-save
*
* @param resource $fileHandle
* @throws Exception
*/
protected function restoreStateAfterSave($fileHandle)
{
fclose($fileHandle);
}
}

View File

@ -0,0 +1,70 @@
<?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\Writer\PDF;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Exception\Exception;
/**
* DomPDF writer
*/
class DomPDF extends AbstractRenderer implements \PhpOffice\PhpWord\Writer\WriterInterface
{
/**
* Create new instance
*
* @param PhpWord $phpWord PhpWord object
*/
public function __construct(PhpWord $phpWord)
{
parent::__construct($phpWord);
$configFile = Settings::getPdfRendererPath() . '/dompdf_config.inc.php';
if (file_exists($configFile)) {
require_once $configFile;
} else {
throw new Exception('Unable to load PDF Rendering library');
}
}
/**
* Save PhpWord to file
*
* @param string $pFilename Name of the file to save as
* @throws Exception
*/
public function save($pFilename = null)
{
$fileHandle = parent::prepareForSave($pFilename);
// Default PDF paper size
$paperSize = 'A4';
$orientation = 'P';
$printPaperSize = 9;
if (isset(self::$paperSizes[$printPaperSize])) {
$paperSize = self::$paperSizes[$printPaperSize];
}
$orientation = ($orientation == 'L') ? 'landscape' : 'portrait';
// Create PDF
$pdf = new \DOMPDF();
$pdf->set_paper(strtolower($paperSize), $orientation);
$pdf->load_html($this->writeDocument());
$pdf->render();
// Write to file
fwrite($fileHandle, $pdf->output());
parent::restoreStateAfterSave($fileHandle);
}
}

View File

@ -9,17 +9,18 @@
namespace PhpOffice\PhpWord\Writer; namespace PhpOffice\PhpWord\Writer;
use PhpOffice\PhpWord\Element\Section;
use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Media;
use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Media;
use PhpOffice\PhpWord\Element\Section;
use PhpOffice\PhpWord\Writer\Word2007\ContentTypes; use PhpOffice\PhpWord\Writer\Word2007\ContentTypes;
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\Header;
use PhpOffice\PhpWord\Writer\Word2007\Notes; use PhpOffice\PhpWord\Writer\Word2007\Notes;
use PhpOffice\PhpWord\Writer\Word2007\Rels; use PhpOffice\PhpWord\Writer\Word2007\Numbering;
use PhpOffice\PhpWord\Writer\Word2007\Header;
use PhpOffice\PhpWord\Writer\Word2007\Styles; use PhpOffice\PhpWord\Writer\Word2007\Styles;
/** /**
@ -57,6 +58,7 @@ class Word2007 extends AbstractWriter implements WriterInterface
$this->writerParts['docprops'] = new DocProps(); $this->writerParts['docprops'] = new DocProps();
$this->writerParts['document'] = new Document(); $this->writerParts['document'] = new Document();
$this->writerParts['styles'] = new Styles(); $this->writerParts['styles'] = new Styles();
$this->writerParts['numbering'] = new Numbering();
$this->writerParts['header'] = new Header(); $this->writerParts['header'] = new Header();
$this->writerParts['footer'] = new Footer(); $this->writerParts['footer'] = new Footer();
$this->writerParts['footnotes'] = new Notes(); $this->writerParts['footnotes'] = new Notes();
@ -97,7 +99,6 @@ class Word2007 extends AbstractWriter implements WriterInterface
$this->addHeaderFooterMedia($objZip, 'footer'); $this->addHeaderFooterMedia($objZip, 'footer');
// Add header/footer contents // Add header/footer contents
$overrides = array();
$rId = Media::countElements('section') + 6; // @see Rels::writeDocRels for 6 first elements $rId = Media::countElements('section') + 6; // @see Rels::writeDocRels for 6 first elements
$sections = $this->phpWord->getSections(); $sections = $this->phpWord->getSections();
foreach ($sections as $section) { foreach ($sections as $section) {
@ -116,9 +117,9 @@ class Word2007 extends AbstractWriter implements WriterInterface
$objZip->addFromString('word/_rels/document.xml.rels', $this->getWriterPart('rels')->writeDocRels($this->docRels)); $objZip->addFromString('word/_rels/document.xml.rels', $this->getWriterPart('rels')->writeDocRels($this->docRels));
$objZip->addFromString('word/document.xml', $this->getWriterPart('document')->writeDocument($this->phpWord)); $objZip->addFromString('word/document.xml', $this->getWriterPart('document')->writeDocument($this->phpWord));
$objZip->addFromString('word/styles.xml', $this->getWriterPart('styles')->writeStyles($this->phpWord)); $objZip->addFromString('word/styles.xml', $this->getWriterPart('styles')->writeStyles($this->phpWord));
$objZip->addFromString('word/numbering.xml', $this->getWriterPart('numbering')->writeNumbering());
// Write static files // Write static files
$objZip->addFile(__DIR__ . '/../_staticDocParts/numbering.xml', 'word/numbering.xml');
$objZip->addFile(__DIR__ . '/../_staticDocParts/settings.xml', 'word/settings.xml'); $objZip->addFile(__DIR__ . '/../_staticDocParts/settings.xml', 'word/settings.xml');
$objZip->addFile(__DIR__ . '/../_staticDocParts/theme1.xml', 'word/theme/theme1.xml'); $objZip->addFile(__DIR__ . '/../_staticDocParts/theme1.xml', 'word/theme/theme1.xml');
$objZip->addFile(__DIR__ . '/../_staticDocParts/webSettings.xml', 'word/webSettings.xml'); $objZip->addFile(__DIR__ . '/../_staticDocParts/webSettings.xml', 'word/webSettings.xml');

View File

@ -279,7 +279,7 @@ class Base extends AbstractWriterPart
{ {
$textObject = $listItem->getTextObject(); $textObject = $listItem->getTextObject();
$depth = $listItem->getDepth(); $depth = $listItem->getDepth();
$listType = $listItem->getStyle()->getListType(); $numId = $listItem->getStyle()->getNumId();
$styleParagraph = $textObject->getParagraphStyle(); $styleParagraph = $textObject->getParagraphStyle();
$xmlWriter->startElement('w:p'); $xmlWriter->startElement('w:p');
@ -290,7 +290,7 @@ class Base extends AbstractWriterPart
$xmlWriter->writeAttribute('w:val', $depth); $xmlWriter->writeAttribute('w:val', $depth);
$xmlWriter->endElement(); // w:ilvl $xmlWriter->endElement(); // w:ilvl
$xmlWriter->startElement('w:numId'); $xmlWriter->startElement('w:numId');
$xmlWriter->writeAttribute('w:val', $listType); $xmlWriter->writeAttribute('w:val', $numId);
$xmlWriter->endElement(); // w:numId $xmlWriter->endElement(); // w:numId
$xmlWriter->endElement(); // w:numPr $xmlWriter->endElement(); // w:numPr
$xmlWriter->endElement(); // w:pPr $xmlWriter->endElement(); // w:pPr
@ -427,25 +427,22 @@ class Base extends AbstractWriterPart
$marginTop = $style->getMarginTop(); $marginTop = $style->getMarginTop();
$marginLeft = $style->getMarginLeft(); $marginLeft = $style->getMarginLeft();
$wrappingStyle = $style->getWrappingStyle(); $wrappingStyle = $style->getWrappingStyle();
$w10wrapType = null;
if (!$withoutP) { if (!$withoutP) {
$xmlWriter->startElement('w:p'); $xmlWriter->startElement('w:p');
if (!is_null($align)) { if (!is_null($align)) {
$xmlWriter->startElement('w:pPr'); $xmlWriter->startElement('w:pPr');
$xmlWriter->startElement('w:jc'); $xmlWriter->startElement('w:jc');
$xmlWriter->writeAttribute('w:val', $align); $xmlWriter->writeAttribute('w:val', $align);
$xmlWriter->endElement(); $xmlWriter->endElement(); // w:jc
$xmlWriter->endElement(); $xmlWriter->endElement(); // w:pPr
} }
} }
$xmlWriter->startElement('w:r'); $xmlWriter->startElement('w:r');
$xmlWriter->startElement('w:pict'); $xmlWriter->startElement('w:pict');
$xmlWriter->startElement('v:shape'); $xmlWriter->startElement('v:shape');
$xmlWriter->writeAttribute('type', '#_x0000_t75'); $xmlWriter->writeAttribute('type', '#_x0000_t75');
$imgStyle = ''; $imgStyle = '';
if (null !== $width) { if (null !== $width) {
$imgStyle .= 'width:' . $width . 'px;'; $imgStyle .= 'width:' . $width . 'px;';
@ -459,33 +456,38 @@ class Base extends AbstractWriterPart
if (null !== $marginLeft) { if (null !== $marginLeft) {
$imgStyle .= 'margin-left:' . $marginLeft . 'in;'; $imgStyle .= 'margin-left:' . $marginLeft . 'in;';
} }
switch ($wrappingStyle) { switch ($wrappingStyle) {
case ImageStyle::WRAPPING_STYLE_BEHIND: case ImageStyle::WRAPPING_STYLE_BEHIND:
$imgStyle .= 'position:absolute;z-index:-251658752;'; $imgStyle .= 'position:absolute;z-index:-251658752;';
break; break;
case ImageStyle::WRAPPING_STYLE_SQUARE: case ImageStyle::WRAPPING_STYLE_INFRONT:
$imgStyle .= 'position:absolute;z-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;'; $imgStyle .= 'position:absolute;z-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;';
break; break;
case ImageStyle::WRAPPING_STYLE_TIGHT: case ImageStyle::WRAPPING_STYLE_SQUARE:
$imgStyle .= 'position:absolute;z-index:251659264;mso-wrap-edited:f;mso-position-horizontal:absolute;mso-position-vertical:absolute'; $imgStyle .= 'position:absolute;z-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;';
$w10wrapType = 'square';
break; break;
case ImageStyle::WRAPPING_STYLE_INFRONT: case ImageStyle::WRAPPING_STYLE_TIGHT:
$imgStyle .= 'position:absolute;zz-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;'; $imgStyle .= 'position:absolute;z-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;';
$w10wrapType = 'tight';
break; break;
} }
$xmlWriter->writeAttribute('style', $imgStyle); $xmlWriter->writeAttribute('style', $imgStyle);
$xmlWriter->startElement('v:imagedata'); $xmlWriter->startElement('v:imagedata');
$xmlWriter->writeAttribute('r:id', 'rId' . $rId); $xmlWriter->writeAttribute('r:id', 'rId' . $rId);
$xmlWriter->writeAttribute('o:title', ''); $xmlWriter->writeAttribute('o:title', '');
$xmlWriter->endElement(); $xmlWriter->endElement(); // v:imagedata
$xmlWriter->endElement();
$xmlWriter->endElement(); if (!is_null($w10wrapType)) {
$xmlWriter->startElement('w10:wrap');
$xmlWriter->writeAttribute('type', $w10wrapType);
$xmlWriter->endElement(); // w10:wrap
}
$xmlWriter->endElement(); $xmlWriter->endElement(); // v:shape
$xmlWriter->endElement(); // w:pict
$xmlWriter->endElement(); // w:r
if (!$withoutP) { if (!$withoutP) {
$xmlWriter->endElement(); // w:p $xmlWriter->endElement(); // w:p

View File

@ -9,8 +9,8 @@
namespace PhpOffice\PhpWord\Writer\Word2007; namespace PhpOffice\PhpWord\Writer\Word2007;
use PhpOffice\PhpWord\Element\Endnote;
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;
/** /**
@ -69,7 +69,7 @@ class Notes extends Base
// Content // Content
foreach ($elements as $element) { foreach ($elements as $element) {
if ($element instanceof Footnote || $element instanceof Endnote) { if ($element instanceof Footnote || $element instanceof Endnote) {
$this->writeNote($xmlWriter, $element, null, $notesTypes); $this->writeNote($xmlWriter, $element, $notesTypes);
} }
} }
@ -83,10 +83,9 @@ class Notes extends Base
* *
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\Footnote|\PhpOffice\PhpWord\Element\Endnote $element * @param \PhpOffice\PhpWord\Element\Footnote|\PhpOffice\PhpWord\Element\Endnote $element
* @param boolean $withoutP * @param string $notesTypes
* @param string $notesTypes
*/ */
protected function writeNote(XMLWriter $xmlWriter, $element, $withoutP = false, $notesTypes = 'footnotes') protected function writeNote(XMLWriter $xmlWriter, $element, $notesTypes = 'footnotes')
{ {
$isFootnote = ($notesTypes == 'footnotes'); $isFootnote = ($notesTypes == 'footnotes');
$elementNode = $isFootnote ? 'w:footnote' : 'w:endnote'; $elementNode = $isFootnote ? 'w:footnote' : 'w:endnote';

View File

@ -0,0 +1,177 @@
<?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\Writer\Word2007;
use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Style\Numbering as NumberingStyle;
use PhpOffice\PhpWord\Style\NumberingLevel;
/**
* Word2007 numbering part writer
*/
class Numbering extends Base
{
/**
* Write word/numbering.xml
*/
public function writeNumbering()
{
$styles = Style::getStyles();
$xmlWriter = $this->getXmlWriter();
$xmlWriter->startDocument('1.0', 'UTF-8', 'yes');
$xmlWriter->startElement('w:numbering');
$xmlWriter->writeAttribute('xmlns:ve', 'http://schemas.openxmlformats.org/markup-compatibility/2006');
$xmlWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office');
$xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
$xmlWriter->writeAttribute('xmlns:m', 'http://schemas.openxmlformats.org/officeDocument/2006/math');
$xmlWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml');
$xmlWriter->writeAttribute('xmlns:wp', 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing');
$xmlWriter->writeAttribute('xmlns:w10', 'urn:schemas-microsoft-com:office:word');
$xmlWriter->writeAttribute('xmlns:w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main');
$xmlWriter->writeAttribute('xmlns:wne', 'http://schemas.microsoft.com/office/word/2006/wordml');
// Abstract numbering definitions
foreach ($styles as $style) {
if ($style instanceof NumberingStyle) {
$levels = $style->getLevels();
$xmlWriter->startElement('w:abstractNum');
$xmlWriter->writeAttribute('w:abstractNumId', $style->getNumId());
$xmlWriter->startElement('w:nsid');
$xmlWriter->writeAttribute('w:val', $this->getRandomHexNumber());
$xmlWriter->endElement(); // w:nsid
$xmlWriter->startElement('w:multiLevelType');
$xmlWriter->writeAttribute('w:val', $style->getType());
$xmlWriter->endElement(); // w:multiLevelType
if (is_array($levels)) {
foreach ($levels as $levelNum => $levelObject) {
if ($levelObject instanceof NumberingLevel) {
$start = $levelObject->getStart();
$format = $levelObject->getFormat();
$restart = $levelObject->getRestart();
$suffix = $levelObject->getSuffix();
$text = $levelObject->getText();
$align = $levelObject->getAlign();
$tabPos = $levelObject->getTabPos();
$left = $levelObject->getLeft();
$hanging = $levelObject->getHanging();
$font = $levelObject->getFont();
$hint = $levelObject->getHint();
$xmlWriter->startElement('w:lvl');
$xmlWriter->writeAttribute('w:ilvl', $levelNum);
if (!is_null($start)) {
$xmlWriter->startElement('w:start');
$xmlWriter->writeAttribute('w:val', $start);
$xmlWriter->endElement(); // w:start
}
if (!is_null($format)) {
$xmlWriter->startElement('w:numFmt');
$xmlWriter->writeAttribute('w:val', $format);
$xmlWriter->endElement(); // w:numFmt
}
if (!is_null($restart)) {
$xmlWriter->startElement('w:lvlRestart');
$xmlWriter->writeAttribute('w:val', $restart);
$xmlWriter->endElement(); // w:lvlRestart
}
if (!is_null($suffix)) {
$xmlWriter->startElement('w:suff');
$xmlWriter->writeAttribute('w:val', $suffix);
$xmlWriter->endElement(); // w:suff
}
if (!is_null($text)) {
$xmlWriter->startElement('w:lvlText');
$xmlWriter->writeAttribute('w:val', $text);
$xmlWriter->endElement(); // w:start
}
if (!is_null($align)) {
$xmlWriter->startElement('w:lvlJc');
$xmlWriter->writeAttribute('w:val', $align);
$xmlWriter->endElement(); // w:lvlJc
}
if (!is_null($tabPos) || !is_null($left) || !is_null($hanging)) {
$xmlWriter->startElement('w:pPr');
if (!is_null($tabPos)) {
$xmlWriter->startElement('w:tabs');
$xmlWriter->startElement('w:tab');
$xmlWriter->writeAttribute('w:val', 'num');
$xmlWriter->writeAttribute('w:pos', $tabPos);
$xmlWriter->endElement(); // w:tab
$xmlWriter->endElement(); // w:tabs
}
if (!is_null($left) || !is_null($hanging)) {
$xmlWriter->startElement('w:ind');
if (!is_null($left)) {
$xmlWriter->writeAttribute('w:left', $left);
}
if (!is_null($hanging)) {
$xmlWriter->writeAttribute('w:hanging', $hanging);
}
$xmlWriter->endElement(); // w:ind
}
$xmlWriter->endElement(); // w:pPr
}
if (!is_null($font) || !is_null($hint)) {
$xmlWriter->startElement('w:rPr');
$xmlWriter->startElement('w:rFonts');
if (!is_null($font)) {
$xmlWriter->writeAttribute('w:ascii', $font);
$xmlWriter->writeAttribute('w:hAnsi', $font);
$xmlWriter->writeAttribute('w:cs', $font);
}
if (!is_null($hint)) {
$xmlWriter->writeAttribute('w:hint', $hint);
}
$xmlWriter->endElement(); // w:rFonts
$xmlWriter->endElement(); // w:rPr
}
$xmlWriter->endElement(); // w:lvl
}
}
}
$xmlWriter->endElement(); // w:abstractNum
}
}
// Numbering definition instances
foreach ($styles as $style) {
if ($style instanceof NumberingStyle) {
$xmlWriter->startElement('w:num');
$xmlWriter->writeAttribute('w:numId', $style->getNumId());
$xmlWriter->startElement('w:abstractNumId');
$xmlWriter->writeAttribute('w:val', $style->getNumId());
$xmlWriter->endElement(); // w:abstractNumId
$xmlWriter->endElement(); // w:num
}
}
$xmlWriter->endElement();
return $xmlWriter->getData();
}
/**
* Get random hexadecimal number value
*
* @param int $length
* @return string
*/
private function getRandomHexNumber($length = 8)
{
return strtoupper(substr(md5(rand()), 0, $length));
}
}

View File

@ -15,7 +15,7 @@ use PhpOffice\PhpWord\Shared\XMLWriter;
/** /**
* Word2007 relationship writer * Word2007 relationship writer
* *
* @since 0.9.2 * @since 0.10.0
*/ */
class Rels extends AbstractWriterPart class Rels extends AbstractWriterPart
{ {

View File

@ -18,6 +18,8 @@ use PhpOffice\PhpWord\Style;
/** /**
* Word2007 styles part writer * Word2007 styles part writer
*
* @todo Do something with the numbering style introduced in 0.10.0
*/ */
class Styles extends Base class Styles extends Base
{ {
@ -38,37 +40,31 @@ class Styles extends Base
// XML header // XML header
$xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); $xmlWriter->startDocument('1.0', 'UTF-8', 'yes');
$xmlWriter->startElement('w:styles'); $xmlWriter->startElement('w:styles');
$xmlWriter->writeAttribute( $xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
'xmlns:r', $xmlWriter->writeAttribute('xmlns:w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main');
'http://schemas.openxmlformats.org/officeDocument/2006/relationships'
);
$xmlWriter->writeAttribute(
'xmlns:w',
'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
);
// Write default styles // Write default styles
$styles = Style::getStyles(); $styles = Style::getStyles();
$this->writeDefaultStyles($xmlWriter, $phpWord, $styles); $this->writeDefaultStyles($xmlWriter, $phpWord, $styles);
// Write other styles
// Write styles
if (count($styles) > 0) { if (count($styles) > 0) {
foreach ($styles as $styleName => $style) { foreach ($styles as $styleName => $style) {
if ($styleName == 'Normal') { if ($styleName == 'Normal') {
continue; continue;
} }
if ($style instanceof Font) {
// Font style
if ($style instanceof Font) {
$paragraphStyle = $style->getParagraphStyle(); $paragraphStyle = $style->getParagraphStyle();
$styleType = $style->getStyleType(); $styleType = $style->getStyleType();
$type = ($styleType == 'title') ? 'paragraph' : 'character'; $type = ($styleType == 'title') ? 'paragraph' : 'character';
if (!is_null($paragraphStyle)) { if (!is_null($paragraphStyle)) {
$type = 'paragraph'; $type = 'paragraph';
} }
$xmlWriter->startElement('w:style'); $xmlWriter->startElement('w:style');
$xmlWriter->writeAttribute('w:type', $type); $xmlWriter->writeAttribute('w:type', $type);
if ($styleType == 'title') { if ($styleType == 'title') {
$arrStyle = explode('_', $styleName); $arrStyle = explode('_', $styleName);
$styleId = 'Heading' . $arrStyle[1]; $styleId = 'Heading' . $arrStyle[1];
@ -80,11 +76,9 @@ class Styles extends Base
$xmlWriter->writeAttribute('w:val', $styleLink); $xmlWriter->writeAttribute('w:val', $styleLink);
$xmlWriter->endElement(); $xmlWriter->endElement();
} }
$xmlWriter->startElement('w:name'); $xmlWriter->startElement('w:name');
$xmlWriter->writeAttribute('w:val', $styleName); $xmlWriter->writeAttribute('w:val', $styleName);
$xmlWriter->endElement(); $xmlWriter->endElement();
if (!is_null($paragraphStyle)) { if (!is_null($paragraphStyle)) {
// Point parent style to Normal // Point parent style to Normal
$xmlWriter->startElement('w:basedOn'); $xmlWriter->startElement('w:basedOn');
@ -94,19 +88,17 @@ class Styles extends Base
} }
$this->writeFontStyle($xmlWriter, $style); $this->writeFontStyle($xmlWriter, $style);
$xmlWriter->endElement(); $xmlWriter->endElement();
// Paragraph style
} elseif ($style instanceof Paragraph) { } elseif ($style instanceof Paragraph) {
$xmlWriter->startElement('w:style'); $xmlWriter->startElement('w:style');
$xmlWriter->writeAttribute('w:type', 'paragraph'); $xmlWriter->writeAttribute('w:type', 'paragraph');
$xmlWriter->writeAttribute('w:customStyle', '1'); $xmlWriter->writeAttribute('w:customStyle', '1');
$xmlWriter->writeAttribute('w:styleId', $styleName); $xmlWriter->writeAttribute('w:styleId', $styleName);
$xmlWriter->startElement('w:name'); $xmlWriter->startElement('w:name');
$xmlWriter->writeAttribute('w:val', $styleName); $xmlWriter->writeAttribute('w:val', $styleName);
$xmlWriter->endElement(); $xmlWriter->endElement();
// Parent style // Parent style
$basedOn = $style->getBasedOn(); $basedOn = $style->getBasedOn();
if (!is_null($basedOn)) { if (!is_null($basedOn)) {
@ -114,7 +106,6 @@ class Styles extends Base
$xmlWriter->writeAttribute('w:val', $basedOn); $xmlWriter->writeAttribute('w:val', $basedOn);
$xmlWriter->endElement(); $xmlWriter->endElement();
} }
// Next paragraph style // Next paragraph style
$next = $style->getNext(); $next = $style->getNext();
if (!is_null($next)) { if (!is_null($next)) {
@ -126,22 +117,20 @@ class Styles extends Base
$this->writeParagraphStyle($xmlWriter, $style); $this->writeParagraphStyle($xmlWriter, $style);
$xmlWriter->endElement(); $xmlWriter->endElement();
// Table style
} elseif ($style instanceof Table) { } elseif ($style instanceof Table) {
$xmlWriter->startElement('w:style'); $xmlWriter->startElement('w:style');
$xmlWriter->writeAttribute('w:type', 'table'); $xmlWriter->writeAttribute('w:type', 'table');
$xmlWriter->writeAttribute('w:customStyle', '1'); $xmlWriter->writeAttribute('w:customStyle', '1');
$xmlWriter->writeAttribute('w:styleId', $styleName); $xmlWriter->writeAttribute('w:styleId', $styleName);
$xmlWriter->startElement('w:name'); $xmlWriter->startElement('w:name');
$xmlWriter->writeAttribute('w:val', $styleName); $xmlWriter->writeAttribute('w:val', $styleName);
$xmlWriter->endElement(); $xmlWriter->endElement();
$xmlWriter->startElement('w:uiPriority'); $xmlWriter->startElement('w:uiPriority');
$xmlWriter->writeAttribute('w:val', '99'); $xmlWriter->writeAttribute('w:val', '99');
$xmlWriter->endElement(); $xmlWriter->endElement();
$this->writeTableStyle($xmlWriter, $style); $this->writeTableStyle($xmlWriter, $style);
$xmlWriter->endElement(); // w:style $xmlWriter->endElement(); // w:style
} }
} }
@ -149,7 +138,6 @@ class Styles extends Base
$xmlWriter->endElement(); // w:styles $xmlWriter->endElement(); // w:styles
// Return
return $xmlWriter->getData(); return $xmlWriter->getData();
} }

File diff suppressed because one or more lines are too long

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\Element;
/**
* Test class for PhpOffice\PhpWord\Element\AbstractElement
*
* @runTestsInSeparateProcesses
*/
class AbstractElementTest extends \PHPUnit_Framework_TestCase
{
/**
* Test set/get element index
*/
public function testElementIndex()
{
$stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Element\AbstractElement');
$ival = rand(0, 100);
$stub->setElementIndex($ival);
$this->assertEquals($stub->getElementIndex(), $ival);
}
/**
* Test set/get element unique Id
*/
public function testElementId()
{
$stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Element\AbstractElement');
$stub->setElementId();
$this->assertEquals(strlen($stub->getElementId()), 6);
}
}

View File

@ -51,34 +51,29 @@ class ImageTest extends \PHPUnit_Framework_TestCase
/** /**
* Valid image types * Valid image types
*/ */
public function testValidImageTypes() public function testImages()
{ {
new Image(__DIR__ . "/../_files/images/mars_noext_jpg"); $images = array(
new Image(__DIR__ . "/../_files/images/mars.jpg"); array('mars.jpg', 'image/jpeg', 'jpg', 'imagecreatefromjpeg', 'imagejpeg'),
new Image(__DIR__ . "/../_files/images/mario.gif"); array('mario.gif', 'image/gif', 'gif', 'imagecreatefromgif', 'imagegif'),
new Image(__DIR__ . "/../_files/images/firefox.png"); array('firefox.png', 'image/png', 'png', 'imagecreatefrompng', 'imagepng'),
new Image(__DIR__ . "/../_files/images/duke_nukem.bmp"); array('duke_nukem.bmp', 'image/bmp', 'bmp', null, null),
new Image(__DIR__ . "/../_files/images/angela_merkel.tif"); array('angela_merkel.tif', 'image/tiff', 'tif', null, null),
} );
/** foreach ($images as $imageData) {
* Image not found list($source, $type, $extension, $createFunction, $imageFunction) = $imageData;
* $source = __DIR__ . "/../_files/images/" . $source;
* @expectedException \PhpOffice\PhpWord\Exception\InvalidImageException $image = new Image($source);
*/ $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $image);
public function testImageNotFound() $this->assertEquals($image->getSource(), $source);
{ $this->assertEquals($image->getMediaId(), md5($source));
new Image(__DIR__ . "/../_files/images/thisisnotarealimage"); $this->assertEquals($image->getImageType(), $type);
} $this->assertEquals($image->getImageExtension(), $extension);
$this->assertEquals($image->getImageCreateFunction(), $createFunction);
/** $this->assertEquals($image->getImageFunction(), $imageFunction);
* Invalid image types $this->assertFalse($image->getIsMemImage());
* }
* @expectedException \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException
*/
public function testInvalidImageTypes()
{
new Image(__DIR__ . "/../_files/images/alexz-johnson.pcx");
} }
/** /**
@ -88,118 +83,61 @@ class ImageTest extends \PHPUnit_Framework_TestCase
{ {
$oImage = new Image( $oImage = new Image(
__DIR__ . "/../_files/images/earth.jpg", __DIR__ . "/../_files/images/earth.jpg",
array('width' => 210, 'height' => 210, 'align' => 'center') array('height' => 210, 'align' => 'center')
); );
$this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Image', $oImage->getStyle()); $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Image', $oImage->getStyle());
} }
/**
* Test invalid local image
*
* @expectedException \PhpOffice\PhpWord\Exception\InvalidImageException
*/
public function testInvalidImageLocal()
{
new Image(__DIR__ . "/../_files/images/thisisnotarealimage");
}
/**
* Test invalid PHP Image
*
* @expectedException \PhpOffice\PhpWord\Exception\InvalidImageException
*/
public function testInvalidImagePhp()
{
$object = new Image('test.php');
}
/**
* Test unsupported image
*
* @expectedException \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException
*/
public function testUnsupportedImage()
{
$object = new Image('http://samples.libav.org/image-samples/RACECAR.BMP');
}
/** /**
* Get relation Id * Get relation Id
*/ */
public function testRelationID() public function testRelationID()
{ {
$oImage = new Image(__DIR__ . "/../_files/images/earth.jpg"); $oImage = new Image(__DIR__ . "/../_files/images/earth.jpg", array('width' => 100));
$iVal = rand(1, 1000); $iVal = rand(1, 1000);
$oImage->setRelationId($iVal); $oImage->setRelationId($iVal);
$this->assertEquals($oImage->getRelationId(), $iVal); $this->assertEquals($oImage->getRelationId(), $iVal);
} }
/** /**
* Get is watermark * Test archived image
*/ */
public function testWatermark() public function testArchivedImage()
{ {
$oImage = new Image(__DIR__ . "/../_files/images/earth.jpg"); $archiveFile = __DIR__ . "/../_files/documents/reader.docx";
$oImage->setIsWatermark(true); $imageFile = 'word/media/image1.jpeg';
$this->assertEquals($oImage->getIsWatermark(), true); $image = new Image("zip://{$archiveFile}#{$imageFile}");
} $this->assertEquals('image/jpeg', $image->getImageType());
/**
* Test PNG
*/
public function testPNG()
{
$src = __DIR__ . "/../_files/images/firefox.png";
$oImage = new Image($src);
$this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $oImage);
$this->assertEquals($oImage->getSource(), $src);
$this->assertEquals($oImage->getMediaId(), md5($src));
$this->assertEquals($oImage->getImageCreateFunction(), 'imagecreatefrompng');
$this->assertEquals($oImage->getImageFunction(), 'imagepng');
$this->assertEquals($oImage->getImageExtension(), 'png');
$this->assertEquals($oImage->getImageType(), 'image/png');
}
/**
* Test GIF
*/
public function testGIF()
{
$src = __DIR__ . "/../_files/images/mario.gif";
$oImage = new Image($src);
$this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $oImage);
$this->assertEquals($oImage->getSource(), $src);
$this->assertEquals($oImage->getMediaId(), md5($src));
$this->assertEquals($oImage->getImageCreateFunction(), 'imagecreatefromgif');
$this->assertEquals($oImage->getImageFunction(), 'imagegif');
$this->assertEquals($oImage->getImageExtension(), 'gif');
$this->assertEquals($oImage->getImageType(), 'image/gif');
}
/**
* Test JPG
*/
public function testJPG()
{
$src = __DIR__ . "/../_files/images/earth.jpg";
$oImage = new Image($src);
$this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $oImage);
$this->assertEquals($oImage->getSource(), $src);
$this->assertEquals($oImage->getMediaId(), md5($src));
$this->assertEquals($oImage->getImageCreateFunction(), 'imagecreatefromjpeg');
$this->assertEquals($oImage->getImageFunction(), 'imagejpeg');
$this->assertEquals($oImage->getImageExtension(), 'jpg');
$this->assertEquals($oImage->getImageType(), 'image/jpeg');
}
/**
* Test BMP
*/
public function testBMP()
{
$oImage = new Image(__DIR__ . "/../_files/images/duke_nukem.bmp");
$this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $oImage);
$this->assertEquals($oImage->getImageCreateFunction(), null);
$this->assertEquals($oImage->getImageFunction(), null);
$this->assertEquals($oImage->getImageExtension(), 'bmp');
$this->assertEquals($oImage->getImageType(), 'image/bmp');
}
/**
* Test TIFF
*/
public function testTIFF()
{
$oImage = new Image(__DIR__ . "/../_files/images/angela_merkel.tif");
$this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $oImage);
$this->assertEquals($oImage->getImageCreateFunction(), null);
$this->assertEquals($oImage->getImageFunction(), null);
$this->assertEquals($oImage->getImageType(), 'image/tiff');
}
/**
* Test PHP Image
*
* @expectedException \PhpOffice\PhpWord\Exception\InvalidImageException
*/
public function testPhpImage()
{
$object = new Image('test.php');
} }
} }

View File

@ -48,11 +48,11 @@ class TableTest extends \PHPUnit_Framework_TestCase
*/ */
public function testStyleArray() public function testStyleArray()
{ {
$oTable = new Table( $oTable = new Table('section', 1, array(
'section', 'borderSize' => 6,
1, 'borderColor' => '006699',
array('borderSize' => 6, 'borderColor' => '006699', 'cellMargin' => 80) 'cellMargin' => 80
); ));
$this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Table', $oTable->getStyle()); $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Table', $oTable->getStyle());
} }
@ -63,7 +63,7 @@ class TableTest extends \PHPUnit_Framework_TestCase
public function testWidth() public function testWidth()
{ {
$oTable = new Table('section', 1); $oTable = new Table('section', 1);
$iVal = rand(1, 1000); $iVal = rand(1, 1000);
$oTable->setWidth($iVal); $oTable->setWidth($iVal);
$this->assertEquals($oTable->getWidth(), $iVal); $this->assertEquals($oTable->getWidth(), $iVal);
} }
@ -73,7 +73,7 @@ class TableTest extends \PHPUnit_Framework_TestCase
*/ */
public function testRow() public function testRow()
{ {
$oTable = new Table('section', 1); $oTable = new Table('section', 1);
$element = $oTable->addRow(); $element = $oTable->addRow();
$this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Row', $element); $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Row', $element);
$this->assertCount(1, $oTable->getRows()); $this->assertCount(1, $oTable->getRows());
@ -89,4 +89,18 @@ class TableTest extends \PHPUnit_Framework_TestCase
$element = $oTable->addCell(); $element = $oTable->addCell();
$this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Cell', $element); $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Cell', $element);
} }
/**
* Add cell
*/
public function testCountColumns()
{
$oTable = new Table('section', 1);
$oTable->addRow();
$element = $oTable->addCell();
$this->assertEquals($oTable->countColumns(), 1);
$element = $oTable->addCell();
$element = $oTable->addCell();
$this->assertEquals($oTable->countColumns(), 3);
}
} }

View File

@ -19,9 +19,9 @@ use PhpOffice\PhpWord\Settings;
class SettingsTest extends \PHPUnit_Framework_TestCase class SettingsTest extends \PHPUnit_Framework_TestCase
{ {
/** /**
* Get/set compatibity option * Test set/get compatibity option
*/ */
public function testGetSetCompatibility() public function testSetGetCompatibility()
{ {
$this->assertTrue(Settings::getCompatibility()); $this->assertTrue(Settings::getCompatibility());
$this->assertTrue(Settings::setCompatibility(false)); $this->assertTrue(Settings::setCompatibility(false));
@ -30,12 +30,26 @@ class SettingsTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* Get/set zip class * Test set/get zip class
*/ */
public function testGetSetZipClass() public function testSetGetZipClass()
{ {
$this->assertEquals(Settings::ZIPARCHIVE, Settings::getZipClass()); $this->assertEquals(Settings::ZIPARCHIVE, Settings::getZipClass());
$this->assertTrue(Settings::setZipClass(Settings::PCLZIP)); $this->assertTrue(Settings::setZipClass(Settings::PCLZIP));
$this->assertFalse(Settings::setZipClass('foo')); $this->assertFalse(Settings::setZipClass('foo'));
} }
/**
* Test set/get PDF renderer
*/
public function testSetGetPdfRenderer()
{
$domPdfPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/dompdf/dompdf');
$this->assertFalse(Settings::setPdfRenderer('FOO', 'dummy/path'));
$this->assertTrue(Settings::setPdfRenderer(Settings::PDF_RENDERER_DOMPDF, $domPdfPath));
$this->assertEquals(Settings::PDF_RENDERER_DOMPDF, Settings::getPdfRendererName());
$this->assertEquals($domPdfPath, Settings::getPdfRendererPath());
$this->assertFalse(Settings::setPdfRendererPath('dummy/path'));
}
} }

View File

@ -0,0 +1,54 @@
<?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\Shared;
use PhpOffice\PhpWord\Shared\XMLReader;
/**
* Test class for PhpOffice\PhpWord\Shared\XMLReader
*
* @runTestsInSeparateProcesses
* @since 0.10.0
*/
class XMLReaderTest extends \PHPUnit_Framework_TestCase
{
/**
* Test get DOMDocument from ZipArchive returns false
*/
public function testGetDomFromZipReturnsFalse()
{
$filename = __DIR__ . "/../_files/documents/reader.docx.zip";
$object = new XMLReader();
$this->assertFalse($object->getDomFromZip($filename, 'yadayadaya'));
}
/**
* Test get elements returns empty
*/
public function testGetElementsReturnsEmpty()
{
$object = new XMLReader();
$this->assertEquals(array(), $object->getElements('w:document'));
}
/**
* Test get element returns null
*/
public function testGetElementReturnsNull()
{
$filename = __DIR__ . "/../_files/documents/reader.docx.zip";
$object = new XMLReader();
$object->getDomFromZip($filename, '[Content_Types].xml');
$element = $object->getElements('*')->item(0);
$this->assertNull($object->getElement('yadayadaya', $element));
}
}

View File

@ -24,14 +24,51 @@ class ZipArchiveTest extends \PHPUnit_Framework_TestCase
public function testAdd() public function testAdd()
{ {
$existingFile = __DIR__ . "/../_files/documents/sheet.xls"; $existingFile = __DIR__ . "/../_files/documents/sheet.xls";
$zipFile = __DIR__ . "/../_files/documents/ziptest.zip"; $zipFile = __DIR__ . "/../_files/documents/ziptest.zip";
$object = new ZipArchive(); $object = new ZipArchive();
$object->open($zipFile); $object->open($zipFile);
$object->addFile($existingFile, 'xls/new.xls'); $object->addFile($existingFile, 'xls/new.xls');
$object->addFromString('content/string.txt', 'Test'); $object->addFromString('content/string.txt', 'Test');
$this->assertTrue($object->locateName('xls/new.xls')); $this->assertTrue($object->locateName('xls/new.xls'));
$this->assertEquals('Test', $object->getFromName('content/string.txt')); $this->assertEquals('Test', $object->getFromName('content/string.txt'));
$this->assertEquals('Test', $object->getFromName('/content/string.txt'));
unlink($zipFile);
}
/**
* Test find if a given name exists in the archive
*/
public function testLocate()
{
$existingFile = __DIR__ . "/../_files/documents/sheet.xls";
$zipFile = __DIR__ . "/../_files/documents/ziptest.zip";
$object = new ZipArchive();
$object->open($zipFile);
$object->addFile($existingFile, 'xls/new.xls');
$object->addFromString('content/string.txt', 'Test');
$this->assertEquals(1, $object->locateName('content/string.txt'));
$this->assertFalse($object->locateName('blablabla'));
unlink($zipFile);
}
/**
* Test returns the name of an entry using its index
*/
public function testNameIndex()
{
$existingFile = __DIR__ . "/../_files/documents/sheet.xls";
$zipFile = __DIR__ . "/../_files/documents/ziptest.zip";
$object = new ZipArchive();
$object->open($zipFile);
$object->addFile($existingFile, 'xls/new.xls');
$object->addFromString('content/string.txt', 'Test');
$this->assertFalse($object->getNameIndex(-1));
$this->assertEquals('content/string.txt', $object->getNameIndex(1));
unlink($zipFile); unlink($zipFile);
} }

View File

@ -0,0 +1,70 @@
<?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\Style;
/**
* Test class for PhpOffice\PhpWord\Style\AbstractStyle
*
* @runTestsInSeparateProcesses
*/
class AbstractStyleTest extends \PHPUnit_Framework_TestCase
{
/**
* Test set style by array
*/
public function testSetStyleByArray()
{
$stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Style\AbstractStyle');
$stub->setStyleByArray(array('index' => 1));
$this->assertEquals(1, $stub->getIndex());
}
/**
* Test setBoolVal, setIntVal, setFloatVal, setEnumVal with normal value
*/
public function testSetValNormal()
{
$stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Style\AbstractStyle');
$this->assertEquals(true, self::callProtectedMethod($stub, 'setBoolVal', array(true, false)));
$this->assertEquals(12, self::callProtectedMethod($stub, 'setIntVal', array(12, 200)));
$this->assertEquals(871.1, self::callProtectedMethod($stub, 'setFloatVal', array(871.1, 2.1)));
$this->assertEquals('a', self::callProtectedMethod($stub, 'setEnumVal', array('a', array('a', 'b'), 'b')));
}
/**
* Test setBoolVal, setIntVal, setFloatVal, setEnumVal with default value
*/
public function testSetValDefault()
{
$stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Style\AbstractStyle');
$this->assertEquals(false, self::callProtectedMethod($stub, 'setBoolVal', array('a', false)));
$this->assertEquals(200, self::callProtectedMethod($stub, 'setIntVal', array('foo', 200)));
$this->assertEquals(2.1, self::callProtectedMethod($stub, 'setFloatVal', array('foo', 2.1)));
$this->assertEquals('b', self::callProtectedMethod($stub, 'setEnumVal', array('z', array('a', 'b'), 'b')));
}
/**
* Helper function to call protected method
*
* @param mixed $object
* @param string $method
* @param array $args
*/
public static function callProtectedMethod($object, $method, array $args = array())
{
$class = new \ReflectionClass(get_class($object));
$method = $class->getMethod($method);
$method->setAccessible(true);
return $method->invokeArgs($object, $args);
}
}

View File

@ -32,7 +32,7 @@ class ImageTest extends \PHPUnit_Framework_TestCase
'align' => 'left', 'align' => 'left',
'marginTop' => 240, 'marginTop' => 240,
'marginLeft' => 240, 'marginLeft' => 240,
'wrappingStyle' => 'inline', 'wrappingStyle' => 'inline'
); );
foreach ($properties as $key => $value) { foreach ($properties as $key => $value) {
$set = "set{$key}"; $set = "set{$key}";
@ -54,7 +54,7 @@ class ImageTest extends \PHPUnit_Framework_TestCase
'height' => 200, 'height' => 200,
'align' => 'left', 'align' => 'left',
'marginTop' => 240, 'marginTop' => 240,
'marginLeft' => 240, 'marginLeft' => 240
); );
foreach ($properties as $key => $value) { foreach ($properties as $key => $value) {
$get = "get{$key}"; $get = "get{$key}";

View File

@ -53,4 +53,16 @@ class ListItemTest extends \PHPUnit_Framework_TestCase
$object->setListType($value); $object->setListType($value);
$this->assertEquals($value, $object->getListType()); $this->assertEquals($value, $object->getListType());
} }
/**
* Test set/get numbering style name
*/
public function testSetGetNumStyle()
{
$expected = 'List Name';
$object = new ListItem();
$object->setNumStyle($expected);
$this->assertEquals($expected, $object->getNumStyle());
}
} }

View File

@ -0,0 +1,49 @@
<?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\Style;
use PhpOffice\PhpWord\Style\NumberingLevel;
/**
* Test class for PhpOffice\PhpWord\Style\NumberingLevel
*
* @runTestsInSeparateProcesses
*/
class NumberingLevelTest extends \PHPUnit_Framework_TestCase
{
/**
* Test setting style with normal value
*/
public function testSetGetNormal()
{
$object = new NumberingLevel();
$attributes = array(
'level' => 1,
'start' => 1,
'format' => 'decimal',
'restart' => 1,
'suffix' => 'space',
'text' => '%1.',
'align' => 'left',
'left' => 360,
'hanging' => 360,
'tabPos' => 360,
'font' => 'Arial',
'hint' => 'default',
);
foreach ($attributes as $key => $value) {
$set = "set{$key}";
$get = "get{$key}";
$object->$set($value);
$this->assertEquals($value, $object->$get());
}
}
}

View File

@ -0,0 +1,110 @@
<?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\Writer;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Writer\HTML;
/**
* Test class for PhpOffice\PhpWord\Writer\HTML
*
* @runTestsInSeparateProcesses
*/
class HTMLTest extends \PHPUnit_Framework_TestCase
{
/**
* Construct
*/
public function testConstruct()
{
$object = new HTML(new PhpWord);
$this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $object->getPhpWord());
}
/**
* Construct with null
*
* @expectedException \PhpOffice\PhpWord\Exception\Exception
* @expectedExceptionMessage No PhpWord assigned.
*/
public function testConstructWithNull()
{
$object = new HTML();
$object->getPhpWord();
}
/**
* Save
*/
public function testSave()
{
$localImage = __DIR__ . "/../_files/images/PhpWord.png";
$archiveImage = 'zip://' . __DIR__ . '/../_files/documents/reader.docx#word/media/image1.jpeg';
$gdImage = 'http://php.net/images/logos/php-med-trans-light.gif';
$objectSrc = __DIR__ . "/../_files/documents/sheet.xls";
$file = __DIR__ . "/../_files/temp.html";
$phpWord = new PhpWord();
$docProps = $phpWord->getDocumentProperties();
$docProps->setTitle('HTML Test');
$phpWord->addFontStyle('Font', array('name' => 'Verdana', 'size' => 11, 'color' => 'FF0000', 'fgColor' => 'FF0000'));
$phpWord->addParagraphStyle('Paragraph', array('align' => 'center'));
$section = $phpWord->addSection();
$section->addText('Test 1', 'Font', 'Paragraph');
$section->addTextBreak();
$section->addText('Test 2', array('name' => 'Tahoma', 'bold' => true, 'italic' => true));
$section->addLink('http://test.com');
$section->addTitle('Test', 1);
$section->addPageBreak();
$section->addListItem('Test');
$section->addImage($localImage);
$section->addImage($archiveImage);
$section->addImage($gdImage);
$section->addObject($objectSrc);
$section->addFootnote();
$section->addEndnote();
$section = $phpWord->addSection();
$textrun = $section->addTextRun(array('align' => 'center'));
$textrun->addText('Test 3');
$textrun->addTextBreak();
$textrun = $section->addTextRun('Paragraph');
$textrun->addLink('http://test.com');
$textrun->addImage($localImage);
$textrun->addFootnote();
$textrun->addEndnote();
$section = $phpWord->addSection();
$table = $section->addTable();
$cell = $table->addRow()->addCell();
$cell->addText('Test 1', array('superscript' => true, 'underline' => 'dash', 'strikethrough' => true));
$cell->addTextRun();
$cell->addLink('http://test.com');
$cell->addTextBreak();
$cell->addListItem('Test');
$cell->addImage($localImage);
$cell->addObject($objectSrc);
$cell->addFootnote();
$cell->addEndnote();
$cell = $table->addRow()->addCell();
$writer = new HTML($phpWord);
$writer->save($file);
$this->assertTrue(file_exists($file));
unlink($file);
}
}

View File

@ -0,0 +1,70 @@
<?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\Writer\PDF;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Writer\PDF;
/**
* Test class for PhpOffice\PhpWord\Writer\PDF\DomPDF
*
* @runTestsInSeparateProcesses
*/
class DomPDFTest extends \PHPUnit_Framework_TestCase
{
/**
* Test construct
*/
public function testConstruct()
{
define('DOMPDF_ENABLE_AUTOLOAD', false);
$file = __DIR__ . "/../../_files/temp.pdf";
$phpWord = new PhpWord();
$section = $phpWord->addSection();
$section->addText('Test 1');
$rendererName = Settings::PDF_RENDERER_DOMPDF;
$rendererLibraryPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/dompdf/dompdf');
Settings::setPdfRenderer($rendererName, $rendererLibraryPath);
$writer = new PDF($phpWord);
$writer->save($file);
$this->assertTrue(file_exists($file));
unlink($file);
}
/**
* Test set/get abstract renderer properties
*/
public function testSetGetAbstractRendererProperties()
{
define('DOMPDF_ENABLE_AUTOLOAD', false);
$file = __DIR__ . "/../../_files/temp.pdf";
$rendererName = Settings::PDF_RENDERER_DOMPDF;
$rendererLibraryPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/dompdf/dompdf');
Settings::setPdfRenderer($rendererName, $rendererLibraryPath);
$writer = new PDF(new PhpWord());
$writer->setFont('arial');
$this->assertEquals('arial', $writer->getFont());
$writer->setPaperSize();
$this->assertEquals(9, $writer->getPaperSize());
$writer->setOrientation();
$this->assertEquals('default', $writer->getOrientation());
$writer->setTempDir(sys_get_temp_dir());
$this->assertEquals(sys_get_temp_dir(), $writer->getTempDir());
}
}

View File

@ -0,0 +1,51 @@
<?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\Writer;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Writer\PDF;
/**
* Test class for PhpOffice\PhpWord\Writer\PDF
*
* @runTestsInSeparateProcesses
*/
class PDFTest extends \PHPUnit_Framework_TestCase
{
/**
* Test normal construct
*/
public function testConstruct()
{
define('DOMPDF_ENABLE_AUTOLOAD', false);
$file = __DIR__ . "/../_files/temp.pdf";
$rendererName = Settings::PDF_RENDERER_DOMPDF;
$rendererLibraryPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/dompdf/dompdf');
Settings::setPdfRenderer($rendererName, $rendererLibraryPath);
$writer = new PDF(new PhpWord());
$writer->save($file);
$this->assertTrue(file_exists($file));
unlink($file);
}
/**
* Test construct exception
*
* @expectedException \PhpOffice\PhpWord\Exception\Exception
* @expectedExceptionMessage PDF rendering library or library path has not been defined.
*/
public function testConstructException()
{
$writer = new PDF(new PhpWord());
}
}

View File

@ -28,7 +28,7 @@ class BaseTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* covers ::_writeText * Test write text element
*/ */
public function testWriteText() public function testWriteText()
{ {
@ -49,7 +49,7 @@ class BaseTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* covers ::_writeTextRun * Test write textrun element
*/ */
public function testWriteTextRun() public function testWriteTextRun()
{ {
@ -74,7 +74,7 @@ class BaseTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* covers ::_writeLink * Test write link element
*/ */
public function testWriteLink() public function testWriteLink()
{ {
@ -97,7 +97,7 @@ class BaseTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* covers ::_writePreserveText * Test write preserve text element
*/ */
public function testWritePreserveText() public function testWritePreserveText()
{ {
@ -121,7 +121,7 @@ class BaseTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* covers ::_writeTextBreak * Test write text break
*/ */
public function testWriteTextBreak() public function testWriteTextBreak()
{ {
@ -146,30 +146,98 @@ class BaseTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* covers ::_writeParagraphStyle * covers ::_writeImage
*/ */
public function testWriteParagraphStyleAlign() public function testWriteImage()
{ {
$phpWord = new PhpWord(); $phpWord = new PhpWord();
$styles = array('align' => 'left', 'width' => 40, 'height' => 40, 'marginTop' => -1, 'marginLeft' => -1);
$wraps = array('inline', 'behind', 'infront', 'square', 'tight');
$section = $phpWord->addSection(); $section = $phpWord->addSection();
foreach ($wraps as $wrap) {
$styles['wrappingStyle'] = $wrap;
$section->addImage(__DIR__ . "/../../_files/images/earth.jpg", $styles);
}
$section->addText('This is my text', null, array('align' => 'right')); $archiveFile = realpath(__DIR__ . '/../../_files/documents/reader.docx');
$imageFile = 'word/media/image1.jpeg';
$source = 'zip://' . $archiveFile . '#' . $imageFile;
$section->addImage($source);
$doc = TestHelperDOCX::getDocument($phpWord); $doc = TestHelperDOCX::getDocument($phpWord);
$element = $doc->getElement('/w:document/w:body/w:p/w:pPr/w:jc');
$this->assertEquals('right', $element->getAttribute('w:val')); // behind
$element = $doc->getElement('/w:document/w:body/w:p[2]/w:r/w:pict/v:shape');
$style = $element->getAttribute('style');
$this->assertRegExp('/z\-index:\-[0-9]*/', $style);
// square
$element = $doc->getElement('/w:document/w:body/w:p[4]/w:r/w:pict/v:shape/w10:wrap');
$this->assertEquals('square', $element->getAttribute('type'));
}
/**
* covers ::_writeWatermark
*/
public function testWriteWatermark()
{
$imageSrc = __DIR__ . "/../../_files/images/earth.jpg";
$phpWord = new PhpWord();
$section = $phpWord->addSection();
$header = $section->addHeader();
$header->addWatermark($imageSrc);
$doc = TestHelperDOCX::getDocument($phpWord);
$element = $doc->getElement("/w:document/w:body/w:sectPr/w:headerReference");
$this->assertStringStartsWith("rId", $element->getAttribute('r:id'));
}
/**
* covers ::_writeTitle
*/
public function testWriteTitle()
{
$phpWord = new PhpWord();
$phpWord->addTitleStyle(1, array('bold' => true), array('spaceAfter' => 240));
$phpWord->addSection()->addTitle('Test', 1);
$doc = TestHelperDOCX::getDocument($phpWord);
$element = "/w:document/w:body/w:p/w:pPr/w:pStyle";
$this->assertEquals('Heading1', $doc->getElementAttribute($element, 'w:val'));
$element = "/w:document/w:body/w:p/w:r/w:fldChar";
$this->assertEquals('end', $doc->getElementAttribute($element, 'w:fldCharType'));
}
/**
* covers ::_writeCheckbox
*/
public function testWriteCheckbox()
{
$rStyle = 'rStyle';
$pStyle = 'pStyle';
$phpWord = new PhpWord();
$phpWord->addFontStyle($rStyle, array('bold' => true));
$phpWord->addParagraphStyle($pStyle, array('hanging' => 120, 'indent' => 120));
$section = $phpWord->addSection();
$section->addCheckbox('Check1', 'Test', $rStyle, $pStyle);
$doc = TestHelperDOCX::getDocument($phpWord);
$element = '/w:document/w:body/w:p/w:r/w:fldChar/w:ffData/w:name';
$this->assertEquals('Check1', $doc->getElementAttribute($element, 'w:val'));
} }
/** /**
* covers ::_writeParagraphStyle * covers ::_writeParagraphStyle
*/ */
public function testWriteParagraphStylePagination() public function testWriteParagraphStyle()
{ {
// Create the doc // Create the doc
$phpWord = new PhpWord(); $phpWord = new PhpWord();
$section = $phpWord->addSection(); $section = $phpWord->addSection();
$attributes = array( $attributes = array(
'align' => 'right',
'widowControl' => false, 'widowControl' => false,
'keepNext' => true, 'keepNext' => true,
'keepLines' => true, 'keepLines' => true,
@ -184,10 +252,13 @@ class BaseTest extends \PHPUnit_Framework_TestCase
$i = 0; $i = 0;
foreach ($attributes as $key => $value) { foreach ($attributes as $key => $value) {
$i++; $i++;
$path = "/w:document/w:body/w:p[{$i}]/w:pPr/w:{$key}"; $nodeName = ($key == 'align') ? 'jc' : $key;
$path = "/w:document/w:body/w:p[{$i}]/w:pPr/w:{$nodeName}";
if ($key != 'align') {
$value = $value ? 1 : 0;
}
$element = $doc->getElement($path); $element = $doc->getElement($path);
$expected = $value ? 1 : 0; $this->assertEquals($value, $element->getAttribute('w:val'));
$this->assertEquals($expected, $element->getAttribute('w:val'));
} }
} }
@ -316,81 +387,4 @@ class BaseTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(5, $element->getAttribute('w:val')); $this->assertEquals(5, $element->getAttribute('w:val'));
} }
/**
* covers ::_writeImage
*/
public function testWriteImagePosition()
{
$phpWord = new PhpWord();
$section = $phpWord->addSection();
$section->addImage(
__DIR__ . "/../../_files/images/earth.jpg",
array(
'marginTop' => -1,
'marginLeft' => -1,
'wrappingStyle' => 'behind'
)
);
$doc = TestHelperDOCX::getDocument($phpWord);
$element = $doc->getElement('/w:document/w:body/w:p/w:r/w:pict/v:shape');
$style = $element->getAttribute('style');
$this->assertRegExp('/z\-index:\-[0-9]*/', $style);
$this->assertRegExp('/position:absolute;/', $style);
}
/**
* covers ::_writeWatermark
*/
public function testWriteWatermark()
{
$imageSrc = __DIR__ . "/../../_files/images/earth.jpg";
$phpWord = new PhpWord();
$section = $phpWord->addSection();
$header = $section->addHeader();
$header->addWatermark($imageSrc);
$doc = TestHelperDOCX::getDocument($phpWord);
$element = $doc->getElement("/w:document/w:body/w:sectPr/w:headerReference");
$this->assertStringStartsWith("rId", $element->getAttribute('r:id'));
}
/**
* covers ::_writeTitle
*/
public function testWriteTitle()
{
$phpWord = new PhpWord();
$phpWord->addTitleStyle(1, array('bold' => true), array('spaceAfter' => 240));
$phpWord->addSection()->addTitle('Test', 1);
$doc = TestHelperDOCX::getDocument($phpWord);
$element = "/w:document/w:body/w:p/w:pPr/w:pStyle";
$this->assertEquals('Heading1', $doc->getElementAttribute($element, 'w:val'));
$element = "/w:document/w:body/w:p/w:r/w:fldChar";
$this->assertEquals('end', $doc->getElementAttribute($element, 'w:fldCharType'));
}
/**
* covers ::_writeCheckbox
*/
public function testWriteCheckbox()
{
$rStyle = 'rStyle';
$pStyle = 'pStyle';
$phpWord = new PhpWord();
$phpWord->addFontStyle($rStyle, array('bold' => true));
$phpWord->addParagraphStyle($pStyle, array('hanging' => 120, 'indent' => 120));
$section = $phpWord->addSection();
$section->addCheckbox('Check1', 'Test', $rStyle, $pStyle);
$doc = TestHelperDOCX::getDocument($phpWord);
$element = '/w:document/w:body/w:p/w:r/w:fldChar/w:ffData/w:name';
$this->assertEquals('Check1', $doc->getElementAttribute($element, 'w:val'));
}
} }

View File

@ -99,12 +99,12 @@ class DocumentTest extends \PHPUnit_Framework_TestCase
$objectSrc = __DIR__ . "/../../_files/documents/sheet.xls"; $objectSrc = __DIR__ . "/../../_files/documents/sheet.xls";
$phpWord = new PhpWord(); $phpWord = new PhpWord();
$phpWord->addParagraphStyle('pStyle', array('align' => 'center')); $phpWord->addParagraphStyle('pStyle', array('align' => 'center')); // Style #1
$phpWord->addFontStyle('fStyle', array('size' => '20')); $phpWord->addFontStyle('fStyle', array('size' => '20')); // Style #2
$phpWord->addTitleStyle(1, array('color' => '333333', 'bold' => true)); $phpWord->addTitleStyle(1, array('color' => '333333', 'bold' => true)); // Style #3
$fontStyle = new Font('text', array('align' => 'center')); $fontStyle = new Font('text', array('align' => 'center'));
$section = $phpWord->addSection(); $section = $phpWord->addSection();
$section->addListItem('List Item', 0, null, null, 'pStyle'); $section->addListItem('List Item', 0, null, null, 'pStyle'); // Style #4
$section->addObject($objectSrc, array('align' => 'center')); $section->addObject($objectSrc, array('align' => 'center'));
$section->addTOC($fontStyle); $section->addTOC($fontStyle);
$section->addTitle('Title 1', 1); $section->addTitle('Title 1', 1);
@ -113,7 +113,7 @@ class DocumentTest extends \PHPUnit_Framework_TestCase
// List item // List item
$element = $doc->getElement('/w:document/w:body/w:p[1]/w:pPr/w:numPr/w:numId'); $element = $doc->getElement('/w:document/w:body/w:p[1]/w:pPr/w:numPr/w:numId');
$this->assertEquals(3, $element->getAttribute('w:val')); $this->assertEquals(4, $element->getAttribute('w:val'));
// Object // Object
$element = $doc->getElement('/w:document/w:body/w:p[2]/w:r/w:object/o:OLEObject'); $element = $doc->getElement('/w:document/w:body/w:p[2]/w:r/w:object/o:OLEObject');