Merge branch 'develop' of https://github.com/PHPOffice/PHPWord.git into develop

This commit is contained in:
Bas-Jan 't Jong 2014-05-20 22:29:26 +02:00
commit 343f378782
188 changed files with 4955 additions and 2502 deletions

1
.gitignore vendored
View File

@ -6,6 +6,7 @@ Thumbs.db
Desktop.ini
composer.phar
phpunit.xml
phpword.ini
/.buildpath
/.idea
/.project

View File

@ -9,7 +9,6 @@ tools:
enabled: true
config:
standard: PSR2
php_cpd: true
php_mess_detector:
enabled: true
config:
@ -17,8 +16,9 @@ tools:
external_code_coverage:
enabled: true
timeout: 900
php_sim:
min_mass: 30
php_cpd: true
# php_sim: # Temporarily disabled to allow focus on things other than duplicates
# min_mass: 40
php_pdepend: true
php_analyzer: true
sensiolabs_security_checker: true

View File

@ -10,8 +10,6 @@ php:
matrix:
allow_failures:
- php: 5.3.3
- php: 5.6
- php: hhvm
env:
@ -23,14 +21,8 @@ before_script:
- sudo apt-get -qq update > /dev/null
- sudo apt-get -qq install graphviz > /dev/null
## Composer
# - curl -s http://getcomposer.org/installer | php
# - php composer.phar install --prefer-source
- composer self-update
- composer require dompdf/dompdf:0.6.*
- composer install --prefer-source --dev
## PHP_CodeSniffer
- pyrus install pear/PHP_CodeSniffer
- phpenv rehash
## PHP Copy/Paste Detector
- curl -o phpcpd.phar https://phar.phpunit.de/phpcpd.phar
## PHP Mess Detector
@ -48,7 +40,7 @@ before_script:
script:
## PHP_CodeSniffer
- phpcs src/ tests/ --standard=PSR2 -n --ignore=src/PhpWord/Shared/PCLZip
- ./vendor/bin/phpcs src/ tests/ --standard=PSR2 -n --ignore=src/PhpWord/Shared/PCLZip
## PHP Copy/Paste Detector
- php phpcpd.phar src/ tests/ --verbose
## PHP Mess Detector
@ -58,7 +50,7 @@ script:
## PHPUnit
- phpunit -c ./ --coverage-text --coverage-html ./build/coverage
## PHPDocumentor
- vendor/bin/phpdoc.php -d ./src -t ./build/docs --ignore "*/src/PhpWord/Shared/PCLZip/*" --template="responsive-twig"
- vendor/bin/phpdoc.php -d ./src -t ./build/docs --ignore "*/src/PhpWord/Shared/*/*" --template="responsive-twig"
after_script:
## PHPDocumentor

View File

@ -4,7 +4,7 @@ This is the changelog between releases of PHPWord. Releases are listed in revers
## 0.11.0 - Not yet released
This release changed PHPWord license from LGPL 2.1 to LGPL 3.
This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3; new relative and absolute positioning for image; new `TextBox` and `ListItemRun` element; refactorings of writer classes into parts, elements, and styles; and ability to add elements to PHPWord object via HTML.
### Features
@ -15,17 +15,30 @@ This release changed PHPWord license from LGPL 2.1 to LGPL 3.
- HTML: Ability to add elements to PHPWord object via html - @basjan GH-231
- ListItemRun: New element that can add a list item with inline formatting like a textrun - @basjan GH-235
- Table: Ability to add table inside a cell (nested table) - @ivanlanin GH-149
- RTF Writer: UTF8 support for RTF: Internal UTF8 text is converted to Unicode before writing - @ivanlanin GH-158
- Table: Ability to define table width (in percent and twip) and position - @ivanlanin GH-237
- RTF Writer: Ability to add links and page breaks in RTF - @ivanlanin GH-196
- ListItemRun: Remove fontStyle parameter because ListItemRun is inherited from TextRun and TextRun doesn't have fontStyle - @ivanlanin
- Config: Ability to use a config file to store various common settings - @ivanlanin GH-200
- ODT Writer: Enable inline font style in TextRun - @ivanlanin
- ODT Writer: Enable underline, strike/doublestrike, smallcaps/allcaps, superscript/subscript font style - @ivanlanin
- ODT Writer: Enable section and column - @ivanlanin
- PDF Writer: Add TCPDF and mPDF as optional PDF renderer library - @ivanlanin
- ODT Writer: Enable title element and custom document properties - @ivanlanin
- ODT Reader: Ability to read standard and custom document properties - @ivanlanin
### Bugfixes
- Header: All images added to the second header were assigned to the first header - @basjan GH-222
- Conversion: Fix conversion from cm to pixel, pixel to cm, and pixel to point - @basjan GH-233 GH-234
- PageBreak: Page break adds new line in the beginning of the new page - @ivanlanin GH-150
### Deprecated
- Static classes `Footnotes`, `Endnotes`, and `TOC`
- `Writer\Word2007\Part`: `Numbering::writeNumbering()`, `Settings::writeSettings()`, `WebSettings::writeWebSettings()`, `ContentTypes::writeContentTypes()`, `Styles::writeStyles()`, `Document::writeDocument()` all changed into `write()`
- `Writer\Word2007\Part\DocProps`: Split into `Writer\Word2007\Part\DocPropsCore` and `Writer\Word2007\Part\DocPropsApp`
- `Element\Title::getBookmarkId()` replaced by `Element\Title::getRelationId()`
### Miscellaneous
@ -38,6 +51,8 @@ This release changed PHPWord license from LGPL 2.1 to LGPL 3.
- QA: Add `.scrutinizer.yml` and include `composer.lock` for preparation to Scrutinizer - @ivanlanin GH-186
- Writer: Refactor writer parts using composite pattern - @ivanlanin
- Docs: Show code quality and test code coverage badge on README
- Style: Change behaviour of `set...` function of boolean properties; when none is defined, assumed true - @ivanlanin
- Shared: Unify PHP ZipArchive and PCLZip features into PhpWord ZipArchive - @ivanlanin
## 0.10.0 - 4 May 2014

View File

