develop_v1.0

# Conflicts:
#	.travis.yml
#	composer.json
This commit is contained in:
troosan 2021-02-21 23:02:55 +01:00
commit c28cbd7f08
153 changed files with 6308 additions and 445 deletions

15
.github/support.yml vendored Normal file
View File

@ -0,0 +1,15 @@
# Label used to mark issues as support requests
supportLabel: Question
# Comment to post on issues marked as support requests. Add a link
# to a support page, or set to `false` to disable
supportComment: >
This looks like a support question. Please ask your support questions on
[StackOverflow](http://stackoverflow.com/questions/tagged/phpword),
or [Gitter](https://gitter.im/PHPOffice/PHPWord).
Thank you for your contributions.
# Whether to close issues marked as support requests
close: true
# Whether to lock issues marked as support requests
lock: false

170
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,170 @@
name: CI
on:
- push
- pull_request
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
php-version:
- '7.2'
- "7.3"
- "7.4"
- "8.0"
name: PHP ${{ matrix.php-version }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
coverage: none
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Update PHPUnit version for PHP 8
id: composer-lock
if: "startsWith(matrix.php-version, '8.')"
run: |
rm -f composer.lock
echo "::set-output name=flags::--ignore-platform-reqs"
composer remove phpunit/phpunit --dev --no-update --no-interaction
composer require phpunit/phpunit ^8.0 --dev --no-update
- name: Install dependencies
run: composer update --no-progress --prefer-dist --optimize-autoloader ${{ steps.composer-lock.outputs.flags }}
- name: Update code to make PHPUnit 8 compatible
if: "startsWith(matrix.php-version, '8.')"
run: |
find ./tests/ -name "*.php" -type f -exec sed -i -e 's/function setUpBeforeClass()$/function setUpBeforeClass(): void/' {} \;
find ./tests/ -name "*.php" -type f -exec sed -i -e 's/function tearDownAfterClass()$/function tearDownAfterClass(): void/' {} \;
find ./tests/ -name "*.php" -type f -exec sed -i -e 's/function setUp()$/function setUp(): void/' {} \;
find ./tests/ -name "*.php" -type f -exec sed -i -e 's/function tearDown()$/function tearDown(): void/' {} \;
find ./tests/ -name "*.php" -type f -exec sed -i -e 's/->assertContains(/->assertStringContainsString(/' {} \;
find ./tests/ -name "*.php" -type f -exec sed -i -e 's/->assertNotContains(/->assertStringNotContainsString(/' {} \;
find ./tests/ -name "*.php" -type f -exec sed -i -e "s/->assertInternalType('array', /->assertIsArray(/" {} \;
sed -i "s/\$this->addWarning('The @expectedException,/\/\/\$this->addWarning('The @expectedException,/" ./vendor/phpunit/phpunit/src/Framework/TestCase.php
sed -i "s/self::createWarning('The optional \$delta/\/\/self::createWarning('The optional \$delta/" ./vendor/phpunit/phpunit/src/Framework/Assert.php
- name: Setup problem matchers for PHP
run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
- name: Setup problem matchers for PHPUnit
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
- name: Configure matchers
uses: mheap/phpunit-matcher-action@v1
- name: Test with PHPUnit
run: ./vendor/bin/phpunit --teamcity --no-coverage -c ./
php-cs-fixer:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
coverage: none
tools: cs2pr
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Code style with PHP-CS-Fixer
run: ./vendor/bin/php-cs-fixer fix --format=checkstyle | cs2pr
phpcs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
coverage: none
tools: cs2pr
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Code style with PHP_CodeSniffer
run: ./vendor/bin/phpcs src/ tests/ --standard=PSR2 -n --ignore=src/PhpWord/Shared/PCLZip --report=checkstyle | cs2pr
coverage:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
coverage: xdebug
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Coverage
run: |
./vendor/bin/phpunit --coverage-clover coverage-clover.xml
curl -LO https://scrutinizer-ci.com/ocular.phar
php ocular.phar code-coverage:upload --format=php-clover coverage-clover.xml

29
.github/workflows/github-pages.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: GithHub Pages
on:
push:
tags:
- '*'
jobs:
github-pages:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
coverage: none # remove xdebug
- name: Build API documentation
run: |
curl -LO https://github.com/phpDocumentor/phpDocumentor/releases/download/v3.0.0/phpDocumentor.phar
php phpDocumentor.phar --directory src/ --target docs/api
- name: Deploy to GithHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/api

View File

@ -0,0 +1,8 @@
user=PHPOffice
project=PHPWord
since-tag=0.17.0
future-release=0.18.0
issues=false
pulls=true

View File

@ -3,6 +3,12 @@ build:
analysis:
tests:
override: [php-scrutinizer-run]
environment:
php:
version: '7.4'
pecl_extensions:
- zip
filter:
excluded_paths: [ 'vendor/*', 'tests/*', 'samples/*', 'src/PhpWord/Shared/PCLZip/*' ]

View File

@ -1,8 +1,55 @@
Change Log
==========
# Changelog
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [0.18.0](https://github.com/PHPOffice/PHPWord/tree/0.18.0) (2021-02-12)
[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.17.0...0.18.0)
### Enhancements
- Add support for charts in template processor [\#2012](https://github.com/PHPOffice/PHPWord/pull/2012) ([dbarzin](https://github.com/dbarzin))
- add/setting page element border style. [\#1986](https://github.com/PHPOffice/PHPWord/pull/1986) ([emnabs](https://github.com/emnabs))
- allow to use customized pdf library [\#1983](https://github.com/PHPOffice/PHPWord/pull/1983) ([SailorMax](https://github.com/SailorMax))
- feat: Update addHtml to handle style inheritance [\#1965](https://github.com/PHPOffice/PHPWord/pull/1965) ([Julien1138](https://github.com/Julien1138))
- Add parsing of Shape node values [\#1924](https://github.com/PHPOffice/PHPWord/pull/1924) ([sven-ahrens](https://github.com/sven-ahrens))
- Allow to redefine TCPDF object [\#1907](https://github.com/PHPOffice/PHPWord/pull/1907) ([SailorMax](https://github.com/SailorMax))
- Enhancements to addHTML parser [\#1902](https://github.com/PHPOffice/PHPWord/pull/1902) ([lubosdz](https://github.com/lubosdz))
- Make Default Paper Configurable [\#1851](https://github.com/PHPOffice/PHPWord/pull/1851) ([oleibman](https://github.com/oleibman))
- Implement various missing features for the ODT writer [\#1796](https://github.com/PHPOffice/PHPWord/pull/1796) ([oleibman](https://github.com/oleibman))
- Added support for "cloudConvert" images [\#1794](https://github.com/PHPOffice/PHPWord/pull/1794) ([ErnestStaug](https://github.com/ErnestStaug))
- Add support for several features for the RTF writer [\#1775](https://github.com/PHPOffice/PHPWord/pull/1775) ([oleibman](https://github.com/oleibman))
- Add font style for Field elements [\#1774](https://github.com/PHPOffice/PHPWord/pull/1774) ([oleibman](https://github.com/oleibman))
- Add support for ListItemRun in HTML writer [\#1766](https://github.com/PHPOffice/PHPWord/pull/1766) ([stefan-91](https://github.com/stefan-91))
- Improvements in RTF writer [\#1755](https://github.com/PHPOffice/PHPWord/pull/1755) ([oleibman](https://github.com/oleibman))
- Allow a closure to be passed with image replacement tags [\#1716](https://github.com/PHPOffice/PHPWord/pull/1716) ([mbardelmeijer](https://github.com/mbardelmeijer))
- Add Option for Dynamic Chart Legend Position [\#1699](https://github.com/PHPOffice/PHPWord/pull/1699) ([Stephan212](https://github.com/Stephan212))
- Add parsing of HTML checkbox input field [\#1832](https://github.com/PHPOffice/PHPWord/pull/1832) ([Matze2010](https://github.com/Matze2010))
### Bug fixes
- Fix image stroke in libreoffice 7.x [\#1992](https://github.com/PHPOffice/PHPWord/pull/1992) ([Adizbek](https://github.com/Adizbek))
- Fix deprecated warning for non-hexadecimal number [\#1988](https://github.com/PHPOffice/PHPWord/pull/1988) ([Ciki](https://github.com/Ciki))
- Fix limit not taken into account when adding image in template [\#1967](https://github.com/PHPOffice/PHPWord/pull/1967) ([jsochor](https://github.com/jsochor))
- Add null check when setComplexValue is not found [\#1936](https://github.com/PHPOffice/PHPWord/pull/1936) ([YannikFirre](https://github.com/YannikFirre))
- Some document have non-standard locale code [\#1824](https://github.com/PHPOffice/PHPWord/pull/1824) ([ErnestStaug](https://github.com/ErnestStaug))
- Fixes PHPDoc @param and @return types for several Converter methods [\#1818](https://github.com/PHPOffice/PHPWord/pull/1818) ([caugner](https://github.com/caugner))
- Update the regexp to avoid catastrophic backtracking [\#1809](https://github.com/PHPOffice/PHPWord/pull/1809) ([juzser](https://github.com/juzser))
- Fix PHPUnit tests on develop branch [\#1771](https://github.com/PHPOffice/PHPWord/pull/1771) ([mdupont](https://github.com/mdupont))
- TemplateProcessor cloneBlock wrongly clones images [\#1763](https://github.com/PHPOffice/PHPWord/pull/1763) ([alarai](https://github.com/alarai))
### Miscellaneous
- Compatibility with PHP 7.4, PHP 8.0 and migrate to Laminas Escaper [\#1946](https://github.com/PHPOffice/PHPWord/pull/1946) ([liborm85](https://github.com/liborm85))
- Remove legacy PHPOffice/Common package, fix PHP 8.0 compatibility [\#1996](https://github.com/PHPOffice/PHPWord/pull/1996) ([liborm85](https://github.com/liborm85))
- Improve Word2007 Test Coverage [\#1858](https://github.com/PHPOffice/PHPWord/pull/1858) ([oleibman](https://github.com/oleibman))
- Fix typo in docs. Update templates-processing.rst [\#1952](https://github.com/PHPOffice/PHPWord/pull/1952) ([mnvx](https://github.com/mnvx))
- Fix documentation and method name for FootnoteProperties [\#1776](https://github.com/PHPOffice/PHPWord/pull/1776) ([mdupont](https://github.com/mdupont))
- fix: documentation about paragraph indentation [\#1764](https://github.com/PHPOffice/PHPWord/pull/1764) ([mdupont](https://github.com/mdupont))
- Update templates-processing.rst [\#1745](https://github.com/PHPOffice/PHPWord/pull/1745) ([igronus](https://github.com/igronus))
- Unused variables $rows, $cols in sample [\#1877](https://github.com/PHPOffice/PHPWord/pull/1877) ([ThanasisMpalatsoukas](https://github.com/ThanasisMpalatsoukas))
- Add unit test for NumberingStyle [\#1744](https://github.com/PHPOffice/PHPWord/pull/1744) ([Manunchik](https://github.com/Manunchik))
- Add unit test for PhpWord Settings [\#1743](https://github.com/PHPOffice/PHPWord/pull/1743) ([Manunchik](https://github.com/Manunchik))
- Add unit test for Media elements [\#1742](https://github.com/PHPOffice/PHPWord/pull/1742) ([Manunchik](https://github.com/Manunchik))
- Update templates processing docs [\#1729](https://github.com/PHPOffice/PHPWord/pull/1729) ([hcdias](https://github.com/hcdias))
v0.17.0 (01 oct 2019)
----------------------
### Added

View File

@ -62,8 +62,7 @@ PHPWord requires the following:
- PHP 5.3.3+
- [XML Parser extension](http://www.php.net/manual/en/xml.installation.php)
- [Zend\Escaper component](http://framework.zend.com/manual/current/en/modules/zend.escaper.introduction.html)
- [Zend\Stdlib component](http://framework.zend.com/manual/current/en/modules/zend.stdlib.hydrator.html)
- [Laminas Escaper component](https://docs.laminas.dev/laminas-escaper/intro/)
- [Zip extension](http://php.net/manual/en/book.zip.php) (optional, used to write OOXML and ODF)
- [GD extension](http://php.net/manual/en/book.image.php) (optional, used to add images)
- [XMLWriter extension](http://php.net/manual/en/book.xmlwriter.php) (optional, used to write OOXML and ODF)

View File

@ -58,19 +58,18 @@
"fix": "Fixes issues found by PHP-CS"
},
"require": {
"php": "^7.1",
"php": "^7.1 || ^8",
"ext-xml": "*",
"zendframework/zend-escaper": "^2.2",
"phpoffice/common": "^0.2.9"
"laminas/laminas-escaper": "^2.2"
},
"require-dev": {
"ext-zip": "*",
"ext-gd": "*",
"phpunit/phpunit": "^7.5",
"phpunit/phpunit": "^7.5 || 8.*",
"squizlabs/php_codesniffer": "^3.0",
"friendsofphp/php-cs-fixer": "^2.14",
"phpmd/phpmd": "2.*",
"dompdf/dompdf":"0.8.*",
"dompdf/dompdf":"0.8.* || 1.0.*",
"tecnickcom/tcpdf": "6.*",
"mpdf/mpdf": "8.*",
"php-coveralls/php-coveralls": "^2.0"
@ -89,7 +88,7 @@
},
"extra": {
"branch-alias": {
"dev-develop": "0.18-dev",
"dev-develop": "0.19-dev",
"develop_v1.0": "1.0-dev"
}
}

View File

@ -41,14 +41,14 @@ master_doc = 'index'
# General information about the project.
project = u'PHPWord'
copyright = u'2014-2017, PHPWord Contributors'
copyright = u'2014-2021, PHPWord Contributors'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.17.0'
version = '0.18.0'
# The full version, including alpha/beta/rc tags.
release = version

View File

@ -359,17 +359,17 @@ The footnote numbering can be controlled by setting the FootnoteProperties on th
.. code-block:: php
$fp = new PhpWord\SimpleType\FootnoteProperties();
$fp = new \PhpOffice\PhpWord\ComplexType\FootnoteProperties();
//sets the position of the footnote (pageBottom (default), beneathText, sectEnd, docEnd)
$fp->setPos(FootnoteProperties::POSITION_DOC_END);
$fp->setPos(\PhpOffice\PhpWord\ComplexType\FootnoteProperties::POSITION_BENEATH_TEXT);
//set the number format to use (decimal (default), upperRoman, upperLetter, ...)
$fp->setNumFmt(FootnoteProperties::NUMBER_FORMAT_LOWER_ROMAN);
$fp->setNumFmt(\PhpOffice\PhpWord\SimpleType\NumberFormat::LOWER_ROMAN);
//force starting at other than 1
$fp->setNumStart(2);
//when to restart counting (continuous (default), eachSect, eachPage)
$fp->setNumRestart(FootnoteProperties::RESTART_NUMBER_EACH_PAGE);
$fp->setNumRestart(\PhpOffice\PhpWord\ComplexType\FootnoteProperties::RESTART_NUMBER_EACH_PAGE);
//And finaly, set it on the Section
$section->setFootnoteProperties($properties);
$section->setFootnoteProperties($fp);
Checkboxes
----------
@ -403,7 +403,9 @@ Currently the following fields are supported:
.. code-block:: php
$section->addField($fieldType, [$properties], [$options], [$fieldText])
$section->addField($fieldType, [$properties], [$options], [$fieldText], [$fontStyle])
- ``$fontStyle``. See :ref:`font-style`.
See ``\PhpOffice\PhpWord\Element\Field`` for list of properties and options available for each field type.
Options which are not specifically defined can be added. Those must start with a ``\``.

View File

@ -130,6 +130,16 @@ To turn it on set ``outputEscapingEnabled`` option to ``true`` in your PHPWord c
\PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(true);
Default Paper
~~~~~~~~~~~~~
By default, all sections of the document will print on A4 paper.
You can alter the default paper by using the following function:
.. code-block:: php
\PhpOffice\PhpWord\Settings::setDefaultPaper('Letter');
Default font
~~~~~~~~~~~~

View File

@ -10,9 +10,7 @@ Mandatory:
- PHP 5.3.3+
- `XML Parser <http://www.php.net/manual/en/xml.installation.php>`__ extension
- `Zend\\Escaper <http://framework.zend.com/manual/current/en/modules/zend.escaper.introduction.html>`__ component
- Zend\\Stdlib component
- `Zend\\Validator <http://framework.zend.com/manual/current/en/modules/zend.validator.html>`__ component
- `Laminas Escaper <https://docs.laminas.dev/laminas-escaper/intro/>`__ component
Optional:
@ -34,7 +32,7 @@ Example:
{
"require": {
"phpoffice/phpword": "v0.17.*"
"phpoffice/phpword": "v0.18.*"
}
}

View File

@ -201,6 +201,7 @@ Available Chart style options:
- ``colors``. A list of colors to use in the chart.
- ``title``. The title for the chart.
- ``showLegend``. Show legend, *true* or *false*.
- ``LegendPosition``. Legend position, *r* (default), *b*, *t*, *l* or *tr*.
- ``categoryLabelPosition``. Label position for categories, *nextTo* (default), *low* or *high*.
- ``valueLabelPosition``. Label position for values, *nextTo* (default), *low* or *high*.
- ``categoryAxisTitle``. The title for the category axis.

View File

@ -63,6 +63,11 @@ Example:
$templateProcessor->setImageValue('CompanyLogo', 'path/to/company/logo.png');
$templateProcessor->setImageValue('UserLogo', array('path' => 'path/to/logo.png', 'width' => 100, 'height' => 100, 'ratio' => false));
$templateProcessor->setImageValue('FeatureImage', function () {
// Closure will only be executed if the replacement tag is found in the template
return array('path' => SlowFeatureImageGenerator::make(), 'width' => 100, 'height' => 100, 'ratio' => false);
});
cloneBlock
""""""""""
@ -190,7 +195,7 @@ Finds a row in a table row identified by `$search` param and clones it as many t
['userId' => 1, 'userName' => 'Batman', 'userAddress' => 'Gotham City'],
['userId' => 2, 'userName' => 'Superman', 'userAddress' => 'Metropolis'],
];
$templateProcessor->cloneRowAndSetValues('userId', );
$templateProcessor->cloneRowAndSetValues('userId', $values);
Will result in
@ -244,9 +249,20 @@ See ``Sample_40_TemplateSetComplexValue.php`` for examples.
$table->addCell(150)->addText('Cell B2');
$table->addCell(150)->addText('Cell B3');
$templateProcessor->setComplexBlock('table', $table);
setChartValue
"""""""""""""
Replace a variable by a chart.
.. code-block:: php
$categories = array('A', 'B', 'C', 'D', 'E');
$series1 = array(1, 3, 2, 5, 4);
$chart = new Chart('doughnut', $categories, $series1);
$templateProcessor->setChartValue('myChart', $chart);
save
"""""""""
""""
Saves the loaded template within the current directory. Returns the file path.
.. code-block:: php
@ -254,7 +270,7 @@ Saves the loaded template within the current directory. Returns the file path.
$filepath = $templateProcessor->save();
saveAs
"""""""""
""""""
Saves a copy of the loaded template in the indicated path.
.. code-block:: php

View File

@ -5,6 +5,8 @@
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
<rule ref="rulesets/naming.xml">
<exclude name="ShortVariable" />
<exclude name="ShortClassName" />
<exclude name="LongVariable" />
</rule>
<rule ref="rulesets/naming.xml/LongVariable">

View File

@ -14,3 +14,7 @@ outputEscapingEnabled = false
defaultFontName = Arial
defaultFontSize = 10
[Paper]
defaultPaper = "A4"

View File

@ -17,9 +17,9 @@ $cols = 5;
$section->addText('Basic table', $header);
$table = $section->addTable();
for ($r = 1; $r <= 8; $r++) {
for ($r = 1; $r <= $rows; $r++) {
$table->addRow();
for ($c = 1; $c <= 5; $c++) {
for ($c = 1; $c <= $cols; $c++) {
$table->addCell(1750)->addText("Row {$r}, Cell {$c}");
}
}

View File

@ -25,6 +25,9 @@ $series2 = array(3, 1, 7, 2, 6);
$series3 = array(8, 3, 2, 5, 4);
$showGridLines = false;
$showAxisLabels = false;
$showLegend = true;
$legendPosition = 't';
// r = right, l = left, t = top, b = bottom, tr = top right
foreach ($chartTypes as $chartType) {
$section->addTitle(ucfirst($chartType), 2);
@ -33,6 +36,8 @@ foreach ($chartTypes as $chartType) {
$chart->getStyle()->setShowGridX($showGridLines);
$chart->getStyle()->setShowGridY($showGridLines);
$chart->getStyle()->setShowAxisLabels($showAxisLabels);
$chart->getStyle()->setShowLegend($showLegend);
$chart->getStyle()->setLegendPosition($legendPosition);
if (in_array($chartType, $twoSeries)) {
$chart->addSeries($categories, $series2);
}

View File

@ -0,0 +1,45 @@
<?php
use PhpOffice\PhpWord\Element\Chart;
use PhpOffice\PhpWord\Shared\Converter;
include_once 'Sample_Header.php';
// Template processor instance creation
echo date('H:i:s'), ' Creating new TemplateProcessor instance...', EOL;
$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('resources/Sample_41_TemplateSetChart.docx');
$chartTypes = array('pie', 'doughnut', 'bar', 'column', 'line', 'area', 'scatter', 'radar', 'stacked_bar', 'percent_stacked_bar', 'stacked_column', 'percent_stacked_column');
$twoSeries = array('bar', 'column', 'line', 'area', 'scatter', 'radar', 'stacked_bar', 'percent_stacked_bar', 'stacked_column', 'percent_stacked_column');
$threeSeries = array('bar', 'line');
$categories = array('A', 'B', 'C', 'D', 'E');
$series1 = array(1, 3, 2, 5, 4);
$series2 = array(3, 1, 7, 2, 6);
$series3 = array(8, 3, 2, 5, 4);
$i = 0;
foreach ($chartTypes as $chartType) {
$chart = new Chart($chartType, $categories, $series1);
if (in_array($chartType, $twoSeries)) {
$chart->addSeries($categories, $series2);
}
if (in_array($chartType, $threeSeries)) {
$chart->addSeries($categories, $series3);
}
$chart->getStyle()
->setWidth(Converter::inchToEmu(3))
->setHeight(Converter::inchToEmu(3));
$templateProcessor->setChart("chart{$i}", $chart);
$i++;
}
echo date('H:i:s'), ' Saving the result document...', EOL;
$templateProcessor->saveAs('results/Sample_41_TemplateSetChart.docx');
echo getEndingNotes(array('Word2007' => 'docx'), 'results/Sample_41_TemplateSetChart.docx');
if (!CLI) {
include_once 'Sample_Footer.php';
}

Binary file not shown.

View File

@ -109,6 +109,7 @@ abstract class AbstractContainer extends AbstractElement
} else {
// All other elements
array_unshift($args, $element); // Prepend element name to the beginning of args array
return call_user_func_array(array($this, 'addElement'), $args);
}
}

View File

@ -17,7 +17,7 @@
namespace PhpOffice\PhpWord\Element;
use PhpOffice\Common\Text as CommonText;
use PhpOffice\PhpWord\Shared\Text as SharedText;
/**
* Bookmark element
@ -45,7 +45,7 @@ class Bookmark extends AbstractElement
*/
public function __construct($name = '')
{
$this->name = CommonText::toUTF8($name);
$this->name = SharedText::toUTF8($name);
}
/**

View File

@ -17,7 +17,7 @@
namespace PhpOffice\PhpWord\Element;
use PhpOffice\Common\Text as CommonText;
use PhpOffice\PhpWord\Shared\Text as SharedText;
/**
* Check box element
@ -55,7 +55,7 @@ class CheckBox extends Text
*/
public function setName($name)
{
$this->name = CommonText::toUTF8($name);
$this->name = SharedText::toUTF8($name);
return $this;
}

View File

@ -17,6 +17,8 @@
namespace PhpOffice\PhpWord\Element;
use PhpOffice\PhpWord\Style\Font;
/**
* Field element
*
@ -115,10 +117,42 @@ class Field extends AbstractElement
/**
* Font style
*
* @var \PhpOffice\PhpWord\Style\Font
* @var string|\PhpOffice\PhpWord\Style\Font
*/
protected $fontStyle;
/**
* Set Font style
*
* @param string|array|\PhpOffice\PhpWord\Style\Font $style
* @return string|\PhpOffice\PhpWord\Style\Font
*/
public function setFontStyle($style = null)
{
if ($style instanceof Font) {
$this->fontStyle = $style;
} elseif (is_array($style)) {
$this->fontStyle = new Font('text');
$this->fontStyle->setStyleByArray($style);
} elseif (null === $style) {
$this->fontStyle = null;
} else {
$this->fontStyle = $style;
}
return $this->fontStyle;
}
/**
* Get Font style
*
* @return string|\PhpOffice\PhpWord\Style\Font
*/
public function getFontStyle()
{
return $this->fontStyle;
}
/**
* Create a new Field Element
*
@ -126,13 +160,15 @@ class Field extends AbstractElement
* @param array $properties
* @param array $options
* @param TextRun|string|null $text
* @param string|array|\PhpOffice\PhpWord\Style\Font $fontStyle
*/
public function __construct($type = null, $properties = array(), $options = array(), $text = null)
public function __construct($type = null, $properties = array(), $options = array(), $text = null, $fontStyle = null)
{
$this->setType($type);
$this->setProperties($properties);
$this->setOptions($options);
$this->setText($text);
$this->setFontStyle($fontStyle);
}
/**

View File

@ -454,7 +454,7 @@ class Image extends AbstractElement
} else {
$this->sourceType = self::SOURCE_GD;
}
} elseif (@file_exists($this->source)) {
} elseif ((strpos($this->source, chr(0)) === false) && @file_exists($this->source)) {
$this->memoryImage = false;
$this->sourceType = self::SOURCE_LOCAL;
} else {

View File

@ -17,7 +17,7 @@
namespace PhpOffice\PhpWord\Element;
use PhpOffice\Common\Text as CommonText;
use PhpOffice\PhpWord\Shared\Text as SharedText;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Style\Paragraph;
@ -79,8 +79,8 @@ class Link extends AbstractElement
*/
public function __construct($source, $text = null, $fontStyle = null, $paragraphStyle = null, $internal = false)
{
$this->source = CommonText::toUTF8($source);
$this->text = is_null($text) ? $this->source : CommonText::toUTF8($text);
$this->source = SharedText::toUTF8($source);
$this->text = is_null($text) ? $this->source : SharedText::toUTF8($text);
$this->fontStyle = $this->setNewStyle(new Font('text'), $fontStyle);
$this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle);
$this->internal = $internal;

View File

@ -17,7 +17,7 @@
namespace PhpOffice\PhpWord\Element;
use PhpOffice\Common\Text as CommonText;
use PhpOffice\PhpWord\Shared\Text as SharedText;
use PhpOffice\PhpWord\Style\ListItem as ListItemStyle;
/**
@ -57,7 +57,7 @@ class ListItem extends AbstractElement
*/
public function __construct($text, $depth = 0, $fontStyle = null, $listStyle = null, $paragraphStyle = null)
{
$this->textObject = new Text(CommonText::toUTF8($text), $fontStyle, $paragraphStyle);
$this->textObject = new Text(SharedText::toUTF8($text), $fontStyle, $paragraphStyle);
$this->depth = $depth;
// Version >= 0.10.0 will pass numbering style name. Older version will use old method

View File

@ -17,7 +17,7 @@
namespace PhpOffice\PhpWord\Element;
use PhpOffice\Common\Text as CommonText;
use PhpOffice\PhpWord\Shared\Text as SharedText;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Style\Paragraph;
@ -59,7 +59,7 @@ class PreserveText extends AbstractElement
$this->fontStyle = $this->setNewStyle(new Font('text'), $fontStyle);
$this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle);
$this->text = CommonText::toUTF8($text);
$this->text = SharedText::toUTF8($text);
$matches = preg_split('/({.*?})/', $this->text, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
if (isset($matches[0])) {
$this->text = $matches;

View File

@ -146,6 +146,20 @@ class Section extends AbstractContainer
*
* @return FootnoteProperties
*/
public function getFootnoteProperties()
{
return $this->footnoteProperties;
}
/**
* Get the footnote properties
*
* @deprecated Use the `getFootnoteProperties` method instead
*
* @return FootnoteProperties
*
* @codeCoverageIgnore
*/
public function getFootnotePropoperties()
{
return $this->footnoteProperties;

View File

@ -17,7 +17,7 @@
namespace PhpOffice\PhpWord\Element;
use PhpOffice\Common\Text as CommonText;
use PhpOffice\PhpWord\Shared\Text as SharedText;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Style\Paragraph;
@ -136,7 +136,7 @@ class Text extends AbstractElement
*/
public function setText($text)
{
$this->text = CommonText::toUTF8($text);
$this->text = SharedText::toUTF8($text);
return $this;
}

View File

@ -17,7 +17,7 @@
namespace PhpOffice\PhpWord\Element;
use PhpOffice\Common\Text as CommonText;
use PhpOffice\PhpWord\Shared\Text as SharedText;
use PhpOffice\PhpWord\Style;
/**
@ -62,7 +62,7 @@ class Title extends AbstractElement
public function __construct($text, $depth = 1)
{
if (is_string($text)) {
$this->text = CommonText::toUTF8($text);
$this->text = SharedText::toUTF8($text);
} elseif ($text instanceof TextRun) {
$this->text = $text;
} else {

View File

@ -26,8 +26,14 @@ class Rtf extends AbstractEscaper
{
protected function escapeAsciiCharacter($code)
{
if (20 > $code || $code >= 80) {
return '{\u' . $code . '}';
if ($code == 9) {
return '{\\tab}';
}
if (0x20 > $code || $code >= 0x80) {
return '{\\u' . $code . '}';
}
if ($code == 123 || $code == 125 || $code == 92) { // open or close brace or backslash
return '\\' . chr($code);
}
return chr($code);
@ -35,7 +41,7 @@ class Rtf extends AbstractEscaper
protected function escapeMultibyteCharacter($code)
{
return '\uc0{\u' . $code . '}';
return '\\uc0{\\u' . $code . '}';
}
/**

View File

@ -17,7 +17,7 @@
namespace PhpOffice\PhpWord\Metadata;
use PhpOffice\Common\Microsoft\PasswordEncoder;
use PhpOffice\PhpWord\Shared\Microsoft\PasswordEncoder;
use PhpOffice\PhpWord\SimpleType\DocProtect;
/**

View File

@ -17,8 +17,8 @@
namespace PhpOffice\PhpWord\Reader;
use PhpOffice\Common\Drawing;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\Drawing;
use PhpOffice\PhpWord\Shared\OLERead;
use PhpOffice\PhpWord\Style;
@ -1581,7 +1581,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
// Variables
$sprmCPicLocation = null;
$sprmCFData = null;
$sprmCFSpec = null;
//$sprmCFSpec = null;
do {
// Variables
@ -1830,7 +1830,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
break;
// sprmCFSpec
case 0x55:
$sprmCFSpec = $operand;
//$sprmCFSpec = $operand;
break;
// sprmCFtcBi
case 0x5E:
@ -2094,11 +2094,11 @@ class MsDoc extends AbstractReader implements ReaderInterface
$sprmCPicLocation += 1;
// stPicName
$stPicName = '';
//$stPicName = '';
for ($inc = 0; $inc <= $cchPicName; $inc++) {
$chr = self::getInt1d($this->dataData, $sprmCPicLocation);
//$chr = self::getInt1d($this->dataData, $sprmCPicLocation);
$sprmCPicLocation += 1;
$stPicName .= chr($chr);
//$stPicName .= chr($chr);
}
}
@ -2143,11 +2143,11 @@ class MsDoc extends AbstractReader implements ReaderInterface
$sprmCPicLocation += 1;
// nameData
if ($cbName > 0) {
$nameData = '';
//$nameData = '';
for ($inc = 0; $inc <= ($cbName / 2); $inc++) {
$chr = self::getInt2d($this->dataData, $sprmCPicLocation);
//$chr = self::getInt2d($this->dataData, $sprmCPicLocation);
$sprmCPicLocation += 2;
$nameData .= chr($chr);
//$nameData .= chr($chr);
}
}
// embeddedBlip

View File

@ -17,8 +17,8 @@
namespace PhpOffice\PhpWord\Reader;
use PhpOffice\Common\XMLReader;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLReader;
/**
* Reader for ODText

View File

@ -17,9 +17,9 @@
namespace PhpOffice\PhpWord\Reader\ODText;
use PhpOffice\Common\XMLReader;
use PhpOffice\PhpWord\Element\TrackChange;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLReader;
/**
* Content reader

View File

@ -17,8 +17,8 @@
namespace PhpOffice\PhpWord\Reader\ODText;
use PhpOffice\Common\XMLReader;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLReader;
/**
* Meta reader

View File

@ -17,8 +17,8 @@
namespace PhpOffice\PhpWord\Reader;
use PhpOffice\Common\XMLReader;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLReader;
use PhpOffice\PhpWord\Shared\ZipArchive;
/**

View File

@ -17,12 +17,12 @@
namespace PhpOffice\PhpWord\Reader\Word2007;
use PhpOffice\Common\XMLReader;
use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType;
use PhpOffice\PhpWord\Element\AbstractContainer;
use PhpOffice\PhpWord\Element\TextRun;
use PhpOffice\PhpWord\Element\TrackChange;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLReader;
/**
* Abstract part reader
@ -95,7 +95,7 @@ abstract class AbstractPart
/**
* Read w:p.
*
* @param \PhpOffice\Common\XMLReader $xmlReader
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @param \PhpOffice\PhpWord\Element\AbstractContainer $parent
* @param string $docPart
@ -202,7 +202,7 @@ abstract class AbstractPart
/**
* Read w:r.
*
* @param \PhpOffice\Common\XMLReader $xmlReader
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @param \PhpOffice\PhpWord\Element\AbstractContainer $parent
* @param string $docPart
@ -270,6 +270,10 @@ abstract class AbstractPart
$name = $xmlReader->getAttribute('name', $node, 'wp:inline/a:graphic/a:graphicData/pic:pic/pic:nvPicPr/pic:cNvPr');
$embedId = $xmlReader->getAttribute('r:embed', $node, 'wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip');
if ($name === null && $embedId === null) { // some Converters puts images on a different path
$name = $xmlReader->getAttribute('name', $node, 'wp:anchor/a:graphic/a:graphicData/pic:pic/pic:nvPicPr/pic:cNvPr');
$embedId = $xmlReader->getAttribute('r:embed', $node, 'wp:anchor/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip');
}
$target = $this->getMediaTarget($docPart, $embedId);
if (!is_null($target)) {
$imageSource = "zip://{$this->docFile}#{$target}";
@ -288,6 +292,19 @@ abstract class AbstractPart
$parent->addTextBreak();
} elseif ($node->nodeName == 'w:tab') {
$parent->addText("\t");
} elseif ($node->nodeName == 'mc:AlternateContent') {
if ($node->hasChildNodes()) {
// Get fallback instead of mc:Choice to make sure it is compatible
$fallbackElements = $node->getElementsByTagName('Fallback');
if ($fallbackElements->length) {
$fallback = $fallbackElements->item(0);
// TextRun
$textContent = htmlspecialchars($fallback->nodeValue, ENT_QUOTES, 'UTF-8');
$parent->addText($textContent, $fontStyle, $paragraphStyle);
}
}
} elseif ($node->nodeName == 'w:t' || $node->nodeName == 'w:delText') {
// TextRun
$textContent = htmlspecialchars($xmlReader->getValue('.', $node), ENT_QUOTES, 'UTF-8');
@ -316,7 +333,7 @@ abstract class AbstractPart
/**
* Read w:tbl.
*
* @param \PhpOffice\Common\XMLReader $xmlReader
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @param mixed $parent
* @param string $docPart
@ -374,7 +391,7 @@ abstract class AbstractPart
/**
* Read w:pPr.
*
* @param \PhpOffice\Common\XMLReader $xmlReader
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @return array|null
*/
@ -409,7 +426,7 @@ abstract class AbstractPart
/**
* Read w:rPr
*
* @param \PhpOffice\Common\XMLReader $xmlReader
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @return array|null
*/
@ -455,7 +472,7 @@ abstract class AbstractPart
/**
* Read w:tblPr
*
* @param \PhpOffice\Common\XMLReader $xmlReader
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @return string|array|null
* @todo Capture w:tblStylePr w:type="firstRow"
@ -505,7 +522,7 @@ abstract class AbstractPart
/**
* Read w:tblpPr
*
* @param \PhpOffice\Common\XMLReader $xmlReader
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @return array
*/
@ -530,7 +547,7 @@ abstract class AbstractPart
/**
* Read w:tblInd
*
* @param \PhpOffice\Common\XMLReader $xmlReader
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @return TblWidthComplexType
*/
@ -548,7 +565,7 @@ abstract class AbstractPart
/**
* Read w:tcPr
*
* @param \PhpOffice\Common\XMLReader $xmlReader
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @return array
*/
@ -569,11 +586,11 @@ abstract class AbstractPart
* Returns the first child element found
*
* @param XMLReader $xmlReader
* @param \DOMElement $parentNode
* @param string|array $elements
* @param \DOMElement|null $parentNode
* @param string|array|null $elements
* @return string|null
*/
private function findPossibleElement(XMLReader $xmlReader, \DOMElement $parentNode = null, $elements)
private function findPossibleElement(XMLReader $xmlReader, \DOMElement $parentNode = null, $elements = null)
{
if (is_array($elements)) {
//if element is an array, we take the first element that exists in the XML
@ -616,7 +633,7 @@ abstract class AbstractPart
/**
* Read style definition
*
* @param \PhpOffice\Common\XMLReader $xmlReader
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $parentNode
* @param array $styleDefs
* @ignoreScrutinizerPatch

View File

@ -17,8 +17,8 @@
namespace PhpOffice\PhpWord\Reader\Word2007;
use PhpOffice\Common\XMLReader;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLReader;
/**
* Core properties reader

View File

@ -17,9 +17,9 @@
namespace PhpOffice\PhpWord\Reader\Word2007;
use PhpOffice\Common\XMLReader;
use PhpOffice\PhpWord\Metadata\DocInfo;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLReader;
/**
* Custom properties reader

View File

@ -17,9 +17,9 @@
namespace PhpOffice\PhpWord\Reader\Word2007;
use PhpOffice\Common\XMLReader;
use PhpOffice\PhpWord\Element\Section;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLReader;
/**
* Document reader
@ -97,7 +97,7 @@ class Document extends AbstractPart
/**
* Read w:sectPr
*
* @param \PhpOffice\Common\XMLReader $xmlReader
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $domNode
* @ignoreScrutinizerPatch
* @return array
@ -141,7 +141,7 @@ class Document extends AbstractPart
/**
* Read w:p node.
*
* @param \PhpOffice\Common\XMLReader $xmlReader
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $node
* @param \PhpOffice\PhpWord\Element\Section &$section
*
@ -170,7 +170,7 @@ class Document extends AbstractPart
/**
* Read w:sectPr node.
*
* @param \PhpOffice\Common\XMLReader $xmlReader
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $node
* @param \PhpOffice\PhpWord\Element\Section &$section
*/

View File

@ -17,8 +17,8 @@
namespace PhpOffice\PhpWord\Reader\Word2007;
use PhpOffice\Common\XMLReader;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLReader;
/**
* Footnotes reader

View File

@ -17,8 +17,8 @@
namespace PhpOffice\PhpWord\Reader\Word2007;
use PhpOffice\Common\XMLReader;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLReader;
/**
* Numbering reader
@ -89,7 +89,7 @@ class Numbering extends AbstractPart
/**
* Read numbering level definition from w:abstractNum and w:num
*
* @param \PhpOffice\Common\XMLReader $xmlReader
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
* @param \DOMElement $subnode
* @param int $levelId
* @return array

View File

@ -17,9 +17,9 @@
namespace PhpOffice\PhpWord\Reader\Word2007;
use PhpOffice\Common\XMLReader;
use PhpOffice\PhpWord\ComplexType\TrackChangesView;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLReader;
use PhpOffice\PhpWord\Style\Language;
/**

View File

@ -17,8 +17,8 @@
namespace PhpOffice\PhpWord\Reader\Word2007;
use PhpOffice\Common\XMLReader;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLReader;
use PhpOffice\PhpWord\Style\Language;
/**

View File

@ -70,6 +70,7 @@ class Settings
const DEFAULT_FONT_SIZE = 10;
const DEFAULT_FONT_COLOR = '000000';
const DEFAULT_FONT_CONTENT_TYPE = 'default'; // default|eastAsia|cs
const DEFAULT_PAPER = 'A4';
/**
* Compatibility option for XMLWriter
@ -119,6 +120,12 @@ class Settings
*/
private static $defaultFontSize = self::DEFAULT_FONT_SIZE;
/**
* Default paper
* @var string
*/
private static $defaultPaper = self::DEFAULT_PAPER;
/**
* The user defined temporary directory.
*
@ -432,6 +439,33 @@ class Settings
return $config;
}
/**
* Get default paper
*
* @return string
*/
public static function getDefaultPaper()
{
return self::$defaultPaper;
}
/**
* Set default paper
*
* @param string $value
* @return bool
*/
public static function setDefaultPaper($value)
{
if (is_string($value) && trim($value) !== '') {
self::$defaultPaper = $value;
return true;
}
return false;
}
/**
* Return the compatibility option used by the XMLWriter
*

View File

@ -133,7 +133,7 @@ class Converter
* Convert inch to EMU
*
* @param float $inch
* @return float
* @return int
*/
public static function inchToEmu($inch = 1)
{
@ -143,7 +143,7 @@ class Converter
/**
* Convert pixel to twip
*
* @param int $pixel
* @param float $pixel
* @return float
*/
public static function pixelToTwip($pixel = 1)
@ -154,7 +154,7 @@ class Converter
/**
* Convert pixel to centimeter
*
* @param int $pixel
* @param float $pixel
* @return float
*/
public static function pixelToCm($pixel = 1)
@ -165,7 +165,7 @@ class Converter
/**
* Convert pixel to point
*
* @param int $pixel
* @param float $pixel
* @return float
*/
public static function pixelToPoint($pixel = 1)
@ -176,7 +176,7 @@ class Converter
/**
* Convert pixel to EMU
*
* @param int $pixel
* @param float $pixel
* @return int
*/
public static function pixelToEmu($pixel = 1)
@ -187,7 +187,7 @@ class Converter
/**
* Convert point to twip unit
*
* @param int $point
* @param float $point
* @return float
*/
public static function pointToTwip($point = 1)
@ -209,7 +209,7 @@ class Converter
/**
* Convert point to EMU
*
* @param int $point
* @param float $point
* @return float
*/
public static function pointToEmu($point = 1)
@ -231,7 +231,7 @@ class Converter
/**
* Convert EMU to pixel
*
* @param int $emu
* @param float $emu
* @return float
*/
public static function emuToPixel($emu = 1)
@ -242,7 +242,7 @@ class Converter
/**
* Convert pica to point
*
* @param int $pica
* @param float $pica
* @return float
*/
public static function picaToPoint($pica = 1)
@ -253,7 +253,7 @@ class Converter
/**
* Convert degree to angle
*
* @param int $degree
* @param float $degree
* @return int
*/
public static function degreeToAngle($degree = 1)
@ -264,7 +264,7 @@ class Converter
/**
* Convert angle to degrees
*
* @param int $angle
* @param float $angle
* @return int
*/
public static function angleToDegree($angle = 1)
@ -272,6 +272,50 @@ class Converter
return round($angle / self::DEGREE_TO_ANGLE);
}
/**
* Convert colorname as string to RGB
*
* @param string $value color name
* @return string color as hex RGB string, or original value if unknown
*/
public static function stringToRgb($value)
{
switch ($value) {
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_YELLOW:
return 'FFFF00';
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_LIGHTGREEN:
return '90EE90';
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_CYAN:
return '00FFFF';
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_MAGENTA:
return 'FF00FF';
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_BLUE:
return '0000FF';
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_RED:
return 'FF0000';
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKBLUE:
return '00008B';
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKCYAN:
return '008B8B';
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKGREEN:
return '006400';
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKMAGENTA:
return '8B008B';
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKRED:
return '8B0000';
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKYELLOW:
return '8B8B00';
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKGRAY:
return 'A9A9A9';
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_LIGHTGRAY:
return 'D3D3D3';
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_BLACK:
return '000000';
}
return $value;
}
/**
* Convert HTML hexadecimal to RGB
*
@ -282,6 +326,8 @@ class Converter
{
if ($value[0] == '#') {
$value = substr($value, 1);
} else {
$value = self::stringToRgb($value);
}
if (strlen($value) == 6) {
@ -292,9 +338,9 @@ class Converter
return false;
}
$red = hexdec($red);
$green = hexdec($green);
$blue = hexdec($blue);
$red = ctype_xdigit($red) ? hexdec($red) : 0;
$green = ctype_xdigit($green) ? hexdec($green) : 0;
$blue = ctype_xdigit($blue) ? hexdec($blue) : 0;
return array($red, $green, $blue);
}

View File

@ -0,0 +1,248 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @see https://github.com/PHPOffice/PHPWord
* @copyright 2010-2018 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Shared;
/**
* Drawing
*/
class Drawing
{
const DPI_96 = 96;
/**
* Convert pixels to EMU
*
* @param int $pValue Value in pixels
* @return int
*/
public static function pixelsToEmu($pValue = 0)
{
return round($pValue * 9525);
}
/**
* Convert EMU to pixels
*
* @param int $pValue Value in EMU
* @return int
*/
public static function emuToPixels($pValue = 0)
{
if ($pValue == 0) {
return 0;
}
return round($pValue / 9525);
}
/**
* Convert pixels to points
*
* @param int $pValue Value in pixels
* @return float
*/
public static function pixelsToPoints($pValue = 0)
{
return $pValue * 0.67777777;
}
/**
* Convert points width to centimeters
*
* @param int $pValue Value in points
* @return float
*/
public static function pointsToCentimeters($pValue = 0)
{
if ($pValue == 0) {
return 0;
}
return (($pValue * 1.333333333) / self::DPI_96) * 2.54;
}
/**
* Convert points width to pixels
*
* @param int $pValue Value in points
* @return float
*/
public static function pointsToPixels($pValue = 0)
{
if ($pValue == 0) {
return 0;
}
return $pValue * 1.333333333;
}
/**
* Convert pixels to centimeters
*
* @param int $pValue Value in pixels
* @return float
*/
public static function pixelsToCentimeters($pValue = 0)
{
//return $pValue * 0.028;
return ($pValue / self::DPI_96) * 2.54;
}
/**
* Convert centimeters width to pixels
*
* @param int $pValue Value in centimeters
* @return float
*/
public static function centimetersToPixels($pValue = 0)
{
if ($pValue == 0) {
return 0;
}
return ($pValue / 2.54) * self::DPI_96;
}
/**
* Convert degrees to angle
*
* @param int $pValue Degrees
* @return int
*/
public static function degreesToAngle($pValue = 0)
{
return (int) round($pValue * 60000);
}
/**
* Convert angle to degrees
*
* @param int $pValue Angle
* @return int
*/
public static function angleToDegrees($pValue = 0)
{
if ($pValue == 0) {
return 0;
}
return round($pValue / 60000);
}
/**
* Convert centimeters width to twips
*
* @param int $pValue
* @return float
*/
public static function centimetersToTwips($pValue = 0)
{
if ($pValue == 0) {
return 0;
}
return $pValue * 566.928;
}
/**
* Convert twips width to centimeters
*
* @param int $pValue
* @return float
*/
public static function twipsToCentimeters($pValue = 0)
{
if ($pValue == 0) {
return 0;
}
return $pValue / 566.928;
}
/**
* Convert inches width to twips
*
* @param int $pValue
* @return float
*/
public static function inchesToTwips($pValue = 0)
{
if ($pValue == 0) {
return 0;
}
return $pValue * 1440;
}
/**
* Convert twips width to inches
*
* @param int $pValue
* @return float
*/
public static function twipsToInches($pValue = 0)
{
if ($pValue == 0) {
return 0;
}
return $pValue / 1440;
}
/**
* Convert twips width to pixels
*
* @param int $pValue
* @return float
*/
public static function twipsToPixels($pValue = 0)
{
if ($pValue == 0) {
return 0;
}
return round($pValue / 15.873984);
}
/**
* Convert HTML hexadecimal to RGB
*
* @param string $pValue HTML Color in hexadecimal
* @return array|false Value in RGB
*/
public static function htmlToRGB($pValue)
{
if ($pValue[0] == '#') {
$pValue = substr($pValue, 1);
}
if (strlen($pValue) == 6) {
list($colorR, $colorG, $colorB) = array($pValue[0] . $pValue[1], $pValue[2] . $pValue[3], $pValue[4] . $pValue[5]);
} elseif (strlen($pValue) == 3) {
list($colorR, $colorG, $colorB) = array($pValue[0] . $pValue[0], $pValue[1] . $pValue[1], $pValue[2] . $pValue[2]);
} else {
return false;
}
$colorR = hexdec($colorR);
$colorG = hexdec($colorG);
$colorB = hexdec($colorB);
return array($colorR, $colorG, $colorB);
}
}

View File

@ -62,10 +62,10 @@ class Html
// Preprocess: remove all line ends, decode HTML entity,
// fix ampersand and angle brackets and add body tag for HTML fragments
$html = str_replace(array("\n", "\r"), '', $html);
$html = str_replace(array('&lt;', '&gt;', '&amp;'), array('_lt_', '_gt_', '_amp_'), $html);
$html = str_replace(array('&lt;', '&gt;', '&amp;', '&quot;'), array('_lt_', '_gt_', '_amp_', '_quot_'), $html);
$html = html_entity_decode($html, ENT_QUOTES, 'UTF-8');
$html = str_replace('&', '&amp;', $html);
$html = str_replace(array('_lt_', '_gt_', '_amp_'), array('&lt;', '&gt;', '&amp;'), $html);
$html = str_replace(array('_lt_', '_gt_', '_amp_', '_quot_'), array('&lt;', '&gt;', '&amp;', '&quot;'), $html);
if (false === $fullHTML) {
$html = '<body>' . $html . '</body>';
@ -75,7 +75,9 @@ class Html
$html = preg_replace('/(\>)\s*(\<)/m', '$1$2', $html);
// Load DOM
$orignalLibEntityLoader = libxml_disable_entity_loader(true);
if (\PHP_VERSION_ID < 80000) {
$orignalLibEntityLoader = libxml_disable_entity_loader(true);
}
$dom = new \DOMDocument();
$dom->preserveWhiteSpace = $preserveWhiteSpace;
$dom->loadHTML($html, LIBXML_NOWARNING);
@ -83,7 +85,9 @@ class Html
$node = $dom->getElementsByTagName('body');
self::parseNode($node->item(0), $element);
libxml_disable_entity_loader($orignalLibEntityLoader);
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($orignalLibEntityLoader);
}
}
/**
@ -99,15 +103,43 @@ class Html
$attributes = $node->attributes; // get all the attributes(eg: id, class)
foreach ($attributes as $attribute) {
switch ($attribute->name) {
$val = $attribute->value;
switch (strtolower($attribute->name)) {
case 'style':
$styles = self::parseStyle($attribute, $styles);
break;
case 'align':
$styles['alignment'] = self::mapAlign($attribute->value);
$styles['alignment'] = self::mapAlign(trim($val));
break;
case 'lang':
$styles['lang'] = $attribute->value;
$styles['lang'] = $val;
break;
case 'width':
// tables, cells
if (false !== strpos($val, '%')) {
// e.g. <table width="100%"> or <td width="50%">
$styles['width'] = (int) $val * 50;
$styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::PERCENT;
} else {
// e.g. <table width="250> where "250" = 250px (always pixels)
$styles['width'] = Converter::pixelToTwip($val);
$styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::TWIP;
}
break;
case 'cellspacing':
// tables e.g. <table cellspacing="2">, where "2" = 2px (always pixels)
$val = (int) $val . 'px';
$styles['cellSpacing'] = Converter::cssToTwip($val);
break;
case 'bgcolor':
// tables, rows, cells e.g. <tr bgColor="#FF0000">
$styles['bgColor'] = trim($val, '# ');
break;
case 'valign':
// cells e.g. <td valign="middle">
if (preg_match('#(?:top|bottom|middle|baseline)#i', $val, $matches)) {
$styles['valign'] = self::mapAlignVertical($matches[0]);
}
break;
}
}
@ -164,6 +196,8 @@ class Html
'img' => array('Image', $node, $element, $styles, null, null, null),
'br' => array('LineBreak', null, $element, $styles, null, null, null),
'a' => array('Link', $node, $element, $styles, null, null, null),
'input' => array('Input', $node, $element, $styles, null, null, null),
'hr' => array('HorizRule', $node, $element, $styles, null, null, null),
);
$newElement = null;
@ -181,7 +215,7 @@ class Html
}
}
$method = "parse{$method}";
$newElement = call_user_func_array(array('PhpOffice\PhpWord\Shared\Html', $method), $arguments);
$newElement = call_user_func_array(array('PhpOffice\PhpWord\Shared\Html', $method), array_values($arguments));
// Retrieve back variables from arguments
foreach ($keys as $key) {
@ -236,6 +270,30 @@ class Html
return $newElement;
}
/**
* Parse input node
*
* @param \DOMNode $node
* @param \PhpOffice\PhpWord\Element\AbstractContainer $element
* @param array &$styles
*/
protected static function parseInput($node, $element, &$styles)
{
$attributes = $node->attributes;
if (null === $attributes->getNamedItem('type')) {
return;
}
$inputType = $attributes->getNamedItem('type')->value;
switch ($inputType) {
case 'checkbox':
$checked = ($checked = $attributes->getNamedItem('checked')) && $checked->value === 'true' ? true : false;
$textrun = $element->addTextRun($styles['paragraph']);
$textrun->addFormField('checkbox')->setValue($checked);
break;
}
}
/**
* Parse heading node
*
@ -364,10 +422,14 @@ class Html
if (!empty($colspan)) {
$cellStyles['gridSpan'] = $colspan - 0;
}
$cell = $element->addCell(null, $cellStyles);
// set cell width to control column widths
$width = isset($cellStyles['width']) ? $cellStyles['width'] : null;
unset($cellStyles['width']); // would not apply
$cell = $element->addCell($width, $cellStyles);
if (self::shouldAddTextRun($node)) {
return $cell->addTextRun(self::parseInlineStyle($node, $styles['paragraph']));
return $cell->addTextRun(self::filterOutNonInheritedStyles(self::parseInlineStyle($node, $styles['paragraph'])));
}
return $cell;
@ -398,15 +460,51 @@ class Html
*/
protected static function recursiveParseStylesInHierarchy(\DOMNode $node, array $style)
{
$parentStyle = self::parseInlineStyle($node, array());
$style = array_merge($parentStyle, $style);
$parentStyle = array();
if ($node->parentNode != null && XML_ELEMENT_NODE == $node->parentNode->nodeType) {
$style = self::recursiveParseStylesInHierarchy($node->parentNode, $style);
$parentStyle = self::recursiveParseStylesInHierarchy($node->parentNode, array());
}
if ($node->nodeName === '#text') {
$parentStyle = array_merge($parentStyle, $style);
} else {
$parentStyle = self::filterOutNonInheritedStyles($parentStyle);
}
$style = self::parseInlineStyle($node, $parentStyle);
return $style;
}
/**
* Removes non-inherited styles from array
*
* @param array &$styles
*/
protected static function filterOutNonInheritedStyles(array $styles)
{
$nonInheritedStyles = array(
'borderSize',
'borderTopSize',
'borderRightSize',
'borderBottomSize',
'borderLeftSize',
'borderColor',
'borderTopColor',
'borderRightColor',
'borderBottomColor',
'borderLeftColor',
'borderStyle',
'spaceAfter',
'spaceBefore',
'underline',
'strikethrough',
'hidden',
);
$styles = array_diff_key($styles, array_flip($nonInheritedStyles));
return $styles;
}
/**
* Parse list node
*
@ -423,7 +521,32 @@ class Html
} else {
$data['listdepth'] = 0;
$styles['list'] = 'listStyle_' . self::$listIndex++;
$element->getPhpWord()->addNumberingStyle($styles['list'], self::getListStyle($isOrderedList));
$style = $element->getPhpWord()->addNumberingStyle($styles['list'], self::getListStyle($isOrderedList));
// extract attributes start & type e.g. <ol type="A" start="3">
$start = 0;
$type = '';
foreach ($node->attributes as $attribute) {
switch ($attribute->name) {
case 'start':
$start = (int) $attribute->value;
break;
case 'type':
$type = $attribute->value;
break;
}
}
$levels = $style->getLevels();
/** @var \PhpOffice\PhpWord\Style\NumberingLevel */
$level = $levels[0];
if ($start > 0) {
$level->setStart($start);
}
$type = $type ? self::mapListType($type) : null;
if ($type) {
$level->setFormat($type);
}
}
if ($node->parentNode->nodeName === 'li') {
return $element->getParent();
@ -505,7 +628,8 @@ class Html
foreach ($properties as $property) {
list($cKey, $cValue) = array_pad(explode(':', $property, 2), 2, null);
$cValue = trim($cValue);
switch (trim($cKey)) {
$cKey = strtolower(trim($cKey));
switch ($cKey) {
case 'text-decoration':
switch ($cValue) {
case 'underline':
@ -578,11 +702,18 @@ class Html
}
$styles['italic'] = $tValue;
break;
case 'margin':
$cValue = Converter::cssToTwip($cValue);
$styles['spaceBefore'] = $cValue;
$styles['spaceAfter'] = $cValue;
break;
case 'margin-top':
$styles['spaceBefore'] = Converter::cssToPoint($cValue);
// BC change: up to ver. 0.17.0 incorrectly converted to points - Converter::cssToPoint($cValue)
$styles['spaceBefore'] = Converter::cssToTwip($cValue);
break;
case 'margin-bottom':
$styles['spaceAfter'] = Converter::cssToPoint($cValue);
// BC change: up to ver. 0.17.0 incorrectly converted to points - Converter::cssToPoint($cValue)
$styles['spaceAfter'] = Converter::cssToTwip($cValue);
break;
case 'border-color':
self::mapBorderColor($styles, $cValue);
@ -606,10 +737,38 @@ class Html
}
break;
case 'border':
if (preg_match('/([0-9]+[^0-9]*)\s+(\#[a-fA-F0-9]+)\s+([a-z]+)/', $cValue, $matches)) {
$styles['borderSize'] = Converter::cssToPoint($matches[1]);
$styles['borderColor'] = trim($matches[2], '#');
$styles['borderStyle'] = self::mapBorderStyle($matches[3]);
case 'border-top':
case 'border-bottom':
case 'border-right':
case 'border-left':
// must have exact order [width color style], e.g. "1px #0011CC solid" or "2pt green solid"
// Word does not accept shortened hex colors e.g. #CCC, only full e.g. #CCCCCC
if (preg_match('/([0-9]+[^0-9]*)\s+(\#[a-fA-F0-9]+|[a-zA-Z]+)\s+([a-z]+)/', $cValue, $matches)) {
if (false !== strpos($cKey, '-')) {
$tmp = explode('-', $cKey);
$which = $tmp[1];
$which = ucfirst($which); // e.g. bottom -> Bottom
} else {
$which = '';
}
// Note - border width normalization:
// Width of border in Word is calculated differently than HTML borders, usually showing up too bold.
// Smallest 1px (or 1pt) appears in Word like 2-3px/pt in HTML once converted to twips.
// Therefore we need to normalize converted twip value to cca 1/2 of value.
// This may be adjusted, if better ratio or formula found.
// BC change: up to ver. 0.17.0 was $size converted to points - Converter::cssToPoint($size)
$size = Converter::cssToTwip($matches[1]);
$size = (int) ($size / 2);
// valid variants may be e.g. borderSize, borderTopSize, borderLeftColor, etc ..
$styles["border{$which}Size"] = $size; // twips
$styles["border{$which}Color"] = trim($matches[2], '#');
$styles["border{$which}Style"] = self::mapBorderStyle($matches[3]);
}
break;
case 'vertical-align':
// https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align
if (preg_match('#(?:top|bottom|middle|sub|baseline)#i', $cValue, $matches)) {
$styles['valign'] = self::mapAlignVertical($matches[0]);
}
break;
}
@ -654,14 +813,14 @@ class Html
case 'float':
if (trim($v) == 'right') {
$style['hPos'] = \PhpOffice\PhpWord\Style\Image::POS_RIGHT;
$style['hPosRelTo'] = \PhpOffice\PhpWord\Style\Image::POS_RELTO_PAGE;
$style['hPosRelTo'] = \PhpOffice\PhpWord\Style\Image::POS_RELTO_MARGIN; // inner section area
$style['pos'] = \PhpOffice\PhpWord\Style\Image::POS_RELATIVE;
$style['wrap'] = \PhpOffice\PhpWord\Style\Image::WRAP_TIGHT;
$style['overlap'] = true;
}
if (trim($v) == 'left') {
$style['hPos'] = \PhpOffice\PhpWord\Style\Image::POS_LEFT;
$style['hPosRelTo'] = \PhpOffice\PhpWord\Style\Image::POS_RELTO_PAGE;
$style['hPosRelTo'] = \PhpOffice\PhpWord\Style\Image::POS_RELTO_MARGIN; // inner section area
$style['pos'] = \PhpOffice\PhpWord\Style\Image::POS_RELATIVE;
$style['wrap'] = \PhpOffice\PhpWord\Style\Image::WRAP_TIGHT;
$style['overlap'] = true;
@ -776,6 +935,58 @@ class Html
}
}
/**
* Transforms a HTML/CSS vertical alignment
*
* @param string $alignment
* @return string|null
*/
protected static function mapAlignVertical($alignment)
{
$alignment = strtolower($alignment);
switch ($alignment) {
case 'top':
case 'baseline':
case 'bottom':
return $alignment;
case 'middle':
return 'center';
case 'sub':
return 'bottom';
case 'text-top':
case 'baseline':
return 'top';
default:
// @discuss - which one should apply:
// - Word uses default vert. alignment: top
// - all browsers use default vert. alignment: middle
// Returning empty string means attribute wont be set so use Word default (top).
return '';
}
}
/**
* Map list style for ordered list
*
* @param string $cssListType
*/
protected static function mapListType($cssListType)
{
switch ($cssListType) {
case 'a':
return NumberFormat::LOWER_LETTER; // a, b, c, ..
case 'A':
return NumberFormat::UPPER_LETTER; // A, B, C, ..
case 'i':
return NumberFormat::LOWER_ROMAN; // i, ii, iii, iv, ..
case 'I':
return NumberFormat::UPPER_ROMAN; // I, II, III, IV, ..
case '1':
default:
return NumberFormat::DECIMAL; // 1, 2, 3, ..
}
}
/**
* Parse line break
*
@ -811,4 +1022,38 @@ class Html
return $element->addLink($target, $node->textContent, $styles['font'], $styles['paragraph']);
}
/**
* Render horizontal rule
* Note: Word rule is not the same as HTML's <hr> since it does not support width and thus neither alignment
*
* @param \DOMNode $node
* @param \PhpOffice\PhpWord\Element\AbstractContainer $element
*/
protected static function parseHorizRule($node, $element)
{
$styles = self::parseInlineStyle($node);
// <hr> is implemented as an empty paragraph - extending 100% inside the section
// Some properties may be controlled, e.g. <hr style="border-bottom: 3px #DDDDDD solid; margin-bottom: 0;">
$fontStyle = $styles + array('size' => 3);
$paragraphStyle = $styles + array(
'lineHeight' => 0.25, // multiply default line height - e.g. 1, 1.5 etc
'spacing' => 0, // twip
'spaceBefore' => 120, // twip, 240/2 (default line height)
'spaceAfter' => 120, // twip
'borderBottomSize' => empty($styles['line-height']) ? 1 : $styles['line-height'],
'borderBottomColor' => empty($styles['color']) ? '000000' : $styles['color'],
'borderBottomStyle' => 'single', // same as "solid"
);
$element->addText('', $fontStyle, $paragraphStyle);
// Notes: <hr/> cannot be:
// - table - throws error "cannot be inside textruns", e.g. lists
// - line - that is a shape, has different behaviour
// - repeated text, e.g. underline "_", because of unpredictable line wrapping
}
}

View File

@ -0,0 +1,235 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @see https://github.com/PHPOffice/PHPWord
* @copyright 2010-2018 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Shared\Microsoft;
/**
* Password encoder for microsoft office applications
*/
class PasswordEncoder
{
const ALGORITHM_MD2 = 'MD2';
const ALGORITHM_MD4 = 'MD4';
const ALGORITHM_MD5 = 'MD5';
const ALGORITHM_SHA_1 = 'SHA-1';
const ALGORITHM_SHA_256 = 'SHA-256';
const ALGORITHM_SHA_384 = 'SHA-384';
const ALGORITHM_SHA_512 = 'SHA-512';
const ALGORITHM_RIPEMD = 'RIPEMD';
const ALGORITHM_RIPEMD_160 = 'RIPEMD-160';
const ALGORITHM_MAC = 'MAC';
const ALGORITHM_HMAC = 'HMAC';
/**
* Mapping between algorithm name and algorithm ID
*
* @var array
* @see https://msdn.microsoft.com/en-us/library/documentformat.openxml.wordprocessing.writeprotection.cryptographicalgorithmsid(v=office.14).aspx
*/
private static $algorithmMapping = array(
self::ALGORITHM_MD2 => array(1, 'md2'),
self::ALGORITHM_MD4 => array(2, 'md4'),
self::ALGORITHM_MD5 => array(3, 'md5'),
self::ALGORITHM_SHA_1 => array(4, 'sha1'),
self::ALGORITHM_MAC => array(5, ''), // 'mac' -> not possible with hash()
self::ALGORITHM_RIPEMD => array(6, 'ripemd'),
self::ALGORITHM_RIPEMD_160 => array(7, 'ripemd160'),
self::ALGORITHM_HMAC => array(9, ''), //'hmac' -> not possible with hash()
self::ALGORITHM_SHA_256 => array(12, 'sha256'),
self::ALGORITHM_SHA_384 => array(13, 'sha384'),
self::ALGORITHM_SHA_512 => array(14, 'sha512'),
);
private static $initialCodeArray = array(
0xE1F0,
0x1D0F,
0xCC9C,
0x84C0,
0x110C,
0x0E10,
0xF1CE,
0x313E,
0x1872,
0xE139,
0xD40F,
0x84F9,
0x280C,
0xA96A,
0x4EC3,
);
private static $encryptionMatrix = array(
array(0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09),
array(0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF),
array(0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0),
array(0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40),
array(0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5),
array(0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A),
array(0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9),
array(0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0),
array(0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC),
array(0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10),
array(0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168),
array(0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C),
array(0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD),
array(0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC),
array(0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4),
);
private static $passwordMaxLength = 15;
/**
* Create a hashed password that MS Word will be able to work with
* @see https://blogs.msdn.microsoft.com/vsod/2010/04/05/how-to-set-the-editing-restrictions-in-word-using-open-xml-sdk-2-0/
*
* @param string $password
* @param string $algorithmName
* @param string $salt
* @param int $spinCount
* @return string
*/
public static function hashPassword($password, $algorithmName = self::ALGORITHM_SHA_1, $salt = null, $spinCount = 10000)
{
$origEncoding = mb_internal_encoding();
mb_internal_encoding('UTF-8');
$password = mb_substr($password, 0, min(self::$passwordMaxLength, mb_strlen($password)));
// Get the single-byte values by iterating through the Unicode characters of the truncated password.
// For each character, if the low byte is not equal to 0, take it. Otherwise, take the high byte.
$passUtf8 = mb_convert_encoding($password, 'UCS-2LE', 'UTF-8');
$byteChars = array();
for ($i = 0; $i < mb_strlen($password); $i++) {
$byteChars[$i] = ord(substr($passUtf8, $i * 2, 1));
if ($byteChars[$i] == 0) {
$byteChars[$i] = ord(substr($passUtf8, $i * 2 + 1, 1));
}
}
// build low-order word and hig-order word and combine them
$combinedKey = self::buildCombinedKey($byteChars);
// build reversed hexadecimal string
$hex = str_pad(strtoupper(dechex($combinedKey & 0xFFFFFFFF)), 8, '0', \STR_PAD_LEFT);
$reversedHex = $hex[6] . $hex[7] . $hex[4] . $hex[5] . $hex[2] . $hex[3] . $hex[0] . $hex[1];
$generatedKey = mb_convert_encoding($reversedHex, 'UCS-2LE', 'UTF-8');
// Implementation Notes List:
// Word requires that the initial hash of the password with the salt not be considered in the count.
// The initial hash of salt + key is not included in the iteration count.
$algorithm = self::getAlgorithm($algorithmName);
$generatedKey = hash($algorithm, $salt . $generatedKey, true);
for ($i = 0; $i < $spinCount; $i++) {
$generatedKey = hash($algorithm, $generatedKey . pack('CCCC', $i, $i >> 8, $i >> 16, $i >> 24), true);
}
$generatedKey = base64_encode($generatedKey);
mb_internal_encoding($origEncoding);
return $generatedKey;
}
/**
* Get algorithm from self::$algorithmMapping
*
* @param string $algorithmName
* @return string
*/
private static function getAlgorithm($algorithmName)
{
$algorithm = self::$algorithmMapping[$algorithmName][1];
if ($algorithm == '') {
$algorithm = 'sha1';
}
return $algorithm;
}
/**
* Returns the algorithm ID
*
* @param string $algorithmName
* @return int
*/
public static function getAlgorithmId($algorithmName)
{
return self::$algorithmMapping[$algorithmName][0];
}
/**
* Build combined key from low-order word and high-order word
*
* @param array $byteChars byte array representation of password
* @return int
*/
private static function buildCombinedKey($byteChars)
{
$byteCharsLength = count($byteChars);
// Compute the high-order word
// Initialize from the initial code array (see above), depending on the passwords length.
$highOrderWord = self::$initialCodeArray[$byteCharsLength - 1];
// For each character in the password:
// For every bit in the character, starting with the least significant and progressing to (but excluding)
// the most significant, if the bit is set, XOR the keys high-order word with the corresponding word from
// the Encryption Matrix
for ($i = 0; $i < $byteCharsLength; $i++) {
$tmp = self::$passwordMaxLength - $byteCharsLength + $i;
$matrixRow = self::$encryptionMatrix[$tmp];
for ($intBit = 0; $intBit < 7; $intBit++) {
if (($byteChars[$i] & (0x0001 << $intBit)) != 0) {
$highOrderWord = ($highOrderWord ^ $matrixRow[$intBit]);
}
}
}
// Compute low-order word
// Initialize with 0
$lowOrderWord = 0;
// For each character in the password, going backwards
for ($i = $byteCharsLength - 1; $i >= 0; $i--) {
// low-order word = (((low-order word SHR 14) AND 0x0001) OR (low-order word SHL 1) AND 0x7FFF)) XOR character
$lowOrderWord = (((($lowOrderWord >> 14) & 0x0001) | (($lowOrderWord << 1) & 0x7FFF)) ^ $byteChars[$i]);
}
// Lastly, low-order word = (((low-order word SHR 14) AND 0x0001) OR (low-order word SHL 1) AND 0x7FFF)) XOR strPassword length XOR 0xCE4B.
$lowOrderWord = (((($lowOrderWord >> 14) & 0x0001) | (($lowOrderWord << 1) & 0x7FFF)) ^ $byteCharsLength ^ 0xCE4B);
// Combine the Low and High Order Word
return self::int32(($highOrderWord << 16) + $lowOrderWord);
}
/**
* Simulate behaviour of (signed) int32
*
* @codeCoverageIgnore
* @param int $value
* @return int
*/
private static function int32($value)
{
$value = ($value & 0xFFFFFFFF);
if ($value & 0x80000000) {
$value = -((~$value & 0xFFFFFFFF) + 1);
}
return $value;
}
}

236
src/PhpWord/Shared/Text.php Normal file
View File

@ -0,0 +1,236 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @see https://github.com/PHPOffice/PHPWord
* @copyright 2010-2018 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Shared;
/**
* Text
*/
class Text
{
/**
* Control characters array
*
* @var string[]
*/
private static $controlCharacters = array();
/**
* Build control characters array
*/
private static function buildControlCharacters()
{
for ($i = 0; $i <= 19; ++$i) {
if ($i != 9 && $i != 10 && $i != 13) {
$find = '_x' . sprintf('%04s', strtoupper(dechex($i))) . '_';
$replace = chr($i);
self::$controlCharacters[$find] = $replace;
}
}
}
/**
* Convert from PHP control character to OpenXML escaped control character
*
* Excel 2007 team:
* ----------------
* That's correct, control characters are stored directly in the shared-strings table.
* We do encode characters that cannot be represented in XML using the following escape sequence:
* _xHHHH_ where H represents a hexadecimal character in the character's value...
* So you could end up with something like _x0008_ in a string (either in a cell value (<v>)
* element or in the shared string <t> element.
*
* @param string $value Value to escape
* @return string
*/
public static function controlCharacterPHP2OOXML($value = '')
{
if (empty(self::$controlCharacters)) {
self::buildControlCharacters();
}
return str_replace(array_values(self::$controlCharacters), array_keys(self::$controlCharacters), $value);
}
/**
* Return a number formatted for being integrated in xml files
* @param float $number
* @param int $decimals
* @return string
*/
public static function numberFormat($number, $decimals)
{
return number_format($number, $decimals, '.', '');
}
/**
* @param int $dec
* @see http://stackoverflow.com/a/7153133/2235790
* @author velcrow
* @return string
*/
public static function chr($dec)
{
if ($dec <= 0x7F) {
return chr($dec);
}
if ($dec <= 0x7FF) {
return chr(($dec >> 6) + 192) . chr(($dec & 63) + 128);
}
if ($dec <= 0xFFFF) {
return chr(($dec >> 12) + 224) . chr((($dec >> 6) & 63) + 128) . chr(($dec & 63) + 128);
}
if ($dec <= 0x1FFFFF) {
return chr(($dec >> 18) + 240) . chr((($dec >> 12) & 63) + 128) . chr((($dec >> 6) & 63) + 128) . chr(($dec & 63) + 128);
}
return '';
}
/**
* Convert from OpenXML escaped control character to PHP control character
*
* @param string $value Value to unescape
* @return string
*/
public static function controlCharacterOOXML2PHP($value = '')
{
if (empty(self::$controlCharacters)) {
self::buildControlCharacters();
}
return str_replace(array_keys(self::$controlCharacters), array_values(self::$controlCharacters), $value);
}
/**
* Check if a string contains UTF-8 data
*
* @param string $value
* @return bool
*/
public static function isUTF8($value = '')
{
return is_string($value) && ($value === '' || preg_match('/^./su', $value) == 1);
}
/**
* Return UTF8 encoded value
*
* @param string $value
* @return string
*/
public static function toUTF8($value = '')
{
if (!is_null($value) && !self::isUTF8($value)) {
$value = utf8_encode($value);
}
return $value;
}
/**
* Returns unicode from UTF8 text
*
* The function is splitted to reduce cyclomatic complexity
*
* @param string $text UTF8 text
* @return string Unicode text
* @since 0.11.0
*/
public static function toUnicode($text)
{
return self::unicodeToEntities(self::utf8ToUnicode($text));
}
/**
* Returns unicode array from UTF8 text
*
* @param string $text UTF8 text
* @return array
* @since 0.11.0
* @see http://www.randomchaos.com/documents/?source=php_and_unicode
*/
public static function utf8ToUnicode($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;
}
}
}
return $unicode;
}
/**
* Returns entites from unicode array
*
* @param array $unicode
* @return string
* @since 0.11.0
* @see http://www.randomchaos.com/documents/?source=php_and_unicode
*/
private static function unicodeToEntities($unicode)
{
$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
*
* @param string $value
* @return string
*/
public static function removeUnderscorePrefix($value)
{
if (!is_null($value)) {
if (substr($value, 0, 1) == '_') {
$value = substr($value, 1);
}
}
return $value;
}
}

View File

@ -0,0 +1,216 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @see https://github.com/PHPOffice/PHPWord
* @copyright 2010-2018 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Shared;
/**
* XML Reader wrapper
*
* @since 0.2.1
*/
class XMLReader
{
/**
* DOMDocument object
*
* @var \DOMDocument
*/
private $dom = null;
/**
* DOMXpath object
*
* @var \DOMXpath
*/
private $xpath = null;
/**
* Get DOMDocument from ZipArchive
*
* @param string $zipFile
* @param string $xmlFile
* @throws \Exception
* @return \DOMDocument|false
*/
public function getDomFromZip($zipFile, $xmlFile)
{
if (file_exists($zipFile) === false) {
throw new \Exception('Cannot find archive file.');
}
$zip = new \ZipArchive();
$zip->open($zipFile);
$content = $zip->getFromName($xmlFile);
$zip->close();
if ($content === false) {
return false;
}
return $this->getDomFromString($content);
}
/**
* Get DOMDocument from content string
*
* @param string $content
* @return \DOMDocument
*/
public function getDomFromString($content)
{
if (\PHP_VERSION_ID < 80000) {
$originalLibXMLEntityValue = libxml_disable_entity_loader(true);
}
$this->dom = new \DOMDocument();
$this->dom->loadXML($content);
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($originalLibXMLEntityValue);
}
return $this->dom;
}
/**
* Get elements
*
* @param string $path
* @param \DOMElement $contextNode
* @return \DOMNodeList
*/
public function getElements($path, \DOMElement $contextNode = null)
{
if ($this->dom === null) {
return array();
}
if ($this->xpath === null) {
$this->xpath = new \DOMXpath($this->dom);
}
if (is_null($contextNode)) {
return $this->xpath->query($path);
}
return $this->xpath->query($path, $contextNode);
}
/**
* Registers the namespace with the DOMXPath object
*
* @param string $prefix The prefix
* @param string $namespaceURI The URI of the namespace
* @throws \InvalidArgumentException If called before having loaded the DOM document
* @return bool true on success or false on failure
*/
public function registerNamespace($prefix, $namespaceURI)
{
if ($this->dom === null) {
throw new \InvalidArgumentException('Dom needs to be loaded before registering a namespace');
}
if ($this->xpath === null) {
$this->xpath = new \DOMXpath($this->dom);
}
return $this->xpath->registerNamespace($prefix, $namespaceURI);
}
/**
* Get element
*
* @param string $path
* @param \DOMElement $contextNode
* @return \DOMElement|null
*/
public function getElement($path, \DOMElement $contextNode = null)
{
$elements = $this->getElements($path, $contextNode);
if ($elements->length > 0) {
return $elements->item(0);
}
return null;
}
/**
* Get element attribute
*
* @param string $attribute
* @param \DOMElement $contextNode
* @param string $path
* @return string|null
*/
public function getAttribute($attribute, \DOMElement $contextNode = null, $path = null)
{
$return = null;
if ($path !== null) {
$elements = $this->getElements($path, $contextNode);
if ($elements->length > 0) {
/** @var \DOMElement $node Type hint */
$node = $elements->item(0);
$return = $node->getAttribute($attribute);
}
} else {
if ($contextNode !== null) {
$return = $contextNode->getAttribute($attribute);
}
}
return ($return == '') ? null : $return;
}
/**
* Get element value
*
* @param string $path
* @param \DOMElement $contextNode
* @return string|null
*/
public function getValue($path, \DOMElement $contextNode = null)
{
$elements = $this->getElements($path, $contextNode);
if ($elements->length > 0) {
return $elements->item(0)->nodeValue;
}
return null;
}
/**
* Count elements
*
* @param string $path
* @param \DOMElement $contextNode
* @return int
*/
public function countElements($path, \DOMElement $contextNode = null)
{
$elements = $this->getElements($path, $contextNode);
return $elements->length;
}
/**
* Element exists
*
* @param string $path
* @param \DOMElement $contextNode
* @return bool
*/
public function elementExists($path, \DOMElement $contextNode = null)
{
return $this->getElements($path, $contextNode)->length > 0;
}
}

View File

@ -0,0 +1,182 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @see https://github.com/PHPOffice/PHPWord
* @copyright 2010-2018 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Shared;
/**
* XMLWriter
*
* @method bool endElement()
* @method mixed flush(bool $empty = null)
* @method bool openMemory()
* @method string outputMemory(bool $flush = null)
* @method bool setIndent(bool $indent)
* @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 writeCData(string $content)
* @method bool writeComment(string $content)
* @method bool writeElement(string $name, string $content = null)
* @method bool writeRaw(string $content)
*/
class XMLWriter extends \XMLWriter
{
/** Temporary storage method */
const STORAGE_MEMORY = 1;
const STORAGE_DISK = 2;
/**
* Temporary filename
*
* @var string
*/
private $tempFileName = '';
/**
* Create a new \PhpOffice\PhpWord\Shared\XMLWriter instance
*
* @param int $pTemporaryStorage Temporary storage location
* @param string $pTemporaryStorageDir Temporary storage folder
* @param bool $compatibility
*/
public function __construct($pTemporaryStorage = self::STORAGE_MEMORY, $pTemporaryStorageDir = null, $compatibility = false)
{
// Open temporary storage
if ($pTemporaryStorage == self::STORAGE_MEMORY) {
$this->openMemory();
} else {
if (!is_dir($pTemporaryStorageDir)) {
$pTemporaryStorageDir = sys_get_temp_dir();
}
// Create temporary filename
$this->tempFileName = @tempnam($pTemporaryStorageDir, 'xml');
// Open storage
$this->openUri($this->tempFileName);
}
if ($compatibility) {
$this->setIndent(false);
$this->setIndentString('');
} else {
$this->setIndent(true);
$this->setIndentString(' ');
}
}
/**
* Destructor
*/
public function __destruct()
{
// Unlink temporary files
if (empty($this->tempFileName)) {
return;
}
if (PHP_OS != 'WINNT' && @unlink($this->tempFileName) === false) {
throw new \Exception('The file ' . $this->tempFileName . ' could not be deleted.');
}
}
/**
* Get written data
*
* @return string
*/
public function getData()
{
if ($this->tempFileName == '') {
return $this->outputMemory(true);
}
$this->flush();
return file_get_contents($this->tempFileName);
}
/**
* Write simple element and attribute(s) block
*
* There are two options:
* 1. If the `$attributes` is an array, then it's an associative array of attributes
* 2. If not, then it's a simple attribute-value pair
*
* @param string $element
* @param string|array $attributes
* @param string $value
*/
public function writeElementBlock($element, $attributes, $value = null)
{
$this->startElement($element);
if (!is_array($attributes)) {
$attributes = array($attributes => $value);
}
foreach ($attributes as $attribute => $value) {
$this->writeAttribute($attribute, $value);
}
$this->endElement();
}
/**
* Write element if ...
*
* @param bool $condition
* @param string $element
* @param string $attribute
* @param mixed $value
*/
public function writeElementIf($condition, $element, $attribute = null, $value = null)
{
if ($condition == true) {
if (is_null($attribute)) {
$this->writeElement($element, $value);
} else {
$this->startElement($element);
$this->writeAttribute($attribute, $value);
$this->endElement();
}
}
}
/**
* Write attribute if ...
*
* @param bool $condition
* @param string $attribute
* @param mixed $value
*/
public function writeAttributeIf($condition, $attribute, $value)
{
if ($condition == true) {
$this->writeAttribute($attribute, $value);
}
}
/**
* @param string $name
* @param mixed $value
* @return bool
*/
public function writeAttribute($name, $value)
{
if (is_float($value)) {
$value = json_encode($value);
}
return parent::writeAttribute($name, $value);
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @see https://github.com/PHPOffice/PHPWord
* @copyright 2010-2018 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\SimpleType;
use PhpOffice\PhpWord\Shared\AbstractEnum;
/**
* Border Styles.
*
* @since 0.18.0
*
* @see http://www.datypic.com/sc/ooxml/t-w_ST_Border.html
*/
final class Border extends AbstractEnum
{
const SINGLE = 'single'; //A single line
const DASH_DOT_STROKED = 'dashDotStroked'; //A line with a series of alternating thin and thick strokes
const DASHED = 'dashed'; //A dashed line
const DASH_SMALL_GAP = 'dashSmallGap'; //A dashed line with small gaps
const DOT_DASH = 'dotDash'; //A line with alternating dots and dashes
const DOT_DOT_DASH = 'dotDotDash'; //A line with a repeating dot - dot - dash sequence
const DOTTED = 'dotted'; //A dotted line
const DOUBLE = 'double'; //A double line
const DOUBLE_WAVE = 'doubleWave'; //A double wavy line
const INSET = 'inset'; //An inset set of lines
const NIL = 'nil'; //No border
const NONE = 'none'; //No border
const OUTSET = 'outset'; //An outset set of lines
const THICK = 'thick'; //A single line
const THICK_THIN_LARGE_GAP = 'thickThinLargeGap'; //A thick line contained within a thin line with a large-sized intermediate gap
const THICK_THIN_MEDIUM_GAP = 'thickThinMediumGap'; //A thick line contained within a thin line with a medium-sized intermediate gap
const THICK_THIN_SMALL_GAP = 'thickThinSmallGap'; //A thick line contained within a thin line with a small intermediate gap
const THIN_THICK_LARGE_GAP = 'thinThickLargeGap'; //A thin line contained within a thick line with a large-sized intermediate gap
const THIN_THICK_MEDIUM_GAP = 'thinThickMediumGap'; //A thick line contained within a thin line with a medium-sized intermediate gap
const THIN_THICK_SMALL_GAP = 'thinThickSmallGap'; //A thick line contained within a thin line with a small intermediate gap
const THIN_THICK_THINLARGE_GAP = 'thinThickThinLargeGap'; //A thin-thick-thin line with a large gap
const THIN_THICK_THIN_MEDIUM_GAP = 'thinThickThinMediumGap'; //A thin-thick-thin line with a medium gap
const THIN_THICK_THIN_SMALL_GAP = 'thinThickThinSmallGap'; //A thin-thick-thin line with a small gap
const THREE_D_EMBOSS = 'threeDEmboss'; //A three-staged gradient line, getting darker towards the paragraph
const THREE_D_ENGRAVE = 'threeDEngrave'; //A three-staged gradient like, getting darker away from the paragraph
const TRIPLE = 'triple'; //A triple line
const WAVE = 'wave'; //A wavy line
}

View File

@ -17,7 +17,7 @@
namespace PhpOffice\PhpWord\Style;
use PhpOffice\Common\Text;
use PhpOffice\PhpWord\Shared\Text;
/**
* Abstract style class

View File

@ -66,6 +66,14 @@ class Chart extends AbstractStyle
*/
private $showLegend = false;
/**
* Chart legend Position.
* Possible values are 'r', 't', 'b', 'l', 'tr'
*
* @var string
*/
private $legendPosition = 'r';
/**
* A list of display options for data labels
*
@ -233,6 +241,7 @@ class Chart extends AbstractStyle
* Set the colors to use in a chart.
*
* @param array $value a list of colors to use in the chart
* @return self
*/
public function setColors($value = array())
{
@ -255,6 +264,7 @@ class Chart extends AbstractStyle
* Set the chart title
*
* @param string $value
* @return self
*/
public function setTitle($value = null)
{
@ -277,6 +287,7 @@ class Chart extends AbstractStyle
* Set chart legend visibility
*
* @param bool $value
* @return self
*/
public function setShowLegend($value = false)
{
@ -285,6 +296,37 @@ class Chart extends AbstractStyle
return $this;
}
/**
* Get chart legend position
*
* @return string
*/
public function getLegendPosition()
{
return $this->legendPosition;
}
/**
* Set chart legend position. choices:
* "r" - right of chart
* "b" - bottom of chart
* "t" - top of chart
* "l" - left of chart
* "tr" - top right of chart
*
* default: right
*
* @param string $legendPosition
* @return self
*/
public function setLegendPosition($legendPosition = 'r')
{
$enum = array('r', 'b', 't', 'l', 'tr');
$this->legendPosition = $this->setEnumVal($legendPosition, $enum, $this->legendPosition);
return $this;
}
/*
* Show labels for axis
*
@ -328,7 +370,10 @@ class Chart extends AbstractStyle
{
foreach (array_keys($this->dataLabelOptions) as $option) {
if (isset($values[$option])) {
$this->dataLabelOptions[$option] = $this->setBoolVal($values[$option], $this->dataLabelOptions[$option]);
$this->dataLabelOptions[$option] = $this->setBoolVal(
$values[$option],
$this->dataLabelOptions[$option]
);
}
}
}

View File

@ -228,6 +228,10 @@ final class Language extends AbstractStyle
*/
private function validateLocale($locale)
{
if ($locale !== null) {
$locale = str_replace('_', '-', $locale);
}
if (strlen($locale) === 2) {
return strtolower($locale) . '-' . strtoupper($locale);
}

View File

@ -17,8 +17,8 @@
namespace PhpOffice\PhpWord\Style;
use PhpOffice\Common\Text;
use PhpOffice\PhpWord\Exception\InvalidStyleException;
use PhpOffice\PhpWord\Shared\Text;
use PhpOffice\PhpWord\SimpleType\Jc;
use PhpOffice\PhpWord\SimpleType\TextAlignment;
@ -85,7 +85,7 @@ class Paragraph extends Border
/**
* Indentation
*
* @var \PhpOffice\PhpWord\Style\Indentation
* @var \PhpOffice\PhpWord\Style\Indentation|null
*/
private $indentation;

View File

@ -17,6 +17,7 @@
namespace PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\SimpleType\VerticalJc;
/**
@ -200,8 +201,11 @@ class Section extends Border
* @param string $value
* @return self
*/
public function setPaperSize($value = 'A4')
public function setPaperSize($value = '')
{
if (!$value) {
$value = Settings::getDefaultPaper();
}
if ($this->paper === null) {
$this->paper = new Paper();
}

View File

@ -17,13 +17,13 @@
namespace PhpOffice\PhpWord;
use PhpOffice\Common\Text;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Escaper\RegExp;
use PhpOffice\PhpWord\Escaper\Xml;
use PhpOffice\PhpWord\Exception\CopyFileException;
use PhpOffice\PhpWord\Exception\CreateTemporaryFileException;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Shared\Text;
use PhpOffice\PhpWord\Shared\XMLWriter;
use PhpOffice\PhpWord\Shared\ZipArchive;
class TemplateProcessor
@ -170,7 +170,9 @@ class TemplateProcessor
*/
protected function transformSingleXml($xml, $xsltProcessor)
{
$orignalLibEntityLoader = libxml_disable_entity_loader(true);
if (\PHP_VERSION_ID < 80000) {
$orignalLibEntityLoader = libxml_disable_entity_loader(true);
}
$domDocument = new \DOMDocument();
if (false === $domDocument->loadXML($xml)) {
throw new Exception('Could not load the given XML document.');
@ -180,7 +182,9 @@ class TemplateProcessor
if (false === $transformedXml) {
throw new Exception('Could not transform the given XML document.');
}
libxml_disable_entity_loader($orignalLibEntityLoader);
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($orignalLibEntityLoader);
}
return $transformedXml;
}
@ -274,6 +278,11 @@ class TemplateProcessor
$elementWriter->write();
$where = $this->findContainingXmlBlockForMacro($search, 'w:r');
if ($where === false) {
return;
}
$block = $this->getSlice($where['start'], $where['end']);
$textParts = $this->splitTextIntoTexts($block);
$this->replaceXmlBlock($search, $textParts, 'w:r');
@ -346,6 +355,46 @@ class TemplateProcessor
}
}
/**
* @param string $search
* @param \PhpOffice\PhpWord\Element\AbstractElement $complexType
*/
public function setChart($search, \PhpOffice\PhpWord\Element\AbstractElement $chart)
{
$elementName = substr(get_class($chart), strrpos(get_class($chart), '\\') + 1);
$objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $elementName;
// Get the next relation id
$rId = $this->getNextRelationsIndex($this->getMainPartName());
$chart->setRelationId($rId);
// Define the chart filename
$filename = "charts/chart{$rId}.xml";
// Get the part writer
$writerPart = new \PhpOffice\PhpWord\Writer\Word2007\Part\Chart();
$writerPart->setElement($chart);
// ContentTypes.xml
$this->zipClass->addFromString("word/{$filename}", $writerPart->write());
// add chart to content type
$xmlRelationsType = "<Override PartName=\"/word/{$filename}\" ContentType=\"application/vnd.openxmlformats-officedocument.drawingml.chart+xml\"/>";
$this->tempDocumentContentTypes = str_replace('</Types>', $xmlRelationsType, $this->tempDocumentContentTypes) . '</Types>';
// Add the chart to relations
$xmlChartRelation = "<Relationship Id=\"rId{$rId}\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart\" Target=\"charts/chart{$rId}.xml\"/>";
$this->tempDocumentRelations[$this->getMainPartName()] = str_replace('</Relationships>', $xmlChartRelation, $this->tempDocumentRelations[$this->getMainPartName()]) . '</Relationships>';
// Write the chart
$xmlWriter = new XMLWriter();
$elementWriter = new $objectClass($xmlWriter, $chart, true);
$elementWriter->write();
// Place it in the template
$this->replaceXmlBlock($search, '<w:p>' . $xmlWriter->getData() . '</w:p>', 'w:p');
}
private function getImageArgs($varNameWithArgs)
{
$varElements = explode(':', $varNameWithArgs);
@ -447,6 +496,13 @@ class TemplateProcessor
$width = null;
$height = null;
$ratio = null;
// a closure can be passed as replacement value which after resolving, can contain the replacement info for the image
// use case: only when a image if found, the replacement tags can be generated
if (is_callable($replaceImage)) {
$replaceImage = $replaceImage();
}
if (is_array($replaceImage) && isset($replaceImage['path'])) {
$imgPath = $replaceImage['path'];
if (isset($replaceImage['width'])) {
@ -575,8 +631,9 @@ class TemplateProcessor
// define templates
// result can be verified via "Open XML SDK 2.5 Productivity Tool" (http://www.microsoft.com/en-us/download/details.aspx?id=30425)
$imgTpl = '<w:pict><v:shape type="#_x0000_t75" style="width:{WIDTH};height:{HEIGHT}"><v:imagedata r:id="{RID}" o:title=""/></v:shape></w:pict>';
$imgTpl = '<w:pict><v:shape type="#_x0000_t75" style="width:{WIDTH};height:{HEIGHT}" stroked="f"><v:imagedata r:id="{RID}" o:title=""/></v:shape></w:pict>';
$i = 0;
foreach ($searchParts as $partFileName => &$partContent) {
$partVariables = $this->getVariablesForPart($partContent);
@ -609,6 +666,10 @@ class TemplateProcessor
// replace on each iteration, because in one tag we can have 2+ inline variables => before proceed next variable we need to change $partContent
$partContent = $this->setValueForPart($wholeTag, $replaceXml, $partContent, $limit);
}
if (++$i >= $limit) {
break;
}
}
}
}
@ -737,7 +798,7 @@ class TemplateProcessor
$xmlBlock = null;
$matches = array();
preg_match(
'/(<\?xml.*)(<w:p\b.*>\${' . $blockname . '}<\/w:.*?p>)(.*)(<w:p\b.*\${\/' . $blockname . '}<\/w:.*?p>)/is',
'/(.*((?s)<w:p\b(?:(?!<w:p\b).)*?\${' . $blockname . '}<\/w:.*?p>))(.*)((?s)<w:p\b(?:(?!<w:p\b).)[^$]*?\${\/' . $blockname . '}<\/w:.*?p>)/is',
$this->tempDocumentMainPart,
$matches
);
@ -1085,7 +1146,7 @@ class TemplateProcessor
{
$results = array();
for ($i = 1; $i <= $count; $i++) {
$results[] = preg_replace('/\$\{(.*?)\}/', '\${\\1#' . $i . '}', $xmlBlock);
$results[] = preg_replace('/\$\{([^:]*?)(:.*?)?\}/', '\${\1#' . $i . '\2}', $xmlBlock);
}
return $results;
@ -1121,7 +1182,7 @@ class TemplateProcessor
* @param string $blockType XML tag type of block
* @return \PhpOffice\PhpWord\TemplateProcessor Fluent interface
*/
protected function replaceXmlBlock($macro, $block, $blockType = 'w:p')
public function replaceXmlBlock($macro, $block, $blockType = 'w:p')
{
$where = $this->findContainingXmlBlockForMacro($macro, $blockType);
if (is_array($where)) {

View File

@ -17,9 +17,9 @@
namespace PhpOffice\PhpWord\Writer\HTML\Element;
use Laminas\Escaper\Escaper;
use PhpOffice\PhpWord\Element\AbstractElement as Element;
use PhpOffice\PhpWord\Writer\AbstractWriter;
use Zend\Escaper\Escaper;
/**
* Abstract HTML element writer
@ -50,7 +50,7 @@ abstract class AbstractElement
protected $withoutP = false;
/**
* @var \Zend\Escaper\Escaper|\PhpOffice\PhpWord\Escaper\AbstractEscaper
* @var \Laminas\Escaper\Escaper|\PhpOffice\PhpWord\Escaper\AbstractEscaper
*/
protected $escaper;

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.
*
* @see https://github.com/PHPOffice/PHPWord
* @copyright 2010-2018 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Writer\HTML\Element;
/**
* ListItem element HTML writer
*
* @since 0.10.0
*/
class ListItemRun extends TextRun
{
/**
* Write list item
*
* @return string
*/
public function write()
{
if (!$this->element instanceof \PhpOffice\PhpWord\Element\ListItemRun) {
return '';
}
$writer = new Container($this->parentWriter, $this->element);
$content = $writer->write() . PHP_EOL;
return $content;
}
}

View File

@ -52,6 +52,7 @@ class Table extends AbstractElement
for ($j = 0; $j < $rowCellCount; $j++) {
$cellStyle = $rowCells[$j]->getStyle();
$cellBgColor = $cellStyle->getBgColor();
$cellBgColor === 'auto' && $cellBgColor = null; // auto cannot be parsed to hexadecimal number
$cellFgColor = null;
if ($cellBgColor) {
$red = hexdec(substr($cellBgColor, 0, 2));

View File

@ -17,9 +17,9 @@
namespace PhpOffice\PhpWord\Writer\HTML\Part;
use Laminas\Escaper\Escaper;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Writer\AbstractWriter;
use Zend\Escaper\Escaper;
/**
* @since 0.11.0
@ -32,7 +32,7 @@ abstract class AbstractPart
private $parentWriter;
/**
* @var \Zend\Escaper\Escaper
* @var \Laminas\Escaper\Escaper
*/
protected $escaper;

View File

@ -0,0 +1,81 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @see https://github.com/PHPOffice/PHPWord
* @copyright 2010-2018 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
// Not fully implemented
// - supports only PAGE and NUMPAGES
// - supports only default formats and options
// - supports style only if specified by name
// - spaces before and after field may be dropped
namespace PhpOffice\PhpWord\Writer\ODText\Element;
/**
* Field element writer
*
* @since 0.11.0
*/
class Field extends Text
{
/**
* Write field element.
*/
public function write()
{
$element = $this->getElement();
if (!$element instanceof \PhpOffice\PhpWord\Element\Field) {
return;
}
$type = strtolower($element->getType());
switch ($type) {
case 'date':
case 'page':
case 'numpages':
$this->writeDefault($element, $type);
break;
}
}
private function writeDefault(\PhpOffice\PhpWord\Element\Field $element, $type)
{
$xmlWriter = $this->getXmlWriter();
$xmlWriter->startElement('text:span');
if (method_exists($element, 'getFontStyle')) {
$fstyle = $element->getFontStyle();
if (is_string($fstyle)) {
$xmlWriter->writeAttribute('text:style-name', $fstyle);
}
}
switch ($type) {
case 'date':
$xmlWriter->startElement('text:date');
$xmlWriter->writeAttribute('text:fixed', 'false');
$xmlWriter->endElement();
break;
case 'page':
$xmlWriter->startElement('text:page-number');
$xmlWriter->writeAttribute('text:fixed', 'false');
$xmlWriter->endElement();
break;
case 'numpages':
$xmlWriter->startElement('text:page-count');
$xmlWriter->endElement();
break;
}
$xmlWriter->endElement(); // text:span
}
}

View File

@ -44,7 +44,7 @@ class Image extends AbstractElement
$height = Converter::pixelToCm($style->getHeight());
$xmlWriter->startElement('text:p');
$xmlWriter->writeAttribute('text:style-name', 'Standard');
$xmlWriter->writeAttribute('text:style-name', 'IM' . $mediaIndex);
$xmlWriter->startElement('draw:frame');
$xmlWriter->writeAttribute('draw:style-name', 'fr' . $mediaIndex);

View File

@ -41,7 +41,7 @@ class Link extends AbstractElement
$xmlWriter->startElement('text:a');
$xmlWriter->writeAttribute('xlink:type', 'simple');
$xmlWriter->writeAttribute('xlink:href', $element->getSource());
$xmlWriter->writeAttribute('xlink:href', ($element->isInternal() ? '#' : '') . $element->getSource());
$this->writeText($element->getText());
$xmlWriter->endElement(); // text:a

View File

@ -30,7 +30,7 @@ class PageBreak extends AbstractElement
$xmlWriter = $this->getXmlWriter();
$xmlWriter->startElement('text:p');
$xmlWriter->writeAttribute('text:style-name', 'P1');
$xmlWriter->writeAttribute('text:style-name', 'PB');
$xmlWriter->endElement();
}
}

View File

@ -17,9 +17,9 @@
namespace PhpOffice\PhpWord\Writer\ODText\Element;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Element\Row as RowElement;
use PhpOffice\PhpWord\Element\Table as TableElement;
use PhpOffice\PhpWord\Shared\XMLWriter;
/**
* Table element writer
@ -60,7 +60,7 @@ class Table extends AbstractElement
/**
* Write column.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\Table $element
*/
private function writeColumns(XMLWriter $xmlWriter, TableElement $element)
@ -77,7 +77,7 @@ class Table extends AbstractElement
/**
* Write row.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\Row $row
*/
private function writeRow(XMLWriter $xmlWriter, RowElement $row)

View File

@ -42,12 +42,12 @@ class Text extends AbstractElement
// @todo Commented for TextRun. Should really checkout this value
// $fStyleIsObject = ($fontStyle instanceof Font) ? true : false;
$fStyleIsObject = false;
//$fStyleIsObject = false;
if ($fStyleIsObject) {
// Don't never be the case, because I browse all sections for cleaning all styles not declared
throw new Exception('PhpWord : $fStyleIsObject wouldn\'t be an object');
}
//if ($fStyleIsObject) {
// Don't never be the case, because I browse all sections for cleaning all styles not declared
// throw new Exception('PhpWord : $fStyleIsObject wouldn\'t be an object');
//}
if (!$this->withoutP) {
$xmlWriter->startElement('text:p'); // text:p
@ -59,18 +59,26 @@ class Text extends AbstractElement
} else {
if (empty($fontStyle)) {
if (empty($paragraphStyle)) {
$xmlWriter->writeAttribute('text:style-name', 'P1');
if (!$this->withoutP) {
$xmlWriter->writeAttribute('text:style-name', 'Normal');
}
} elseif (is_string($paragraphStyle)) {
$xmlWriter->writeAttribute('text:style-name', $paragraphStyle);
if (!$this->withoutP) {
$xmlWriter->writeAttribute('text:style-name', $paragraphStyle);
}
}
$this->writeChangeInsertion(true, $element->getTrackChange());
$this->writeText($element->getText());
$this->replaceTabs($element->getText(), $xmlWriter);
$this->writeChangeInsertion(false, $element->getTrackChange());
} else {
if (empty($paragraphStyle)) {
$xmlWriter->writeAttribute('text:style-name', 'Standard');
if (!$this->withoutP) {
$xmlWriter->writeAttribute('text:style-name', 'Normal');
}
} elseif (is_string($paragraphStyle)) {
$xmlWriter->writeAttribute('text:style-name', $paragraphStyle);
if (!$this->withoutP) {
$xmlWriter->writeAttribute('text:style-name', $paragraphStyle);
}
}
// text:span
$xmlWriter->startElement('text:span');
@ -78,7 +86,7 @@ class Text extends AbstractElement
$xmlWriter->writeAttribute('text:style-name', $fontStyle);
}
$this->writeChangeInsertion(true, $element->getTrackChange());
$this->writeText($element->getText());
$this->replaceTabs($element->getText(), $xmlWriter);
$this->writeChangeInsertion(false, $element->getTrackChange());
$xmlWriter->endElement();
}
@ -88,6 +96,34 @@ class Text extends AbstractElement
}
}
private function replacetabs($text, $xmlWriter)
{
if (preg_match('/^ +/', $text, $matches)) {
$num = strlen($matches[0]);
$xmlWriter->startElement('text:s');
$xmlWriter->writeAttributeIf($num > 1, 'text:c', "$num");
$xmlWriter->endElement();
$text = preg_replace('/^ +/', '', $text);
}
preg_match_all('/([\\s\\S]*?)(\\t| +| ?$)/', $text, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$this->writeText($match[1]);
if ($match[2] === '') {
break;
} elseif ($match[2] === "\t") {
$xmlWriter->writeElement('text:tab');
} elseif ($match[2] === ' ') {
$xmlWriter->writeElement('text:s');
break;
} else {
$num = strlen($match[2]);
$xmlWriter->startElement('text:s');
$xmlWriter->writeAttributeIf($num > 1, 'text:c', "$num");
$xmlWriter->endElement();
}
}
}
private function writeChangeInsertion($start = true, TrackChange $trackChange = null)
{
if ($trackChange == null || $trackChange->getChangeType() != TrackChange::INSERTED) {

View File

@ -22,7 +22,7 @@ namespace PhpOffice\PhpWord\Writer\ODText\Element;
*
* @since 0.10.0
*/
class TextRun extends AbstractElement
class TextRun extends Text
{
/**
* Write element
@ -33,6 +33,12 @@ class TextRun extends AbstractElement
$element = $this->getElement();
$xmlWriter->startElement('text:p');
/** @scrutinizer ignore-call */
$pStyle = $element->getParagraphStyle();
if (!is_string($pStyle)) {
$pStyle = 'Normal';
}
$xmlWriter->writeAttribute('text:style-name', $pStyle);
$containerWriter = new Container($xmlWriter, $element);
$containerWriter->write();

View File

@ -36,7 +36,22 @@ class Title extends AbstractElement
}
$xmlWriter->startElement('text:h');
$xmlWriter->writeAttribute('text:outline-level', $element->getDepth());
$hdname = 'HD';
$sect = $element->getParent();
if ($sect instanceof \PhpOffice\PhpWord\Element\Section) {
if (self::compareToFirstElement($element, $sect->getElements())) {
$hdname = 'HE';
}
}
$depth = $element->getDepth();
$xmlWriter->writeAttribute('text:style-name', "$hdname$depth");
$xmlWriter->writeAttribute('text:outline-level', $depth);
$xmlWriter->startElement('text:span');
if ($depth > 0) {
$xmlWriter->writeAttribute('text:style-name', 'Heading_' . $depth);
} else {
$xmlWriter->writeAttribute('text:style-name', 'Title');
}
$text = $element->getText();
if (is_string($text)) {
$this->writeText($text);
@ -44,6 +59,21 @@ class Title extends AbstractElement
$containerWriter = new Container($xmlWriter, $text);
$containerWriter->write();
}
$xmlWriter->endElement(); // text:span
$xmlWriter->endElement(); // text:h
}
/**
* Test if element is same as first element in array
*
* @param \PhpOffice\PhpWord\Element\AbstractElement $elem
*
* @param \PhpOffice\PhpWord\Element\AbstractElement[] $elemarray
*
* @return bool
*/
private static function compareToFirstElement($elem, $elemarray)
{
return $elem === $elemarray[0];
}
}

View File

@ -17,8 +17,8 @@
namespace PhpOffice\PhpWord\Writer\ODText\Part;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Shared\XMLWriter;
use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart as Word2007AbstractPart;
@ -36,7 +36,7 @@ abstract class AbstractPart extends Word2007AbstractPart
/**
* Write common root attributes.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
*/
protected function writeCommonRootAttributes(XMLWriter $xmlWriter)
{
@ -72,7 +72,7 @@ abstract class AbstractPart extends Word2007AbstractPart
/**
* Write font faces declaration.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
*/
protected function writeFontFaces(XMLWriter $xmlWriter)
{

View File

@ -17,14 +17,15 @@
namespace PhpOffice\PhpWord\Writer\ODText\Part;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Element\AbstractContainer;
use PhpOffice\PhpWord\Element\Field;
use PhpOffice\PhpWord\Element\Image;
use PhpOffice\PhpWord\Element\Table;
use PhpOffice\PhpWord\Element\Text;
use PhpOffice\PhpWord\Element\TextRun;
use PhpOffice\PhpWord\Element\TrackChange;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLWriter;
use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Style\Paragraph;
@ -46,6 +47,7 @@ class Content extends AbstractPart
* @var array
*/
private $autoStyles = array('Section' => array(), 'Image' => array(), 'Table' => array());
private $imageParagraphStyles = array();
/**
* Write part
@ -128,6 +130,9 @@ class Content extends AbstractPart
$xmlWriter->startElement('text:section');
$xmlWriter->writeAttribute('text:name', $name);
$xmlWriter->writeAttribute('text:style-name', $name);
$xmlWriter->startElement('text:p');
$xmlWriter->writeAttribute('text:style-name', 'SB' . $section->getSectionId());
$xmlWriter->endElement();
$containerWriter = new Container($xmlWriter, $section);
$containerWriter->write();
$xmlWriter->endElement(); // text:section
@ -146,7 +151,7 @@ class Content extends AbstractPart
*
* @since 0.11.0
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
*/
private function writeAutoStyles(XMLWriter $xmlWriter)
{
@ -168,34 +173,65 @@ class Content extends AbstractPart
/**
* Write automatic styles.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
*/
private function writeTextStyles(XMLWriter $xmlWriter)
{
$styles = Style::getStyles();
$paragraphStyleCount = 0;
if (count($styles) > 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->write();
}
if ($style instanceof Paragraph) {
$paragraphStyleCount++;
}
}
}
if ($paragraphStyleCount == 0) {
$style = new Paragraph();
$style->setStyleName('PB');
$style->setAuto();
$styleWriter = new ParagraphStyleWriter($xmlWriter, $style);
$styleWriter->write();
$sects = $this->getParentWriter()->getPhpWord()->getSections();
$countsects = count($sects);
for ($i = 0; $i < $countsects; ++$i) {
$iplus1 = $i + 1;
$style = new Paragraph();
$style->setStyleName("SB$iplus1");
$style->setAuto();
$pnstart = $sects[$i]->getStyle()->getPageNumberingStart();
$style->setNumLevel($pnstart);
$styleWriter = new ParagraphStyleWriter($xmlWriter, $style);
$styleWriter->write();
}
foreach ($styles as $style) {
$sty = $style->getStyleName();
if (substr($sty, 0, 8) === 'Heading_') {
$style = new Paragraph();
$style->setStyleName('P1');
$style->setStyleName('HD' . substr($sty, 8));
$style->setAuto();
$styleWriter = new ParagraphStyleWriter($xmlWriter, $style);
$styleWriter->write();
$style = new Paragraph();
$style->setStyleName('HE' . substr($sty, 8));
$style->setAuto();
$styleWriter = new ParagraphStyleWriter($xmlWriter, $style);
$styleWriter->write();
}
}
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->write();
}
if ($style instanceof Paragraph) {
$paragraphStyleCount++;
}
}
}
foreach ($this->imageParagraphStyles as $style) {
$styleWriter = new \PhpOffice\PhpWord\Writer\ODText\Style\Paragraph($xmlWriter, $style);
$styleWriter->write();
}
}
/**
@ -231,20 +267,29 @@ class Content extends AbstractPart
$elements = $container->getElements();
foreach ($elements as $element) {
if ($element instanceof TextRun) {
$this->getElementStyleTextRun($element, $paragraphStyleCount);
$this->getContainerStyle($element, $paragraphStyleCount, $fontStyleCount);
} elseif ($element instanceof Text) {
$this->getElementStyle($element, $paragraphStyleCount, $fontStyleCount);
} elseif ($element instanceof Field) {
$this->getElementStyleField($element, $fontStyleCount);
} elseif ($element instanceof Image) {
$style = $element->getStyle();
$style->setStyleName('fr' . $element->getMediaIndex());
$this->autoStyles['Image'][] = $style;
$sty = new \PhpOffice\PhpWord\Style\Paragraph();
$sty->setStyleName('IM' . $element->getMediaIndex());
$sty->setAuto();
$sty->setAlignment($style->getAlignment());
$this->imageParagraphStyles[] = $sty;
} elseif ($element instanceof Table) {
/** @var \PhpOffice\PhpWord\Style\Table $style */
$style = $element->getStyle();
if (is_string($style)) {
$style = Style::getStyle($style);
}
if ($style === null) {
$style = new TableStyle();
} elseif (is_string($style)) {
$style = Style::getStyle($style);
}
$style->setStyleName($element->getElementId());
$style->setColumnWidths($element->findFirstDefinedCellWidths());
@ -260,7 +305,7 @@ class Content extends AbstractPart
* @param int $paragraphStyleCount
* @param int $fontStyleCount
*/
private function getElementStyle(&$element, &$paragraphStyleCount, &$fontStyleCount)
private function getElementStyle($element, &$paragraphStyleCount, &$fontStyleCount)
{
$fontStyle = $element->getFontStyle();
$paragraphStyle = $element->getParagraphStyle();
@ -268,16 +313,91 @@ class Content extends AbstractPart
if ($fontStyle instanceof Font) {
// Font
$fontStyleCount++;
$style = $phpWord->addFontStyle("T{$fontStyleCount}", $fontStyle);
$style->setAuto();
$element->setFontStyle("T{$fontStyleCount}");
} elseif ($paragraphStyle instanceof Paragraph) {
$name = $fontStyle->getStyleName();
if (!$name) {
$fontStyleCount++;
$style = $phpWord->addFontStyle("T{$fontStyleCount}", $fontStyle, null);
$style->setAuto();
$style->setParagraph(null);
$element->setFontStyle("T{$fontStyleCount}");
} else {
$element->setFontStyle($name);
}
}
if ($paragraphStyle instanceof Paragraph) {
// Paragraph
$name = $paragraphStyle->getStyleName();
if (!$name) {
$paragraphStyleCount++;
$style = $phpWord->addParagraphStyle("P{$paragraphStyleCount}", $paragraphStyle);
$style->setAuto();
$element->setParagraphStyle("P{$paragraphStyleCount}");
} else {
$element->setParagraphStyle($name);
}
} elseif ($paragraphStyle) {
$paragraphStyleCount++;
$style = $phpWord->addParagraphStyle("P{$paragraphStyleCount}", array());
$parstylename = "P$paragraphStyleCount" . "_$paragraphStyle";
$style = $phpWord->addParagraphStyle($parstylename, $paragraphStyle);
$style->setAuto();
$element->setParagraphStyle("P{$paragraphStyleCount}");
$element->setParagraphStyle($parstylename);
}
}
/**
* Get font style of individual field element
*
* @param \PhpOffice\PhpWord\Element\Field $element
* @param int $paragraphStyleCount
* @param int $fontStyleCount
*/
private function getElementStyleField($element, &$fontStyleCount)
{
$fontStyle = $element->getFontStyle();
$phpWord = $this->getParentWriter()->getPhpWord();
if ($fontStyle instanceof Font) {
$name = $fontStyle->getStyleName();
if (!$name) {
$fontStyleCount++;
$style = $phpWord->addFontStyle("T{$fontStyleCount}", $fontStyle, null);
$style->setAuto();
$style->setParagraph(null);
$element->setFontStyle("T{$fontStyleCount}");
} else {
$element->setFontStyle($name);
}
}
}
/**
* Get style of individual element
*
* @param \PhpOffice\PhpWord\Element\TextRun $element
* @param int $paragraphStyleCount
*/
private function getElementStyleTextRun($element, &$paragraphStyleCount)
{
$paragraphStyle = $element->getParagraphStyle();
$phpWord = $this->getParentWriter()->getPhpWord();
if ($paragraphStyle instanceof Paragraph) {
// Paragraph
$name = $paragraphStyle->getStyleName();
if (!$name) {
$paragraphStyleCount++;
$style = $phpWord->addParagraphStyle("P{$paragraphStyleCount}", $paragraphStyle);
$style->setAuto();
$element->setParagraphStyle("P{$paragraphStyleCount}");
} else {
$element->setParagraphStyle($name);
}
} elseif ($paragraphStyle) {
$paragraphStyleCount++;
$parstylename = "P$paragraphStyleCount" . "_$paragraphStyle";
$style = $phpWord->addParagraphStyle($parstylename, $paragraphStyle);
$style->setAuto();
$element->setParagraphStyle($parstylename);
}
}

View File

@ -17,7 +17,7 @@
namespace PhpOffice\PhpWord\Writer\ODText\Part;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Shared\XMLWriter;
/**
* ODText meta part writer: meta.xml
@ -86,7 +86,7 @@ class Meta extends AbstractPart
/**
* Write individual property
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param string $property
* @param string $value
*

View File

@ -17,8 +17,9 @@
namespace PhpOffice\PhpWord\Writer\ODText\Part;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Shared\Converter;
use PhpOffice\PhpWord\Shared\XMLWriter;
use PhpOffice\PhpWord\Style;
/**
@ -65,7 +66,7 @@ class Styles extends AbstractPart
/**
* Write default styles.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
*/
private function writeDefault(XMLWriter $xmlWriter)
{
@ -86,6 +87,9 @@ class Styles extends AbstractPart
$latinLang = $language != null && is_string($language->getLatin()) ? explode('-', $language->getLatin()) : array('fr', 'FR');
$asianLang = $language != null && is_string($language->getEastAsia()) ? explode('-', $language->getEastAsia()) : array('zh', 'CN');
$complexLang = $language != null && is_string($language->getBidirectional()) ? explode('-', $language->getBidirectional()) : array('hi', 'IN');
if ($this->getParentWriter()->getPhpWord()->getSettings()->hasHideGrammaticalErrors()) {
$latinLang = $asianLang = $complexLang = array('zxx', 'none');
}
// Font
$xmlWriter->startElement('style:text-properties');
@ -114,7 +118,7 @@ class Styles extends AbstractPart
/**
* Write named styles.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
*/
private function writeNamed(XMLWriter $xmlWriter)
{
@ -134,24 +138,74 @@ class Styles extends AbstractPart
}
/**
* Write page layout styles.
* Convert int in twips to inches/cm then to string and append unit
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param int|float $twips
* @param float $factor
* return string
*/
private static function cvttwiptostr($twips, $factor = 1.0)
{
$ins = (string) ($twips * $factor / Converter::INCH_TO_TWIP) . 'in';
$cms = (string) ($twips * $factor * Converter::INCH_TO_CM / Converter::INCH_TO_TWIP) . 'cm';
return (strlen($ins) < strlen($cms)) ? $ins : $cms;
}
/**
* call writePageLayoutIndiv to write page layout styles for each page
*
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
*/
private function writePageLayout(XMLWriter $xmlWriter)
{
$sections = $this->getParentWriter()->getPhpWord()->getSections();
$countsects = count($sections);
for ($i = 0; $i < $countsects; ++$i) {
$this->writePageLayoutIndiv($xmlWriter, $sections[$i], $i + 1);
}
}
/**
* Write page layout styles.
*
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\Section $section
* @param int $sectionNbr
*/
private function writePageLayoutIndiv(XMLWriter $xmlWriter, $section, $sectionNbr)
{
$sty = $section->getStyle();
if (count($section->getHeaders()) > 0) {
$topfactor = 0.5;
} else {
$topfactor = 1.0;
}
if (count($section->getFooters()) > 0) {
$botfactor = 0.5;
} else {
$botfactor = 1.0;
}
$orient = $sty->getOrientation();
$pwidth = self::cvttwiptostr($sty->getPageSizeW());
$pheight = self::cvttwiptostr($sty->getPageSizeH());
$mtop = self::cvttwiptostr($sty->getMarginTop(), $topfactor);
$mbottom = self::cvttwiptostr($sty->getMarginBottom(), $botfactor);
$mleft = self::cvttwiptostr($sty->getMarginRight());
$mright = self::cvttwiptostr($sty->getMarginLeft());
$xmlWriter->startElement('style:page-layout');
$xmlWriter->writeAttribute('style:name', 'Mpm1');
$xmlWriter->writeAttribute('style:name', "Mpm$sectionNbr");
$xmlWriter->startElement('style:page-layout-properties');
$xmlWriter->writeAttribute('fo:page-width', '21.001cm');
$xmlWriter->writeAttribute('fo:page-height', '29.7cm');
$xmlWriter->writeAttribute('fo:page-width', $pwidth);
$xmlWriter->writeAttribute('fo:page-height', $pheight);
$xmlWriter->writeAttribute('style:num-format', '1');
$xmlWriter->writeAttribute('style:print-orientation', 'portrait');
$xmlWriter->writeAttribute('fo:margin-top', '2.501cm');
$xmlWriter->writeAttribute('fo:margin-bottom', '2cm');
$xmlWriter->writeAttribute('fo:margin-left', '2.501cm');
$xmlWriter->writeAttribute('fo:margin-right', '2.501cm');
$xmlWriter->writeAttribute('style:print-orientation', $orient);
$xmlWriter->writeAttribute('fo:margin-top', $mtop);
$xmlWriter->writeAttribute('fo:margin-bottom', $mbottom);
$xmlWriter->writeAttribute('fo:margin-left', $mleft);
$xmlWriter->writeAttribute('fo:margin-right', $mright);
$xmlWriter->writeAttribute('style:writing-mode', 'lr-tb');
$xmlWriter->writeAttribute('style:layout-grid-color', '#c0c0c0');
$xmlWriter->writeAttribute('style:layout-grid-lines', '25199');
@ -176,9 +230,23 @@ class Styles extends AbstractPart
$xmlWriter->endElement(); // style:page-layout-properties
$xmlWriter->startElement('style:header-style');
if ($topfactor < 1.0) {
$xmlWriter->startElement('style:header-footer-properties');
$xmlWriter->writeAttribute('fo:min-height', $mtop);
$xmlWriter->writeAttribute('fo:margin-bottom', $mtop);
$xmlWriter->writeAttribute('style:dynamic-spacing', 'true');
$xmlWriter->endElement(); // style:header-footer-properties
}
$xmlWriter->endElement(); // style:header-style
$xmlWriter->startElement('style:footer-style');
if ($botfactor < 1.0) {
$xmlWriter->startElement('style:header-footer-properties');
$xmlWriter->writeAttribute('fo:min-height', $mbottom);
$xmlWriter->writeAttribute('fo:margin-top', $mbottom);
$xmlWriter->writeAttribute('style:dynamic-spacing', 'true');
$xmlWriter->endElement(); // style:header-footer-properties
}
$xmlWriter->endElement(); // style:footer-style
$xmlWriter->endElement(); // style:page-layout
@ -187,17 +255,50 @@ class Styles extends AbstractPart
/**
* Write master style.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
*/
private function writeMaster(XMLWriter $xmlWriter)
{
$xmlWriter->startElement('office:master-styles');
$xmlWriter->startElement('style:master-page');
$xmlWriter->writeAttribute('style:name', 'Standard');
$xmlWriter->writeAttribute('style:page-layout-name', 'Mpm1');
$xmlWriter->endElement(); // style:master-page
$sections = $this->getParentWriter()->getPhpWord()->getSections();
$countsects = count($sections);
for ($i = 0; $i < $countsects; ++$i) {
$iplus1 = $i + 1;
$xmlWriter->startElement('style:master-page');
$xmlWriter->writeAttribute('style:name', "Standard$iplus1");
$xmlWriter->writeAttribute('style:page-layout-name', "Mpm$iplus1");
// Multiple headers and footers probably not supported,
// and, even if they are, I'm not sure how,
// so quit after generating one.
foreach ($sections[$i]->getHeaders() as $hdr) {
$xmlWriter->startElement('style:header');
foreach ($hdr->getElements() as $elem) {
$cl1 = get_class($elem);
$cl2 = str_replace('\\Element\\', '\\Writer\\ODText\\Element\\', $cl1);
if (class_exists($cl2)) {
$wtr = new $cl2($xmlWriter, $elem);
$wtr->write();
}
}
$xmlWriter->endElement(); // style:header
break;
}
foreach ($sections[$i]->getFooters() as $hdr) {
$xmlWriter->startElement('style:footer');
foreach ($hdr->getElements() as $elem) {
$cl1 = get_class($elem);
$cl2 = str_replace('\\Element\\', '\\Writer\\ODText\\Element\\', $cl1);
if (class_exists($cl2)) {
$wtr = new $cl2($xmlWriter, $elem);
$wtr->write();
}
}
$xmlWriter->endElement(); // style:footer
break;
}
$xmlWriter->endElement(); // style:master-page
}
$xmlWriter->endElement(); // office:master-styles
}
}

View File

@ -35,6 +35,14 @@ class Font extends AbstractStyle
}
$xmlWriter = $this->getXmlWriter();
$stylep = (method_exists($style, 'getParagraph')) ? $style->getParagraph() : null;
if ($stylep instanceof \PhpOffice\PhpWord\Style\Paragraph) {
$temp1 = clone $stylep;
$temp1->setStyleName($style->getStyleName());
$temp2 = new \PhpOffice\PhpWord\Writer\ODText\Style\Paragraph($xmlWriter, $temp1);
$temp2->write();
}
$xmlWriter->startElement('style:style');
$xmlWriter->writeAttribute('style:name', $style->getStyleName());
$xmlWriter->writeAttribute('style:family', 'text');
@ -53,7 +61,7 @@ class Font extends AbstractStyle
// Color
$color = $style->getColor();
$xmlWriter->writeAttributeIf($color != '', 'fo:color', '#' . $color);
$xmlWriter->writeAttributeIf($color != '', 'fo:color', '#' . \PhpOffice\PhpWord\Shared\Converter::stringToRgb($color));
// Bold & italic
$xmlWriter->writeAttributeIf($style->isBold(), 'fo:font-weight', 'bold');
@ -82,6 +90,15 @@ class Font extends AbstractStyle
$xmlWriter->writeAttributeIf($style->isSuperScript(), 'style:text-position', 'super');
$xmlWriter->writeAttributeIf($style->isSubScript(), 'style:text-position', 'sub');
if ($style->isNoProof()) {
$xmlWriter->writeAttribute('fo:language', 'zxx');
$xmlWriter->writeAttribute('style:language-asian', 'zxx');
$xmlWriter->writeAttribute('style:language-complex', 'zxx');
$xmlWriter->writeAttribute('fo:country', 'none');
$xmlWriter->writeAttribute('style:country-asian', 'none');
$xmlWriter->writeAttribute('style:country-complex', 'none');
}
// @todo Foreground-Color
// @todo Background color

View File

@ -17,6 +17,8 @@
namespace PhpOffice\PhpWord\Writer\ODText\Style;
use PhpOffice\PhpWord\Shared\Converter;
/**
* Font style writer
*
@ -35,31 +37,119 @@ class Paragraph extends AbstractStyle
}
$xmlWriter = $this->getXmlWriter();
$marginTop = (is_null($style->getSpaceBefore()) || $style->getSpaceBefore() == 0) ? '0' : round(17.6 / $style->getSpaceBefore(), 2);
$marginBottom = (is_null($style->getSpaceAfter()) || $style->getSpaceAfter() == 0) ? '0' : round(17.6 / $style->getSpaceAfter(), 2);
$marginTop = $style->getSpaceBefore();
$marginBottom = $style->getSpaceAfter();
$xmlWriter->startElement('style:style');
$styleName = $style->getStyleName();
$styleAuto = false;
$mpm = '';
$psm = '';
$pagestart = -1;
$breakafter = $breakbefore = $breakauto = false;
if ($style->isAuto()) {
if (substr($styleName, 0, 2) === 'PB') {
$styleAuto = true;
$breakafter = true;
} elseif (substr($styleName, 0, 2) === 'SB') {
$styleAuto = true;
$mpm = 'Standard' . substr($styleName, 2);
$psn = $style->getNumLevel();
$pagestart = $psn;
} elseif (substr($styleName, 0, 2) === 'HD') {
$styleAuto = true;
$psm = 'Heading_' . substr($styleName, 2);
$stylep = \PhpOffice\PhpWord\Style::getStyle($psm);
if ($stylep instanceof \PhpOffice\PhpWord\Style\Font) {
if (method_exists($stylep, 'getParagraph')) {
$stylep = $stylep->getParagraph();
}
}
if ($stylep instanceof \PhpOffice\PhpWord\Style\Paragraph) {
if ($stylep->hasPageBreakBefore()) {
$breakbefore = true;
}
}
} elseif (substr($styleName, 0, 2) === 'HE') {
$styleAuto = true;
$psm = 'Heading_' . substr($styleName, 2);
$breakauto = true;
} else {
$styleAuto = true;
$psm = 'Normal';
if (preg_match('/^P\\d+_(\\w+)$/', $styleName, $matches)) {
$psm = $matches[1];
}
}
}
$xmlWriter->writeAttribute('style:name', $style->getStyleName());
$xmlWriter->writeAttribute('style:family', 'paragraph');
if ($style->isAuto()) {
$xmlWriter->writeAttribute('style:parent-style-name', 'Standard');
$xmlWriter->writeAttribute('style:master-page-name', 'Standard');
if ($styleAuto) {
$xmlWriter->writeAttributeIf($psm !== '', 'style:parent-style-name', $psm);
$xmlWriter->writeAttributeIf($mpm !== '', 'style:master-page-name', $mpm);
}
$xmlWriter->startElement('style:paragraph-properties');
if ($style->isAuto()) {
$xmlWriter->writeAttribute('style:page-number', 'auto');
} else {
$xmlWriter->writeAttribute('fo:margin-top', $marginTop . 'cm');
$xmlWriter->writeAttribute('fo:margin-bottom', $marginBottom . 'cm');
$xmlWriter->writeAttribute('fo:text-align', $style->getAlignment());
if ($styleAuto) {
if ($breakafter) {
$xmlWriter->writeAttribute('fo:break-after', 'page');
$xmlWriter->writeAttribute('fo:margin-top', '0cm');
$xmlWriter->writeAttribute('fo:margin-bottom', '0cm');
} elseif ($breakbefore) {
$xmlWriter->writeAttribute('fo:break-before', 'page');
} elseif ($breakauto) {
$xmlWriter->writeAttribute('fo:break-before', 'auto');
}
if ($pagestart > 0) {
$xmlWriter->writeAttribute('style:page-number', $pagestart);
}
}
if (!$breakafter && !$breakbefore && !$breakauto) {
$twipToPoint = Converter::INCH_TO_TWIP / Converter::INCH_TO_POINT; // 20
$xmlWriter->writeAttributeIf($marginTop !== null, 'fo:margin-top', ($marginTop / $twipToPoint) . 'pt');
$xmlWriter->writeAttributeIf($marginBottom !== null, 'fo:margin-bottom', ($marginBottom / $twipToPoint) . 'pt');
}
$temp = $style->getAlignment();
$xmlWriter->writeAttributeIf($temp !== '', 'fo:text-align', $temp);
$temp = $style->getLineHeight();
$xmlWriter->writeAttributeIf($temp !== null, 'fo:line-height', ((string) ($temp * 100) . '%'));
$xmlWriter->writeAttributeIf($style->hasPageBreakBefore() === true, 'fo:break-before', 'page');
$tabs = $style->getTabs();
if ($tabs !== null && count($tabs) > 0) {
$xmlWriter->startElement('style:tab-stops');
foreach ($tabs as $tab) {
$xmlWriter->startElement('style:tab-stop');
$xmlWriter->writeAttribute('style:type', $tab->getType());
$xmlWriter->writeAttribute('style:position', (string) ($tab->getPosition() / Converter::INCH_TO_TWIP) . 'in');
$xmlWriter->endElement();
}
$xmlWriter->endElement();
}
//Right to left
$xmlWriter->writeAttributeIf($style->isBidi(), 'style:writing-mode', 'rl-tb');
//Indentation
$indent = $style->getIndentation();
//if ($indent instanceof \PhpOffice\PhpWord\Style\Indentation) {
if (!empty($indent)) {
$marg = $indent->getLeft();
$xmlWriter->writeAttributeIf($marg !== null, 'fo:margin-left', (string) ($marg / Converter::INCH_TO_TWIP) . 'in');
$marg = $indent->getRight();
$xmlWriter->writeAttributeIf($marg !== null, 'fo:margin-right', (string) ($marg / Converter::INCH_TO_TWIP) . 'in');
}
$xmlWriter->endElement(); //style:paragraph-properties
if ($styleAuto && substr($styleName, 0, 2) === 'SB') {
$xmlWriter->startElement('style:text-properties');
$xmlWriter->writeAttribute('text:display', 'none');
$xmlWriter->endElement();
}
$xmlWriter->endElement(); //style:style
}
}

View File

@ -35,6 +35,16 @@ class DomPDF extends AbstractRenderer implements WriterInterface
*/
protected $includeFile = null;
/**
* Gets the implementation of external PDF library that should be used.
*
* @return Dompdf implementation
*/
protected function createExternalWriterInstance()
{
return new DompdfLib();
}
/**
* Save PhpWord to file.
*
@ -49,7 +59,7 @@ class DomPDF extends AbstractRenderer implements WriterInterface
$orientation = 'portrait';
// Create PDF
$pdf = new DompdfLib();
$pdf = $this->createExternalWriterInstance();
$pdf->setPaper(strtolower($paperSize), $orientation);
$pdf->loadHtml(str_replace(PHP_EOL, '', $this->getContent()));
$pdf->render();

View File

@ -44,6 +44,18 @@ class MPDF extends AbstractRenderer implements WriterInterface
parent::__construct($phpWord);
}
/**
* Gets the implementation of external PDF library that should be used.
*
* @return Mpdf implementation
*/
protected function createExternalWriterInstance()
{
$mPdfClass = $this->getMPdfClassName();
return new $mPdfClass();
}
/**
* Save PhpWord to file.
*
@ -58,8 +70,7 @@ class MPDF extends AbstractRenderer implements WriterInterface
$orientation = strtoupper('portrait');
// Create PDF
$mPdfClass = $this->getMPdfClassName();
$pdf = new $mPdfClass();
$pdf = $this->createExternalWriterInstance();
$pdf->_setPageSize($paperSize, $orientation);
$pdf->addPage($orientation);

View File

@ -36,6 +36,20 @@ class TCPDF extends AbstractRenderer implements WriterInterface
*/
protected $includeFile = 'tcpdf.php';
/**
* Gets the implementation of external PDF library that should be used.
*
* @param string $orientation Page orientation
* @param string $unit Unit measure
* @param string $paperSize Paper size
*
* @return \TCPDF implementation
*/
protected function createExternalWriterInstance($orientation, $unit, $paperSize)
{
return new \TCPDF($orientation, $unit, $paperSize);
}
/**
* Save PhpWord to file.
*
@ -50,7 +64,7 @@ class TCPDF extends AbstractRenderer implements WriterInterface
$orientation = 'P';
// Create PDF
$pdf = new \TCPDF($orientation, 'pt', $paperSize);
$pdf = $this->createExternalWriterInstance($orientation, 'pt', $paperSize);
$pdf->setFontSubsetting(false);
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);

View File

@ -17,10 +17,10 @@
namespace PhpOffice\PhpWord\Writer\RTF\Element;
use PhpOffice\Common\Text as CommonText;
use PhpOffice\PhpWord\Element\AbstractElement as Element;
use PhpOffice\PhpWord\Escaper\Rtf;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Shared\Text as SharedText;
use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Style\Font as FontStyle;
use PhpOffice\PhpWord\Style\Paragraph as ParagraphStyle;
@ -41,14 +41,14 @@ abstract class AbstractElement extends HTMLAbstractElement
*
* @var \PhpOffice\PhpWord\Style\Font
*/
private $fontStyle;
protected $fontStyle;
/**
* Paragraph style
*
* @var \PhpOffice\PhpWord\Style\Paragraph
*/
private $paragraphStyle;
protected $paragraphStyle;
public function __construct(AbstractWriter $parentWriter, Element $element, $withoutP = false)
{
@ -126,7 +126,7 @@ abstract class AbstractElement extends HTMLAbstractElement
return $this->escaper->escape($text);
}
return CommonText::toUnicode($text); // todo: replace with `return $text;` later.
return SharedText::toUnicode($text); // todo: replace with `return $text;` later.
}
/**

View File

@ -58,6 +58,7 @@ class Table extends AbstractElement
$content .= $this->writeRow($rows[$i]);
$content .= '\row' . PHP_EOL;
}
$content .= '\pard' . PHP_EOL;
}
return $content;

View File

@ -32,6 +32,7 @@ class TextRun extends AbstractElement
public function write()
{
$writer = new Container($this->parentWriter, $this->element);
$this->getStyles();
$content = '';
$content .= $this->writeOpening();

View File

@ -24,4 +24,69 @@ namespace PhpOffice\PhpWord\Writer\RTF\Element;
*/
class Title extends Text
{
protected function getStyles()
{
/** @var \PhpOffice\PhpWord\Element\Title $element Type hint */
$element = $this->element;
$style = $element->getStyle();
$style = str_replace('Heading', 'Heading_', $style);
$style = \PhpOffice\PhpWord\Style::getStyle($style);
if ($style instanceof \PhpOffice\PhpWord\Style\Font) {
$this->fontStyle = $style;
$pstyle = $style->getParagraph();
if ($pstyle instanceof \PhpOffice\PhpWord\Style\Paragraph && $pstyle->hasPageBreakBefore()) {
$sect = $element->getParent();
if ($sect instanceof \PhpOffice\PhpWord\Element\Section) {
$elems = $sect->getElements();
if ($elems[0] === $element) {
$pstyle = clone $pstyle;
$pstyle->setPageBreakBefore(false);
}
}
}
$this->paragraphStyle = $pstyle;
}
}
/**
* Write element
*
* @return string
*/
public function write()
{
/** @var \PhpOffice\PhpWord\Element\Title $element Type hint */
$element = $this->element;
$elementClass = str_replace('\\Writer\\RTF', '', get_class($this));
if (!$element instanceof $elementClass || !is_string($element->getText())) {
return '';
}
$this->getStyles();
$content = '';
$content .= $this->writeOpening();
$endout = '';
$style = $element->getStyle();
if (is_string($style)) {
$style = str_replace('Heading', '', $style);
if (is_numeric($style)) {
$style = (int) $style - 1;
if ($style >= 0 && $style <= 8) {
$content .= '{\\outlinelevel' . $style;
$endout = '}';
}
}
}
$content .= '{';
$content .= $this->writeFontStyle();
$content .= $this->writeText($element->getText());
$content .= '}';
$content .= $this->writeClosing();
$content .= $endout;
return $content;
}
}

View File

@ -17,6 +17,7 @@
namespace PhpOffice\PhpWord\Writer\RTF\Part;
use PhpOffice\PhpWord\Element\Footer;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Writer\RTF\Element\Container;
use PhpOffice\PhpWord\Writer\RTF\Style\Section as SectionStyleWriter;
@ -105,11 +106,36 @@ class Document extends AbstractPart
$content .= '\lang' . $langId;
$content .= '\kerning1'; // Point size (in half-points) above which to kern character pairs
$content .= '\fs' . (Settings::getDefaultFontSize() * 2); // Set the font size in half-points
if ($docSettings->hasEvenAndOddHeaders()) {
$content .= '\\facingp';
}
$content .= PHP_EOL;
return $content;
}
/**
* Write titlepg directive if any "f" headers or footers
*
* @param \PhpOffice\PhpWord\Element\Section $section
* @return string
*/
private static function writeTitlepg($section)
{
foreach ($section->getHeaders() as $header) {
if ($header->getType() === Footer::FIRST) {
return '\\titlepg' . PHP_EOL;
}
}
foreach ($section->getFooters() as $header) {
if ($header->getType() === Footer::FIRST) {
return '\\titlepg' . PHP_EOL;
}
}
return '';
}
/**
* Write sections
*
@ -120,10 +146,53 @@ class Document extends AbstractPart
$content = '';
$sections = $this->getParentWriter()->getPhpWord()->getSections();
$evenOdd = $this->getParentWriter()->getPhpWord()->getSettings()->hasEvenAndOddHeaders();
foreach ($sections as $section) {
$styleWriter = new SectionStyleWriter($section->getStyle());
$styleWriter->setParentWriter($this->getParentWriter());
$content .= $styleWriter->write();
$content .= self::writeTitlepg($section);
foreach ($section->getHeaders() as $header) {
$type = $header->getType();
if ($evenOdd || $type !== FOOTER::EVEN) {
$content .= '{\\header';
if ($type === Footer::FIRST) {
$content .= 'f';
} elseif ($evenOdd) {
$content .= ($type === FOOTER::EVEN) ? 'l' : 'r';
}
foreach ($header->getElements() as $element) {
$cl = get_class($element);
$cl2 = str_replace('Element', 'Writer\\RTF\\Element', $cl);
if (class_exists($cl2)) {
$elementWriter = new $cl2($this->getParentWriter(), $element);
$content .= $elementWriter->write();
}
}
$content .= '}' . PHP_EOL;
}
}
foreach ($section->getFooters() as $footer) {
$type = $footer->getType();
if ($evenOdd || $type !== FOOTER::EVEN) {
$content .= '{\\footer';
if ($type === Footer::FIRST) {
$content .= 'f';
} elseif ($evenOdd) {
$content .= ($type === FOOTER::EVEN) ? 'l' : 'r';
}
foreach ($footer->getElements() as $element) {
$cl = get_class($element);
$cl2 = str_replace('Element', 'Writer\\RTF\\Element', $cl);
if (class_exists($cl2)) {
$elementWriter = new $cl2($this->getParentWriter(), $element);
$content .= $elementWriter->write();
}
}
$content .= '}' . PHP_EOL;
}
}
$elementWriter = new Container($this->getParentWriter(), $section);
$content .= $elementWriter->write();

View File

@ -49,6 +49,7 @@ class Font extends AbstractStyle
}
$content = '';
$content .= $this->getValueIf($style->isRTL(), '\rtlch');
$content .= '\cf' . $this->colorIndex;
$content .= '\f' . $this->nameIndex;

View File

@ -67,6 +67,14 @@ class Paragraph extends AbstractStyle
$content .= $this->writeIndentation($style->getIndentation());
$content .= $this->getValueIf($spaceBefore !== null, '\sb' . round($spaceBefore));
$content .= $this->getValueIf($spaceAfter !== null, '\sa' . round($spaceAfter));
$lineHeight = $style->getLineHeight();
if ($lineHeight) {
$lineHeightAdjusted = (int) ($lineHeight * 240);
$content .= "\\sl$lineHeightAdjusted\\slmult1";
}
if ($style->hasPageBreakBefore()) {
$content .= '\\page';
}
$styles = $style->getStyleValues();
$content .= $this->writeTabs($styles['tabs']);

View File

@ -53,6 +53,7 @@ class Section extends AbstractStyle
$content .= $this->getValueIf($style->getHeaderHeight() !== null, '\headery' . round($style->getHeaderHeight()));
$content .= $this->getValueIf($style->getFooterHeight() !== null, '\footery' . round($style->getFooterHeight()));
$content .= $this->getValueIf($style->getGutter() !== null, '\guttersxn' . round($style->getGutter()));
$content .= $this->getValueIf($style->getPageNumberingStart() !== null, '\pgnstarts' . $style->getPageNumberingStart() . '\pgnrestart');
$content .= ' ';
// Borders

View File

@ -17,10 +17,10 @@
namespace PhpOffice\PhpWord\Writer\Word2007\Element;
use PhpOffice\Common\Text as CommonText;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Element\AbstractElement as Element;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Shared\Text as SharedText;
use PhpOffice\PhpWord\Shared\XMLWriter;
/**
* Abstract element writer
@ -32,7 +32,7 @@ abstract class AbstractElement
/**
* XML writer
*
* @var \PhpOffice\Common\XMLWriter
* @var \PhpOffice\PhpWord\Shared\XMLWriter
*/
private $xmlWriter;
@ -58,7 +58,7 @@ abstract class AbstractElement
/**
* Create new instance
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\AbstractElement $element
* @param bool $withoutP
*/
@ -72,7 +72,7 @@ abstract class AbstractElement
/**
* Get XML Writer
*
* @return \PhpOffice\Common\XMLWriter
* @return \PhpOffice\PhpWord\Shared\XMLWriter
*/
protected function getXmlWriter()
{
@ -207,7 +207,7 @@ abstract class AbstractElement
*/
protected function getText($text)
{
return CommonText::controlCharacterPHP2OOXML($text);
return SharedText::controlCharacterPHP2OOXML($text);
}
/**

View File

@ -17,10 +17,10 @@
namespace PhpOffice\PhpWord\Writer\Word2007\Element;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Element\AbstractContainer as ContainerElement;
use PhpOffice\PhpWord\Element\AbstractElement as Element;
use PhpOffice\PhpWord\Element\TextBreak as TextBreakElement;
use PhpOffice\PhpWord\Shared\XMLWriter;
/**
* Container element writer (section, textrun, header, footnote, cell, etc.)
@ -71,7 +71,7 @@ class Container extends AbstractElement
/**
* Write individual element
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\AbstractElement $element
* @param bool $withoutP
* @return string

View File

@ -65,6 +65,7 @@ class Field extends Text
$instruction .= $this->buildPropertiesAndOptions($element);
}
$xmlWriter->startElement('w:r');
$this->writeFontStyle();
$xmlWriter->startElement('w:instrText');
$xmlWriter->writeAttribute('xml:space', 'preserve');
$xmlWriter->text($instruction);

View File

@ -17,8 +17,8 @@
namespace PhpOffice\PhpWord\Writer\Word2007\Element;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Element\FormField as FormFieldElement;
use PhpOffice\PhpWord\Shared\XMLWriter;
/**
* FormField element writer
@ -105,7 +105,7 @@ class FormField extends Text
* Write textinput.
*
* @see http://www.datypic.com/sc/ooxml/t-w_CT_FFTextInput.html
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\FormField $element
*/
private function writeTextInput(XMLWriter $xmlWriter, FormFieldElement $element)
@ -121,7 +121,7 @@ class FormField extends Text
* Write checkbox.
*
* @see http://www.datypic.com/sc/ooxml/t-w_CT_FFCheckBox.html
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\FormField $element
*/
private function writeCheckBox(XMLWriter $xmlWriter, FormFieldElement $element)
@ -144,7 +144,7 @@ class FormField extends Text
* Write dropdown.
*
* @see http://www.datypic.com/sc/ooxml/t-w_CT_FFDDList.html
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\FormField $element
*/
private function writeDropDown(XMLWriter $xmlWriter, FormFieldElement $element)

View File

@ -17,8 +17,8 @@
namespace PhpOffice\PhpWord\Writer\Word2007\Element;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Element\Image as ImageElement;
use PhpOffice\PhpWord\Shared\XMLWriter;
use PhpOffice\PhpWord\Style\Font as FontStyle;
use PhpOffice\PhpWord\Style\Frame as FrameStyle;
use PhpOffice\PhpWord\Writer\Word2007\Style\Font as FontStyleWriter;

View File

@ -17,8 +17,8 @@
namespace PhpOffice\PhpWord\Writer\Word2007\Element;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Element\SDT as SDTElement;
use PhpOffice\PhpWord\Shared\XMLWriter;
/**
* Structured document tag element writer
@ -77,7 +77,7 @@ class SDT extends Text
* Write text.
*
* @see http://www.datypic.com/sc/ooxml/t-w_CT_SdtText.html
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
*/
private function writePlainText(XMLWriter $xmlWriter)
{
@ -89,7 +89,7 @@ class SDT extends Text
* Write combo box.
*
* @see http://www.datypic.com/sc/ooxml/t-w_CT_SdtComboBox.html
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\SDT $element
*/
private function writeComboBox(XMLWriter $xmlWriter, SDTElement $element)
@ -108,7 +108,7 @@ class SDT extends Text
* Write drop down list.
*
* @see http://www.datypic.com/sc/ooxml/t-w_CT_SdtDropDownList.html
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\SDT $element
*/
private function writeDropDownList(XMLWriter $xmlWriter, SDTElement $element)
@ -120,7 +120,7 @@ class SDT extends Text
* Write date.
*
* @see http://www.datypic.com/sc/ooxml/t-w_CT_SdtDate.html
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\SDT $element
*/
private function writeDate(XMLWriter $xmlWriter, SDTElement $element)

View File

@ -17,8 +17,8 @@
namespace PhpOffice\PhpWord\Writer\Word2007\Element;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Element\Shape as ShapeElement;
use PhpOffice\PhpWord\Shared\XMLWriter;
use PhpOffice\PhpWord\Style\Shape as ShapeStyle;
use PhpOffice\PhpWord\Writer\Word2007\Style\Shape as ShapeStyleWriter;
@ -77,7 +77,7 @@ class Shape extends AbstractElement
/**
* Write arc.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Style\Shape $style
*/
private function writeArc(XMLWriter $xmlWriter, ShapeStyle $style)
@ -91,7 +91,7 @@ class Shape extends AbstractElement
/**
* Write curve.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Style\Shape $style
*/
private function writeCurve(XMLWriter $xmlWriter, ShapeStyle $style)
@ -106,7 +106,7 @@ class Shape extends AbstractElement
/**
* Write line.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Style\Shape $style
*/
private function writeLine(XMLWriter $xmlWriter, ShapeStyle $style)
@ -120,7 +120,7 @@ class Shape extends AbstractElement
/**
* Write polyline.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Style\Shape $style
*/
private function writePolyline(XMLWriter $xmlWriter, ShapeStyle $style)
@ -131,7 +131,7 @@ class Shape extends AbstractElement
/**
* Write rectangle.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Style\Shape $style
*/
private function writeRoundRect(XMLWriter $xmlWriter, ShapeStyle $style)

View File

@ -17,8 +17,8 @@
namespace PhpOffice\PhpWord\Writer\Word2007\Element;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Element\TOC as TOCElement;
use PhpOffice\PhpWord\Shared\XMLWriter;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Writer\Word2007\Style\Font as FontStyleWriter;
use PhpOffice\PhpWord\Writer\Word2007\Style\Paragraph as ParagraphStyleWriter;
@ -64,7 +64,7 @@ class TOC extends AbstractElement
/**
* Write title
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\TOC $element
* @param \PhpOffice\PhpWord\Element\Title $title
* @param bool $writeFieldMark
@ -132,7 +132,7 @@ class TOC extends AbstractElement
/**
* Write style
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\TOC $element
* @param int $indent
*/
@ -178,7 +178,7 @@ class TOC extends AbstractElement
/**
* Write TOC Field.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\TOC $element
*/
private function writeFieldMark(XMLWriter $xmlWriter, TOCElement $element)

View File

@ -17,10 +17,10 @@
namespace PhpOffice\PhpWord\Writer\Word2007\Element;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Element\Cell as CellElement;
use PhpOffice\PhpWord\Element\Row as RowElement;
use PhpOffice\PhpWord\Element\Table as TableElement;
use PhpOffice\PhpWord\Shared\XMLWriter;
use PhpOffice\PhpWord\Style\Cell as CellStyle;
use PhpOffice\PhpWord\Style\Row as RowStyle;
use PhpOffice\PhpWord\Writer\Word2007\Style\Cell as CellStyleWriter;
@ -71,7 +71,7 @@ class Table extends AbstractElement
/**
* Write column.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\Table $element
*/
private function writeColumns(XMLWriter $xmlWriter, TableElement $element)
@ -93,7 +93,7 @@ class Table extends AbstractElement
/**
* Write row.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\Row $row
*/
private function writeRow(XMLWriter $xmlWriter, RowElement $row)
@ -119,7 +119,7 @@ class Table extends AbstractElement
/**
* Write cell.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\Cell $cell
*/
private function writeCell(XMLWriter $xmlWriter, CellElement $cell)

View File

@ -17,9 +17,9 @@
namespace PhpOffice\PhpWord\Writer\Word2007\Part;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Shared\XMLWriter;
use PhpOffice\PhpWord\Writer\AbstractWriter;
/**
@ -73,7 +73,7 @@ abstract class AbstractPart
/**
* Get XML Writer
*
* @return \PhpOffice\Common\XMLWriter
* @return \PhpOffice\PhpWord\Shared\XMLWriter
*/
protected function getXmlWriter()
{

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