@ -33,14 +33,18 @@
],
"require": {
"php": ">=5.3.3",
"ext-xml": "*",
"ext-zip": "*"
"ext-xml": "*"
},
"require-dev": {
"phpunit/phpunit": "3.7.*",
"phpdocumentor/phpdocumentor":"2.*"
"phpdocumentor/phpdocumentor":"2.*",
"squizlabs/php_codesniffer": "1.*",
"dompdf/dompdf":"0.6.*",
"tecnick.com/tcpdf": "6.*",
"mpdf/mpdf": "5.*"
},
"suggest": {
"ext-zip": "Used to create docx files",
"ext-gd2": "Required to add images",
"ext-xmlwriter": "Required to write DOCX and ODT",
"ext-xsl": "Required to apply XSL style sheet to template part",

192
composer.lock generated
View File

@ -3,7 +3,7 @@
"This file locks the dependencies of your project to a known state",
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
],
"hash": "6daefa91649add98af3850b0a3f13415",
"hash": "91993ff980d11a416fcf3a7309a4044f",
"packages": [
],
@ -619,6 +619,49 @@
],
"time": "2014-04-24 13:29:03"
},
{
"name": "mpdf/mpdf",
"version": "v5.7.2",
"source": {
"type": "git",
"url": "https://github.com/finwe/mpdf.git",
"reference": "1627f9e7d2ef0f635a886f611079216ed2929717"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/finwe/mpdf/zipball/1627f9e7d2ef0f635a886f611079216ed2929717",
"reference": "1627f9e7d2ef0f635a886f611079216ed2929717",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": ">=4.3.10"
},
"type": "library",
"autoload": {
"classmap": [
"mpdf.php",
"classes"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-1.0+"
],
"authors": [
{
"name": "Ian Back"
}
],
"description": "A PHP class to generate PDF files from HTML with Unicode/UTF-8 and CJK support",
"homepage": "http://www.mpdf1.com/mpdf/index.php",
"keywords": [
"pdf",
"php",
"utf-8"
],
"time": "2014-05-16 07:18:10"
},
{
"name": "nikic/php-parser",
"version": "v0.9.4",
@ -833,16 +876,16 @@
},
{
"name": "phpdocumentor/phpdocumentor",
"version": "v2.4.0",
"version": "v2.5.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/phpDocumentor2.git",
"reference": "d7503ada7386aa6b2956224d50a8d0226a22a99f"
"reference": "bf9fa40f6d00412410025b2e16eb16c315eb0216"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/phpDocumentor2/zipball/d7503ada7386aa6b2956224d50a8d0226a22a99f",
"reference": "d7503ada7386aa6b2956224d50a8d0226a22a99f",
"url": "https://api.github.com/repos/phpDocumentor/phpDocumentor2/zipball/bf9fa40f6d00412410025b2e16eb16c315eb0216",
"reference": "bf9fa40f6d00412410025b2e16eb16c315eb0216",
"shasum": ""
},
"require": {
@ -895,12 +938,13 @@
"ext-xslcache": "Enabling the XSLCache extension improves the generation of xml based templates."
},
"bin": [
"bin/phpdoc.php"
"bin/phpdoc.php",
"bin/phpdoc"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-develop": "2.4-dev"
"dev-develop": "2.5-dev"
}
},
"autoload": {
@ -924,7 +968,7 @@
"documentation",
"phpdoc"
],
"time": "2014-04-01 18:14:51"
"time": "2014-05-17 12:25:35"
},
{
"name": "phpdocumentor/reflection",
@ -1863,6 +1907,81 @@
],
"time": "2012-12-21 11:40:51"
},
{
"name": "squizlabs/php_codesniffer",
"version": "1.5.3",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "396178ada8499ec492363587f037125bf7b07fcc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/396178ada8499ec492363587f037125bf7b07fcc",
"reference": "396178ada8499ec492363587f037125bf7b07fcc",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=5.1.2"
},
"suggest": {
"phpunit/php-timer": "dev-master"
},
"bin": [
"scripts/phpcs"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-phpcs-fixer": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"CodeSniffer.php",
"CodeSniffer/CLI.php",
"CodeSniffer/Exception.php",
"CodeSniffer/File.php",
"CodeSniffer/Report.php",
"CodeSniffer/Reporting.php",
"CodeSniffer/Sniff.php",
"CodeSniffer/Tokens.php",
"CodeSniffer/Reports/",
"CodeSniffer/CommentParser/",
"CodeSniffer/Tokenizers/",
"CodeSniffer/DocGenerators/",
"CodeSniffer/Standards/AbstractPatternSniff.php",
"CodeSniffer/Standards/AbstractScopeSniff.php",
"CodeSniffer/Standards/AbstractVariableSniff.php",
"CodeSniffer/Standards/IncorrectPatternException.php",
"CodeSniffer/Standards/Generic/Sniffs/",
"CodeSniffer/Standards/MySource/Sniffs/",
"CodeSniffer/Standards/PEAR/Sniffs/",
"CodeSniffer/Standards/PSR1/Sniffs/",
"CodeSniffer/Standards/PSR2/Sniffs/",
"CodeSniffer/Standards/Squiz/Sniffs/",
"CodeSniffer/Standards/Zend/Sniffs/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "http://www.squizlabs.com/php-codesniffer",
"keywords": [
"phpcs",
"standards"
],
"time": "2014-05-01 03:07:07"
},
{
"name": "symfony/config",
"version": "v2.4.4",
@ -2453,6 +2572,63 @@
"homepage": "http://symfony.com",
"time": "2014-04-18 20:37:09"
},
{
"name": "tecnick.com/tcpdf",
"version": "6.0.078",
"source": {
"type": "git",
"url": "git://git.code.sf.net/p/tcpdf/code",
"reference": "e1cbda79b99f3cdc8fdf26b39eb4870d2cd9fbac"
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"autoload": {
"classmap": [
"fonts",
"config",
"include",
"tcpdf.php",
"tcpdf_parser.php",
"tcpdf_import.php",
"tcpdf_barcodes_1d.php",
"tcpdf_barcodes_2d.php",
"include/tcpdf_colors.php",
"include/tcpdf_filters.php",
"include/tcpdf_font_data.php",
"include/tcpdf_fonts.php",
"include/tcpdf_images.php",
"include/tcpdf_static.php",
"include/barcodes/datamatrix.php",
"include/barcodes/pdf417.php",
"include/barcodes/qrcode.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPLv3"
],
"authors": [
{
"name": "Nicola Asuni",
"email": "info@tecnick.com",
"homepage": "http://nicolaasuni.tecnick.com"
}
],
"description": "TCPDF is a PHP class for generating PDF documents.",
"homepage": "http://www.tcpdf.org/",
"keywords": [
"PDFD32000-2008",
"TCPDF",
"barcodes",
"datamatrix",
"pdf",
"pdf417",
"qrcode"
],
"time": "2014-05-12 19:50:13"
},
{
"name": "twig/twig",
"version": "v1.15.1",

View File

@ -61,25 +61,23 @@ Writers
+---------------------------+----------------------+--------+-------+-------+--------+-------+
| Features | | DOCX | ODT | RTF | HTML | PDF |
+===========================+======================+========+=======+=======+========+=======+
| **Document Properties** | Standard | ✓ | | | | |
| **Document Properties** | Standard | ✓ | | | | |
+---------------------------+----------------------+--------+-------+-------+--------+-------+
| | Extended | ✓ | | | | |
+---------------------------+----------------------+--------+-------+-------+--------+-------+
| | UserDefined | ✓ | | | | |
| | Custom | ✓ | ✓ | | | |
+---------------------------+----------------------+--------+-------+-------+--------+-------+
| **Element Type** | Text | ✓ | ✓ | ✓ | ✓ | ✓ |
+---------------------------+----------------------+--------+-------+-------+--------+-------+
| | Text Run | ✓ | ✓ | ✓ | ✓ | ✓ |
+---------------------------+----------------------+--------+-------+-------+--------+-------+
| | Title | ✓ | | | ✓ | ✓ |
| | Title | ✓ | | | ✓ | ✓ |
+---------------------------+----------------------+--------+-------+-------+--------+-------+
| | Link | ✓ | ✓ | | ✓ | ✓ |
| | Link | ✓ | ✓ | | ✓ | ✓ |
+---------------------------+----------------------+--------+-------+-------+--------+-------+
| | Preserve Text | ✓ | | | | |
+---------------------------+----------------------+--------+-------+-------+--------+-------+
| | Text Break | ✓ | ✓ | ✓ | ✓ | ✓ |
+---------------------------+----------------------+--------+-------+-------+--------+-------+
| | Page Break | ✓ | | | | |
| | Page Break | ✓ | | | | |
+---------------------------+----------------------+--------+-------+-------+--------+-------+
| | List | ✓ | | | | |
+---------------------------+----------------------+--------+-------+-------+--------+-------+
@ -124,9 +122,7 @@ Readers
+===========================+======================+========+=======+=======+
| **Document Properties** | Standard | ✓ | | |
+---------------------------+----------------------+--------+-------+-------+
| | Extended | ✓ | | |
+---------------------------+----------------------+--------+-------+-------+
| | UserDefined | ✓ | | |
| | Custom | ✓ | | |
+---------------------------+----------------------+--------+-------+-------+
| **Element Type** | Text | ✓ | ✓ | |
+---------------------------+----------------------+--------+-------+-------+

View File

@ -78,16 +78,15 @@ Below are the supported features for each file formats.
| Features | | DOCX | ODT | RTF | HTML | PDF |
|-------------------------|--------------------|------|-----|-----|------|-----|
| **Document Properties** | Standard | ✓ | | | | |
| | Extended | ✓ | | | | |
| | UserDefined | ✓ | | | | |
| **Document Properties** | Standard | ✓ | ✓ | | | |
| | Custom | ✓ | ✓ | | | |
| **Element Type** | Text | ✓ | ✓ | ✓ | ✓ | ✓ |
| | Text Run | ✓ | ✓ | ✓ | ✓ | ✓ |
| | Title | ✓ | | | ✓ | ✓ |
| | Link | ✓ | ✓ | | ✓ | ✓ |
| | Title | ✓ | | | ✓ | ✓ |
| | Link | ✓ | ✓ | | ✓ | ✓ |
| | Preserve Text | ✓ | | | | |
| | Text Break | ✓ | ✓ | ✓ | ✓ | ✓ |
| | Page Break | ✓ | | | | |
| | Page Break | ✓ | | | | |
| | List | ✓ | | | | |
| | Table | ✓ | ✓ | | ✓ | ✓ |
| | Image | ✓ | ✓ | | ✓ | |
@ -111,8 +110,7 @@ Below are the supported features for each file formats.
| Features | | DOCX | ODT | RTF |
|-------------------------|--------------------|------|-----|-----|
| **Document Properties** | Standard | ✓ | | |
| | Extended | ✓ | | |
| | UserDefined | ✓ | | |
| | Custom | ✓ | | |
| **Element Type** | Text | ✓ | ✓ | |
| | Text Run | ✓ | | |
| | Title | ✓ | ✓ | |

View File

@ -8,11 +8,17 @@
<rule ref="rulesets/design.xml/ExitExpression" />
<rule ref="rulesets/design.xml/EvalExpression" />
<rule ref="rulesets/design.xml/GotoStatement" />
<rule ref="rulesets/design.xml/NumberOfChildren" />
<rule ref="rulesets/design.xml/DepthOfInheritance" />
<rule ref="rulesets/design.xml/CouplingBetweenObjects">
<!-- AbstractContainer needs more coupling (default: 13) -->
<properties>
<property name="minimum" value="15" />
<property name="minimum" value="20" />
</properties>
</rule>
<rule ref="rulesets/design.xml/NumberOfChildren">
<!-- AbstractStyle needs more children (default: 15) -->
<properties>
<property name="minimum" value="20" />
</properties>
</rule>
<rule ref="rulesets/unusedcode.xml" />

View File

@ -10,7 +10,7 @@
syntaxCheck="false">
<testsuites>
<testsuite name="PhpWord Test Suite">
<directory>./tests/PhpWord/</directory>
<directory>./tests/PhpWord</directory>
</testsuite>
</testsuites>
<filter>
@ -22,9 +22,6 @@
</whitelist>
</filter>
<logging>
<!--
For http://phpoffice.github.io/PHPWord/coverage/ and Scrutinizer
-->
<log type="coverage-html" target="./build/coverage" charset="UTF-8" highlight="true" />
<log type="coverage-clover" target="./build/logs/clover.xml" />
</logging>

14
phpword.ini.dist Normal file
View File

@ -0,0 +1,14 @@
; Default config file for PHPWord
; Copy this file into phpword.ini and use Settings::loadConfig to load
[General]
compatibility = true
zipClass = ZipArchive
pdfRendererName = DomPDF
pdfRendererPath =
[Font]
defaultFontName = Arial
defaultFontSize = 10

View File

@ -22,7 +22,8 @@ $section->addTextBreak(2);
$section->addText('I am styled by a font style definition.', 'rStyle');
$section->addText('I am styled by a paragraph style definition.', null, 'pStyle');
$section->addText('I am styled by both font and paragraph style.', 'rStyle', 'pStyle');
$section->addTextBreak();
$section->addPageBreak();
// Inline font style
$fontStyle['name'] = 'Times New Roman';
@ -36,10 +37,11 @@ $fontStyle['color'] = 'FF0000';
$fontStyle['fgColor'] = 'yellow';
$fontStyle['smallCaps'] = true;
$section->addText('I am inline styled.', $fontStyle);
$section->addTextBreak();
// Link
$section->addLink('http://www.google.com', null, 'NLink');
$section->addLink('http://www.google.com', 'Google');
$section->addTextBreak();
// Image

View File

@ -18,7 +18,7 @@ $section = $phpWord->addSection(array(
'colsNum' => 2,
'colsSpace' => 1440,
'breakType' => 'continuous'));
$section->addText('Three columns, one inch (1440 twips) spacing. ' . $filler);
$section->addText('Two columns, one inch (1440 twips) spacing. ' . $filler);
// Normal
$section = $phpWord->addSection(array('breakType' => 'continuous'));

View File

@ -51,7 +51,7 @@ for($i = 1; $i <= 8; $i++) {
// 3. colspan (gridSpan) and rowspan (vMerge)
$section->addTextBreak(1);
$section->addPageBreak();
$section->addText("Table with colspan and rowspan", $header);
$styleTable = array('borderSize' => 6, 'borderColor' => '999999');
@ -87,11 +87,12 @@ $table->addCell(null, $cellRowContinue);
// 4. Nested table
$section->addTextBreak(2);
$section->addText('Nested table', $header);
$section->addText('Nested table in a centered and 50% width table.', $header);
$cell = $section->addTable()->addRow()->addCell();
$table = $section->addTable(array('width' => 50 * 50, 'unit' => 'pct', 'align' => 'center'));
$cell = $table->addRow()->addCell();
$cell->addText('This cell contains nested table.');
$innerCell = $cell->addTable()->addRow()->addCell();
$innerCell = $cell->addTable(array('align' => 'center'))->addRow()->addCell();
$innerCell->addText('Inside nested table');
// Save file

View File

@ -8,7 +8,7 @@ $phpWord = new \PhpOffice\PhpWord\PhpWord();
$section = $phpWord->addSection();
// In section
$textbox = $section->addTextBox(array('align' => 'left', 'width' => 400, 'height' => 150, 'borderSize' => 1, 'borderColor' => '#FF0000'));
$textbox = $section->addTextBox(array('align' => 'center', 'width' => 400, 'height' => 150, 'borderSize' => 1, 'borderColor' => '#FF0000'));
$textbox->addText('Text box content in section.');
$textbox->addText('Another line.');
$cell = $textbox->addTable()->addRow()->addCell();
@ -22,7 +22,7 @@ $textbox->addText('Textbox inside table');
// Inside header with textrun
$header = $section->addHeader();
$textbox = $header->addTextBox(array('align' => 'center', 'width' => 600, 'borderSize' => 1, 'borderColor' => '#00FF00'));
$textbox = $header->addTextBox(array('width' => 600, 'borderSize' => 1, 'borderColor' => '#00FF00'));
$textrun = $textbox->addTextRun();
$textrun->addText('TextBox in header. TextBox can contain a TextRun ');
$textrun->addText('with bold text', array('bold' => true));

View File

@ -2,23 +2,25 @@
/**
* Header file
*/
error_reporting(E_ALL);
use PhpOffice\PhpWord\Autoloader;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\IOFactory;
error_reporting(E_ALL & ~E_DEPRECATED);
define('CLI', (PHP_SAPI == 'cli') ? true : false);
define('EOL', CLI ? PHP_EOL : '<br />');
define('SCRIPT_FILENAME', basename($_SERVER['SCRIPT_FILENAME'], '.php'));
define('IS_INDEX', SCRIPT_FILENAME == 'index');
require_once '../src/PhpWord/Autoloader.php';
\PhpOffice\PhpWord\Autoloader::register();
Autoloader::register();
Settings::loadConfig();
// 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)) {
if (Settings::getPdfRendererPath() === null) {
$writers['PDF'] = null;
}
@ -60,7 +62,7 @@ function write($phpWord, $filename, $writers)
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 = IOFactory::createWriter($phpWord, $writer);
$xmlWriter->save("{$filename}.{$extension}");
rename("{$filename}.{$extension}", "results/{$filename}.{$extension}");
} else {

View File

@ -10,7 +10,7 @@ if (!CLI) {
<a class="btn btn-lg btn-primary" href="http://phpword.readthedocs.org/en/develop/" role="button"><i class="fa fa-book fa-lg" title="Docs"></i> Read the Docs</a>
</p>
</div>
<?
<?php
$requirements = array(
'php' => array('PHP 5.3.0', version_compare(phpversion(), '5.3.0', '>=')),
'zip' => array('PHP extension ZipArchive', extension_loaded('zip')),

View File

@ -416,8 +416,9 @@ class DocumentProperties
{
if ($this->isCustomPropertySet($propertyName)) {
return $this->customProperties[$propertyName]['value'];
} else {
return null;
}
}
/**
@ -430,8 +431,9 @@ class DocumentProperties
{
if ($this->isCustomPropertySet($propertyName)) {
return $this->customProperties[$propertyName]['type'];
} else {
return null;
}
}
/**

View File

@ -35,15 +35,81 @@ abstract class AbstractContainer extends AbstractElement
protected $elements = array();
/**
* Set element index and unique id, and add element into elements collection
* Container type Section|Header|Footer|Footnote|Endnote|Cell|TextRun|TextBox|ListItemRun
*
* @var string
*/
protected function addElement(AbstractElement $element)
protected $container;
/**
* Add element
*
* Each element has different number of parameters passed
*
* @param string $elementName
* @return \PhpOffice\PhpWord\Element\AbstractElement
*/
protected function addElement($elementName)
{
// $type = str_replace('PhpOffice\\PhpWord\\Element\\', '', get_class($element)));
$elementClass = __NAMESPACE__ . '\\' . $elementName;
$this->checkValidity($elementName);
// Get arguments
$args = func_get_args();
$argsCount = func_num_args();
$withoutP = in_array($this->container, array('TextRun', 'Footnote', 'Endnote', 'ListItemRun'));
if ($withoutP && ($elementName == 'Text' || $elementName == 'PreserveText')) {
$args[3] = null;
}
// Create element dynamically
/** @var \PhpOffice\PhpWord\Element\AbstractElement $element Type hint */
if ($argsCount == 2) { // TextRun, TextBox, Table, Footnote, Endnote
$element = new $elementClass($args[1]);
} elseif ($argsCount == 3) { // Object, TextBreak, Title
$element = new $elementClass($args[1], $args[2]);
} elseif ($argsCount == 4) { // PreserveText, Text, Image
$element = new $elementClass($args[1], $args[2], $args[3]);
} elseif ($argsCount == 5) { // CheckBox, Link, ListItemRun, TOC
$element = new $elementClass($args[1], $args[2], $args[3], $args[4]);
} elseif ($argsCount == 6) { // ListItem
$element = new $elementClass($args[1], $args[2], $args[3], $args[4], $args[5]);
} else { // Page Break
$element = new $elementClass();
}
// Set relation Id for media collection
$mediaContainer = $this->getMediaContainer();
if (in_array($elementName, array('Link', 'Image', 'Object'))) {
if ($elementName == 'Image') {
$rId = Media::addElement($mediaContainer, strtolower($elementName), $args[1], $element);
} else {
$rId = Media::addElement($mediaContainer, strtolower($elementName), $args[1]);
}
$element->setRelationId($rId);
}
if ($elementName == 'Object') {
/** @var \PhpOffice\PhpWord\Element\Object $element Type hint */
$rIdIcon = Media::addElement($mediaContainer, 'image', $element->getIcon(), new Image($element->getIcon()));
$element->setImageRelationId($rIdIcon);
}
// Set relation Id for other collection
if (in_array($elementName, array('Footnote', 'Endnote', 'Title')) && $this->phpWord instanceof PhpWord) {
$addMethod = "add{$elementName}";
$rId = $this->phpWord->$addMethod($element);
$element->setRelationId($rId);
}
// Set other properties and add element into collection
$element->setDocPart($this->getDocPart(), $this->getDocPartId());
$element->setElementIndex($this->countElements() + 1);
$element->setElementId();
$element->setPhpWord($this->phpWord);
$this->elements[] = $element;
return $element;
}
/**
@ -59,62 +125,24 @@ abstract class AbstractContainer extends AbstractElement
/**
* Count elements
*
* @return integer
* @return int
*/
public function countElements()
{
return count($this->elements);
}
/**
* Add generic element with style
*
* This is how all elements should be added with dependency injection: with
* just one simple $style. Currently this function supports TextRun, Table,
* and TextBox since all other elements have different arguments
*
* @todo Change the function name into something better?
*
* @param string $elementName
* @param mixed $style
* @return \PhpOffice\PhpWord\Element\AbstractElement
*/
private function addGenericElement($elementName, $style)
{
$elementClass = __NAMESPACE__ . '\\' . $elementName;
$this->checkValidity($elementName);
$element = new $elementClass($style);
$element->setDocPart($this->getDocPart(), $this->getDocPartId());
$this->addElement($element);
return $element;
}
/**
* Add text/preservetext element
*
* @param string $text
* @param mixed $fontStyle
* @param mixed $paragraphStyle
* @param string $elementName Text|PreserveText
* @return \PhpOffice\PhpWord\Element\Text|\PhpOffice\PhpWord\Element\PreserveText
*/
public function addText($text, $fontStyle = null, $paragraphStyle = null, $elementName = 'Text')
public function addText($text, $fontStyle = null, $paragraphStyle = null)
{
$this->checkValidity($elementName);
$elementClass = substr(get_class($this), 0, strrpos(get_class($this), '\\')) . '\\' . $elementName;
// Reset paragraph style for footnote and textrun. They have their own
if (in_array($this->container, array('textrun', 'footnote', 'endnote', 'listitemrun'))) {
$paragraphStyle = null;
}
$element = new $elementClass($text, $fontStyle, $paragraphStyle);
$element->setDocPart($this->getDocPart(), $this->getDocPartId());
$this->addElement($element);
return $element;
return $this->addElement('Text', $text, $fontStyle, $paragraphStyle);
}
/**
@ -125,7 +153,7 @@ abstract class AbstractContainer extends AbstractElement
*/
public function addTextRun($paragraphStyle = null)
{
return $this->addGenericElement('TextRun', $paragraphStyle);
return $this->addElement('TextRun', $paragraphStyle);
}
/**
@ -153,18 +181,7 @@ abstract class AbstractContainer extends AbstractElement
*/
public function addLink($target, $text = null, $fontStyle = null, $paragraphStyle = null)
{
$this->checkValidity('Link');
$elementDocPart = $this->checkElementDocPart();
$element = new Link($target, $text, $fontStyle, $paragraphStyle);
$element->setDocPart($this->getDocPart(), $this->getDocPartId());
$rId = Media::addElement($elementDocPart, 'link', $target);
$element->setRelationId($rId);
$this->addElement($element);
return $element;
return $this->addElement('Link', $target, $text, $fontStyle, $paragraphStyle);
}
/**
@ -177,7 +194,7 @@ abstract class AbstractContainer extends AbstractElement
*/
public function addPreserveText($text, $fontStyle = null, $paragraphStyle = null)
{
return $this->addText($text, $fontStyle, $paragraphStyle, 'PreserveText');
return $this->addElement('PreserveText', $text, $fontStyle, $paragraphStyle);
}
/**
@ -189,12 +206,8 @@ abstract class AbstractContainer extends AbstractElement
*/
public function addTextBreak($count = 1, $fontStyle = null, $paragraphStyle = null)
{
$this->checkValidity('TextBreak');
for ($i = 1; $i <= $count; $i++) {
$element = new TextBreak($fontStyle, $paragraphStyle);
$element->setDocPart($this->getDocPart(), $this->getDocPartId());
$this->addElement($element);
$this->addElement('TextBreak', $fontStyle, $paragraphStyle);
}
}
@ -210,33 +223,20 @@ abstract class AbstractContainer extends AbstractElement
*/
public function addListItem($text, $depth = 0, $fontStyle = null, $listStyle = null, $paragraphStyle = null)
{
$this->checkValidity('ListItem');
$element = new ListItem($text, $depth, $fontStyle, $listStyle, $paragraphStyle);
$element->setDocPart($this->getDocPart(), $this->getDocPartId());
$this->addElement($element);
return $element;
return $this->addElement('ListItem', $text, $depth, $fontStyle, $listStyle, $paragraphStyle);
}
/**
* Add listitemrun element
*
* @param int $depth
* @param mixed $fontStyle
* @param mixed $listStyle
* @param mixed $paragraphStyle
* @return \PhpOffice\PhpWord\Element\ListItemRun
*/
public function addListItemRun($depth = 0, $fontStyle = null, $listStyle = null, $paragraphStyle = null)
public function addListItemRun($depth = 0, $listStyle = null, $paragraphStyle = null)
{
$this->checkValidity('ListItemRun');
$element = new ListItemRun($depth, $fontStyle, $listStyle, $paragraphStyle);
$element->setDocPart($this->getDocPart(), $this->getDocPartId());
$this->addElement($element);
return $element;
return $this->addElement('ListItemRun', $depth, $listStyle, $paragraphStyle);
}
/**
@ -244,11 +244,10 @@ abstract class AbstractContainer extends AbstractElement
*
* @param mixed $style
* @return \PhpOffice\PhpWord\Element\Table
* @todo Merge with the same function on Footer
*/
public function addTable($style = null)
{
return $this->addGenericElement('Table', $style);
return $this->addElement('Table', $style);
}
/**
@ -256,23 +255,12 @@ abstract class AbstractContainer extends AbstractElement
*
* @param string $source
* @param mixed $style Image style
* @param boolean $isWatermark
* @param bool $isWatermark
* @return \PhpOffice\PhpWord\Element\Image
*/
public function addImage($source, $style = null, $isWatermark = false)
{
$this->checkValidity('Image');
$elementDocPart = $this->checkElementDocPart();
$element = new Image($source, $style, $isWatermark);
$element->setDocPart($this->getDocPart(), $this->getDocPartId());
$rId = Media::addElement($elementDocPart, 'image', $source, $element);
$element->setRelationId($rId);
$this->addElement($element);
return $element;
return $this->addElement('Image', $source, $style, $isWatermark);
}
/**
@ -283,49 +271,21 @@ abstract class AbstractContainer extends AbstractElement
* @param string $source
* @param mixed $style
* @return \PhpOffice\PhpWord\Element\Object
* @throws \PhpOffice\PhpWord\Exception\Exception
*/
public function addObject($source, $style = null)
{
$this->checkValidity('Object');
$elementDocPart = $this->checkElementDocPart();
$element = new Object($source, $style);
$element->setDocPart($this->getDocPart(), $this->getDocPartId());
$rId = Media::addElement($elementDocPart, 'object', $source);
$element->setRelationId($rId);
$rIdIcon = Media::addElement($elementDocPart, 'image', $element->getIcon(), new Image($element->getIcon()));
$element->setImageRelationId($rIdIcon);
$this->addElement($element);
return $element;
return $this->addElement('Object', $source, $style);
}
/**
* Add footnote element
*
* @param mixed $paragraphStyle
* @param string $elementName
* @return \PhpOffice\PhpWord\Element\Footnote
*/
public function addFootnote($paragraphStyle = null, $elementName = 'Footnote')
public function addFootnote($paragraphStyle = null)
{
$this->checkValidity($elementName);
$elementClass = substr(get_class($this), 0, strrpos(get_class($this), '\\')) . '\\' . $elementName;
$docPart = strtolower($elementName);
$addMethod = "add{$elementName}";
$element = new $elementClass($paragraphStyle);
$element->setDocPart($docPart, $this->getDocPartId());
if ($this->phpWord instanceof PhpWord) {
$rId = $this->phpWord->$addMethod($element);
$element->setRelationId($rId);
}
$this->addElement($element);
return $element;
return $this->addElement('Footnote', $paragraphStyle);
}
/**
@ -336,7 +296,7 @@ abstract class AbstractContainer extends AbstractElement
*/
public function addEndnote($paragraphStyle = null)
{
return $this->addFootnote($paragraphStyle, 'Endnote');
return $this->addElement('Endnote', $paragraphStyle);
}
/**
@ -350,13 +310,7 @@ abstract class AbstractContainer extends AbstractElement
*/
public function addCheckBox($name, $text, $fontStyle = null, $paragraphStyle = null)
{
$this->checkValidity('CheckBox');
$element = new CheckBox($name, $text, $fontStyle, $paragraphStyle);
$element->setDocPart($this->getDocPart(), $this->getDocPartId());
$this->addElement($element);
return $element;
return $this->addElement('CheckBox', $name, $text, $fontStyle, $paragraphStyle);
}
/**
@ -367,47 +321,51 @@ abstract class AbstractContainer extends AbstractElement
*/
public function addTextBox($style = null)
{
return $this->addGenericElement('TextBox', $style);
return $this->addElement('TextBox', $style);
}
/**
* Check if a method is allowed for the current container
*
* @param string $method
* @return boolean
* @return bool
* @throws \BadMethodCallException
*/
private function checkValidity($method)
{
// Valid containers for each element
$allContainers = array('section', 'header', 'footer', 'cell', 'textrun', 'footnote', 'endnote', 'textbox', 'listitemrun');
$allContainers = array(
'Section', 'Header', 'Footer', 'Footnote', 'Endnote',
'Cell', 'TextRun', 'TextBox', 'ListItemRun',
);
$validContainers = array(
'Text' => $allContainers,
'Link' => $allContainers,
'TextBreak' => $allContainers,
'Image' => $allContainers,
'Object' => $allContainers,
'TextRun' => array('section', 'header', 'footer', 'cell', 'textbox'),
'ListItem' => array('section', 'header', 'footer', 'cell', 'textbox'),
'ListItemRun' => array('section', 'header', 'footer', 'cell', 'textbox'),
'Table' => array('section', 'header', 'footer', 'cell', 'textbox'),
'CheckBox' => array('section', 'header', 'footer', 'cell'),
'TextBox' => array('section', 'header', 'footer', 'cell'),
'Footnote' => array('section', 'textrun', 'cell'),
'Endnote' => array('section', 'textrun', 'cell'),
'PreserveText' => array('header', 'footer', 'cell'),
'TextRun' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'),
'ListItem' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'),
'ListItemRun' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'),
'Table' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'),
'CheckBox' => array('Section', 'Header', 'Footer', 'Cell'),
'TextBox' => array('Section', 'Header', 'Footer', 'Cell'),
'Footnote' => array('Section', 'TextRun', 'Cell'),
'Endnote' => array('Section', 'TextRun', 'Cell'),
'PreserveText' => array('Header', 'Footer', 'Cell'),
);
// Special condition, e.g. preservetext can only exists in cell when
// the cell is located in header or footer
$validSubcontainers = array(
'PreserveText' => array(array('cell'), array('header', 'footer')),
'Footnote' => array(array('cell', 'textrun'), array('section')),
'Endnote' => array(array('cell', 'textrun'), array('section')),
'PreserveText' => array(array('Cell'), array('Header', 'Footer')),
'Footnote' => array(array('Cell', 'TextRun'), array('Section')),
'Endnote' => array(array('Cell', 'TextRun'), array('Section')),
);
// Check if a method is valid for current container
if (array_key_exists($method, $validContainers)) {
if (!in_array($this->container, $validContainers[$method])) {
throw new \BadMethodCallException("Cannot put $method in $this->container.");
throw new \BadMethodCallException("Cannot add $method in $this->container.");
}
}
// Check if a method is valid for current container, located in other container
@ -417,7 +375,7 @@ abstract class AbstractContainer extends AbstractElement
$allowedDocParts = $rules[1];
foreach ($containers as $container) {
if ($this->container == $container && !in_array($this->getDocPart(), $allowedDocParts)) {
throw new \BadMethodCallException("Cannot put $method in $this->container.");
throw new \BadMethodCallException("Cannot add $method in $this->container.");
}
}
}
@ -426,17 +384,21 @@ abstract class AbstractContainer extends AbstractElement
}
/**
* Return element location in document: section, headerx, or footerx
* Return media element (image, object, link) container name
*
* @return string section|headerx|footerx|footnote|endnote
*/
private function checkElementDocPart()
private function getMediaContainer()
{
$inOtherPart = in_array($this->container, array('cell', 'textrun', 'textbox', 'listitemrun'));
$docPart = $inOtherPart ? $this->getDocPart() : $this->container;
$docPartId = $inOtherPart ? $this->getDocPartId() : $this->sectionId;
$inHeaderFooter = ($docPart == 'header' || $docPart == 'footer');
$docPartId = $inHeaderFooter ? $this->getDocPartId() : $docPartId;
$partName = $this->container;
if (in_array($partName, array('Cell', 'TextRun', 'TextBox', 'ListItemRun'))) {
$partName = $this->getDocPart();
}
if ($partName == 'Header' || $partName == 'Footer') {
$partName .= $this->getDocPartId();
}
return $inHeaderFooter ? $docPart . $docPartId : $docPart;
return strtolower($partName);
}
/**
@ -444,6 +406,7 @@ abstract class AbstractContainer extends AbstractElement
*
* @param string $src
* @param mixed $style
* @return \PhpOffice\PhpWord\Element\Image
* @deprecated 0.9.0
* @codeCoverageIgnore
*/
@ -456,6 +419,7 @@ abstract class AbstractContainer extends AbstractElement
* Create textrun element
*
* @param mixed $paragraphStyle
* @return \PhpOffice\PhpWord\Element\TextRun
* @deprecated 0.10.0
* @codeCoverageIgnore
*/
@ -468,6 +432,7 @@ abstract class AbstractContainer extends AbstractElement
* Create footnote element
*
* @param mixed $paragraphStyle
* @return \PhpOffice\PhpWord\Element\Footnote
* @deprecated 0.10.0
* @codeCoverageIgnore
*/

View File

@ -34,13 +34,6 @@ abstract class AbstractElement
*/
protected $phpWord;
/**
* Container type section|header|footer|cell|textrun|footnote|endnote|textbox
*
* @var string
*/
protected $container;
/**
* Section Id
*
@ -57,7 +50,7 @@ abstract class AbstractElement
*
* @var string
*/
protected $docPart = 'section';
protected $docPart = 'Section';
/**
* Document part Id
@ -66,21 +59,21 @@ abstract class AbstractElement
* because the max number of header/footer in every page is 3, i.e.
* AUTO, FIRST, and EVEN (AUTO = ODD)
*
* @var integer
* @var int
*/
protected $docPartId = 1;
/**
* Index of element in the elements collection (start with 1)
*
* @var integer
* @var int
*/
protected $elementIndex = 1;
/**
* Unique Id for element
*
* @var integer
* @var int
*/
protected $elementId;
@ -114,7 +107,7 @@ abstract class AbstractElement
/**
* Get section number
*
* @return integer
* @return int
*/
public function getSectionId()
{
@ -125,7 +118,7 @@ abstract class AbstractElement
* Set doc part
*
* @param string $docPart
* @param integer $docPartId
* @param int $docPartId
*/
public function setDocPart($docPart, $docPartId = 1)
{
@ -146,7 +139,7 @@ abstract class AbstractElement
/**
* Get doc part Id
*
* @return integer
* @return int
*/
public function getDocPartId()
{
@ -212,13 +205,13 @@ abstract class AbstractElement
}
/**
* Check if element is located in section doc part (as opposed to header/footer)
* Check if element is located in Section doc part (as opposed to Header/Footer)
*
* @return boolean
* @return bool
*/
public function isInSection()
{
return ($this->docPart == 'section');
return ($this->docPart == 'Section');
}
/**
@ -226,7 +219,8 @@ abstract class AbstractElement
*
* @param mixed $styleObject Style object
* @param mixed $styleValue Style value
* @param boolean $returnObject Always return object
* @param bool $returnObject Always return object
* @return mixed
*/
protected function setStyle($styleObject, $styleValue = null, $returnObject = false)
{

View File

@ -24,6 +24,11 @@ use PhpOffice\PhpWord\Style\Cell as CellStyle;
*/
class Cell extends AbstractContainer
{
/**
* @var string Container type
*/
protected $container = 'Cell';
/**
* Cell width
*
@ -36,22 +41,18 @@ class Cell extends AbstractContainer
*
* @var \PhpOffice\PhpWord\Style\Cell
*/
private $cellStyle;
private $style;
/**
* Create new instance
*
* @param string $docPart section|header|footer
* @param int $docPartId
* @param int $width
* @param array|\PhpOffice\PhpWord\Style\Cell $style
*/
public function __construct($docPart, $docPartId, $width = null, $style = null)
public function __construct($width = null, $style = null)
{
$this->container = 'cell';
$this->setDocPart($docPart, $docPartId);
$this->width = $width;
$this->cellStyle = $this->setStyle(new CellStyle(), $style, true);
$this->style = $this->setStyle(new CellStyle(), $style, true);
}
/**
@ -61,7 +62,7 @@ class Cell extends AbstractContainer
*/
public function getStyle()
{
return $this->cellStyle;
return $this->style;
}
/**

View File

@ -26,6 +26,11 @@ use PhpOffice\PhpWord\Style\Paragraph;
*/
class Endnote extends Footnote
{
/**
* @var string Container type
*/
protected $container = 'Endnote';
/**
* Create new instance
*
@ -33,7 +38,6 @@ class Endnote extends Footnote
*/
public function __construct($paragraphStyle = null)
{
$this->container = 'endnote';
$this->paragraphStyle = $this->setStyle(new Paragraph(), $paragraphStyle);
}
}

View File

@ -33,11 +33,9 @@ class Footer extends AbstractContainer
const EVEN = 'even';
/**
* Container type
*
* @var string
* @var string Container type
*/
protected $container = 'footer';
protected $container = 'Footer';
/**
* Header type

View File

@ -24,6 +24,11 @@ use PhpOffice\PhpWord\Style\Paragraph;
*/
class Footnote extends AbstractContainer
{
/**
* @var string Container type
*/
protected $container = 'Footnote';
/**
* Paragraph style
*
@ -38,7 +43,6 @@ class Footnote extends AbstractContainer
*/
public function __construct($paragraphStyle = null)
{
$this->container = 'footnote';
$this->paragraphStyle = $this->setStyle(new Paragraph(), $paragraphStyle);
}

View File

@ -22,13 +22,10 @@ namespace PhpOffice\PhpWord\Element;
*/
class Header extends Footer
{
/**
* Container type
*
* @var string
* @var string Container type
*/
protected $container = 'header';
protected $container = 'Header';
/**
* Add a Watermark Element

View File

@ -19,7 +19,7 @@ namespace PhpOffice\PhpWord\Element;
use PhpOffice\PhpWord\Exception\InvalidImageException;
use PhpOffice\PhpWord\Exception\UnsupportedImageTypeException;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Shared\ZipArchive;
use PhpOffice\PhpWord\Style\Image as ImageStyle;
/**
@ -283,6 +283,8 @@ class Image extends AbstractElement
* Check memory image, supported type, image functions, and proportional width/height
*
* @param string $source
* @throws \PhpOffice\PhpWord\Exception\InvalidImageException
* @throws \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException
*/
private function checkImage($source)
{
@ -346,8 +348,7 @@ class Image extends AbstractElement
list($zipFilename, $imageFilename) = explode('#', $source);
$tempFilename = tempnam(sys_get_temp_dir(), 'PHPWordImage');
$zipClass = Settings::getZipClass();
$zip = new $zipClass();
$zip = new ZipArchive();
if ($zip->open($zipFilename) !== false) {
if ($zip->locateName($imageFilename)) {
$imageContent = $zip->getFromName($imageFilename);

View File

@ -26,27 +26,26 @@ use PhpOffice\PhpWord\Style\ListItem as ListItemStyle;
class ListItem extends AbstractElement
{
/**
* ListItem Style
* Element style
*
* @var \PhpOffice\PhpWord\Style\ListItem
*/
private $style;
/**
* Textrun
* Text object
*
* @var Text
* @var \PhpOffice\PhpWord\Element\Text
*/
private $textObject;
/**
* ListItem Depth
* Depth
*
* @var int
*/
private $depth;
/**
* Create a new ListItem
*
@ -70,7 +69,9 @@ class ListItem extends AbstractElement
}
/**
* Get ListItem style
* Get style
*
* @return \PhpOffice\PhpWord\Style\ListItem
*/
public function getStyle()
{
@ -78,7 +79,9 @@ class ListItem extends AbstractElement
}
/**
* Get ListItem TextRun
* Get Text object
*
* @return \PhpOffice\PhpWord\Element\Text
*/
public function getTextObject()
{
@ -86,10 +89,23 @@ class ListItem extends AbstractElement
}
/**
* Get ListItem depth
* Get depth
*
* @return int
*/
public function getDepth()
{
return $this->depth;
}
/**
* Get text
*
* @return string
* @since 0.11.0
*/
public function getText()
{
return $this->textObject->getText();
}
}

View File

@ -17,7 +17,6 @@
namespace PhpOffice\PhpWord\Element;
use PhpOffice\PhpWord\Shared\String;
use PhpOffice\PhpWord\Style\ListItem as ListItemStyle;
use PhpOffice\PhpWord\Style\Paragraph;
@ -26,6 +25,11 @@ use PhpOffice\PhpWord\Style\Paragraph;
*/
class ListItemRun extends TextRun
{
/**
* @var string Container type
*/
protected $container = 'ListItemRun';
/**
* ListItem Style
*
@ -44,13 +48,11 @@ class ListItemRun extends TextRun
* Create a new ListItem
*
* @param int $depth
* @param mixed $fontStyle
* @param array|string|null $listStyle
* @param mixed $paragraphStyle
*/
public function __construct($depth = 0, $fontStyle = null, $listStyle = null, $paragraphStyle = null)
public function __construct($depth = 0, $listStyle = null, $paragraphStyle = null)
{
$this->container = 'listitemrun';
$this->depth = $depth;
// Version >= 0.10.0 will pass numbering style name. Older version will use old method

View File

@ -58,6 +58,7 @@ class Object extends AbstractElement
*
* @param string $source
* @param mixed $style
* @throws \PhpOffice\PhpWord\Exception\InvalidObjectException
*/
public function __construct($source, $style = null)
{

View File

@ -54,7 +54,7 @@ class PreserveText extends AbstractElement
* @param string $text
* @param mixed $fontStyle
* @param mixed $paragraphStyle
* @return $this
* @return self
*/
public function __construct($text = null, $fontStyle = null, $paragraphStyle = null)
{

View File

@ -43,21 +43,18 @@ class Row extends AbstractElement
/**
* Row cells
*
* @var array
* @var \PhpOffice\PhpWord\Element\Cell[]
*/
private $cells = array();
/**
* Create a new table row
*
* @param string $docPart
* @param int $docPartId
* @param int $height
* @param mixed $style
*/
public function __construct($docPart, $docPartId, $height = null, $style = null)
public function __construct($height = null, $style = null)
{
$this->setDocPart($docPart, $docPartId);
$this->height = $height;
$this->style = $this->setStyle(new RowStyle(), $style, true);
}
@ -67,19 +64,22 @@ class Row extends AbstractElement
*
* @param int $width
* @param mixed $style
* @return \PhpOffice\PhpWord\Element\Cell
*/
public function addCell($width = null, $style = null)
{
$cell = new Cell($this->getDocPart(), $this->getDocPartId(), $width, $style);
$cell = new Cell($width, $style);
$cell->setDocPart($this->getDocPart(), $this->getDocPartId());
$cell->setPhpWord($this->phpWord);
$this->cells[] = $cell;
return $cell;
}
/**
* Get all cells
*
* @return array
* @return \PhpOffice\PhpWord\Element\Cell[]
*/
public function getCells()
{

View File

@ -18,7 +18,6 @@
namespace PhpOffice\PhpWord\Element;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Style\Section as SectionSettings;
/**
@ -26,6 +25,11 @@ use PhpOffice\PhpWord\Style\Section as SectionSettings;
*/
class Section extends AbstractContainer
{
/**
* @var string Container type
*/
protected $container = 'Section';
/**
* Section settings
*
@ -55,7 +59,6 @@ class Section extends AbstractContainer
*/
public function __construct($sectionCount, $settings = null)
{
$this->container = 'section';
$this->sectionId = $sectionCount;
$this->setDocPart($this->container, $this->sectionId);
$this->settings = new SectionSettings();
@ -98,15 +101,7 @@ class Section extends AbstractContainer
*/
public function addTitle($text, $depth = 1)
{
$title = new Title($text, $depth);
$title->setDocPart($this->getDocPart(), $this->getDocPartId());
if ($this->phpWord instanceof PhpWord) {
$bookmarkId = $this->phpWord->addTitle($title);
$title->setBookmarkId($bookmarkId);
}
$this->addElement($title);
return $title;
return $this->addElement('Title', $text, $depth);
}
/**
@ -114,7 +109,7 @@ class Section extends AbstractContainer
*/
public function addPageBreak()
{
$this->addElement(new PageBreak());
return $this->addElement('PageBreak');
}
/**
@ -128,10 +123,7 @@ class Section extends AbstractContainer
*/
public function addTOC($fontStyle = null, $tocStyle = null, $minDepth = 1, $maxDepth = 9)
{
$toc = new TOC($fontStyle, $tocStyle, $minDepth, $maxDepth);
$this->addElement($toc);
return $toc;
return $this->addElement('TOC', $fontStyle, $tocStyle, $minDepth, $maxDepth);
}
/**
@ -214,6 +206,7 @@ class Section extends AbstractContainer
if (in_array($type, array(Header::AUTO, Header::FIRST, Header::EVEN))) {
$index = count($collection);
/** @var \PhpOffice\PhpWord\Element\AbstractContainer $container Type hint */
$container = new $containerClass($this->sectionId, ++$index, $type);
$container->setPhpWord($this->phpWord);

View File

@ -95,6 +95,7 @@ class TOC extends AbstractElement
$titles = $this->phpWord->getTitles()->getItems();
foreach ($titles as $i => $title) {
/** @var \PhpOffice\PhpWord\Element\Title $title Type hint */
$depth = $title->getDepth();
if ($this->minDepth > $depth) {
unset($titles[$i]);

View File

@ -34,14 +34,14 @@ class Table extends AbstractElement
/**
* Table rows
*
* @var array
* @var \PhpOffice\PhpWord\Element\Row[]
*/
private $rows = array();
/**
* Table width
*
* @var integer
* @var int
*/
private $width = null;
@ -59,35 +59,40 @@ class Table extends AbstractElement
/**
* Add a row
*
* @param integer $height
* @param int $height
* @param mixed $style
* @return \PhpOffice\PhpWord\Element\Row
*/
public function addRow($height = null, $style = null)
{
$row = new Row($this->getDocPart(), $this->getDocPartId(), $height, $style);
$row = new Row($height, $style);
$row->setDocPart($this->getDocPart(), $this->getDocPartId());
$row->setPhpWord($this->phpWord);
$this->rows[] = $row;
return $row;
}
/**
* Add a cell
*
* @param integer $width
* @param int $width
* @param mixed $style
* @return Cell
* @return \PhpOffice\PhpWord\Element\Cell
*/
public function addCell($width = null, $style = null)
{
$index = count($this->rows) - 1;
$cell = $this->rows[$index]->addCell($width, $style);
$row = $this->rows[$index];
$cell = $row->addCell($width, $style);
return $cell;
}
/**
* Get all rows
*
* @return array
* @return \PhpOffice\PhpWord\Element\Row[]
*/
public function getRows()
{
@ -107,7 +112,7 @@ class Table extends AbstractElement
/**
* Set table width
*
* @param integer $width
* @param int $width
*/
public function setWidth($width)
{
@ -117,7 +122,7 @@ class Table extends AbstractElement
/**
* Get table width
*
* @return integer
* @return int
*/
public function getWidth()
{
@ -127,7 +132,7 @@ class Table extends AbstractElement
/**
* Get column count
*
* @return integer
* @return int
*/
public function countColumns()
{
@ -135,7 +140,9 @@ class Table extends AbstractElement
if (is_array($this->rows)) {
$rowCount = count($this->rows);
for ($i = 0; $i < $rowCount; $i++) {
$cellCount = count($this->rows[$i]->getCells());
/** @var \PhpOffice\PhpWord\Element\Row $row Type hint */
$row = $this->rows[$i];
$cellCount = count($row->getCells());
if ($columnCount < $cellCount) {
$columnCount = $cellCount;
}

View File

@ -26,6 +26,11 @@ use PhpOffice\PhpWord\Style\TextBox as TextBoxStyle;
*/
class TextBox extends AbstractContainer
{
/**
* @var string Container type
*/
protected $container = 'TextBox';
/**
* TextBox style
*
@ -40,7 +45,6 @@ class TextBox extends AbstractContainer
*/
public function __construct($style = null)
{
$this->container = 'textbox';
$this->style = $this->setStyle(new TextBoxStyle(), $style);
}

View File

@ -24,6 +24,11 @@ use PhpOffice\PhpWord\Style\Paragraph;
*/
class TextRun extends AbstractContainer
{
/**
* @var string Container type
*/
protected $container = 'TextRun';
/**
* Paragraph style
*
@ -38,7 +43,6 @@ class TextRun extends AbstractContainer
*/
public function __construct($paragraphStyle = null)
{
$this->container = 'textrun';
$this->paragraphStyle = $this->setStyle(new Paragraph(), $paragraphStyle);
}

View File

@ -39,13 +39,6 @@ class Title extends AbstractElement
*/
private $depth = 1;
/**
* Title Bookmark ID
*
* @var int
*/
private $bookmarkId = 1;
/**
* Name of the heading style, e.g. 'Heading1'
*
@ -53,14 +46,6 @@ class Title extends AbstractElement
*/
private $style;
/**
* Title anchor
*
* @var int
* @deprecated 0.10.0
*/
private $anchor;
/**
* Create a new Title Element
*
@ -79,26 +64,6 @@ class Title extends AbstractElement
return $this;
}
/**
* Set Bookmark ID
*
* @param int $bookmarkId
*/
public function setBookmarkId($bookmarkId)
{
$this->bookmarkId = $bookmarkId;
}
/**
* Get Anchor
*
* @return int
*/
public function getBookmarkId()
{
return $this->bookmarkId;
}
/**
* Get Title Text content
*
@ -128,28 +93,4 @@ class Title extends AbstractElement
{
return $this->style;
}
/**
* Set Anchor
*
* @param int $anchor
* @deprecated 0.10.0
* @codeCoverageIgnore
*/
public function setAnchor($anchor)
{
$this->anchor = $anchor;
}
/**
* Get Anchor
*
* @return int
* @deprecated 0.10.0
* @codeCoverageIgnore
*/
public function getAnchor()
{
return '_Toc' . (252634154 + $this->bookmarkId);
}
}

View File

@ -22,24 +22,22 @@ use PhpOffice\PhpWord\Collection\Footnotes;
use PhpOffice\PhpWord\Collection\Titles;
use PhpOffice\PhpWord\Element\Section;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Style;
/**
* PHPWord main class
*/
class PhpWord
{
const DEFAULT_FONT_COLOR = '000000'; // HEX
const DEFAULT_FONT_CONTENT_TYPE = 'default'; // default|eastAsia|cs
const DEFAULT_FONT_NAME = 'Arial';
/**
* Default font size, in points.
* Default font settings
*
* OOXML defined font size values in halfpoints, i.e. twice of what PhpWord
* use, and the conversion will be conducted during XML writing.
* @const string|int
* @deprecated 0.11.0 Use Settings constants
*/
const DEFAULT_FONT_SIZE = 10;
const DEFAULT_FONT_NAME = Settings::DEFAULT_FONT_NAME;
const DEFAULT_FONT_SIZE = Settings::DEFAULT_FONT_SIZE;
const DEFAULT_FONT_COLOR = Settings::DEFAULT_FONT_COLOR;
const DEFAULT_FONT_CONTENT_TYPE = Settings::DEFAULT_FONT_CONTENT_TYPE;
/**
* Document properties object
@ -76,19 +74,6 @@ class PhpWord
*/
private $endnotes;
/**
* Default font name
*
* @var string
*/
private $defaultFontName;
/**
* Default font size
* @var int
*/
private $defaultFontSize;
/**
* Create new
*/
@ -98,8 +83,6 @@ class PhpWord
$this->titles = new Titles();
$this->footnotes = new Footnotes();
$this->endnotes = new Endnotes();
$this->defaultFontName = self::DEFAULT_FONT_NAME;
$this->defaultFontSize = self::DEFAULT_FONT_SIZE;
}
/**
@ -220,7 +203,7 @@ class PhpWord
*/
public function getDefaultFontName()
{
return $this->defaultFontName;
return Settings::getDefaultFontName();
}
/**
@ -230,7 +213,7 @@ class PhpWord
*/
public function setDefaultFontName($fontName)
{
$this->defaultFontName = $fontName;
Settings::setDefaultFontName($fontName);
}
/**
@ -240,7 +223,7 @@ class PhpWord
*/
public function getDefaultFontSize()
{
return $this->defaultFontSize;
return Settings::getDefaultFontSize();
}
/**
@ -250,17 +233,18 @@ class PhpWord
*/
public function setDefaultFontSize($fontSize)
{
$this->defaultFontSize = $fontSize;
Settings::setDefaultFontSize($fontSize);
}
/**
* Set default paragraph style definition to styles.xml
*
* @param array $styles Paragraph style definition
* @return \PhpOffice\PhpWord\Style\Paragraph
*/
public function setDefaultParagraphStyle($styles)
{
Style::setDefaultParagraphStyle($styles);
return Style::setDefaultParagraphStyle($styles);
}
/**
@ -268,10 +252,11 @@ class PhpWord
*
* @param string $styleName
* @param array $styles
* @return \PhpOffice\PhpWord\Style\Paragraph
*/
public function addParagraphStyle($styleName, $styles)
{
Style::addParagraphStyle($styleName, $styles);
return Style::addParagraphStyle($styleName, $styles);
}
/**
@ -280,10 +265,11 @@ class PhpWord
* @param string $styleName
* @param mixed $fontStyle
* @param mixed $paragraphStyle
* @return \PhpOffice\PhpWord\Style\Font
*/
public function addFontStyle($styleName, $fontStyle, $paragraphStyle = null)
{
Style::addFontStyle($styleName, $fontStyle, $paragraphStyle);
return Style::addFontStyle($styleName, $fontStyle, $paragraphStyle);
}
/**
@ -292,33 +278,11 @@ class PhpWord
* @param string $styleName
* @param mixed $styleTable
* @param mixed $styleFirstRow
* @return \PhpOffice\PhpWord\Style\Table
*/
public function addTableStyle($styleName, $styleTable, $styleFirstRow = null)
{
Style::addTableStyle($styleName, $styleTable, $styleFirstRow);
}
/**
* Adds a heading style definition to styles.xml
*
* @param int $titleCount
* @param mixed $fontStyle
* @param mixed $paragraphStyle
*/
public function addTitleStyle($titleCount, $fontStyle, $paragraphStyle = null)
{
Style::addTitleStyle($titleCount, $fontStyle, $paragraphStyle);
}
/**
* Adds a hyperlink style to styles.xml
*
* @param string $styleName
* @param mixed $styles
*/
public function addLinkStyle($styleName, $styles)
{
Style::addLinkStyle($styleName, $styles);
return Style::addTableStyle($styleName, $styleTable, $styleFirstRow);
}
/**
@ -326,10 +290,36 @@ class PhpWord
*
* @param string $styleName
* @param mixed $styles
* @return \PhpOffice\PhpWord\Style\Numbering
*/
public function addNumberingStyle($styleName, $styles)
{
Style::addNumberingStyle($styleName, $styles);
return Style::addNumberingStyle($styleName, $styles);
}
/**
* Adds a hyperlink style to styles.xml
*
* @param string $styleName
* @param mixed $styles
* @return \PhpOffice\PhpWord\Style\Font
*/
public function addLinkStyle($styleName, $styles)
{
return Style::addLinkStyle($styleName, $styles);
}
/**
* Adds a heading style definition to styles.xml
*
* @param int $depth
* @param mixed $fontStyle
* @param mixed $paragraphStyle
* @return \PhpOffice\PhpWord\Style\Font
*/
public function addTitleStyle($depth, $fontStyle, $paragraphStyle = null)
{
return Style::addTitleStyle($depth, $fontStyle, $paragraphStyle);
}
/**

View File

@ -54,47 +54,47 @@ abstract class AbstractReader implements ReaderInterface
/**
* Set read data only
*
* @param bool $pValue
* @param bool $value
* @return self
*/
public function setReadDataOnly($pValue = true)
public function setReadDataOnly($value = true)
{
$this->readDataOnly = $pValue;
$this->readDataOnly = $value;
return $this;
}
/**
* Open file for reading
*
* @param string $pFilename
* @param string $filename
* @return resource
* @throws \PhpOffice\PhpWord\Exception\Exception
*/
protected function openFile($pFilename)
protected function openFile($filename)
{
// Check if file exists
if (!file_exists($pFilename) || !is_readable($pFilename)) {
throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
if (!file_exists($filename) || !is_readable($filename)) {
throw new Exception("Could not open " . $filename . " for reading! File does not exist.");
}
// Open file
$this->fileHandle = fopen($pFilename, 'r');
$this->fileHandle = fopen($filename, 'r');
if ($this->fileHandle === false) {
throw new Exception("Could not open file " . $pFilename . " for reading.");
throw new Exception("Could not open file " . $filename . " for reading.");
}
}
/**
* Can the current ReaderInterface read the file?
*
* @param string $pFilename
* @param string $filename
* @return bool
*/
public function canRead($pFilename)
public function canRead($filename)
{
// Check if file exists
try {
$this->openFile($pFilename);
$this->openFile($filename);
} catch (Exception $e) {
return false;
}

View File

@ -40,6 +40,7 @@ class ODText extends AbstractReader implements ReaderInterface
$readerParts = array(
'content.xml' => 'Content',
'meta.xml' => 'Meta',
);
foreach ($readerParts as $xmlFile => $partName) {
@ -62,6 +63,7 @@ class ODText extends AbstractReader implements ReaderInterface
{
$partClass = "PhpOffice\\PhpWord\\Reader\\ODText\\{$partName}";
if (class_exists($partClass)) {
/** @var \PhpOffice\PhpWord\Reader\ODText\AbstractPart $part Type hint */
$part = new $partClass($docFile, $xmlFile);
$part->setRels($relationships);
$part->read($phpWord);

View File

@ -17,16 +17,33 @@
namespace PhpOffice\PhpWord\Reader\ODText;
use PhpOffice\PhpWord\Reader\Word2007\AbstractPart as Word2007AbstractPart;
use PhpOffice\PhpWord\Shared\XMLReader;
/**
* Abstract part reader
*/
abstract class AbstractPart extends \PhpOffice\PhpWord\Reader\Word2007\AbstractPart
abstract class AbstractPart extends Word2007AbstractPart
{
/**
* Read w:p (override)
*
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @param mixed $parent
* @param string $docPart
*
* @todo Get font style for preserve text
*/
protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart)
{
}
/**
* Read w:r (override)
*
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @param mixed $parent
* @param string $docPart
* @param mixed $paragraphStyle
@ -35,6 +52,18 @@ abstract class AbstractPart extends \PhpOffice\PhpWord\Reader\Word2007\AbstractP
{
}
/**
* Read w:tbl (override)
*
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @param mixed $parent
* @param string $docPart
*/
protected function readTable(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart)
{
}
/**
* Read w:pPr (override)
*/
@ -55,4 +84,16 @@ abstract class AbstractPart extends \PhpOffice\PhpWord\Reader\Word2007\AbstractP
protected function readTableStyle(XMLReader $xmlReader, \DOMElement $domNode)
{
}
/**
* Read style definition (override)
*
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $parentNode
* @param array $styleDefs
* @return array
*/
protected function readStyleDefs(XMLReader $xmlReader, \DOMElement $parentNode = null, $styleDefs = array())
{
}
}

View File

@ -22,6 +22,8 @@ use PhpOffice\PhpWord\Shared\XMLReader;
/**
* Content reader
*
* @since 0.10.0
*/
class Content extends AbstractPart
{

View File

@ -0,0 +1,79 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2010-2014 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Reader\ODText;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLReader;
/**
* Meta reader
*
* @since 0.11.0
*/
class Meta extends AbstractPart
{
/**
* Read meta.xml
*
* @param \PhpOffice\PhpWord\PhpWord $phpWord
* @todo Process property type
*/
public function read(PhpWord &$phpWord)
{
$xmlReader = new XMLReader();
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
$docProps = $phpWord->getDocumentProperties();
$metaNode = $xmlReader->getElement('office:meta');
// Standard properties
$properties = array(
'title' => 'dc:title',
'subject' => 'dc:subject',
'description' => 'dc:description',
'keywords' => 'meta:keyword',
'creator' => 'meta:initial-creator',
'lastModifiedBy' => 'dc:creator',
// 'created' => 'meta:creation-date',
// 'modified' => 'dc:date',
);
foreach ($properties as $property => $path) {
$method = "set{$property}";
$propertyNode = $xmlReader->getElement($path, $metaNode);
if ($propertyNode !== null && method_exists($docProps, $method)) {
$docProps->$method($propertyNode->nodeValue);
}
}
// Custom properties
$propertyNodes = $xmlReader->getElements('meta:user-defined', $metaNode);
foreach ($propertyNodes as $propertyNode) {
$property = $xmlReader->getAttribute('meta:name', $propertyNode);
// Set category, company, and manager property
if (in_array($property, array('Category', 'Company', 'Manager'))) {
$method = "set{$property}";
$docProps->$method($propertyNode->nodeValue);
// Set other custom properties
} else {
$docProps->setCustomProperty($property, $propertyNode->nodeValue);
}
}
}
}

View File

@ -25,15 +25,15 @@ interface ReaderInterface
/**
* Can the current ReaderInterface read the file?
*
* @param string $pFilename
* @param string $filename
* @return boolean
*/
public function canRead($pFilename);
public function canRead($filename);
/**
* Loads PhpWord from file
*
* @param string $pFilename
* @param string $filename
*/
public function load($pFilename);
public function load($filename);
}

View File

@ -18,8 +18,8 @@
namespace PhpOffice\PhpWord\Reader;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Shared\XMLReader;
use PhpOffice\PhpWord\Shared\ZipArchive;
/**
* Reader for Word2007
@ -87,6 +87,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
{
$partClass = "PhpOffice\\PhpWord\\Reader\\Word2007\\{$partName}";
if (class_exists($partClass)) {
/** @var \PhpOffice\PhpWord\Reader\Word2007\AbstractPart $part Type hint */
$part = new $partClass($docFile, $xmlFile);
$part->setRels($relationships);
$part->read($phpWord);
@ -109,8 +110,7 @@ class Word2007 extends AbstractReader implements ReaderInterface
// word/_rels/*.xml.rels
$wordRelsPath = 'word/_rels/';
$zipClass = Settings::getZipClass();
$zip = new $zipClass();
$zip = new ZipArchive();
if ($zip->open($docFile) === true) {
for ($i = 0; $i < $zip->numFiles; $i++) {
$xmlFile = $zip->getNameIndex($i);

View File

@ -22,9 +22,22 @@ use PhpOffice\PhpWord\Shared\XMLReader;
/**
* Abstract part reader
*
* This class is inherited by ODText reader
*/
abstract class AbstractPart
{
/**
* Conversion method
*
* @const int
*/
const READ_VALUE = 'attributeValue'; // Read attribute value
const READ_EQUAL = 'attributeEquals'; // Read `true` when attribute value equals specified value
const READ_TRUE = 'attributeTrue'; // Read `true` when element exists
const READ_FALSE = 'attributeFalse'; // Read `false` when element exists
const READ_SIZE = 'attributeMultiplyByTwo'; // Read special attribute value for Font::$size
/**
* Document file
*
@ -73,6 +86,96 @@ abstract class AbstractPart
$this->rels = $value;
}
/**
* Read w:p
*
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @param mixed $parent
* @param string $docPart
*
* @todo Get font style for preserve text
*/
protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart)
{
// Paragraph style
$paragraphStyle = null;
$headingMatches = array();
if ($xmlReader->elementExists('w:pPr', $domNode)) {
$paragraphStyle = $this->readParagraphStyle($xmlReader, $domNode);
if (is_array($paragraphStyle) && array_key_exists('styleName', $paragraphStyle)) {
preg_match('/Heading(\d)/', $paragraphStyle['styleName'], $headingMatches);
}
}
// PreserveText
if ($xmlReader->elementExists('w:r/w:instrText', $domNode)) {
$ignoreText = false;
$textContent = '';
$fontStyle = $this->readFontStyle($xmlReader, $domNode);
$nodes = $xmlReader->getElements('w:r', $domNode);
foreach ($nodes as $node) {
$instrText = $xmlReader->getValue('w:instrText', $node);
if ($xmlReader->elementExists('w:fldChar', $node)) {
$fldCharType = $xmlReader->getAttribute('w:fldCharType', $node, 'w:fldChar');
if ($fldCharType == 'begin') {
$ignoreText = true;
} elseif ($fldCharType == 'end') {
$ignoreText = false;
}
}
if (!is_null($instrText)) {
$textContent .= '{' . $instrText . '}';
} else {
if ($ignoreText === false) {
$textContent .= $xmlReader->getValue('w:t', $node);
}
}
}
$parent->addPreserveText($textContent, $fontStyle, $paragraphStyle);
// 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}", $paragraphStyle);
// Heading
} elseif (!empty($headingMatches)) {
$textContent = '';
$nodes = $xmlReader->getElements('w:r', $domNode);
foreach ($nodes as $node) {
$textContent .= $xmlReader->getValue('w:t', $node);
}
$parent->addTitle($textContent, $headingMatches[1]);
// Text and TextRun
} else {
$runCount = $xmlReader->countElements('w:r', $domNode);
$linkCount = $xmlReader->countElements('w:hyperlink', $domNode);
$runLinkCount = $runCount + $linkCount;
if ($runLinkCount == 0) {
$parent->addTextBreak(null, $paragraphStyle);
} else {
if ($runLinkCount > 1) {
$textrun = $parent->addTextRun($paragraphStyle);
$textParent = &$textrun;
} else {
$textParent = &$parent;
}
$nodes = $xmlReader->getElements('*', $domNode);
foreach ($nodes as $node) {
$this->readRun($xmlReader, $node, $textParent, $docPart, $paragraphStyle);
}
}
}
}
/**
* Read w:r
*
@ -135,143 +238,145 @@ abstract class AbstractPart
}
}
/**
* Read w:tbl
*
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @param mixed $parent
* @param string $docPart
*/
protected function readTable(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart)
{
// Table style
$tblStyle = null;
if ($xmlReader->elementExists('w:tblPr', $domNode)) {
$tblStyle = $this->readTableStyle($xmlReader, $domNode);
}
/** @var \PhpOffice\PhpWord\Element\Table $table Type hint */
$table = $parent->addTable($tblStyle);
$tblNodes = $xmlReader->getElements('*', $domNode);
foreach ($tblNodes as $tblNode) {
if ($tblNode->nodeName == 'w:tblGrid') { // Column
// @todo Do something with table columns
} elseif ($tblNode->nodeName == 'w:tr') { // Row
$rowHeight = $xmlReader->getAttribute('w:val', $tblNode, 'w:trPr/w:trHeight');
$rowHRule = $xmlReader->getAttribute('w:hRule', $tblNode, 'w:trPr/w:trHeight');
$rowHRule = $rowHRule == 'exact' ? true : false;
$rowStyle = array(
'tblHeader' => $xmlReader->elementExists('w:trPr/w:tblHeader', $tblNode),
'cantSplit' => $xmlReader->elementExists('w:trPr/w:cantSplit', $tblNode),
'exactHeight' => $rowHRule,
);
$row = $table->addRow($rowHeight, $rowStyle);
$rowNodes = $xmlReader->getElements('*', $tblNode);
foreach ($rowNodes as $rowNode) {
if ($rowNode->nodeName == 'w:trPr') { // Row style
// @todo Do something with row style
} elseif ($rowNode->nodeName == 'w:tc') { // Cell
$cellWidth = $xmlReader->getAttribute('w:w', $rowNode, 'w:tcPr/w:tcW');
$cellStyle = null;
$cellStyleNode = $xmlReader->getElement('w:tcPr', $rowNode);
if (!is_null($cellStyleNode)) {
$cellStyle = $this->readCellStyle($xmlReader, $cellStyleNode);
}
$cell = $row->addCell($cellWidth, $cellStyle);
$cellNodes = $xmlReader->getElements('*', $rowNode);
foreach ($cellNodes as $cellNode) {
if ($cellNode->nodeName == 'w:p') { // Paragraph
$this->readParagraph($xmlReader, $cellNode, $cell, $docPart);
}
}
}
}
}
}
}
/**
* Read w:pPr
*
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @return array|null
*/
protected function readParagraphStyle(XMLReader $xmlReader, \DOMElement $domNode)
{
if (!$xmlReader->elementExists('w:pPr', $domNode)) {
return;
return null;
}
$style = array();
$mapping = array(
'w:pStyle' => 'styleName',
'w:ind' => 'indent', 'w:spacing' => 'spacing',
'w:jc' => 'align', 'w:basedOn' => 'basedOn', 'w:next' => 'next',
'w:widowControl' => 'widowControl', 'w:keepNext' => 'keepNext',
'w:keepLines' => 'keepLines', 'w:pageBreakBefore' => 'pageBreakBefore',
$styleNode = $xmlReader->getElement('w:pPr', $domNode);
$styleDefs = array(
'styleName' => array(self::READ_VALUE, 'w:pStyle'),
'align' => array(self::READ_VALUE, 'w:jc'),
'basedOn' => array(self::READ_VALUE, 'w:basedOn'),
'next' => array(self::READ_VALUE, 'w:next'),
'indent' => array(self::READ_VALUE, 'w:ind', 'w:left'),
'hanging' => array(self::READ_VALUE, 'w:ind', 'w:hanging'),
'spaceAfter' => array(self::READ_VALUE, 'w:spacing', 'w:after'),
'spaceBefore' => array(self::READ_VALUE, 'w:spacing', 'w:before'),
'widowControl' => array(self::READ_FALSE, 'w:widowControl'),
'keepNext' => array(self::READ_TRUE, 'w:keepNext'),
'keepLines' => array(self::READ_TRUE, 'w:keepLines'),
'pageBreakBefore' => array(self::READ_TRUE, 'w:pageBreakBefore'),
);
$nodes = $xmlReader->getElements('w:pPr/*', $domNode);
foreach ($nodes as $node) {
if (!array_key_exists($node->nodeName, $mapping)) {
continue;
}
$property = $mapping[$node->nodeName];
switch ($node->nodeName) {
case 'w:ind':
$style['indent'] = $xmlReader->getAttribute('w:left', $node);
$style['hanging'] = $xmlReader->getAttribute('w:hanging', $node);
break;
case 'w:spacing':
$style['spaceAfter'] = $xmlReader->getAttribute('w:after', $node);
$style['spaceBefore'] = $xmlReader->getAttribute('w:before', $node);
// Commented. Need to adjust the number when return value is null
// $style['spacing'] = $xmlReader->getAttribute('w:line', $node);
break;
case 'w:keepNext':
case 'w:keepLines':
case 'w:pageBreakBefore':
$style[$property] = true;
break;
case 'w:widowControl':
$style[$property] = false;
break;
case 'w:pStyle':
case 'w:jc':
case 'w:basedOn':
case 'w:next':
$style[$property] = $xmlReader->getAttribute('w:val', $node);
break;
}
}
return $style;
return $this->readStyleDefs($xmlReader, $styleNode, $styleDefs);
}
/**
* Read w:rPr
*
* @return array|null
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @return array
*/
protected function readFontStyle(XMLReader $xmlReader, \DOMElement $domNode)
{
if (is_null($domNode)) {
return;
return null;
}
// Hyperlink has an extra w:r child
if ($domNode->nodeName == 'w:hyperlink') {
$domNode = $xmlReader->getElement('w:r', $domNode);
}
if (!$xmlReader->elementExists('w:rPr', $domNode)) {
return;
return null;
}
$style = array();
$mapping = array(
'w:rStyle' => 'styleName',
'w:b' => 'bold', 'w:i' => 'italic', 'w:color' => 'color',
'w:strike' => 'strikethrough', 'w:u' => 'underline',
'w:highlight' => 'fgColor', 'w:sz' => 'size',
'w:rFonts' => 'name', 'w:vertAlign' => 'superScript',
$styleNode = $xmlReader->getElement('w:rPr', $domNode);
$styleDefs = array(
'styleName' => array(self::READ_VALUE, 'w:rStyle'),
'name' => array(self::READ_VALUE, 'w:rFonts', 'w:ascii'),
'hint' => array(self::READ_VALUE, 'w:rFonts', 'w:hint'),
'size' => array(self::READ_SIZE, 'w:sz'),
'color' => array(self::READ_VALUE, 'w:color'),
'underline' => array(self::READ_VALUE, 'w:u'),
'bold' => array(self::READ_TRUE, 'w:b'),
'italic' => array(self::READ_TRUE, 'w:i'),
'strikethrough' => array(self::READ_TRUE, 'w:strike'),
'doubleStrikethrough' => array(self::READ_TRUE, 'w:dstrike'),
'smallCaps' => array(self::READ_TRUE, 'w:smallCaps'),
'allCaps' => array(self::READ_TRUE, 'w:caps'),
'superScript' => array(self::READ_EQUAL, 'w:vertAlign', 'w:val', 'superscript'),
'subScript' => array(self::READ_EQUAL, 'w:vertAlign', 'w:val', 'subscript'),
'fgColor' => array(self::READ_VALUE, 'w:highlight'),
);
$nodes = $xmlReader->getElements('w:rPr/*', $domNode);
foreach ($nodes as $node) {
if (!array_key_exists($node->nodeName, $mapping)) {
continue;
}
$property = $mapping[$node->nodeName];
switch ($node->nodeName) {
case 'w:rFonts':
$style['name'] = $xmlReader->getAttribute('w:ascii', $node);
$style['hint'] = $xmlReader->getAttribute('w:hint', $node);
break;
case 'w:b':
case 'w:i':
case 'w:strike':
$style[$property] = true;
break;
case 'w:rStyle':
case 'w:u':
case 'w:highlight':
case 'w:color':
$style[$property] = $xmlReader->getAttribute('w:val', $node);
break;
case 'w:sz':
$style[$property] = $xmlReader->getAttribute('w:val', $node) / 2;
break;
case 'w:vertAlign':
$style[$property] = $xmlReader->getAttribute('w:val', $node);
if ($style[$property] == 'superscript') {
$style['superScript'] = true;
} else {
$style['superScript'] = false;
$style['subScript'] = true;
}
break;
}
}
return $style;
return $this->readStyleDefs($xmlReader, $styleNode, $styleDefs);
}
/**
* Read w:tblPr
*
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @return string|array|null
* @todo Capture w:tblStylePr w:type="firstRow"
*/
@ -285,42 +390,85 @@ abstract class AbstractPart
if ($xmlReader->elementExists('w:tblPr/w:tblStyle', $domNode)) {
$style = $xmlReader->getAttribute('w:val', $domNode, 'w:tblPr/w:tblStyle');
} else {
$style = array();
$mapping = array(
'w:tblCellMar' => 'cellMargin',
'w:tblBorders' => 'border',
);
$nodes = $xmlReader->getElements('w:tblPr/*', $domNode);
foreach ($nodes as $node) {
if (!array_key_exists($node->nodeName, $mapping)) {
continue;
}
// $property = $mapping[$node->nodeName];
switch ($node->nodeName) {
case 'w:tblCellMar':
foreach ($margins as $side) {
$ucfSide = ucfirst($side);
$style["cellMargin$ucfSide"] = $xmlReader->getAttribute('w:w', $node, "w:$side");
}
break;
case 'w:tblBorders':
foreach ($borders as $side) {
$ucfSide = ucfirst($side);
$style["border{$ucfSide}Size"] = $xmlReader->getAttribute('w:sz', $node, "w:$side");
$style["border{$ucfSide}Color"] = $xmlReader->getAttribute('w:color', $node, "w:$side");
}
break;
}
$styleNode = $xmlReader->getElement('w:tblPr', $domNode);
$styleDefs = array();
// $styleDefs['styleName'] = array(self::READ_VALUE, 'w:tblStyle');
foreach ($margins as $side) {
$ucfSide = ucfirst($side);
$styleDefs["cellMargin$ucfSide"] = array(self::READ_VALUE, "w:tblCellMar/w:$side", 'w:w');
}
foreach ($borders as $side) {
$ucfSide = ucfirst($side);
$styleDefs["border{$ucfSide}Size"] = array(self::READ_VALUE, "w:tblBorders/w:$side", 'w:sz');
$styleDefs["border{$ucfSide}Color"] = array(self::READ_VALUE, "w:tblBorders/w:$side", 'w:color');
}
$style = $this->readStyleDefs($xmlReader, $styleNode, $styleDefs);
}
}
return $style;
}
/**
* Read w:tcPr
*
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @return array
*/
private function readCellStyle(XMLReader $xmlReader, \DOMElement $domNode)
{
$styleDefs = array(
'valign' => array(self::READ_VALUE, 'w:vAlign'),
'textDirection' => array(self::READ_VALUE, 'w:textDirection'),
'gridSpan' => array(self::READ_VALUE, 'w:gridSpan'),
'vMerge' => array(self::READ_VALUE, 'w:vMerge'),
'bgColor' => array(self::READ_VALUE, 'w:shd/w:fill'),
);
return $this->readStyleDefs($xmlReader, $domNode, $styleDefs);
}
/**
* Read style definition
*
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $parentNode
* @param array $styleDefs
* @return array
*/
protected function readStyleDefs(XMLReader $xmlReader, \DOMElement $parentNode = null, $styleDefs = array())
{
$styles = array();
foreach ($styleDefs as $styleProp => $styleVal) {
@list($method, $element, $attribute, $expected) = $styleVal;
if ($xmlReader->elementExists($element, $parentNode)) {
$node = $xmlReader->getElement($element, $parentNode);
// Use w:val as default if no attribute assigned
$attribute = ($attribute === null) ? 'w:val' : $attribute;
$attributeValue = $xmlReader->getAttribute($attribute, $node);
// Assign style value based on conversion model
if ($method == self::READ_VALUE) {
$styles[$styleProp] = $attributeValue;
} elseif ($method == self::READ_SIZE) {
$styles[$styleProp] = $attributeValue / 2;
} elseif ($method == self::READ_TRUE) {
$styles[$styleProp] = true;
} elseif ($method == self::READ_FALSE) {
$styles[$styleProp] = false;
} elseif ($method == self::READ_EQUAL && $attributeValue == $expected) {
$styles[$styleProp] = true;
}
}
}
return $styles;
}
/**
* Returns the target of image, object, or link as stored in ::readMainRels
*

View File

@ -56,9 +56,7 @@ class Document extends AbstractPart
if (!is_null($settingsNode)) {
$settings = $this->readSectionStyle($xmlReader, $settingsNode);
$section->setSettings($settings);
if (!is_null($settings)) {
$this->readHeaderFooter($settings, $section);
}
$this->readHeaderFooter($settings, $section);
}
$section = $phpWord->addSection();
}
@ -71,9 +69,7 @@ class Document extends AbstractPart
case 'w:sectPr': // Last section
$settings = $this->readSectionStyle($xmlReader, $node);
$section->setSettings($settings);
if (!is_null($settings)) {
$this->readHeaderFooter($settings, $section);
}
$this->readHeaderFooter($settings, $section);
break;
}
}
@ -118,241 +114,45 @@ class Document extends AbstractPart
}
}
/**
* Read w:p
*
* @param mixed $parent
* @param string $docPart
*
* @todo Get font style for preserve text
*/
private function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart)
{
// Paragraph style
$paragraphStyle = null;
$headingMatches = array();
if ($xmlReader->elementExists('w:pPr', $domNode)) {
$paragraphStyle = $this->readParagraphStyle($xmlReader, $domNode);
if (is_array($paragraphStyle) && array_key_exists('styleName', $paragraphStyle)) {
preg_match('/Heading(\d)/', $paragraphStyle['styleName'], $headingMatches);
}
}
// PreserveText
if ($xmlReader->elementExists('w:r/w:instrText', $domNode)) {
$ignoreText = false;
$textContent = '';
$fontStyle = $this->readFontStyle($xmlReader, $domNode);
$nodes = $xmlReader->getElements('w:r', $domNode);
foreach ($nodes as $node) {
$instrText = $xmlReader->getValue('w:instrText', $node);
if ($xmlReader->elementExists('w:fldChar', $node)) {
$fldCharType = $xmlReader->getAttribute('w:fldCharType', $node, 'w:fldChar');
if ($fldCharType == 'begin') {
$ignoreText = true;
} elseif ($fldCharType == 'end') {
$ignoreText = false;
}
}
if (!is_null($instrText)) {
$textContent .= '{' . $instrText . '}';
} else {
if ($ignoreText === false) {
$textContent .= $xmlReader->getValue('w:t', $node);
}
}
}
$parent->addPreserveText($textContent, $fontStyle, $paragraphStyle);
// 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}", $paragraphStyle);
// Heading
} elseif (!empty($headingMatches)) {
$textContent = '';
$nodes = $xmlReader->getElements('w:r', $domNode);
foreach ($nodes as $node) {
$textContent .= $xmlReader->getValue('w:t', $node);
}
$parent->addTitle($textContent, $headingMatches[1]);
// Text and TextRun
} else {
$runCount = $xmlReader->countElements('w:r', $domNode);
$linkCount = $xmlReader->countElements('w:hyperlink', $domNode);
$runLinkCount = $runCount + $linkCount;
if ($runLinkCount == 0) {
$parent->addTextBreak(null, $paragraphStyle);
} else {
if ($runLinkCount > 1) {
$textrun = $parent->addTextRun($paragraphStyle);
$textParent = &$textrun;
} else {
$textParent = &$parent;
}
$nodes = $xmlReader->getElements('*', $domNode);
foreach ($nodes as $node) {
$this->readRun($xmlReader, $node, $textParent, $docPart, $paragraphStyle);
}
}
}
}
/**
* Read w:tbl
*
* @param mixed $parent
* @param string $docPart
*/
private function readTable(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart)
{
// Table style
$tblStyle = null;
if ($xmlReader->elementExists('w:tblPr', $domNode)) {
$tblStyle = $this->readTableStyle($xmlReader, $domNode);
}
$table = $parent->addTable($tblStyle);
$tblNodes = $xmlReader->getElements('*', $domNode);
foreach ($tblNodes as $tblNode) {
if ($tblNode->nodeName == 'w:tblGrid') { // Column
// @todo Do something with table columns
} elseif ($tblNode->nodeName == 'w:tr') { // Row
$rowHeight = $xmlReader->getAttribute('w:val', $tblNode, 'w:trPr/w:trHeight');
$rowHRule = $xmlReader->getAttribute('w:hRule', $tblNode, 'w:trPr/w:trHeight');
$rowHRule = $rowHRule == 'exact' ? true : false;
$rowStyle = array(
'tblHeader' => $xmlReader->elementExists('w:trPr/w:tblHeader', $tblNode),
'cantSplit' => $xmlReader->elementExists('w:trPr/w:cantSplit', $tblNode),
'exactHeight' => $rowHRule,
);
$row = $table->addRow($rowHeight, $rowStyle);
$rowNodes = $xmlReader->getElements('*', $tblNode);
foreach ($rowNodes as $rowNode) {
if ($rowNode->nodeName == 'w:trPr') { // Row style
// @todo Do something with row style
} elseif ($rowNode->nodeName == 'w:tc') { // Cell
$cellWidth = $xmlReader->getAttribute('w:w', $rowNode, 'w:tcPr/w:tcW');
$cellStyle = null;
$cellStyleNode = $xmlReader->getElement('w:tcPr', $rowNode);
if (!is_null($cellStyleNode)) {
$cellStyle = $this->readCellStyle($xmlReader, $cellStyleNode);
}
$cell = $row->addCell($cellWidth, $cellStyle);
$cellNodes = $xmlReader->getElements('*', $rowNode);
foreach ($cellNodes as $cellNode) {
if ($cellNode->nodeName == 'w:p') { // Paragraph
$this->readParagraph($xmlReader, $cellNode, $cell, $docPart);
}
}
}
}
}
}
}
/**
* Read w:sectPr
*
* @return array|null
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @return array
*/
private function readSectionStyle(XMLReader $xmlReader, \DOMElement $domNode)
{
$ret = null;
$mapping = array(
'w:type' => 'breakType', 'w:pgSz' => 'pageSize',
'w:pgMar' => 'pageMargin', 'w:cols' => 'columns',
'w:headerReference' => 'header', 'w:footerReference' => 'footer',
$styleDefs = array(
'breakType' => array(self::READ_VALUE, 'w:type'),
'pageSizeW' => array(self::READ_VALUE, 'w:pgSz', 'w:w'),
'pageSizeH' => array(self::READ_VALUE, 'w:pgSz', 'w:h'),
'orientation' => array(self::READ_VALUE, 'w:pgSz', 'w:orient'),
'colsNum' => array(self::READ_VALUE, 'w:cols', 'w:num'),
'colsSpace' => array(self::READ_VALUE, 'w:cols', 'w:space'),
'topMargin' => array(self::READ_VALUE, 'w:pgMar', 'w:top'),
'leftMargin' => array(self::READ_VALUE, 'w:pgMar', 'w:left'),
'bottomMargin' => array(self::READ_VALUE, 'w:pgMar', 'w:bottom'),
'rightMargin' => array(self::READ_VALUE, 'w:pgMar', 'w:right'),
'headerHeight' => array(self::READ_VALUE, 'w:pgMar', 'w:header'),
'footerHeight' => array(self::READ_VALUE, 'w:pgMar', 'w:footer'),
'gutter' => array(self::READ_VALUE, 'w:pgMar', 'w:gutter'),
);
$styles = $this->readStyleDefs($xmlReader, $domNode, $styleDefs);
// Header and footer
// @todo Cleanup this part
$nodes = $xmlReader->getElements('*', $domNode);
foreach ($nodes as $node) {
if (!array_key_exists($node->nodeName, $mapping)) {
continue;
}
$property = $mapping[$node->nodeName];
switch ($node->nodeName) {
case 'w:type':
$ret['breakType'] = $xmlReader->getAttribute('w:val', $node);
break;
case 'w:pgSz':
$ret['pageSizeW'] = $xmlReader->getAttribute('w:w', $node);
$ret['pageSizeH'] = $xmlReader->getAttribute('w:h', $node);
$ret['orientation'] = $xmlReader->getAttribute('w:orient', $node);
break;
case 'w:pgMar':
$ret['topMargin'] = $xmlReader->getAttribute('w:top', $node);
$ret['leftMargin'] = $xmlReader->getAttribute('w:left', $node);
$ret['bottomMargin'] = $xmlReader->getAttribute('w:bottom', $node);
$ret['rightMargin'] = $xmlReader->getAttribute('w:right', $node);
$ret['headerHeight'] = $xmlReader->getAttribute('w:header', $node);
$ret['footerHeight'] = $xmlReader->getAttribute('w:footer', $node);
$ret['gutter'] = $xmlReader->getAttribute('w:gutter', $node);
break;
case 'w:cols':
$ret['colsNum'] = $xmlReader->getAttribute('w:num', $node);
$ret['colsSpace'] = $xmlReader->getAttribute('w:space', $node);
break;
case 'w:headerReference':
case 'w:footerReference':
$id = $xmlReader->getAttribute('r:id', $node);
$ret['hf'][$id] = array(
'method' => $property,
'type' => $xmlReader->getAttribute('w:type', $node),
);
break;
if ($node->nodeName == 'w:headerReference' || $node->nodeName == 'w:footerReference') {
$id = $xmlReader->getAttribute('r:id', $node);
$styles['hf'][$id] = array(
'method' => str_replace('w:', '', str_replace('Reference', '', $node->nodeName)),
'type' => $xmlReader->getAttribute('w:type', $node),
);
}
}
return $ret;
}
/**
* Read w:tcPr
*
* @return array|null
*/
private function readCellStyle(XMLReader $xmlReader, \DOMElement $domNode)
{
$style = null;
$mapping = array(
'w:shd' => 'bgColor',
'w:vAlign' => 'valign', 'w:textDirection' => 'textDirection',
'w:gridSpan' => 'gridSpan', 'w:vMerge' => 'vMerge',
);
$nodes = $xmlReader->getElements('*', $domNode);
foreach ($nodes as $node) {
if (!array_key_exists($node->nodeName, $mapping)) {
continue;
}
$property = $mapping[$node->nodeName];
switch ($node->nodeName) {
case 'w:shd':
$style['bgColor'] = $xmlReader->getAttribute('w:fill', $node);
break;
default:
$style[$property] = $xmlReader->getAttribute('w:val', $node);
break;
}
}
return $style;
return $styles;
}
}

View File

@ -87,6 +87,8 @@ class Numbering extends AbstractPart
/**
* Read numbering level definition from w:abstractNum and w:num
*
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $subnode
* @param integer $levelId
* @return array
*/

View File

@ -29,8 +29,9 @@ class Settings
*
* @const string
*/
const PCLZIP = 'PhpOffice\\PhpWord\\Shared\\ZipArchive';
const ZIPARCHIVE = 'ZipArchive';
const PCLZIP = 'PclZip';
const OLD_LIB = 'PhpOffice\\PhpWord\\Shared\\ZipArchive'; // @deprecated 0.11
/**
* PDF rendering libraries
@ -38,6 +39,8 @@ class Settings
* @const string
*/
const PDF_RENDERER_DOMPDF = 'DomPDF';
const PDF_RENDERER_TCPDF = 'TCPDF';
const PDF_RENDERER_MPDF = 'MPDF';
/**
* Measurement units multiplication factor
@ -48,14 +51,25 @@ class Settings
* - Indentation: left, right, firstLine, hanging
* - Spacing: before, after
*
* @const int|float
* @const string
*/
const UNIT_TWIP = 1; // = 1/20 point
const UNIT_CM = 567;
const UNIT_MM = 56.7;
const UNIT_INCH = 1440;
const UNIT_POINT = 20; // = 1/72 inch
const UNIT_PICA = 240; // = 1/6 inch = 12 points
const UNIT_TWIP = 'twip'; // = 1/20 point
const UNIT_CM = 'cm';
const UNIT_MM = 'mm';
const UNIT_INCH = 'inch';
const UNIT_POINT = 'point'; // = 1/72 inch
const UNIT_PICA = 'pica'; // = 1/6 inch = 12 points
/**
* Default font settings
*
* OOXML defined font size values in halfpoints, i.e. twice of what PhpWord
* use, and the conversion will be conducted during XML writing.
*/
const DEFAULT_FONT_NAME = 'Arial';
const DEFAULT_FONT_SIZE = 10;
const DEFAULT_FONT_COLOR = '000000';
const DEFAULT_FONT_CONTENT_TYPE = 'default'; // default|eastAsia|cs
/**
* Compatibility option for XMLWriter
@ -71,13 +85,6 @@ class Settings
*/
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
*
@ -95,10 +102,23 @@ class Settings
/**
* Measurement unit
*
* @var string
* @var int|float
*/
private static $measurementUnit = self::UNIT_TWIP;
/**
* Default font name
*
* @var string
*/
private static $defaultFontName = self::DEFAULT_FONT_NAME;
/**
* Default font size
* @var int
*/
private static $defaultFontSize = self::DEFAULT_FONT_SIZE;
/**
* Return the compatibility option used by the XMLWriter
*
@ -119,12 +139,10 @@ class Settings
*/
public static function setCompatibility($compatibility)
{
if (is_bool($compatibility)) {
self::$xmlWriterCompatibility = $compatibility;
return true;
}
$compatibility = (bool)$compatibility;
self::$xmlWriterCompatibility = $compatibility;
return false;
return true;
}
/**
@ -145,8 +163,7 @@ class Settings
*/
public static function setZipClass($zipClass)
{
if (($zipClass === self::PCLZIP) ||
($zipClass === self::ZIPARCHIVE)) {
if (in_array($zipClass, array(self::PCLZIP, self::ZIPARCHIVE, self::OLD_LIB))) {
self::$zipClass = $zipClass;
return true;
}
@ -186,7 +203,8 @@ class Settings
*/
public static function setPdfRendererName($libraryName)
{
if (!in_array($libraryName, self::$pdfRenderers)) {
$pdfRenderers = array(self::PDF_RENDERER_DOMPDF, self::PDF_RENDERER_TCPDF, self::PDF_RENDERER_MPDF);
if (!in_array($libraryName, $pdfRenderers)) {
return false;
}
self::$pdfRendererName = $libraryName;
@ -222,7 +240,7 @@ class Settings
/**
* Get measurement unit
*
* @return int|float
* @return string
*/
public static function getMeasurementUnit()
{
@ -232,7 +250,7 @@ class Settings
/**
* Set measurement unit
*
* @param int|float $value
* @param string $value
* @return bool
*/
public static function setMeasurementUnit($value)
@ -247,6 +265,102 @@ class Settings
return true;
}
/**
* Get default font name
*
* @return string
*/
public static function getDefaultFontName()
{
return self::$defaultFontName;
}
/**
* Set default font name
*
* @param string $value
* @return bool
*/
public static function setDefaultFontName($value)
{
if (is_string($value) && trim($value) !== '') {
self::$defaultFontName = $value;
return true;
}
return false;
}
/**
* Get default font size
*
* @return integer
*/
public static function getDefaultFontSize()
{
return self::$defaultFontSize;
}
/**
* Set default font size
*
* @param int $value
* @return bool
*/
public static function setDefaultFontSize($value)
{
$value = intval($value);
if ($value > 0) {
self::$defaultFontSize = $value;
return true;
}
return false;
}
/**
* Load setting from phpword.yml or phpword.yml.dist
*
* @param string $filename
* @return array
*/
public static function loadConfig($filename = null)
{
// Get config file
$configFile = null;
$configPath = __DIR__ . '/../../';
if ($filename !== null) {
$files = array($filename);
} else {
$files = array("{$configPath}phpword.ini", "{$configPath}phpword.ini.dist");
}
foreach ($files as $file) {
if (file_exists($file)) {
$configFile = realpath($file);
break;
}
}
// Parse config file
$config = array();
if ($configFile !== null) {
$config = parse_ini_file($configFile);
if ($config === false) {
return $config;
}
}
// Set config value
foreach ($config as $key => $value) {
$method = "set{$key}";
if (method_exists(__CLASS__, $method)) {
self::$method($value);
}
}
return $config;
}
/**
* Return the compatibility option used by the XMLWriter
*

View File

@ -27,9 +27,8 @@ class Html
*
* Note: $stylesheet parameter is removed to avoid PHPMD error for unused parameter
*
* @param \PhpOffice\PhpWord\Element\AbstractElement $object Where the parts need to be added
* @param \PhpOffice\PhpWord\Element\AbstractContainer $object Where the parts need to be added
* @param string $html the code to parse
*
*/
public static function addHtml($object, $html)
{
@ -53,7 +52,7 @@ class Html
*
* @param \DOMNode $node Node to check on attributes and to compile a style array
* @param array $style is supplied, the inline style attributes are added to the already existing style
*
* @return array
*/
protected static function parseInlineStyle($node, $style = array())
{
@ -93,6 +92,7 @@ class Html
}
}
}
return $style;
}
@ -100,10 +100,9 @@ class Html
* parse a node and add a corresponding element to the object
*
* @param \DOMNode $node node to parse
* @param \PhpOffice\PhpWord\Element\AbstractElement $object object to add an element corresponding with the node
* @param \PhpOffice\PhpWord\Element\AbstractContainer $object object to add an element corresponding with the node
* @param array $styles Array with all styles
* @param array $data Array to transport data to a next level in the DOM tree, for example level of listitems
*
*/
protected static function parseNode(
$node,
@ -171,17 +170,26 @@ class Html
case 'table':
$styles['paragraphStyle'] = self::parseInlineStyle($node, $styles['paragraphStyle']);
$newobject = $object->addTable();
// if ($attributes->getNamedItem('width') !== null)$newobject->setWidth($attributes->getNamedItem('width')->value);
// if ($attributes->getNamedItem('width') !== null) {
// $newobject->setWidth($attributes->getNamedItem('width')->value);
// }
break;
case 'tr':
/** @var \PhpOffice\PhpWord\Element\Table $object Type hint */
$styles['paragraphStyle'] = self::parseInlineStyle($node, $styles['paragraphStyle']);
$newobject = $object->addRow();
// if ($attributes->getNamedItem('height') !== null)$newobject->setHeight($attributes->getNamedItem('height')->value);
// if ($attributes->getNamedItem('height') !== null) {
// $newobject->setHeight($attributes->getNamedItem('height')->value);
// }
break;
case 'td':
/** @var \PhpOffice\PhpWord\Element\Row $object Type hint */
$styles['paragraphStyle'] = self::parseInlineStyle($node, $styles['paragraphStyle']);
// if ($attributes->getNamedItem('width') !== null)$newobject=$object->addCell($width=$attributes->getNamedItem('width')->value);
// else $newobject=$object->addCell();
// if ($attributes->getNamedItem('width') !== null) {
// $newobject=$object->addCell($width=$attributes->getNamedItem('width')->value);
// } else {
// $newobject=$object->addCell();
// }
$newobject = $object->addCell();
break;
case 'ul':
@ -207,12 +215,19 @@ class Html
case 'li':
$cNodes = $node->childNodes;
if (count($cNodes) > 0) {
$text = '';
foreach ($cNodes as $cNode) {
if ($cNode->nodeName == '#text') {
$text = $cNode->nodeValue;
}
}
$object->addListItem($text, $data['listdepth'], $styles['fontStyle'], $styles['listStyle'], $styles['paragraphStyle']);
$object->addListItem(
$text,
$data['listdepth'],
$styles['fontStyle'],
$styles['listStyle'],
$styles['paragraphStyle']
);
}
}

View File

@ -85,6 +85,54 @@ class String
return $value;
}
/**
* Returns unicode from UTF8 text
*
* @param string $text UTF8 text
* @return string Unicode text
* @since 0.11.0
* @link http://www.randomchaos.com/documents/?source=php_and_unicode
*/
public static function toUnicode($text)
{
$unicode = array();
$values = array();
$lookingFor = 1;
// Gets unicode for each character
for ($i = 0; $i < strlen($text); $i++) {
$thisValue = ord($text[$i]);
if ($thisValue < 128) {
$unicode[] = $thisValue;
} else {
if (count($values) == 0) {
$lookingFor = $thisValue < 224 ? 2 : 3;
}
$values[] = $thisValue;
if (count($values) == $lookingFor) {
if ($lookingFor == 3) {
$number = (($values[0] % 16) * 4096) + (($values[1] % 64) * 64) + ($values[2] % 64);
} else {
$number = (($values[0] % 32) * 64) + ($values[1] % 64);
}
$unicode[] = $number;
$values = array();
$lookingFor = 1;
}
}
}
// Converts text with utf8 characters into rtf utf8 entites preserving ascii
$entities = '';
foreach ($unicode as $value) {
if ($value != 65279) {
$entities .= $value > 127 ? '\uc0{\u' . $value . '}' : chr($value);
}
}
return $entities;
}
/**
* Return name without underscore for < 0.10.0 variable name compatibility
*

View File

@ -18,7 +18,6 @@
namespace PhpOffice\PhpWord\Shared;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Settings;
/**
* XML Reader wrapper
@ -47,6 +46,7 @@ class XMLReader
* @param string $zipFile
* @param string $xmlFile
* @return \DOMDocument|false
* @throws \PhpOffice\PhpWord\Exception\Exception
*/
public function getDomFromZip($zipFile, $xmlFile)
{
@ -54,12 +54,8 @@ class XMLReader
throw new Exception('Cannot find archive file.');
}
$zipClass = Settings::getZipClass();
$zip = new $zipClass();
$canOpen = $zip->open($zipFile);
if ($canOpen === false) {
throw new Exception('Cannot open archive file.');
}
$zip = new ZipArchive();
$zip->open($zipFile);
$contents = $zip->getFromName($xmlFile);
$zip->close();
@ -76,6 +72,7 @@ class XMLReader
* Get elements
*
* @param string $path
* @param \DOMElement $contextNode
* @return \DOMNodeList
*/
public function getElements($path, \DOMElement $contextNode = null)
@ -94,9 +91,10 @@ class XMLReader
* Get element
*
* @param string $path
* @param \DOMElement $contextNode
* @return \DOMElement|null
*/
public function getElement($path, \DOMElement $contextNode)
public function getElement($path, \DOMElement $contextNode = null)
{
$elements = $this->getElements($path, $contextNode);
if ($elements->length > 0) {
@ -110,19 +108,23 @@ class XMLReader
* Get element attribute
*
* @param string $attribute
* @param \DOMElement $contextNode
* @param string $path
* @return string|null
*/
public function getAttribute($attribute, \DOMElement $contextNode, $path = null)
public function getAttribute($attribute, \DOMElement $contextNode = null, $path = null)
{
if (is_null($path)) {
$return = $contextNode->getAttribute($attribute);
} else {
$return = null;
if ($path !== null) {
$elements = $this->getElements($path, $contextNode);
if ($elements->length > 0) {
$return = $elements->item(0)->getAttribute($attribute);
} else {
$return = null;
/** @var \DOMElement $node Type hint */
$node = $elements->item(0);
$return = $node->getAttribute($attribute);
}
} else {
if ($contextNode !== null) {
$return = $contextNode->getAttribute($attribute);
}
}
@ -133,9 +135,10 @@ class XMLReader
* Get element value
*
* @param string $path
* @param \DOMElement $contextNode
* @return string|null
*/
public function getValue($path, \DOMElement $contextNode)
public function getValue($path, \DOMElement $contextNode = null)
{
$elements = $this->getElements($path, $contextNode);
if ($elements->length > 0) {
@ -149,9 +152,10 @@ class XMLReader
* Count elements
*
* @param string $path
* @param \DOMElement $contextNode
* @return integer
*/
public function countElements($path, \DOMElement $contextNode)
public function countElements($path, \DOMElement $contextNode = null)
{
$elements = $this->getElements($path, $contextNode);
@ -162,9 +166,10 @@ class XMLReader
* Element exists
*
* @param string $path
* @param \DOMElement $contextNode
* @return boolean
*/
public function elementExists($path, \DOMElement $contextNode)
public function elementExists($path, \DOMElement $contextNode = null)
{
return $this->getElements($path, $contextNode)->length > 0;
}

View File

@ -19,21 +19,16 @@ namespace PhpOffice\PhpWord\Shared;
use PhpOffice\PhpWord\Settings;
// @codeCoverageIgnoreStart
if (!defined('DATE_W3C')) {
define('DATE_W3C', 'Y-m-d\TH:i:sP');
}
// @codeCoverageIgnoreEnd
/**
* XMLWriter wrapper
*
* @method bool writeElement(string $name, string $content = null)
* @method bool startElement(string $name)
* @method bool writeAttribute(string $name, string $value)
* @method bool endElement()
* @method bool startDocument(string $version = 1.0, string $encoding = null, string $standalone = null)
* @method bool startElement(string $name)
* @method bool text(string $content)
* @method bool writeAttribute(string $name, mixed $value)
* @method bool writeElement(string $name, string $content = null)
* @method bool writeRaw(string $content)
*/
class XMLWriter
{
@ -63,6 +58,11 @@ class XMLWriter
*/
public function __construct($tempLocation = self::STORAGE_MEMORY, $tempFolder = './')
{
// Define date format
if (!defined('DATE_W3C')) {
define('DATE_W3C', 'Y-m-d\TH:i:sP');
}
// Create internal XMLWriter
$this->xmlWriter = new \XMLWriter();
@ -135,32 +135,17 @@ class XMLWriter
}
}
/**
* Fallback method for writeRaw, introduced in PHP 5.2
*
* @param string $text
* @return bool
*/
public function writeRaw($text)
{
if (isset($this->xmlWriter) && is_object($this->xmlWriter) && (method_exists($this->xmlWriter, 'writeRaw'))) {
return $this->xmlWriter->writeRaw($text);
}
return $this->text($text);
}
/**
* Write element if ...
*
* @param bool $condition
* @param string $element
* @param string $attribute
* @param string $value
* @param mixed $value
*/
public function writeElementIf($condition, $element, $attribute = null, $value = null)
{
if ($condition) {
if ($condition == true) {
if (is_null($attribute)) {
$this->xmlWriter->writeElement($element, $value);
} else {
@ -176,11 +161,11 @@ class XMLWriter
*
* @param bool $condition
* @param string $attribute
* @param string $value
* @param mixed $value
*/
public function writeAttributeIf($condition, $attribute, $value)
{
if ($condition) {
if ($condition == true) {
$this->xmlWriter->writeAttribute($attribute, $value);
}
}

View File

@ -17,32 +17,43 @@
namespace PhpOffice\PhpWord\Shared;
// PCLZIP needs the temp path to end in a back slash
// @codeCoverageIgnoreStart
if (!defined('PCLZIP_TEMPORARY_DIR')) {
define('PCLZIP_TEMPORARY_DIR', sys_get_temp_dir() . '/');
}
require_once 'PCLZip/pclzip.lib.php';
// @codeCoverageIgnoreEnd
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Settings;
/**
* PCLZip wrapper
* ZipArchive wrapper
*
* Wraps zip archive functionality of PHP ZipArchive and PCLZip. PHP ZipArchive
* properties and methods are bypassed and used as the model for the PCLZip
* emulation. Only needed PHP ZipArchive features are implemented.
*
* @method bool addFile(string $filename, string $localname = null)
* @method bool addFromString(string $localname, string $contents)
* @method string getNameIndex(int $index)
* @method int locateName(string $name)
*
* @since 0.10.0
*/
class ZipArchive
{
/** constants */
const OVERWRITE = 'OVERWRITE';
const CREATE = 'CREATE';
/** @const int Flags for open method */
const CREATE = 1; // Emulate \ZipArchive::CREATE
const OVERWRITE = 8; // Emulate \ZipArchive::OVERWRITE
/**
* Number of files (emulate ZipArchive::$numFiles)
*
* @var string
* @var int
*/
public $numFiles = 0;
/**
* Archive filename (emulate ZipArchive::$filename)
*
* @var string
*/
public $filename;
/**
* Temporary storage directory
*
@ -51,44 +62,161 @@ class ZipArchive
private $tempDir;
/**
* Zip Archive Stream Handle
* Internal zip archive object
*
* @var string
* @var \ZipArchive|\PclZip
*/
private $zip;
/**
* Use PCLZip (default behaviour)
*
* @var bool
*/
private $usePclzip = true;
/**
* Create new instance
*/
public function __construct()
{
$this->usePclzip = (Settings::getZipClass() != 'ZipArchive');
if ($this->usePclzip) {
if (!defined('PCLZIP_TEMPORARY_DIR')) {
define('PCLZIP_TEMPORARY_DIR', sys_get_temp_dir() . '/');
}
require_once 'PCLZip/pclzip.lib.php';
}
}
/**
* Catch function calls: pass to ZipArchive or PCLZip
*
* `call_user_func_array` can only used for public function, hence the `public` in all `pcl...` methods
*
* @param mixed $function
* @param mixed $args
* @return mixed
*/
public function __call($function, $args)
{
// Set object and function
$zipFunction = $function;
if (!$this->usePclzip) {
$zipObject = $this->zip;
} else {
$zipObject = $this;
$zipFunction = "pclzip{$zipFunction}";
}
// Run function
$result = false;
if (method_exists($zipObject, $zipFunction)) {
$result = @call_user_func_array(array($zipObject, $zipFunction), $args);
}
return $result;
}
/**
* Open a new zip archive
*
* @param string $filename Filename for the zip archive
* @return boolean
* @param string $filename The file name of the ZIP archive to open
* @param int $flags The mode to use to open the archive
* @return bool
*/
public function open($filename)
public function open($filename, $flags = null)
{
$this->tempDir = sys_get_temp_dir();
$this->zip = new \PclZip($filename);
$this->numFiles = count($this->zip->listContent());
$result = true;
$this->filename = $filename;
if (!$this->usePclzip) {
$zip = new \ZipArchive();
$result = $zip->open($this->filename, $flags);
// Scrutizer will report the property numFiles does not exist
// See https://github.com/scrutinizer-ci/php-analyzer/issues/190
$this->numFiles = $zip->numFiles;
} else {
$zip = new \PclZip($this->filename);
$this->tempDir = sys_get_temp_dir();
$this->numFiles = count($zip->listContent());
}
$this->zip = $zip;
return $result;
}
/**
* Close the active archive
*
* @return bool
* @throws \PhpOffice\PhpWord\Exception\Exception
*/
public function close()
{
if (!$this->usePclzip) {
if ($this->zip->close() === false) {
throw new Exception("Could not close zip file $this->filename.");
}
}
return true;
}
/**
* Close this zip archive (emulate \ZipArchive)
* Extract the archive contents (emulate \ZipArchive)
*
* @codeCoverageIgnore
* @param string $destination
* @param string|array $entries
* @return bool
* @since 0.10.0
*/
public function close()
public function extractTo($destination, $entries = null)
{
if (!is_dir($destination)) {
return false;
}
if (!$this->usePclzip) {
return $this->zip->extractTo($destination, $entries);
} else {
return $this->pclzipExtractTo($destination, $entries);
}
}
/**
* Extract file from archive by given file name (emulate \ZipArchive)
*
* @param string $filename Filename for the file in zip archive
* @return string $contents File string contents
*/
public function getFromName($filename)
{
if (!$this->usePclzip) {
$contents = $this->zip->getFromName($filename);
if ($contents === false) {
$filename = substr($filename, 1);
$contents = $this->zip->getFromName($filename);
}
} else {
$contents = $this->pclzipGetFromName($filename);
}
return $contents;
}
/**
* Add a new file to the zip archive (emulate \ZipArchive)
*
* @param string $filename Directory/Name of the file to add to the zip archive
* @param string $filename Directory/Name of the file to add to the zip archive
* @param string $localname Directory/Name of the file added to the zip
* @return bool
*/
public function addFile($filename, $localname = null)
public function pclzipAddFile($filename, $localname = null)
{
/** @var \PclZip $zip Type hint */
$zip = $this->zip;
$filename = realpath($filename);
$filenameParts = pathinfo($filename);
$localnameParts = pathinfo($localname);
@ -102,13 +230,10 @@ class ZipArchive
$filenameParts = pathinfo($temppath);
}
$res = $this->zip->add(
$filename,
PCLZIP_OPT_REMOVE_PATH,
$filenameParts['dirname'],
PCLZIP_OPT_ADD_PATH,
$localnameParts["dirname"]
);
$pathRemoved = $filenameParts['dirname'];
$pathAdded = $localnameParts['dirname'];
$res = $zip->add($filename, PCLZIP_OPT_REMOVE_PATH, $pathRemoved, PCLZIP_OPT_ADD_PATH, $pathAdded);
return ($res == 0) ? false : true;
}
@ -117,10 +242,13 @@ class ZipArchive
* Add a new file to the zip archive from a string of raw data (emulate \ZipArchive)
*
* @param string $localname Directory/Name of the file to add to the zip archive
* @param string $contents String of data to add to the zip archive
* @param string $contents String of data to add to the zip archive
* @return bool
*/
public function addFromString($localname, $contents)
public function pclzipAddFromString($localname, $contents)
{
/** @var \PclZip $zip Type hint */
$zip = $this->zip;
$filenameParts = pathinfo($localname);
// Write $contents to a temp file
@ -129,13 +257,11 @@ class ZipArchive
fclose($handle);
// Add temp file to zip
$res = $this->zip->add(
$this->tempDir . '/' . $filenameParts["basename"],
PCLZIP_OPT_REMOVE_PATH,
$this->tempDir,
PCLZIP_OPT_ADD_PATH,
$filenameParts["dirname"]
);
$filename = $this->tempDir . '/' . $filenameParts["basename"];
$pathRemoved = $this->tempDir;
$pathAdded = $filenameParts['dirname'];
$res = $zip->add($filename, PCLZIP_OPT_REMOVE_PATH, $pathRemoved, PCLZIP_OPT_ADD_PATH, $pathAdded);
// Remove temp file
@unlink($this->tempDir . '/' . $filenameParts["basename"]);
@ -143,15 +269,97 @@ class ZipArchive
return ($res == 0) ? false : true;
}
/**
* Extract the archive contents (emulate \ZipArchive)
*
* @param string $destination
* @param string|array $entries
* @return bool
* @since 0.10.0
*/
public function pclzipExtractTo($destination, $entries = null)
{
/** @var \PclZip $zip Type hint */
$zip = $this->zip;
// Extract all files
if (is_null($entries)) {
$result = $zip->extract(PCLZIP_OPT_PATH, $destination);
return ($result > 0) ? true : false;
}
// Extract by entries
if (!is_array($entries)) {
$entries = array($entries);
}
foreach ($entries as $entry) {
$entryIndex = $this->locateName($entry);
$result = $zip->extractByIndex($entryIndex, PCLZIP_OPT_PATH, $destination);
if ($result <= 0) {
return false;
}
}
return true;
}
/**
* Extract file from archive by given file name (emulate \ZipArchive)
*
* @param string $filename Filename for the file in zip archive
* @return string $contents File string contents
*/
public function pclzipGetFromName($filename)
{
/** @var \PclZip $zip Type hint */
$zip = $this->zip;
$listIndex = $this->pclzipLocateName($filename);
$contents = false;
if ($listIndex !== false) {
$extracted = $zip->extractByIndex($listIndex, PCLZIP_OPT_EXTRACT_AS_STRING);
} else {
$filename = substr($filename, 1);
$listIndex = $this->pclzipLocateName($filename);
$extracted = $zip->extractByIndex($listIndex, PCLZIP_OPT_EXTRACT_AS_STRING);
}
if ((is_array($extracted)) && ($extracted != 0)) {
$contents = $extracted[0]["content"];
}
return $contents;
}
/**
* Returns the name of an entry using its index (emulate \ZipArchive)
*
* @param int $index
* @return string
* @since 0.10.0
*/
public function pclzipGetNameIndex($index)
{
/** @var \PclZip $zip Type hint */
$zip = $this->zip;
$list = $zip->listContent();
if (isset($list[$index])) {
return $list[$index]['filename'];
} else {
return false;
}
}
/**
* Returns the index of the entry in the archive (emulate \ZipArchive)
*
* @param string $filename Filename for the file in zip archive
* @return integer|false
* @return int
*/
public function locateName($filename)
public function pclzipLocateName($filename)
{
$list = $this->zip->listContent();
/** @var \PclZip $zip Type hint */
$zip = $this->zip;
$list = $zip->listContent();
$listCount = count($list);
$listIndex = -1;
for ($i = 0; $i < $listCount; ++$i) {
@ -164,81 +372,4 @@ class ZipArchive
return ($listIndex > -1) ? $listIndex : false;
}
/**
* Extract file from archive by given file name (emulate \ZipArchive)
*
* @param string $filename Filename for the file in zip archive
* @return string|false $contents File string contents
*/
public function getFromName($filename)
{
$listIndex = $this->locateName($filename);
$contents = false;
if ($listIndex !== false) {
$extracted = $this->zip->extractByIndex($listIndex, PCLZIP_OPT_EXTRACT_AS_STRING);
} else {
$filename = substr($filename, 1);
$listIndex = $this->locateName($filename);
$extracted = $this->zip->extractByIndex($listIndex, PCLZIP_OPT_EXTRACT_AS_STRING);
}
if ((is_array($extracted)) && ($extracted != 0)) {
$contents = $extracted[0]["content"];
}
return $contents;
}
/**
* Returns the name of an entry using its index (emulate \ZipArchive)
*
* @param integer $index
* @return string|false
* @since 0.10.0
*/
public function getNameIndex($index)
{
$list = $this->zip->listContent();
if (isset($list[$index])) {
return $list[$index]['filename'];
} else {
return false;
}
}
/**
* Extract the archive contents (emulate \ZipArchive)
*
* @param string $destination
* @param string|array $entries
* @return boolean
* @since 0.10.0
*/
public function extractTo($destination, $entries = null)
{
if (!is_dir($destination)) {
return false;
}
// Extract all files
if (is_null($entries)) {
$result = $this->zip->extract(PCLZIP_OPT_PATH, $destination);
return ($result > 0) ? true : false;
}
// Extract by entries
if (!is_array($entries)) {
$entries = array($entries);
}
foreach ($entries as $entry) {
$entryIndex = $this->locateName($entry);
$result = $this->zip->extractByIndex($entryIndex, PCLZIP_OPT_PATH, $destination);
if ($result <= 0) {
return false;
}
}
return true;
}
}

View File

@ -17,6 +17,7 @@
namespace PhpOffice\PhpWord;
use PhpOffice\PhpWord\Style\AbstractStyle;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Style\Numbering;
use PhpOffice\PhpWord\Style\Paragraph;
@ -39,10 +40,11 @@ class Style
*
* @param string $styleName
* @param array $styles
* @return \PhpOffice\PhpWord\Style\Paragraph
*/
public static function addParagraphStyle($styleName, $styles)
{
self::setStyleValues($styleName, new Paragraph(), $styles);
return self::setStyleValues($styleName, new Paragraph(), $styles);
}
/**
@ -51,10 +53,11 @@ class Style
* @param string $styleName
* @param array $fontStyle
* @param array $paragraphStyle
* @return \PhpOffice\PhpWord\Style\Font
*/
public static function addFontStyle($styleName, $fontStyle, $paragraphStyle = null)
{
self::setStyleValues($styleName, new Font('text', $paragraphStyle), $fontStyle);
return self::setStyleValues($styleName, new Font('text', $paragraphStyle), $fontStyle);
}
/**
@ -62,10 +65,37 @@ class Style
*
* @param string $styleName
* @param array $styles
* @return \PhpOffice\PhpWord\Style\Font
*/
public static function addLinkStyle($styleName, $styles)
{
self::setStyleValues($styleName, new Font('link'), $styles);
return self::setStyleValues($styleName, new Font('link'), $styles);
}
/**
* Add numbering style
*
* @param string $styleName
* @param array $styleValues
* @return \PhpOffice\PhpWord\Style\Numbering
* @since 0.10.0
*/
public static function addNumberingStyle($styleName, $styleValues)
{
return self::setStyleValues($styleName, new Numbering(), $styleValues);
}
/**
* Add title style
*
* @param int $depth
* @param array $fontStyle
* @param array $paragraphStyle
* @return \PhpOffice\PhpWord\Style\Font
*/
public static function addTitleStyle($depth, $fontStyle, $paragraphStyle = null)
{
return self::setStyleValues("Heading_{$depth}", new Font('title', $paragraphStyle), $fontStyle);
}
/**
@ -74,41 +104,17 @@ class Style
* @param string $styleName
* @param array $styleTable
* @param array|null $styleFirstRow
* @return \PhpOffice\PhpWord\Style\Table
*/
public static function addTableStyle($styleName, $styleTable, $styleFirstRow = null)
{
self::setStyleValues($styleName, new Table($styleTable, $styleFirstRow), null);
}
/**
* Add title style
*
* @param int $titleCount
* @param array $fontStyle
* @param array $paragraphStyle
*/
public static function addTitleStyle($titleCount, $fontStyle, $paragraphStyle = null)
{
self::setStyleValues("Heading_{$titleCount}", new Font('title', $paragraphStyle), $fontStyle);
}
/**
* 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);
return self::setStyleValues($styleName, new Table($styleTable, $styleFirstRow), null);
}
/**
* Count styles
*
* @return integer
* @return int
* @since 0.10.0
*/
public static function countStyles()
@ -129,16 +135,17 @@ class Style
* Set default paragraph style
*
* @param array $styles Paragraph style definition
* @return \PhpOffice\PhpWord\Style\Paragraph
*/
public static function setDefaultParagraphStyle($styles)
{
self::addParagraphStyle('Normal', $styles);
return self::addParagraphStyle('Normal', $styles);
}
/**
* Get all styles
*
* @return array
* @return \PhpOffice\PhpWord\Style\AbstractStyle[]
*/
public static function getStyles()
{
@ -149,7 +156,7 @@ class Style
* Get style by name
*
* @param string $styleName
* @return Paragraph|Font|Table|Numbering|null
* @return \PhpOffice\PhpWord\Style\AbstractStyle Paragraph|Font|Table|Numbering
*/
public static function getStyle($styleName)
{
@ -163,21 +170,30 @@ class Style
/**
* Set style values and put it to static style collection
*
* @param string $styleName
* @param Paragraph|Font|Table|Numbering $styleObject
* @param array|null $styleValues
* The $styleValues could be an array or object
*
* @param string $name
* @param \PhpOffice\PhpWord\Style\AbstractStyle $style
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $value
* @return \PhpOffice\PhpWord\Style\AbstractStyle
*/
private static function setStyleValues($styleName, $styleObject, $styleValues = null)
private static function setStyleValues($name, $style, $value = null)
{
if (!array_key_exists($styleName, self::$styles)) {
if (!is_null($styleValues) && is_array($styleValues)) {
foreach ($styleValues as $key => $value) {
$styleObject->setStyleValue($key, $value);
if (!array_key_exists($name, self::$styles)) {
if ($value !== null) {
if (is_array($value)) {
$style->setStyleByArray($value);
} elseif ($value instanceof AbstractStyle) {
if (get_class($style) == get_class($value)) {
$style = $value;
}
}
}
$styleObject->setStyleName($styleName);
$styleObject->setIndex(self::countStyles() + 1); // One based index
self::$styles[$styleName] = $styleObject;
$style->setStyleName($name);
$style->setIndex(self::countStyles() + 1); // One based index
self::$styles[$name] = $style;
}
return self::getStyle($name);
}
}

View File

@ -49,6 +49,14 @@ abstract class AbstractStyle
*/
protected $aliases = array();
/**
* Is this an automatic style? (Used primarily in OpenDocument driver)
*
* @var bool
* @since 0.11.0
*/
private $isAuto = false;
/**
* Get style name
*
@ -95,6 +103,29 @@ abstract class AbstractStyle
return $this;
}
/**
* Get is automatic style flag
*
* @return bool
*/
public function isAuto()
{
return $this->isAuto;
}
/**
* Set is automatic style flag
*
* @param bool $value
* @return self
*/
public function setAuto($value = true)
{
$this->isAuto = $this->setBoolVal($value, $this->isAuto);
return $this;
}
/**
* Set style value template method
*
@ -123,12 +154,12 @@ abstract class AbstractStyle
/**
* Set style by using associative array
*
* @param array $styles
* @param array $values
* @return self
*/
public function setStyleByArray($styles = array())
public function setStyleByArray($values = array())
{
foreach ($styles as $key => $value) {
foreach ($values as $key => $value) {
$this->setStyleValue($key, $value);
}
@ -138,13 +169,13 @@ abstract class AbstractStyle
/**
* Set default for null and empty value
*
* @param mixed $value
* @param mixed $default
* @return mixed
* @param string $value (was: mixed)
* @param string $default (was: mixed)
* @return string (was: mixed)
*/
protected function setNonEmptyVal($value, $default)
{
if (is_null($value) || $value == '') {
if ($value === null || $value == '') {
$value = $default;
}
@ -152,13 +183,13 @@ abstract class AbstractStyle
}
/**
* Set boolean value
* Set bool value
*
* @param mixed $value
* @param boolean|null $default
* @return boolean|null
* @param bool $value
* @param bool $default
* @return bool
*/
protected function setBoolVal($value, $default = null)
protected function setBoolVal($value, $default)
{
if (!is_bool($value)) {
$value = $default;
@ -184,9 +215,9 @@ abstract class AbstractStyle
}
/**
* Set float value: Convert string that contains only numeric into integer
* Set integer value: Convert string that contains only numeric into integer
*
* @param mixed $value
* @param int|null $value
* @param int|null $default
* @return int|null
*/
@ -227,6 +258,8 @@ abstract class AbstractStyle
* @param mixed $value
* @param array $enum
* @param mixed $default
* @return mixed
* @throws \InvalidArgumentException
*/
protected function setEnumVal($value = null, $enum = array(), $default = null)
{
@ -245,11 +278,13 @@ abstract class AbstractStyle
* @param mixed $value
* @param string $styleName
* @param mixed $style
* @return mixed
*/
protected function setObjectVal($value, $styleName, &$style)
{
$styleClass = substr(get_class($this), 0, strrpos(get_class($this), '\\')) . '\\' . $styleName;
if (is_array($value)) {
/** @var \PhpOffice\PhpWord\Style\AbstractStyle $style Type hint */
if (!$style instanceof $styleClass) {
$style = new $styleClass();
}
@ -265,6 +300,7 @@ abstract class AbstractStyle
* Set style using associative array
*
* @param array $style
* @return self
* @deprecated 0.11.0
* @codeCoverageIgnore
*/

View File

@ -0,0 +1,78 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2010-2014 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Style;
/**
* Alignment style
*
* @link http://www.schemacentral.com/sc/ooxml/t-w_CT_Jc.html
* @since 0.11.0
*/
class Alignment extends AbstractStyle
{
/**
* @const string Alignment http://www.schemacentral.com/sc/ooxml/t-w_ST_Jc.html
*/
const ALIGN_LEFT = 'left'; // Align left
const ALIGN_RIGHT = 'right'; // Align right
const ALIGN_CENTER = 'center'; // Align center
const ALIGN_BOTH = 'both'; // Align both
const ALIGN_JUSTIFY = 'justify'; // Alias for align both
/**
* @var string Alignment
*/
private $value = null;
/**
* Create a new instance
*
* @param array $style
*/
public function __construct($style = array())
{
$this->setStyleByArray($style);
}
/**
* Get alignment
*
* @return string
*/
public function getValue()
{
return $this->value;
}
/**
* Set alignment
*
* @param string $value
* @return self
*/
public function setValue($value = null)
{
if (strtolower($value) == self::ALIGN_JUSTIFY) {
$value = self::ALIGN_BOTH;
}
$enum = array(self::ALIGN_LEFT, self::ALIGN_RIGHT, self::ALIGN_CENTER, self::ALIGN_BOTH, self::ALIGN_JUSTIFY);
$this->value = $this->setEnumVal($value, $enum, $this->value);
return $this;
}
}

View File

@ -78,22 +78,6 @@ class Border extends AbstractStyle
*/
protected $borderBottomColor;
/**
* Set border size
*
* @param int|float $value
* @return self
*/
public function setBorderSize($value = null)
{
$this->setBorderTopSize($value);
$this->setBorderLeftSize($value);
$this->setBorderRightSize($value);
$this->setBorderBottomSize($value);
return $this;
}
/**
* Get border size
*
@ -110,17 +94,17 @@ class Border extends AbstractStyle
}
/**
* Set border color
* Set border size
*
* @param string $value
* @param int|float $value
* @return self
*/
public function setBorderColor($value = null)
public function setBorderSize($value = null)
{
$this->setBorderTopColor($value);
$this->setBorderLeftColor($value);
$this->setBorderRightColor($value);
$this->setBorderBottomColor($value);
$this->setBorderTopSize($value);
$this->setBorderLeftSize($value);
$this->setBorderRightSize($value);
$this->setBorderBottomSize($value);
return $this;
}
@ -141,14 +125,17 @@ class Border extends AbstractStyle
}
/**
* Set border top size
* Set border color
*
* @param int|float $value
* @param string $value
* @return self
*/
public function setBorderTopSize($value = null)
public function setBorderColor($value = null)
{
$this->borderTopSize = $value;
$this->setBorderTopColor($value);
$this->setBorderLeftColor($value);
$this->setBorderRightColor($value);
$this->setBorderBottomColor($value);
return $this;
}
@ -163,6 +150,29 @@ class Border extends AbstractStyle
return $this->borderTopSize;
}
/**
* Set border top size
*
* @param int|float $value
* @return self
*/
public function setBorderTopSize($value = null)
{
$this->borderTopSize = $this->setNumericVal($value, $this->borderTopSize);
return $this;
}
/**
* Get border top color
*
* @return string
*/
public function getBorderTopColor()
{
return $this->borderTopColor;
}
/**
* Set border top color
*
@ -177,13 +187,13 @@ class Border extends AbstractStyle
}
/**
* Get border top color
* Get border left size
*
* @return string
* @return int|float
*/
public function getBorderTopColor()
public function getBorderLeftSize()
{
return $this->borderTopColor;
return $this->borderLeftSize;
}
/**
@ -194,19 +204,19 @@ class Border extends AbstractStyle
*/
public function setBorderLeftSize($value = null)
{
$this->borderLeftSize = $value;
$this->borderLeftSize = $this->setNumericVal($value, $this->borderLeftSize);
return $this;
}
/**
* Get border left size
* Get border left color
*
* @return int|float
* @return string
*/
public function getBorderLeftSize()
public function getBorderLeftColor()
{
return $this->borderLeftSize;
return $this->borderLeftColor;
}
/**
@ -223,13 +233,13 @@ class Border extends AbstractStyle
}
/**
* Get border left color
* Get border right size
*
* @return string
* @return int|float
*/
public function getBorderLeftColor()
public function getBorderRightSize()
{
return $this->borderLeftColor;
return $this->borderRightSize;
}
/**
@ -240,19 +250,19 @@ class Border extends AbstractStyle
*/
public function setBorderRightSize($value = null)
{
$this->borderRightSize = $value;
$this->borderRightSize = $this->setNumericVal($value, $this->borderRightSize);
return $this;
}
/**
* Get border right size
* Get border right color
*
* @return int|float
* @return string
*/
public function getBorderRightSize()
public function getBorderRightColor()
{
return $this->borderRightSize;
return $this->borderRightColor;
}
/**
@ -269,13 +279,13 @@ class Border extends AbstractStyle
}
/**
* Get border right color
* Get border bottom size
*
* @return string
* @return int|float
*/
public function getBorderRightColor()
public function getBorderBottomSize()
{
return $this->borderRightColor;
return $this->borderBottomSize;
}
/**
@ -286,19 +296,19 @@ class Border extends AbstractStyle
*/
public function setBorderBottomSize($value = null)
{
$this->borderBottomSize = $value;
$this->borderBottomSize = $this->setNumericVal($value, $this->borderBottomSize);
return $this;
}
/**
* Get border bottom size
* Get border bottom color
*
* @return int|float
* @return string
*/
public function getBorderBottomSize()
public function getBorderBottomColor()
{
return $this->borderBottomSize;
return $this->borderBottomColor;
}
/**
@ -315,30 +325,14 @@ class Border extends AbstractStyle
}
/**
* Get border bottom color
*
* @return string
*/
public function getBorderBottomColor()
{
return $this->borderBottomColor;
}
/**
* Has borders?
* Check if any of the border is not null
*
* @return bool
*/
public function hasBorders()
public function hasBorder()
{
$hasBorders = false;
$borders = $this->getBorderSize();
for ($i = 0; $i < count($borders); $i++) {
if (!is_null($borders[$i])) {
$hasBorders = true;
}
}
return $hasBorders;
return $borders !== array_filter($borders, 'is_null');
}
}

View File

@ -146,6 +146,8 @@ class Cell extends Border
{
if (!is_null($this->shading)) {
return $this->shading->getFill();
} else {
return null;
}
}

View File

@ -17,8 +17,6 @@
namespace PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\PhpWord;
/**
* Font style
*/
@ -86,30 +84,30 @@ class Font extends AbstractStyle
/**
* Font name
*
* @var int|float
* @var string
*/
private $name = PhpWord::DEFAULT_FONT_NAME;
private $name;
/**
* Font Content Type
*
* @var string
*/
private $hint = PhpWord::DEFAULT_FONT_CONTENT_TYPE;
private $hint;
/**
* Font size
*
* @var int|float
*/
private $size = PhpWord::DEFAULT_FONT_SIZE;
private $size;
/**
* Font color
*
* @var string
*/
private $color = PhpWord::DEFAULT_FONT_COLOR;
private $color;
/**
* Bold
@ -241,9 +239,9 @@ class Font extends AbstractStyle
* @param string $value
* @return self
*/
public function setName($value = PhpWord::DEFAULT_FONT_NAME)
public function setName($value = null)
{
$this->name = $this->setNonEmptyVal($value, PhpWord::DEFAULT_FONT_NAME);
$this->name = $value;
return $this;
}
@ -264,9 +262,9 @@ class Font extends AbstractStyle
* @param string $value
* @return self
*/
public function setHint($value = PhpWord::DEFAULT_FONT_CONTENT_TYPE)
public function setHint($value = null)
{
$this->hint = $this->setNonEmptyVal($value, PhpWord::DEFAULT_FONT_CONTENT_TYPE);
$this->hint = $value;
return $this;
}
@ -287,9 +285,9 @@ class Font extends AbstractStyle
* @param int|float $value
* @return self
*/
public function setSize($value = PhpWord::DEFAULT_FONT_SIZE)
public function setSize($value = null)
{
$this->size = $this->setNumericVal($value, PhpWord::DEFAULT_FONT_SIZE);
$this->size = $this->setNumericVal($value, $this->size);
return $this;
}
@ -310,9 +308,9 @@ class Font extends AbstractStyle
* @param string $value
* @return self
*/
public function setColor($value = PhpWord::DEFAULT_FONT_COLOR)
public function setColor($value = null)
{
$this->color = $this->setNonEmptyVal($value, PhpWord::DEFAULT_FONT_COLOR);
$this->color = $value;
return $this;
}
@ -333,7 +331,7 @@ class Font extends AbstractStyle
* @param bool $value
* @return self
*/
public function setBold($value = false)
public function setBold($value = true)
{
$this->bold = $this->setBoolVal($value, $this->bold);
@ -356,7 +354,7 @@ class Font extends AbstractStyle
* @param bool $value
* @return self
*/
public function setItalic($value = false)
public function setItalic($value = true)
{
$this->italic = $this->setBoolVal($value, $this->italic);
@ -402,12 +400,9 @@ class Font extends AbstractStyle
* @param bool $value
* @return self
*/
public function setSuperScript($value = false)
public function setSuperScript($value = true)
{
$this->superScript = $this->setBoolVal($value, $this->superScript);
$this->toggleFalse($this->subScript, $this->superScript);
return $this;
return $this->setPairedProperty($this->superScript, $this->subScript, $value);
}
/**
@ -426,15 +421,9 @@ class Font extends AbstractStyle
* @param bool $value
* @return self
*/
public function setSubScript($value = false)
public function setSubScript($value = true)
{
$this->subScript = $this->setBoolVal($value, $this->subScript);
$this->toggleFalse($this->subScript, $this->superScript);
if ($this->subScript) {
$this->superScript = false;
}
return $this;
return $this->setPairedProperty($this->subScript, $this->superScript, $value);
}
/**
@ -453,12 +442,9 @@ class Font extends AbstractStyle
* @param bool $value
* @return self
*/
public function setStrikethrough($value = false)
public function setStrikethrough($value = true)
{
$this->strikethrough = $this->setBoolVal($value, $this->strikethrough);
$this->toggleFalse($this->doubleStrikethrough, $this->strikethrough);
return $this;
return $this->setPairedProperty($this->strikethrough, $this->doubleStrikethrough, $value);
}
/**
@ -477,12 +463,9 @@ class Font extends AbstractStyle
* @param bool $value
* @return self
*/
public function setDoubleStrikethrough($value = false)
public function setDoubleStrikethrough($value = true)
{
$this->doubleStrikethrough = $this->setBoolVal($value, $this->doubleStrikethrough);
$this->toggleFalse($this->strikethrough, $this->doubleStrikethrough);
return $this;
return $this->setPairedProperty($this->doubleStrikethrough, $this->strikethrough, $value);
}
/**
@ -501,12 +484,9 @@ class Font extends AbstractStyle
* @param bool $value
* @return self
*/
public function setSmallCaps($value = false)
public function setSmallCaps($value = true)
{
$this->smallCaps = $this->setBoolVal($value, $this->smallCaps);
$this->toggleFalse($this->allCaps, $this->smallCaps);
return $this;
return $this->setPairedProperty($this->smallCaps, $this->allCaps, $value);
}
/**
@ -525,12 +505,9 @@ class Font extends AbstractStyle
* @param bool $value
* @return self
*/
public function setAllCaps($value = false)
public function setAllCaps($value = true)
{
$this->allCaps = $this->setBoolVal($value, $this->allCaps);
$this->toggleFalse($this->smallCaps, $this->allCaps);
return $this;
return $this->setPairedProperty($this->allCaps, $this->smallCaps, $value);
}
/**
@ -565,6 +542,8 @@ class Font extends AbstractStyle
{
if (!is_null($this->shading)) {
return $this->shading->getFill();
} else {
return null;
}
}
@ -649,16 +628,21 @@ class Font extends AbstractStyle
}
/**
* Toggle $target property to false when $source true
* Set $property value and set $pairProperty = false when $value = true
*
* @param bool $target Target property
* @param bool $sourceValue
* @param bool $property
* @param bool $pairProperty
* @param bool $value
* @return self
*/
private function toggleFalse(&$target, $sourceValue)
private function setPairedProperty(&$property, &$pairProperty, $value)
{
if ($sourceValue == true) {
$target = false;
$property = $this->setBoolVal($value, $property);
if ($value == true) {
$pairProperty = false;
}
return $this;
}
/**

View File

@ -94,9 +94,9 @@ class Image extends AbstractStyle
/**
* Alignment
*
* @var string
* @var \PhpOffice\PhpWord\Style\Alignment
*/
private $align;
private $alignment;
/**
* Margin Top
@ -154,8 +154,18 @@ class Image extends AbstractStyle
*/
private $posVerticalRel = self::POSITION_RELATIVE_TO_LINE;
/**
* Create new instance
*/
public function __construct()
{
$this->alignment = new Alignment();
}
/**
* Get width
*
* @return int
*/
public function getWidth()
{
@ -166,14 +176,19 @@ class Image extends AbstractStyle
* Set width
*
* @param int $value
* @return self
*/
public function setWidth($value = null)
{
$this->width = $value;
return $this;
}
/**
* Get height
*
* @return int
*/
public function getHeight()
{
@ -184,32 +199,40 @@ class Image extends AbstractStyle
* Set height
*
* @param int $value
* @return self
*/
public function setHeight($value = null)
{
$this->height = $value;
return $this;
}
/**
* Get alignment
*
* @return string
*/
public function getAlign()
{
return $this->align;
return $this->alignment->getValue();
}
/**
* Set alignment
*
* @param string $value
* @return self
*/
public function setAlign($value = null)
{
$this->align = $value;
$this->alignment->setValue($value);
return $this;
}
/**
* Get Margin Top
* Get margin top
*
* @return int
*/
@ -219,7 +242,7 @@ class Image extends AbstractStyle
}
/**
* Set Margin Top
* Set margin top
*
* @param int $value
* @return self
@ -227,11 +250,12 @@ class Image extends AbstractStyle
public function setMarginTop($value = null)
{
$this->marginTop = $value;
return $this;
}
/**
* Get Margin Left
* Get margin left
*
* @return int
*/
@ -241,7 +265,7 @@ class Image extends AbstractStyle
}
/**
* Set Margin Left
* Set margin left
*
* @param int $value
* @return self
@ -249,6 +273,7 @@ class Image extends AbstractStyle
public function setMarginLeft($value = null)
{
$this->marginLeft = $value;
return $this;
}

View File

@ -25,6 +25,9 @@ use PhpOffice\PhpWord\Shared\String;
*/
class Paragraph extends AbstractStyle
{
/**
* @const int One line height equals 240 twip
*/
const LINE_HEIGHT = 240;
/**
@ -34,13 +37,6 @@ class Paragraph extends AbstractStyle
*/
protected $aliases = array('line-height' => 'lineHeight');
/**
* Paragraph alignment
*
* @var string
*/
private $align;
/**
* Text line height
*
@ -111,11 +107,27 @@ class Paragraph extends AbstractStyle
*/
private $spacing;
/**
* Alignment
*
* @var \PhpOffice\PhpWord\Style\Alignment
*/
private $alignment;
/**
* Create new instance
*/
public function __construct()
{
$this->alignment = new Alignment();
}
/**
* Set Style value
*
* @param string $key
* @param mixed $value
* @return self
*/
public function setStyleValue($key, $value)
{
@ -130,27 +142,24 @@ class Paragraph extends AbstractStyle
}
/**
* Get Paragraph Alignment
* Get alignment
*
* @return string
*/
public function getAlign()
{
return $this->align;
return $this->alignment->getValue();
}
/**
* Set Paragraph Alignment
* Set alignment
*
* @param string $value
* @return self
*/
public function setAlign($value = null)
{
if (strtolower($value) == 'justify') {
$value = 'both';
}
$this->align = $value;
$this->alignment->setValue($value);
return $this;
}
@ -164,6 +173,8 @@ class Paragraph extends AbstractStyle
{
if (!is_null($this->spacing)) {
return $this->spacing->getBefore();
} else {
return null;
}
}
@ -187,6 +198,8 @@ class Paragraph extends AbstractStyle
{
if (!is_null($this->spacing)) {
return $this->spacing->getAfter();
} else {
return null;
}
}
@ -210,6 +223,8 @@ class Paragraph extends AbstractStyle
{
if (!is_null($this->spacing)) {
return $this->spacing->getLine();
} else {
return null;
}
}
@ -238,7 +253,7 @@ class Paragraph extends AbstractStyle
* Set the line height
*
* @param int|float|string $lineHeight
* @return $this
* @return self
* @throws \PhpOffice\PhpWord\Exception\InvalidStyleException
*/
public function setLineHeight($lineHeight)
@ -265,6 +280,8 @@ class Paragraph extends AbstractStyle
{
if (!is_null($this->indentation)) {
return $this->indentation->getLeft();
} else {
return null;
}
}
@ -288,6 +305,8 @@ class Paragraph extends AbstractStyle
{
if (!is_null($this->indentation)) {
return $this->indentation->getHanging();
} else {
return null;
}
}
@ -412,7 +431,7 @@ class Paragraph extends AbstractStyle
* @param bool $value
* @return self
*/
public function setKeepNext($value = false)
public function setKeepNext($value = true)
{
$this->keepNext = $this->setBoolVal($value, $this->keepNext);
@ -435,7 +454,7 @@ class Paragraph extends AbstractStyle
* @param bool $value
* @return self
*/
public function setKeepLines($value = false)
public function setKeepLines($value = true)
{
$this->keepLines = $this->setBoolVal($value, $this->keepLines);
@ -458,7 +477,7 @@ class Paragraph extends AbstractStyle
* @param bool $value
* @return self
*/
public function setPageBreakBefore($value = false)
public function setPageBreakBefore($value = true)
{
$this->pageBreakBefore = $this->setBoolVal($value, $this->pageBreakBefore);

View File

@ -68,7 +68,7 @@ class Row extends AbstractStyle
* @param bool $value
* @return self
*/
public function setTblHeader($value = false)
public function setTblHeader($value = true)
{
$this->tblHeader = $this->setBoolVal($value, $this->tblHeader);
@ -91,7 +91,7 @@ class Row extends AbstractStyle
* @param bool $value
* @return self
*/
public function setCantSplit($value = false)
public function setCantSplit($value = true)
{
$this->cantSplit = $this->setBoolVal($value, $this->cantSplit);
@ -114,7 +114,7 @@ class Row extends AbstractStyle
* @param bool $value
* @return self
*/
public function setExactHeight($value = false)
public function setExactHeight($value = true)
{
$this->exactHeight = $this->setBoolVal($value, $this->exactHeight);

View File

@ -181,15 +181,19 @@ class Section extends Border
{
$enum = array(self::ORIENTATION_PORTRAIT, self::ORIENTATION_LANDSCAPE);
$this->orientation = $this->setEnumVal($value, $enum, $this->orientation);
$longSize = $this->pageSizeW >= $this->pageSizeH ? $this->pageSizeW : $this->pageSizeH;
$shortSize = $this->pageSizeW < $this->pageSizeH ? $this->pageSizeW : $this->pageSizeH;
/** @var int|float $longSide Type hint */
$longSide = $this->pageSizeW >= $this->pageSizeH ? $this->pageSizeW : $this->pageSizeH;
/** @var int|float $shortSide Type hint */
$shortSide = $this->pageSizeW < $this->pageSizeH ? $this->pageSizeW : $this->pageSizeH;
if ($this->orientation == self::ORIENTATION_PORTRAIT) {
$this->pageSizeW = $shortSize;
$this->pageSizeH = $longSize;
$this->pageSizeW = $shortSide;
$this->pageSizeH = $longSide;
} else {
$this->pageSizeW = $longSize;
$this->pageSizeH = $shortSize;
$this->pageSizeW = $longSide;
$this->pageSizeH = $shortSide;
}
return $this;
@ -420,7 +424,7 @@ class Section extends Border
* Set page numbering start
*
* @param null|int $pageNumberingStart
* @return $this
* @return self
*/
public function setPageNumberingStart($pageNumberingStart = null)
{

View File

@ -22,40 +22,54 @@ namespace PhpOffice\PhpWord\Style;
*/
class Table extends Border
{
/**
* @const string Table width units http://www.schemacentral.com/sc/ooxml/t-w_ST_TblWidth.html
*/
const WIDTH_AUTO = 'auto'; // Automatically determined width
const WIDTH_PERCENT = 'pct'; // Width in fiftieths (1/50) of a percent (1% = 50 unit)
const WIDTH_TWIP = 'dxa'; // Width in twentieths (1/20) of a point (twip)
/**
* Is this a first row style?
*
* @var bool
*/
private $isFirstRow = false;
/**
* Style for first row
*
* @var \PhpOffice\PhpWord\Style\Table
*/
private $firstRow = null;
private $firstRowStyle;
/**
* Cell margin top
*
* @var int
*/
private $cellMarginTop = null;
private $cellMarginTop;
/**
* Cell margin left
*
* @var int
*/
private $cellMarginLeft = null;
private $cellMarginLeft;
/**
* Cell margin right
*
* @var int
*/
private $cellMarginRight = null;
private $cellMarginRight;
/**
* Cell margin bottom
*
* @var int
*/
private $cellMarginBottom = null;
private $cellMarginBottom;
/**
* Border size inside horizontal
@ -92,42 +106,60 @@ class Table extends Border
*/
private $shading;
/**
* @var \PhpOffice\PhpWord\Style\Alignment Alignment
*/
private $alignment;
/**
* @var int|float Width value
*/
private $width = 0;
/**
* @var string Width unit
*/
private $unit = self::WIDTH_AUTO;
/**
* Create new table style
*
* @param mixed $styleTable
* @param mixed $styleFirstRow
* @param mixed $tableStyle
* @param mixed $firstRowStyle
*/
public function __construct($styleTable = null, $styleFirstRow = null)
public function __construct($tableStyle = null, $firstRowStyle = null)
{
if (!is_null($styleFirstRow) && is_array($styleFirstRow)) {
$this->firstRow = clone $this;
$this->alignment = new Alignment();
unset($this->firstRow->firstRow);
unset($this->firstRow->cellMarginBottom);
unset($this->firstRow->cellMarginTop);
unset($this->firstRow->cellMarginLeft);
unset($this->firstRow->cellMarginRight);
unset($this->firstRow->borderInsideVColor);
unset($this->firstRow->borderInsideVSize);
unset($this->firstRow->borderInsideHColor);
unset($this->firstRow->borderInsideHSize);
$this->firstRow->setStyleByArray($styleFirstRow);
// Clone first row from table style, but with certain properties disabled
if ($firstRowStyle !== null && is_array($firstRowStyle)) {
$this->firstRowStyle = clone $this;
$this->firstRowStyle->isFirstRow = true;
unset($this->firstRowStyle->firstRowStyle);
unset($this->firstRowStyle->borderInsideHSize);
unset($this->firstRowStyle->borderInsideHColor);
unset($this->firstRowStyle->borderInsideVSize);
unset($this->firstRowStyle->borderInsideVColor);
unset($this->firstRowStyle->cellMarginTop);
unset($this->firstRowStyle->cellMarginLeft);
unset($this->firstRowStyle->cellMarginRight);
unset($this->firstRowStyle->cellMarginBottom);
$this->firstRowStyle->setStyleByArray($firstRowStyle);
}
if (!is_null($styleTable) && is_array($styleTable)) {
$this->setStyleByArray($styleTable);
if ($tableStyle !== null && is_array($tableStyle)) {
$this->setStyleByArray($tableStyle);
}
}
/**
* Get First Row Style
* Set first row
*
* @return \PhpOffice\PhpWord\Style\Table
*/
public function getFirstRow()
{
return $this->firstRow;
return $this->firstRowStyle;
}
/**
@ -139,36 +171,20 @@ class Table extends Border
{
if (!is_null($this->shading)) {
return $this->shading->getFill();
} else {
return null;
}
return null;
}
/**
* Set background
*
* @param string $value
* @return \PhpOffice\PhpWord\Style\Table
* @return self
*/
public function setBgColor($value = null)
{
$this->setShading(array('fill' => $value));
}
/**
* Set TLRBHV Border Size
*
* @param int $value Border size in eighths of a point (1/8 point)
* @return self
*/
public function setBorderSize($value = null)
{
$this->setBorderTopSize($value);
$this->setBorderLeftSize($value);
$this->setBorderRightSize($value);
$this->setBorderBottomSize($value);
$this->setBorderInsideHSize($value);
$this->setBorderInsideVSize($value);
return $this;
}
@ -191,19 +207,19 @@ class Table extends Border
}
/**
* Set TLRBHV Border Color
* Set TLRBHV Border Size
*
* @param string $value
* @param int $value Border size in eighths of a point (1/8 point)
* @return self
*/
public function setBorderColor($value = null)
public function setBorderSize($value = null)
{
$this->setBorderTopColor($value);
$this->setBorderLeftColor($value);
$this->setBorderRightColor($value);
$this->setBorderBottomColor($value);
$this->setBorderInsideHColor($value);
$this->setBorderInsideVColor($value);
$this->setBorderTopSize($value);
$this->setBorderLeftSize($value);
$this->setBorderRightSize($value);
$this->setBorderBottomSize($value);
$this->setBorderInsideHSize($value);
$this->setBorderInsideVSize($value);
return $this;
}
@ -226,13 +242,21 @@ class Table extends Border
}
/**
* Set border size inside horizontal
* Set TLRBHV Border Color
*
* @param int $value
* @param string $value
* @return self
*/
public function setBorderInsideHSize($value = null)
public function setBorderColor($value = null)
{
$this->borderInsideHSize = $value;
$this->setBorderTopColor($value);
$this->setBorderLeftColor($value);
$this->setBorderRightColor($value);
$this->setBorderBottomColor($value);
$this->setBorderInsideHColor($value);
$this->setBorderInsideVColor($value);
return $this;
}
/**
@ -242,37 +266,18 @@ class Table extends Border
*/
public function getBorderInsideHSize()
{
return (isset($this->borderInsideHSize)) ? $this->borderInsideHSize : null;
return $this->getTableOnlyProperty('borderInsideHSize');
}
/**
* Set border size inside vertical
* Set border size inside horizontal
*
* @param int $value
* @return self
*/
public function setBorderInsideVSize($value = null)
public function setBorderInsideHSize($value = null)
{
$this->borderInsideVSize = $value;
}
/**
* Get border size inside vertical
*
* @return int
*/
public function getBorderInsideVSize()
{
return (isset($this->borderInsideVSize)) ? $this->borderInsideVSize : null;
}
/**
* Set border color inside horizontal
*
* @param string $value
*/
public function setBorderInsideHColor($value = null)
{
$this->borderInsideHColor = $value;
return $this->setTableOnlyProperty('borderInsideHSize', $value);
}
/**
@ -282,17 +287,39 @@ class Table extends Border
*/
public function getBorderInsideHColor()
{
return (isset($this->borderInsideHColor)) ? $this->borderInsideHColor : null;
return $this->getTableOnlyProperty('borderInsideHColor');
}
/**
* Set border color inside vertical
* Set border color inside horizontal
*
* @param string $value
* @return self
*/
public function setBorderInsideVColor($value = null)
public function setBorderInsideHColor($value = null)
{
$this->borderInsideVColor = $value;
return $this->setTableOnlyProperty('borderInsideHColor', $value, false);
}
/**
* Get border size inside vertical
*
* @return int
*/
public function getBorderInsideVSize()
{
return $this->getTableOnlyProperty('borderInsideVSize');
}
/**
* Set border size inside vertical
*
* @param int $value
* @return self
*/
public function setBorderInsideVSize($value = null)
{
return $this->setTableOnlyProperty('borderInsideVSize', $value);
}
/**
@ -302,17 +329,18 @@ class Table extends Border
*/
public function getBorderInsideVColor()
{
return (isset($this->borderInsideVColor)) ? $this->borderInsideVColor : null;
return $this->getTableOnlyProperty('borderInsideVColor');
}
/**
* Set cell margin top
* Set border color inside vertical
*
* @param int $value
* @param string $value
* @return self
*/
public function setCellMarginTop($value = null)
public function setBorderInsideVColor($value = null)
{
$this->cellMarginTop = $value;
return $this->setTableOnlyProperty('borderInsideVColor', $value, false);
}
/**
@ -322,17 +350,18 @@ class Table extends Border
*/
public function getCellMarginTop()
{
return $this->cellMarginTop;
return $this->getTableOnlyProperty('cellMarginTop');
}
/**
* Set cell margin left
* Set cell margin top
*
* @param int $value
* @return self
*/
public function setCellMarginLeft($value = null)
public function setCellMarginTop($value = null)
{
$this->cellMarginLeft = $value;
return $this->setTableOnlyProperty('cellMarginTop', $value);
}
/**
@ -342,17 +371,18 @@ class Table extends Border
*/
public function getCellMarginLeft()
{
return $this->cellMarginLeft;
return $this->getTableOnlyProperty('cellMarginLeft');
}
/**
* Set cell margin right
* Set cell margin left
*
* @param int $value
* @return self
*/
public function setCellMarginRight($value = null)
public function setCellMarginLeft($value = null)
{
$this->cellMarginRight = $value;
return $this->setTableOnlyProperty('cellMarginLeft', $value);
}
/**
@ -362,17 +392,18 @@ class Table extends Border
*/
public function getCellMarginRight()
{
return $this->cellMarginRight;
return $this->getTableOnlyProperty('cellMarginRight');
}
/**
* Set cell margin bottom
* Set cell margin right
*
* @param int $value
* @return self
*/
public function setCellMarginBottom($value = null)
public function setCellMarginRight($value = null)
{
$this->cellMarginBottom = $value;
return $this->setTableOnlyProperty('cellMarginRight', $value);
}
/**
@ -382,13 +413,40 @@ class Table extends Border
*/
public function getCellMarginBottom()
{
return $this->cellMarginBottom;
return $this->getTableOnlyProperty('cellMarginBottom');
}
/**
* Set cell margin bottom
*
* @param int $value
* @return self
*/
public function setCellMarginBottom($value = null)
{
return $this->setTableOnlyProperty('cellMarginBottom', $value);
}
/**
* Get cell margin
*
* @return integer[]
*/
public function getCellMargin()
{
return array(
$this->cellMarginTop,
$this->cellMarginLeft,
$this->cellMarginRight,
$this->cellMarginBottom
);
}
/**
* Set TLRB cell margin
*
* @param int $value Margin in twips
* @return self
*/
public function setCellMargin($value = null)
{
@ -396,16 +454,20 @@ class Table extends Border
$this->setCellMarginLeft($value);
$this->setCellMarginRight($value);
$this->setCellMarginBottom($value);
return $this;
}
/**
* Get cell margin
* Check if any of the margin is not null
*
* @return int[]
* @return bool
*/
public function getCellMargin()
public function hasMargin()
{
return array($this->cellMarginTop, $this->cellMarginLeft, $this->cellMarginRight, $this->cellMarginBottom);
$margins = $this->getCellMargin();
return $margins !== array_filter($margins, 'is_null');
}
/**
@ -432,20 +494,114 @@ class Table extends Border
}
/**
* Has margins?
* Get alignment
*
* @return bool
* @return string
*/
public function hasMargins()
public function getAlign()
{
$hasMargins = false;
$margins = $this->getCellMargin();
for ($i = 0; $i < count($margins); $i++) {
if (!is_null($margins[$i])) {
$hasMargins = true;
return $this->alignment->getValue();
}
/**
* Set alignment
*
* @param string $value
* @return self
*/
public function setAlign($value = null)
{
$this->alignment->setValue($value);
return $this;
}
/**
* Get width
*
* @return int|float
*/
public function getWidth()
{
return $this->width;
}
/**
* Set width
*
* @param int|float $value
* @return self
*/
public function setWidth($value = null)
{
$this->width = $this->setNumericVal($value, $this->width);
return $this;
}
/**
* Get width unit
*
* @return string
*/
public function getUnit()
{
return $this->unit;
}
/**
* Set width unit
*
* @param string $value
* @return self
*/
public function setUnit($value = null)
{
$enum = array(self::WIDTH_AUTO, self::WIDTH_PERCENT, self::WIDTH_TWIP);
$this->unit = $this->setEnumVal($value, $enum, $this->unit);
return $this;
}
/**
* Get table style only property by checking if it's a firstRow
*
* This is necessary since firstRow style is cloned from table style but
* without certain properties activated, e.g. margins
*
* @param string $property
* @return int|string|null
*/
private function getTableOnlyProperty($property)
{
if ($this->isFirstRow === false) {
return $this->$property;
}
return null;
}
/**
* Set table style only property by checking if it's a firstRow
*
* This is necessary since firstRow style is cloned from table style but
* without certain properties activated, e.g. margins
*
* @param string $property
* @param int|string $value
* @param bool $isNumeric
* @return self
*/
private function setTableOnlyProperty($property, $value, $isNumeric = true)
{
if ($this->isFirstRow === false) {
if ($isNumeric === true) {
$this->$property = $this->setNumericVal($value, $this->$property);
} else {
$this->$property = $value;
}
}
return $hasMargins;
return $this;
}
}

View File

@ -19,6 +19,7 @@ namespace PhpOffice\PhpWord;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Shared\String;
use PhpOffice\PhpWord\Shared\ZipArchive;
/**
* Template
@ -78,8 +79,7 @@ class Template
throw new Exception("Could not copy the template from {$strFilename} to {$this->tempFileName}.");
}
$zipClass = Settings::getZipClass();
$this->zipClass = new $zipClass();
$this->zipClass = new ZipArchive();
$this->zipClass->open($this->tempFileName);
// Find and load headers and footers

View File

@ -19,7 +19,7 @@ namespace PhpOffice\PhpWord\Writer;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Shared\ZipArchive;
/**
* Abstract writer class
@ -149,6 +149,7 @@ abstract class AbstractWriter implements WriterInterface
* @param bool $value
* @param string $directory
* @return self
* @throws \PhpOffice\PhpWord\Exception\Exception
*/
public function setUseDiskCaching($value = false, $directory = null)
{
@ -256,41 +257,34 @@ abstract class AbstractWriter implements WriterInterface
* Get ZipArchive object
*
* @param string $filename
* @return mixed ZipArchive object
* @return \PhpOffice\PhpWord\Shared\ZipArchive
* @throws \PhpOffice\PhpWord\Exception\Exception
*/
protected function getZipArchive($filename)
{
// Create new ZIP file and open it for writing
$zipClass = Settings::getZipClass();
$objZip = new $zipClass();
// Retrieve OVERWRITE and CREATE constants from the instantiated zip class
$reflection = new \ReflectionObject($objZip);
$zipOverWrite = $reflection->getConstant('OVERWRITE');
$zipCreate = $reflection->getConstant('CREATE');
// Remove any existing file
if (file_exists($filename)) {
unlink($filename);
}
// Try opening the ZIP file
if ($objZip->open($filename, $zipOverWrite) !== true) {
if ($objZip->open($filename, $zipCreate) !== true) {
$zip = new ZipArchive();
if ($zip->open($filename, ZipArchive::OVERWRITE) !== true) {
if ($zip->open($filename, ZipArchive::CREATE) !== true) {
throw new Exception("Could not open " . $filename . " for writing.");
}
}
return $objZip;
return $zip;
}
/**
* Add files to package
*
* @param mixed $objZip
* @param \PhpOffice\PhpWord\Shared\ZipArchive $zip
* @param mixed $elements
*/
protected function addFilesToPackage($objZip, $elements)
protected function addFilesToPackage(ZipArchive $zip, $elements)
{
foreach ($elements as $element) {
$type = $element['type']; // image|object|link
@ -308,10 +302,10 @@ abstract class AbstractWriter implements WriterInterface
call_user_func($element['imageFunction'], $image);
$imageContents = ob_get_contents();
ob_end_clean();
$objZip->addFromString($target, $imageContents);
$zip->addFromString($target, $imageContents);
imagedestroy($image);
} else {
$this->addFileToPackage($objZip, $element['source'], $target);
$this->addFileToPackage($zip, $element['source'], $target);
}
}
}
@ -321,11 +315,11 @@ abstract class AbstractWriter implements WriterInterface
*
* Get the actual source from an archive image
*
* @param mixed $objZip
* @param \PhpOffice\PhpWord\Shared\ZipArchive $zipPackage
* @param string $source
* @param string $target
*/
protected function addFileToPackage($objZip, $source, $target)
protected function addFileToPackage($zipPackage, $source, $target)
{
$isArchive = strpos($source, 'zip://') !== false;
$actualSource = null;
@ -333,8 +327,7 @@ abstract class AbstractWriter implements WriterInterface
$source = substr($source, 6);
list($zipFilename, $imageFilename) = explode('#', $source);
$zipClass = \PhpOffice\PhpWord\Settings::getZipClass();
$zip = new $zipClass();
$zip = new ZipArchive;
if ($zip->open($zipFilename) !== false) {
if ($zip->locateName($imageFilename)) {
$zip->extractTo($this->getTempDir(), $imageFilename);
@ -347,7 +340,7 @@ abstract class AbstractWriter implements WriterInterface
}
if (!is_null($actualSource)) {
$objZip->addFile($actualSource, $target);
$zipPackage->addFile($actualSource, $target);
}
}

View File

@ -19,9 +19,10 @@ namespace PhpOffice\PhpWord\Writer;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Style\Paragraph;
use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Writer\HTML\Element\Container;
use PhpOffice\PhpWord\Writer\HTML\Element\TextRun as TextRunWriter;
use PhpOffice\PhpWord\Writer\HTML\Style\Font as FontStyleWriter;
@ -62,14 +63,10 @@ class HTML extends AbstractWriter implements WriterInterface
* Save PhpWord to file
*
* @param string $filename
* @throws Exception
* @throws \PhpOffice\PhpWord\Exception\Exception
*/
public function save($filename = null)
{
if (is_null($this->phpWord)) {
throw new Exception('PhpWord object unassigned.');
}
$this->setTempDir(sys_get_temp_dir() . '/PHPWordWriter/');
$hFile = fopen($filename, 'w');
if ($hFile !== false) {
@ -111,7 +108,8 @@ class HTML extends AbstractWriter implements WriterInterface
*/
private function writeHead()
{
$properties = $this->getPhpWord()->getDocumentProperties();
$phpWord = $this->getPhpWord();
$properties = $phpWord->getDocumentProperties();
$propertiesMapping = array(
'creator' => 'author',
'title' => '',
@ -176,8 +174,8 @@ class HTML extends AbstractWriter implements WriterInterface
// Default styles
$defaultStyles = array(
'*' => array(
'font-family' => $this->getPhpWord()->getDefaultFontName(),
'font-size' => $this->getPhpWord()->getDefaultFontSize() . 'pt',
'font-family' => Settings::getDefaultFontName(),
'font-size' => Settings::getDefaultFontSize() . 'pt',
),
'a.NoteRef' => array(
'text-decoration' => 'none',

View File

@ -48,9 +48,16 @@ abstract class AbstractElement
*/
protected $withoutP = false;
/**
* Write element
*/
abstract public function write();
/**
* Create new instance
*
* @param \PhpOffice\PhpWord\Writer\AbstractWriter $parentWriter
* @param \PhpOffice\PhpWord\Element\AbstractElement $element
* @param bool $withoutP
*/
public function __construct(AbstractWriter $parentWriter, Element $element, $withoutP = false)

View File

@ -17,6 +17,8 @@
namespace PhpOffice\PhpWord\Writer\HTML\Element;
use PhpOffice\PhpWord\Element\AbstractContainer as ContainerElement;
/**
* Container element HTML writer
*
@ -24,6 +26,13 @@ namespace PhpOffice\PhpWord\Writer\HTML\Element;
*/
class Container extends AbstractElement
{
/**
* Namespace; Can't use __NAMESPACE__ in inherited class (RTF)
*
* @var string
*/
protected $namespace = 'PhpOffice\\PhpWord\\Writer\\HTML\\Element';
/**
* Write container
*
@ -32,14 +41,19 @@ class Container extends AbstractElement
public function write()
{
$container = $this->element;
if (!$container instanceof ContainerElement) {
return '';
}
$containerClass = substr(get_class($container), strrpos(get_class($container), '\\') + 1);
$withoutP = in_array($containerClass, array('TextRun', 'Footnote', 'Endnote')) ? true : false;
$content = '';
$elements = $container->getElements();
foreach ($elements as $element) {
$writerClass = str_replace('\\Element', '\\Writer\\HTML\\Element', get_class($element));
$elementClass = get_class($element);
$writerClass = str_replace('PhpOffice\\PhpWord\\Element', $this->namespace, $elementClass);
if (class_exists($writerClass)) {
/** @var \PhpOffice\PhpWord\Writer\HTML\Element\AbstractElement $writer Type hint */
$writer = new $writerClass($this->parentWriter, $element, $withoutP);
$content .= $writer->write();
}

View File

@ -38,11 +38,17 @@ class Footnote extends AbstractElement
*/
public function write()
{
$noteId = count($this->parentWriter->getNotes()) + 1;
if (!$this->element instanceof \PhpOffice\PhpWord\Element\Footnote) {
return '';
}
/** @var \PhpOffice\PhpWord\Writer\HTML $parentWriter Type hint */
$parentWriter = $this->parentWriter;
$noteId = count($parentWriter->getNotes()) + 1;
$noteMark = $this->noteType . '-' . $this->element->getRelationId();
$content = "<a name=\"{$noteMark}\"><a href=\"#note-{$noteId}\" class=\"NoteRef\"><sup>{$noteId}</sup></a>";
$this->parentWriter->addNote($noteId, $noteMark);
$parentWriter->addNote($noteId, $noteMark);
return $content;
}

View File

@ -18,6 +18,7 @@
namespace PhpOffice\PhpWord\Writer\HTML\Element;
use PhpOffice\PhpWord\Element\Image as ImageElement;
use PhpOffice\PhpWord\Shared\ZipArchive;
use PhpOffice\PhpWord\Writer\HTML\Style\Image as ImageStyleWriter;
/**
@ -34,8 +35,14 @@ class Image extends Text
*/
public function write()
{
if (!$this->element instanceof ImageElement) {
return '';
}
/** @var \PhpOffice\PhpWord\Writer\HTML $parentWriter Type hint */
$parentWriter = $this->parentWriter;
$content = '';
if (!$this->parentWriter->isPdf()) {
if (!$parentWriter->isPdf()) {
$imageData = $this->getBase64ImageData($this->element);
if (!is_null($imageData)) {
$styleWriter = new ImageStyleWriter($this->element->getStyle());
@ -53,6 +60,7 @@ class Image extends Text
/**
* Get Base64 image data
*
* @param \PhpOffice\PhpWord\Element\Image $element
* @return string|null
*/
private function getBase64ImageData(ImageElement $element)
@ -69,8 +77,7 @@ class Image extends Text
$source = substr($source, 6);
list($zipFilename, $imageFilename) = explode('#', $source);
$zipClass = \PhpOffice\PhpWord\Settings::getZipClass();
$zip = new $zipClass();
$zip = new ZipArchive();
if ($zip->open($zipFilename) !== false) {
if ($zip->locateName($imageFilename)) {
$zip->extractTo($this->parentWriter->getTempDir(), $imageFilename);

View File

@ -31,6 +31,10 @@ class Link extends Text
*/
public function write()
{
if (!$this->element instanceof \PhpOffice\PhpWord\Element\Link) {
return '';
}
$content = '';
$content .= $this->writeOpening();
$content .= "<a href=\"{$this->element->getTarget()}\">{$this->element->getText()}</a>";

View File

@ -31,6 +31,10 @@ class ListItem extends AbstractElement
*/
public function write()
{
if (!$this->element instanceof \PhpOffice\PhpWord\Element\ListItem) {
return '';
}
$text = htmlspecialchars($this->element->getTextObject()->getText());
$content = '<p>' . $text . '</p>' . PHP_EOL;

View File

@ -31,15 +31,20 @@ class Table extends AbstractElement
*/
public function write()
{
if (!$this->element instanceof \PhpOffice\PhpWord\Element\Table) {
return '';
}
$content = '';
$rows = $this->element->getRows();
$rowCount = count($rows);
if ($rowCount > 0) {
$content .= '<table>' . PHP_EOL;
foreach ($rows as $row) {
// $height = $row->getHeight();
/** @var $row \PhpOffice\PhpWord\Element\Row Type hint */
$rowStyle = $row->getStyle();
$tblHeader = $rowStyle->getTblHeader();
// $height = $row->getHeight();
$tblHeader = $rowStyle->isTblHeader();
$content .= '<tr>' . PHP_EOL;
foreach ($row->getCells() as $cell) {
$writer = new Container($this->parentWriter, $cell);

View File

@ -53,7 +53,7 @@ class Text extends AbstractElement
/**
* Closing tag
*
* @var strings
* @var string
*/
private $closingTags = '';
@ -64,12 +64,14 @@ class Text extends AbstractElement
*/
public function write()
{
/** @var \PhpOffice\PhpWord\Element\Text $element Type hint */
$element = $this->element;
$this->getFontStyle();
$content = '';
$content .= $this->writeOpening();
$content .= $this->openingTags;
$content .= htmlspecialchars($this->element->getText());
$content .= htmlspecialchars($element->getText());
$content .= $this->closingTags;
$content .= $this->closingText;
$content .= $this->writeClosing();
@ -140,12 +142,14 @@ class Text extends AbstractElement
*/
private function getParagraphStyle()
{
/** @var \PhpOffice\PhpWord\Element\Text $element Type hint */
$element = $this->element;
$style = '';
if (method_exists($this->element, 'getParagraphStyle')) {
if (!method_exists($element, 'getParagraphStyle')) {
return $style;
}
$paragraphStyle = $this->element->getParagraphStyle();
$paragraphStyle = $element->getParagraphStyle();
$pStyleIsObject = ($paragraphStyle instanceof Paragraph);
if ($pStyleIsObject) {
$styleWriter = new ParagraphStyleWriter($paragraphStyle);
@ -164,8 +168,10 @@ class Text extends AbstractElement
*/
private function getFontStyle()
{
/** @var \PhpOffice\PhpWord\Element\Text $element Type hint */
$element = $this->element;
$style = '';
$fontStyle = $this->element->getFontStyle();
$fontStyle = $element->getFontStyle();
$fStyleIsObject = ($fontStyle instanceof Font);
if ($fStyleIsObject) {
$styleWriter = new FontStyleWriter($fontStyle);

View File

@ -31,6 +31,10 @@ class Title extends AbstractElement
*/
public function write()
{
if (!$this->element instanceof \PhpOffice\PhpWord\Element\Title) {
return '';
}
$tag = 'h' . $this->element->getDepth();
$text = htmlspecialchars($this->element->getText());
$content = "<{$tag}>{$text}</{$tag}>" . PHP_EOL;

View File

@ -56,7 +56,7 @@ abstract class AbstractStyle
public function getStyle()
{
if (!$this->style instanceof Style && !is_array($this->style)) {
return;
return '';
}
return $this->style;
@ -87,12 +87,12 @@ abstract class AbstractStyle
/**
* Get value if ...
*
* @param bool $condition
* @param bool|null $condition
* @param string $value
* @return string
*/
protected function getValueIf($condition, $value)
{
return $condition ? $value : '';
return $condition == true ? $value : '';
}
}

View File

@ -17,7 +17,7 @@
namespace PhpOffice\PhpWord\Writer\HTML\Style;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Style\Font as FontStyle;
/**
@ -35,8 +35,8 @@ class Font extends AbstractStyle
public function write()
{
$style = $this->getStyle();
if (!$style instanceof \PhpOffice\PhpWord\Style\Font) {
return;
if (!$style instanceof FontStyle) {
return '';
}
$css = array();
@ -47,9 +47,9 @@ class Font extends AbstractStyle
$underline = $style->getUnderline() != FontStyle::UNDERLINE_NONE;
$lineThrough = $style->isStrikethrough() || $style->isDoubleStrikethrough();
$css['font-family'] = $this->getValueIf($font != PhpWord::DEFAULT_FONT_NAME, "'{$font}'");
$css['font-size'] = $this->getValueIf($size != PhpWord::DEFAULT_FONT_SIZE, "{$size}pt");
$css['color'] = $this->getValueIf($color != PhpWord::DEFAULT_FONT_COLOR, "#{$color}");
$css['font-family'] = $this->getValueIf($font !== null, "'{$font}'");
$css['font-size'] = $this->getValueIf($size !== null, "{$size}pt");
$css['color'] = $this->getValueIf($color != Settings::DEFAULT_FONT_COLOR, "#{$color}");
$css['background'] = $this->getValueIf($fgColor != '', $fgColor);
$css['font-weight'] = $this->getValueIf($style->isBold(), 'bold');
$css['font-style'] = $this->getValueIf($style->isItalic(), 'italic');

View File

@ -33,12 +33,14 @@ class Image extends AbstractStyle
{
$style = $this->getStyle();
if (!$style instanceof \PhpOffice\PhpWord\Style\Image) {
return;
return '';
}
$css = array();
$css['width'] = $this->getValueIf($style->getWidth(), $style->getWidth() . 'px');
$css['height'] = $this->getValueIf($style->getHeight(), $style->getHeight() . 'px');
$width = $style->getWidth();
$height = $style->getHeight();
$css['width'] = $this->getValueIf(is_numeric($width), $width . 'px');
$css['height'] = $this->getValueIf(is_numeric($height), $height . 'px');
return $this->assembleCss($css);
}

View File

@ -17,8 +17,6 @@
namespace PhpOffice\PhpWord\Writer\HTML\Style;
use PhpOffice\PhpWord\Settings;
/**
* Paragraph style HTML writer
*
@ -35,7 +33,7 @@ class Paragraph extends AbstractStyle
{
$style = $this->getStyle();
if (!$style instanceof \PhpOffice\PhpWord\Style\Paragraph) {
return;
return '';
}
$css = array();
@ -48,8 +46,8 @@ class Paragraph extends AbstractStyle
if (!is_null($spacing)) {
$before = $spacing->getBefore();
$after = $spacing->getAfter();
$css['margin-top'] = $this->getValueIf(!is_null($before), ($before / Settings::UNIT_POINT) . 'pt');
$css['margin-bottom'] = $this->getValueIf(!is_null($after), ($after / Settings::UNIT_POINT) . 'pt');
$css['margin-top'] = $this->getValueIf(!is_null($before), ($before / 20) . 'pt');
$css['margin-bottom'] = $this->getValueIf(!is_null($after), ($after / 20) . 'pt');
}
return $this->assembleCss($css);

View File

@ -17,7 +17,6 @@
namespace PhpOffice\PhpWord\Writer;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Media;
use PhpOffice\PhpWord\PhpWord;
@ -49,6 +48,7 @@ class ODText extends AbstractWriter implements WriterInterface
foreach (array_keys($this->parts) as $partName) {
$partClass = get_class($this) . '\\Part\\' . $partName;
if (class_exists($partClass)) {
/** @var $partObject \PhpOffice\PhpWord\Writer\ODText\Part\AbstractPart Type hint */
$partObject = new $partClass();
$partObject->setParentWriter($this);
$this->writerParts[strtolower($partName)] = $partObject;
@ -63,35 +63,27 @@ class ODText extends AbstractWriter implements WriterInterface
* Save PhpWord to file
*
* @param string $filename
* @throws \PhpOffice\PhpWord\Exception\Exception
*/
public function save($filename = null)
{
if (is_null($this->phpWord)) {
throw new Exception('PhpWord object unassigned.');
}
$filename = $this->getTempFile($filename);
$objZip = $this->getZipArchive($filename);
$zip = $this->getZipArchive($filename);
// Add section media files
$sectionMedia = Media::getElements('section');
if (!empty($sectionMedia)) {
$this->addFilesToPackage($objZip, $sectionMedia);
$this->addFilesToPackage($zip, $sectionMedia);
}
// Write parts
foreach ($this->parts as $partName => $fileName) {
if ($fileName != '') {
$objZip->addFromString($fileName, $this->getWriterPart($partName)->write());
$zip->addFromString($fileName, $this->getWriterPart($partName)->write());
}
}
// Close file
if ($objZip->close() === false) {
throw new Exception("Could not close zip file $filename.");
}
// Close zip archive and cleanup temp file
$zip->close();
$this->cleanupTempFile();
}
}

View File

@ -17,11 +17,13 @@
namespace PhpOffice\PhpWord\Writer\ODText\Element;
use PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement as Word2007AbstractElement;
/**
* Abstract element writer
*
* @since 0.11.0
*/
abstract class AbstractElement extends \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement
abstract class AbstractElement extends Word2007AbstractElement
{
}

View File

@ -17,12 +17,14 @@
namespace PhpOffice\PhpWord\Writer\ODText\Element;
use PhpOffice\PhpWord\Writer\Word2007\Element\Container as Word2007Container;
/**
* Container element writer (section, textrun, header, footnote, cell, etc.)
*
* @since 0.11.0
*/
class Container extends \PhpOffice\PhpWord\Writer\Word2007\Element\Container
class Container extends Word2007Container
{
/**
* Namespace; Can't use __NAMESPACE__ in inherited class (ODText)

View File

@ -33,6 +33,9 @@ class Image extends AbstractElement
{
$xmlWriter = $this->getXmlWriter();
$element = $this->getElement();
if (!$element instanceof \PhpOffice\PhpWord\Element\Image) {
return;
}
$mediaIndex = $element->getMediaIndex();
$target = 'Pictures/' . $element->getTarget();

View File

@ -31,6 +31,9 @@ class Link extends AbstractElement
{
$xmlWriter = $this->getXmlWriter();
$element = $this->getElement();
if (!$element instanceof \PhpOffice\PhpWord\Element\Link) {
return;
}
if (!$this->withoutP) {
$xmlWriter->startElement('text:p'); // text:p

View File

@ -31,6 +31,9 @@ class Table extends AbstractElement
{
$xmlWriter = $this->getXmlWriter();
$element = $this->getElement();
if (!$element instanceof \PhpOffice\PhpWord\Element\Table) {
return;
}
$rows = $element->getRows();
$rowCount = count($rows);
$colCount = $element->countColumns();
@ -46,6 +49,7 @@ class Table extends AbstractElement
foreach ($rows as $row) {
$xmlWriter->startElement('table:table-row');
/** @var $row \PhpOffice\PhpWord\Element\Row Type hint */
foreach ($row->getCells() as $cell) {
$xmlWriter->startElement('table:table-cell');
$xmlWriter->writeAttribute('office:value-type', 'string');

View File

@ -17,6 +17,8 @@
namespace PhpOffice\PhpWord\Writer\ODText\Element;
use PhpOffice\PhpWord\Exception\Exception;
/**
* Text element writer
*
@ -31,6 +33,9 @@ class Text extends AbstractElement
{
$xmlWriter = $this->getXmlWriter();
$element = $this->getElement();
if (!$element instanceof \PhpOffice\PhpWord\Element\Text) {
return;
}
$fontStyle = $element->getFontStyle();
$paragraphStyle = $element->getParagraphStyle();

View File

@ -0,0 +1,43 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2010-2014 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Writer\ODText\Element;
/**
* Title element writer
*
* @since 0.11.0
*/
class Title extends AbstractElement
{
/**
* Write element
*/
public function write()
{
$xmlWriter = $this->getXmlWriter();
$element = $this->getElement();
if (!$element instanceof \PhpOffice\PhpWord\Element\Title) {
return;
}
$xmlWriter->startElement('text:h');
$xmlWriter->writeAttribute('text:outline-level', $element->getDepth());
$xmlWriter->writeRaw($element->getText());
$xmlWriter->endElement(); // text:h
}
}

View File

@ -17,15 +17,16 @@
namespace PhpOffice\PhpWord\Writer\ODText\Part;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Shared\XMLWriter;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart as Word2007AbstractPart;
/**
* ODText writer part abstract
*/
abstract class AbstractPart extends \PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart
abstract class AbstractPart extends Word2007AbstractPart
{
/**
* Write common root attributes
@ -67,7 +68,7 @@ abstract class AbstractPart extends \PhpOffice\PhpWord\Writer\Word2007\Part\Abst
protected function writeFontFaces(XMLWriter $xmlWriter)
{
$xmlWriter->startElement('office:font-face-decls');
$arrFonts = array();
$fontTable = array();
$styles = Style::getStyles();
$numFonts = 0;
if (count($styles) > 0) {
@ -76,8 +77,8 @@ abstract class AbstractPart extends \PhpOffice\PhpWord\Writer\Word2007\Part\Abst
if ($style instanceof Font) {
$numFonts++;
$name = $style->getName();
if (!in_array($name, $arrFonts)) {
$arrFonts[] = $name;
if (!in_array($name, $fontTable)) {
$fontTable[] = $name;
// style:font-face
$xmlWriter->startElement('style:font-face');
@ -88,10 +89,10 @@ abstract class AbstractPart extends \PhpOffice\PhpWord\Writer\Word2007\Part\Abst
}
}
}
if (!in_array(PhpWord::DEFAULT_FONT_NAME, $arrFonts)) {
if (!in_array(Settings::getDefaultFontName(), $fontTable)) {
$xmlWriter->startElement('style:font-face');
$xmlWriter->writeAttribute('style:name', PhpWord::DEFAULT_FONT_NAME);
$xmlWriter->writeAttribute('svg:font-family', PhpWord::DEFAULT_FONT_NAME);
$xmlWriter->writeAttribute('style:name', Settings::getDefaultFontName());
$xmlWriter->writeAttribute('svg:font-family', Settings::getDefaultFontName());
$xmlWriter->endElement();
}
$xmlWriter->endElement();

View File

@ -17,21 +17,34 @@
namespace PhpOffice\PhpWord\Writer\ODText\Part;
use PhpOffice\PhpWord\Element\Image;
use PhpOffice\PhpWord\Element\Table;
use PhpOffice\PhpWord\Element\Text;
use PhpOffice\PhpWord\Media;
use PhpOffice\PhpWord\Element\TextRun;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLWriter;
use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Style\Paragraph;
use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Style\Table as TableStyle;
use PhpOffice\PhpWord\Writer\ODText\Element\Container;
use PhpOffice\PhpWord\Writer\ODText\Style\Paragraph as ParagraphStyleWriter;
/**
* ODText content part writer: content.xml
*/
class Content extends AbstractPart
{
/**
* Auto style collection
*
* Collect inline style information from section, image, and table elements
*
* @todo Merge font and paragraph styles
* @var array
*/
private $autoStyles = array('Section' => array(), 'Image' => array(), 'Table' => array());
/**
* Write part
*
@ -39,8 +52,10 @@ class Content extends AbstractPart
*/
public function write()
{
$phpWord = $this->getParentWriter()->getPhpWord();
$xmlWriter = $this->getXmlWriter();
$phpWord = $this->getParentWriter()->getPhpWord();
$this->getAutoStyles($phpWord);
$xmlWriter->startDocument('1.0', 'UTF-8');
$xmlWriter->startElement('office:document-content');
@ -51,14 +66,15 @@ class Content extends AbstractPart
$xmlWriter->writeAttribute('xmlns:field', 'urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0');
$xmlWriter->writeAttribute('xmlns:formx', 'urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0');
$this->getAutomaticStyles($phpWord);
// Font declarations and automatic styles
$this->writeFontFaces($xmlWriter); // office:font-face-decls
$this->writeAutomaticStyles($xmlWriter, $phpWord); // office:automatic-styles
$this->writeAutoStyles($xmlWriter); // office:automatic-styles
// Body
$xmlWriter->startElement('office:body');
$xmlWriter->startElement('office:text');
// text:sequence-decls
// Sequence declarations
$sequences = array('Illustration', 'Table', 'Text', 'Drawing');
$xmlWriter->startElement('text:sequence-decls');
foreach ($sequences as $sequence) {
@ -69,42 +85,61 @@ class Content extends AbstractPart
}
$xmlWriter->endElement(); // text:sequence-decl
// Sections
$sections = $phpWord->getSections();
$sectionCount = count($sections);
if ($sectionCount > 0) {
foreach ($sections as $section) {
// $xmlWriter->startElement('text:section');
$containerWriter = new Container($xmlWriter, $section);
$containerWriter->write();
// $xmlWriter->endElement(); // text:section
}
foreach ($sections as $section) {
$name = 'Section' . $section->getSectionId();
$xmlWriter->startElement('text:section');
$xmlWriter->writeAttribute('text:name', $name);
$xmlWriter->writeAttribute('text:style-name', $name);
$containerWriter = new Container($xmlWriter, $section);
$containerWriter->write();
$xmlWriter->endElement(); // text:section
}
$xmlWriter->endElement(); // office:text
$xmlWriter->endElement(); // office:body
$xmlWriter->endElement(); // office:document-content
return $xmlWriter->getData();
}
/**
* Write automatic styles
* Write automatic styles other than fonts and paragraphs
*
* @since 0.11.0
*/
private function writeAutomaticStyles(XMLWriter $xmlWriter, PhpWord $phpWord)
private function writeAutoStyles(XMLWriter $xmlWriter)
{
$xmlWriter->startElement('office:automatic-styles');
// Font and paragraph
$this->writeTextStyles($xmlWriter);
foreach ($this->autoStyles as $element => $style) {
$writerClass = 'PhpOffice\\PhpWord\\Writer\\ODText\\Style\\' . $element;
/** @var \PhpOffice\PhpWord\Writer\ODText\Style\AbstractStyle $styleWriter Type hint */
$styleWriter = new $writerClass($xmlWriter, $style);
$styleWriter->write();
}
$xmlWriter->endElement(); // office:automatic-styles
}
/**
* Write automatic styles
*/
private function writeTextStyles(XMLWriter $xmlWriter)
{
$styles = Style::getStyles();
$paragraphStyleCount = 0;
if (count($styles) > 0) {
foreach ($styles as $styleName => $style) {
if (preg_match('#^T[0-9]+$#', $styleName) != 0
|| preg_match('#^P[0-9]+$#', $styleName) != 0
) {
foreach ($styles as $style) {
if ($style->isAuto() === true) {
$styleClass = str_replace('\\Style\\', '\\Writer\\ODText\\Style\\', get_class($style));
if (class_exists($styleClass)) {
/** @var \PhpOffice\PhpWord\Writer\ODText\Style\AbstractStyle $styleWriter Type hint */
$styleWriter = new $styleClass($xmlWriter, $style);
$styleWriter->setIsAuto(true);
$styleWriter->write();
}
if ($style instanceof Paragraph) {
@ -115,92 +150,90 @@ class Content extends AbstractPart
if ($paragraphStyleCount == 0) {
$style = new Paragraph();
$style->setStyleName('P1');
$styleWriter = new \PhpOffice\PhpWord\Writer\ODText\Style\Paragraph($xmlWriter, $style);
$styleWriter->setIsAuto(true);
$style->setAuto();
$styleWriter = new ParagraphStyleWriter($xmlWriter, $style);
$styleWriter->write();
}
}
// Images
$images = Media::getElements('section');
foreach ($images as $image) {
if ($image['type'] == 'image') {
$xmlWriter->startElement('style:style');
$xmlWriter->writeAttribute('style:name', 'fr' . $image['rID']);
$xmlWriter->writeAttribute('style:family', 'graphic');
$xmlWriter->writeAttribute('style:parent-style-name', 'Graphics');
$xmlWriter->startElement('style:graphic-properties');
$xmlWriter->writeAttribute('style:vertical-pos', 'top');
$xmlWriter->writeAttribute('style:vertical-rel', 'baseline');
$xmlWriter->endElement();
$xmlWriter->endElement();
}
}
// Tables
$sections = $phpWord->getSections();
$sectionCount = count($sections);
if ($sectionCount > 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:automatic-styles
}
/**
* Set automatic styles
* Get automatic styles
*/
private function getAutomaticStyles(PhpWord $phpWord)
private function getAutoStyles(PhpWord $phpWord)
{
$sections = $phpWord->getSections();
$sectionCount = count($sections);
if ($sectionCount > 0) {
$paragraphStyleCount = 0;
$fontStyleCount = 0;
foreach ($sections as $section) {
$elements = $section->getElements();
foreach ($elements as $element) {
if ($element instanceof Text) {
$fontStyle = $element->getFontStyle();
$paragraphStyle = $element->getParagraphStyle();
$paragraphStyleCount = 0;
$fontStyleCount = 0;
foreach ($sections as $section) {
$style = $section->getSettings();
$style->setStyleName("Section{$section->getSectionId()}");
$this->autoStyles['Section'][] = $style;
$this->getContainerStyle($section, $paragraphStyleCount, $fontStyleCount);
}
}
// Font
if ($fontStyle instanceof Font) {
$fontStyleCount++;
$arrStyle = array(
'color' => $fontStyle->getColor(),
'name' => $fontStyle->getName()
);
$phpWord->addFontStyle('T' . $fontStyleCount, $arrStyle);
$element->setFontStyle('T' . $fontStyleCount);
// Paragraph
} elseif ($paragraphStyle instanceof Paragraph) {
$paragraphStyleCount++;
$phpWord->addParagraphStyle('P' . $paragraphStyleCount, array());
$element->setParagraphStyle('P' . $paragraphStyleCount);
}
}
/**
* Get all styles of each elements in container recursively
*
* Table style can be null or string of the style name
*
* @param \PhpOffice\PhpWord\Element\AbstractContainer $container
* @param int $paragraphStyleCount
* @param int $fontStyleCount
* @todo Simplify the logic
*/
private function getContainerStyle($container, &$paragraphStyleCount, &$fontStyleCount)
{
$elements = $container->getElements();
foreach ($elements as $element) {
if ($element instanceof TextRun) {
$this->getContainerStyle($element, $paragraphStyleCount, $fontStyleCount);
} elseif ($element instanceof Text) {
$this->getElementStyle($element, $paragraphStyleCount, $fontStyleCount);
} elseif ($element instanceof Image) {
$style = $element->getStyle();
$style->setStyleName('fr' . $element->getMediaIndex());
$this->autoStyles['Image'][] = $style;
} elseif ($element instanceof Table) {
$style = $element->getStyle();
if ($style === null) {
$style = new TableStyle();
} elseif (is_string($style)) {
$style = Style::getStyle($style);
}
$style->setStyleName($element->getElementId());
$this->autoStyles['Table'][] = $style;
}
}
}
/**
* Get style of individual element
*
* @param \PhpOffice\PhpWord\Element\Text $element
* @param int $paragraphStyleCount
* @param int $fontStyleCount
*/
private function getElementStyle(&$element, &$paragraphStyleCount, &$fontStyleCount)
{
$fontStyle = $element->getFontStyle();
$paragraphStyle = $element->getParagraphStyle();
$phpWord = $this->getParentWriter()->getPhpWord();
// Font
if ($fontStyle instanceof Font) {
$fontStyleCount++;
$style = $phpWord->addFontStyle("T{$fontStyleCount}", $fontStyle);
$style->setAuto();
$element->setFontStyle("T{$fontStyleCount}");
// Paragraph
} elseif ($paragraphStyle instanceof Paragraph) {
$paragraphStyleCount++;
$style = $phpWord->addParagraphStyle("P{$paragraphStyleCount}", array());
$style->setAuto();
$element->setParagraphStyle("P{$paragraphStyleCount}");
}
}
}

View File

@ -17,10 +17,12 @@
namespace PhpOffice\PhpWord\Writer\ODText\Part;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLWriter;
/**
* ODText meta part writer: meta.xml
*
* @since 0.11.0
*/
class Meta extends AbstractPart
{
@ -44,27 +46,61 @@ class Meta extends AbstractPart
$xmlWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0');
$xmlWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office');
$xmlWriter->writeAttribute('xmlns:grddl', 'http://www.w3.org/2003/g/data-view#');
// office:meta
$xmlWriter->startElement('office:meta');
// Core properties
$xmlWriter->writeElement('dc:title', $docProps->getTitle());
$xmlWriter->writeElement('dc:subject', $docProps->getSubject());
$xmlWriter->writeElement('dc:description', $docProps->getDescription());
$xmlWriter->writeElement('dc:creator', $docProps->getLastModifiedBy());
$xmlWriter->writeElement('dc:date', gmdate('Y-m-d\TH:i:s.000', $docProps->getModified()));
$xmlWriter->writeElement('dc:description', $docProps->getDescription());
$xmlWriter->writeElement('dc:subject', $docProps->getSubject());
$xmlWriter->writeElement('dc:title', $docProps->getTitle());
$xmlWriter->writeElement('meta:creation-date', gmdate('Y-m-d\TH:i:s.000', $docProps->getCreated()));
// Extended properties
$xmlWriter->writeElement('meta:generator', 'PHPWord');
$xmlWriter->writeElement('meta:initial-creator', $docProps->getCreator());
$xmlWriter->writeElement('meta:creation-date', gmdate('Y-m-d\TH:i:s.000', $docProps->getCreated()));
$xmlWriter->writeElement('meta:keyword', $docProps->getKeywords());
// @todo : Where these properties are written ?
// $docProps->getCategory()
// $docProps->getCompany()
// Category, company, and manager are put in meta namespace
$properties = array('Category', 'Company', 'Manager');
foreach ($properties as $property) {
$method = "get{$property}";
if ($docProps->$method() !== null) {
$this->writeCustomProperty($xmlWriter, $property, $docProps->$method());
}
}
$xmlWriter->endElement();
// Other custom properties
// @todo Check type. Currently all assumed as string
foreach ($docProps->getCustomProperties() as $property) {
$value = $docProps->getCustomPropertyValue($property);
$this->writeCustomProperty($xmlWriter, $property, $value);
}
$xmlWriter->endElement();
$xmlWriter->endElement(); // office:meta
$xmlWriter->endElement(); // office:document-meta
// Return
return $xmlWriter->getData();
}
/**
* Write individual property
*
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param string $property
* @param string $value
* @param string $type string (default/null)
*
* @todo Handle other `$type`: double|date|dateTime|duration|boolean
*/
private function writeCustomProperty(XMLWriter $xmlWriter, $property, $value, $type = null)
{
$xmlWriter->startElement('meta:user-defined');
$xmlWriter->writeAttribute('meta:name', $property);
if ($type !== null) {
$xmlWriter->writeAttribute('meta:value-type', $type);
}
$xmlWriter->writeRaw($value);
$xmlWriter->endElement(); // meta:user-defined
}
}

View File

@ -17,11 +17,12 @@
namespace PhpOffice\PhpWord\Writer\ODText\Part;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Shared\XMLWriter;
use PhpOffice\PhpWord\Style;
/**
* ODText styloes part writer: styles.xml
* ODText styles part writer: styles.xml
*/
class Styles extends AbstractPart
{
@ -36,22 +37,38 @@ class Styles extends AbstractPart
// XML header
$xmlWriter->startDocument('1.0', 'UTF-8');
// Styles:Styles
$xmlWriter->startElement('office:document-styles');
$this->writeCommonRootAttributes($xmlWriter);
// office:font-face-decls
// Font declarations
$this->writeFontFaces($xmlWriter);
// office:styles
// Office styles
$xmlWriter->startElement('office:styles');
$this->writeDefault($xmlWriter);
$this->writeNamed($xmlWriter);
$xmlWriter->endElement();
// style:default-style
// Automatic styles
$xmlWriter->startElement('office:automatic-styles');
$this->writePageLayout($xmlWriter);
$this->writeMaster($xmlWriter);
$xmlWriter->endElement();
$xmlWriter->endElement(); // office:document-styles
return $xmlWriter->getData();
}
/**
* Write default styles
*/
private function writeDefault(XMLWriter $xmlWriter)
{
$xmlWriter->startElement('style:default-style');
$xmlWriter->writeAttribute('style:family', 'paragraph');
// style:paragraph-properties
// Paragraph
$xmlWriter->startElement('style:paragraph-properties');
$xmlWriter->writeAttribute('fo:hyphenation-ladder-count', 'no-limit');
$xmlWriter->writeAttribute('style:text-autospace', 'ideograph-alpha');
@ -59,54 +76,59 @@ class Styles extends AbstractPart
$xmlWriter->writeAttribute('style:line-break', 'strict');
$xmlWriter->writeAttribute('style:tab-stop-distance', '1.249cm');
$xmlWriter->writeAttribute('style:writing-mode', 'page');
$xmlWriter->endElement();
$xmlWriter->endElement(); // style:paragraph-properties
// style:text-properties
// Font
$xmlWriter->startElement('style:text-properties');
$xmlWriter->writeAttribute('style:use-window-font-color', 'true');
$xmlWriter->writeAttribute('style:font-name', PhpWord::DEFAULT_FONT_NAME);
$xmlWriter->writeAttribute('fo:font-size', PhpWord::DEFAULT_FONT_SIZE . 'pt');
$xmlWriter->writeAttribute('style:font-name', Settings::getDefaultFontName());
$xmlWriter->writeAttribute('fo:font-size', Settings::getDefaultFontSize() . 'pt');
$xmlWriter->writeAttribute('fo:language', 'fr');
$xmlWriter->writeAttribute('fo:country', 'FR');
$xmlWriter->writeAttribute('style:letter-kerning', 'true');
$xmlWriter->writeAttribute('style:font-name-asian', PhpWord::DEFAULT_FONT_NAME . '2');
$xmlWriter->writeAttribute('style:font-size-asian', PhpWord::DEFAULT_FONT_SIZE . 'pt');
$xmlWriter->writeAttribute('style:font-name-asian', Settings::getDefaultFontName() . '2');
$xmlWriter->writeAttribute('style:font-size-asian', Settings::getDefaultFontSize() . 'pt');
$xmlWriter->writeAttribute('style:language-asian', 'zh');
$xmlWriter->writeAttribute('style:country-asian', 'CN');
$xmlWriter->writeAttribute('style:font-name-complex', PhpWord::DEFAULT_FONT_NAME . '2');
$xmlWriter->writeAttribute('style:font-size-complex', PhpWord::DEFAULT_FONT_SIZE . 'pt');
$xmlWriter->writeAttribute('style:font-name-complex', Settings::getDefaultFontName() . '2');
$xmlWriter->writeAttribute('style:font-size-complex', Settings::getDefaultFontSize() . 'pt');
$xmlWriter->writeAttribute('style:language-complex', 'hi');
$xmlWriter->writeAttribute('style:country-complex', 'IN');
$xmlWriter->writeAttribute('fo:hyphenate', 'false');
$xmlWriter->writeAttribute('fo:hyphenation-remain-char-count', '2');
$xmlWriter->writeAttribute('fo:hyphenation-push-char-count', '2');
$xmlWriter->endElement();
$xmlWriter->endElement(); // style:text-properties
$xmlWriter->endElement();
$xmlWriter->endElement(); // style:default-style
}
// Write Style Definitions
/**
* Write named styles
*/
private function writeNamed(XMLWriter $xmlWriter)
{
$styles = Style::getStyles();
if (count($styles) > 0) {
foreach ($styles as $styleName => $style) {
if (preg_match('#^T[0-9]+$#', $styleName) == 0
&& preg_match('#^P[0-9]+$#', $styleName) == 0
) {
foreach ($styles as $style) {
if ($style->isAuto() === false) {
$styleClass = str_replace('\\Style\\', '\\Writer\\ODText\\Style\\', get_class($style));
if (class_exists($styleClass)) {
/** @var $styleWriter \PhpOffice\PhpWord\Writer\ODText\Style\AbstractStyle Type hint */
$styleWriter = new $styleClass($xmlWriter, $style);
$styleWriter->write();
}
}
}
}
$xmlWriter->endElement();
// office:automatic-styles
$xmlWriter->startElement('office:automatic-styles');
// style:page-layout
}
/**
* Write page layout styles
*/
private function writePageLayout(XMLWriter $xmlWriter)
{
$xmlWriter->startElement('style:page-layout');
$xmlWriter->writeAttribute('style:name', 'Mpm1');
// style:page-layout-properties
$xmlWriter->startElement('style:page-layout-properties');
$xmlWriter->writeAttribute('fo:page-width', "21.001cm");
$xmlWriter->writeAttribute('fo:page-height', '29.7cm');
@ -128,36 +150,38 @@ class Styles extends AbstractPart
$xmlWriter->writeAttribute('style:layout-grid-base-width', '0.37cm');
$xmlWriter->writeAttribute('style:layout-grid-snap-to', 'true');
$xmlWriter->writeAttribute('style:footnote-max-height', '0cm');
//style:footnote-sep
$xmlWriter->startElement('style:footnote-sep');
$xmlWriter->writeAttribute('style:width', '0.018cm');
$xmlWriter->writeAttribute('style:line-style', 'solid');
$xmlWriter->writeAttribute('style:adjustment', 'left');
$xmlWriter->writeAttribute('style:rel-width', '25%');
$xmlWriter->writeAttribute('style:color', '#000000');
$xmlWriter->endElement();
$xmlWriter->endElement();
// style:header-style
$xmlWriter->startElement('style:header-style');
$xmlWriter->endElement();
// style:footer-style
$xmlWriter->startElement('style:footer-style');
$xmlWriter->endElement();
$xmlWriter->endElement();
$xmlWriter->endElement();
$xmlWriter->endElement(); //style:footnote-sep
// office:master-styles
$xmlWriter->endElement(); // style:page-layout-properties
$xmlWriter->startElement('style:header-style');
$xmlWriter->endElement(); // style:header-style
$xmlWriter->startElement('style:footer-style');
$xmlWriter->endElement(); // style:footer-style
$xmlWriter->endElement(); // style:page-layout
}
/**
* Write master style
*/
private function writeMaster(XMLWriter $xmlWriter)
{
$xmlWriter->startElement('office:master-styles');
// style:master-page
$xmlWriter->startElement('style:master-page');
$xmlWriter->writeAttribute('style:name', 'Standard');
$xmlWriter->writeAttribute('style:page-layout-name', 'Mpm1');
$xmlWriter->endElement();
$xmlWriter->endElement();
$xmlWriter->endElement(); // style:master-page
$xmlWriter->endElement();
// Return
return $xmlWriter->getData();
$xmlWriter->endElement(); // office:master-styles
}
}

View File

@ -17,11 +17,13 @@
namespace PhpOffice\PhpWord\Writer\ODText\Style;
use PhpOffice\PhpWord\Writer\Word2007\Style\AbstractStyle as Word2007AbstractStyle;
/**
* Style writer
*
* @since 0.10.0
*/
abstract class AbstractStyle extends \PhpOffice\PhpWord\Writer\Word2007\Style\AbstractStyle
abstract class AbstractStyle extends Word2007AbstractStyle
{
}

View File

@ -24,11 +24,6 @@ namespace PhpOffice\PhpWord\Writer\ODText\Style;
*/
class Font extends AbstractStyle
{
/**
* Is automatic style
*/
private $isAuto = false;
/**
* Write style
*/
@ -47,18 +42,18 @@ class Font extends AbstractStyle
// Name
$font = $style->getName();
$xmlWriter->writeAttributeIf($font, 'style:font-name', $font);
$xmlWriter->writeAttributeIf($font, 'style:font-name-complex', $font);
$xmlWriter->writeAttributeIf($font != '', 'style:font-name', $font);
$xmlWriter->writeAttributeIf($font != '', 'style:font-name-complex', $font);
$size = $style->getSize();
// Size
$xmlWriter->writeAttributeIf($size, 'fo:font-size', $size . 'pt');
$xmlWriter->writeAttributeIf($size, 'style:font-size-asian', $size . 'pt');
$xmlWriter->writeAttributeIf($size, 'style:font-size-complex', $size . 'pt');
$xmlWriter->writeAttributeIf(is_numeric($size), 'fo:font-size', $size . 'pt');
$xmlWriter->writeAttributeIf(is_numeric($size), 'style:font-size-asian', $size . 'pt');
$xmlWriter->writeAttributeIf(is_numeric($size), 'style:font-size-complex', $size . 'pt');
// Color
$color = $style->getColor();
$xmlWriter->writeAttributeIf($color, 'fo:color', '#' . $color);
$xmlWriter->writeAttributeIf($color != '', 'fo:color', '#' . $color);
// Bold & italic
$xmlWriter->writeAttributeIf($style->isBold(), 'fo:font-weight', 'bold');
@ -67,17 +62,28 @@ class Font extends AbstractStyle
$xmlWriter->writeAttributeIf($style->isItalic(), 'style:font-style-asian', 'italic');
$xmlWriter->writeAttributeIf($style->isItalic(), 'style:font-style-complex', 'italic');
// Underline
// @todo Various mode of underline
$underline = $style->getUnderline();
$xmlWriter->writeAttributeIf($underline != 'none', 'style:text-underline-style', 'solid');
// Strikethrough, double strikethrough
$xmlWriter->writeAttributeIf($style->isStrikethrough(), 'style:text-line-through-type', 'single');
$xmlWriter->writeAttributeIf($style->isDoubleStrikethrough(), 'style:text-line-through-type', 'double');
// Small caps, all caps
$xmlWriter->writeAttributeIf($style->isSmallCaps(), 'fo:font-variant', 'small-caps');
$xmlWriter->writeAttributeIf($style->isAllCaps(), 'fo:text-transform', 'uppercase');
// Superscript/subscript
$xmlWriter->writeAttributeIf($style->isSuperScript(), 'style:text-position', 'super');
$xmlWriter->writeAttributeIf($style->isSubScript(), 'style:text-position', 'sub');
// @todo Foreground-Color
// @todo Background color
$xmlWriter->endElement(); // style:text-properties
$xmlWriter->endElement(); // style:style
}
/**
* Set is automatic style
*
* @param bool $value
*/
public function setIsAuto($value)
{
$this->isAuto = $value;
}
}

View File

@ -0,0 +1,49 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2010-2014 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Writer\ODText\Style;
/**
* Image style writer
*
* @since 0.11.0
*/
class Image extends AbstractStyle
{
/**
* Write style
*/
public function write()
{
/** @var \PhpOffice\PhpWord\Style\Image $style Type hint */
$style = $this->getStyle();
if (!$style instanceof \PhpOffice\PhpWord\Style\Image) {
return;
}
$xmlWriter = $this->getXmlWriter();
$xmlWriter->startElement('style:style');
$xmlWriter->writeAttribute('style:name', $style->getStyleName());
$xmlWriter->writeAttribute('style:family', 'graphic');
$xmlWriter->writeAttribute('style:parent-style-name', 'Graphics');
$xmlWriter->startElement('style:graphic-properties');
$xmlWriter->writeAttribute('style:vertical-pos', 'top');
$xmlWriter->writeAttribute('style:vertical-rel', 'baseline');
$xmlWriter->endElement(); // style:graphic-properties
$xmlWriter->endElement(); // style:style
}
}

View File

@ -24,11 +24,6 @@ namespace PhpOffice\PhpWord\Writer\ODText\Style;
*/
class Paragraph extends AbstractStyle
{
/**
* Is automatic style
*/
private $isAuto = false;
/**
* Write style
*/
@ -46,13 +41,13 @@ class Paragraph extends AbstractStyle
$xmlWriter->startElement('style:style');
$xmlWriter->writeAttribute('style:name', $style->getStyleName());
$xmlWriter->writeAttribute('style:family', 'paragraph');
if ($this->isAuto) {
if ($style->isAuto()) {
$xmlWriter->writeAttribute('style:parent-style-name', 'Standard');
$xmlWriter->writeAttribute('style:master-page-name', 'Standard');
}
$xmlWriter->startElement('style:paragraph-properties');
if ($this->isAuto) {
if ($style->isAuto()) {
$xmlWriter->writeAttribute('style:page-number', 'auto');
} else {
$xmlWriter->writeAttribute('fo:margin-top', $marginTop . 'cm');
@ -63,14 +58,4 @@ class Paragraph extends AbstractStyle
$xmlWriter->endElement(); //style:style
}
/**
* Set is automatic style
*
* @param bool $value
*/
public function setIsAuto($value)
{
$this->isAuto = $value;
}
}

View File

@ -0,0 +1,51 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2010-2014 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Writer\ODText\Style;
/**
* Section style writer
*
* @since 0.11.0
*/
class Section extends AbstractStyle
{
/**
* Write style
*/
public function write()
{
/** @var \PhpOffice\PhpWord\Style\Section $style Type hint */
$style = $this->getStyle();
if (!$style instanceof \PhpOffice\PhpWord\Style\Section) {
return;
}
$xmlWriter = $this->getXmlWriter();
$xmlWriter->startElement('style:style');
$xmlWriter->writeAttribute('style:name', $style->getStyleName());
$xmlWriter->writeAttribute('style:family', "section");
$xmlWriter->startElement('style:section-properties');
$xmlWriter->startElement('style:columns');
$xmlWriter->writeAttribute('fo:column-count', $style->getColsNum());
$xmlWriter->endElement(); // style:columns
$xmlWriter->endElement(); // style:section-properties
$xmlWriter->endElement(); // style:style
}
}

Some files were not shown because too many files have changed in this diff Show More