This commit is contained in:
wangjinlei
2024-07-17 09:23:45 +08:00
parent edf9deeb1a
commit 881ac3e056
1001 changed files with 41032 additions and 5452 deletions

View File

@@ -1,38 +0,0 @@
---
name: Bug report
about: Create a report to help improve PHPWord
labels: Bug Report
---
### Describe the Bug
A clear and concise description of what the bug is.
### Steps to Reproduce
Please provide a code sample that reproduces the issue.
```php
<?php
require __DIR__ . '/vendor/autoload.php';
$phpWord = new \PhpOffice\PhpWord\PhpWord();
$section = $phpWord->addSection();
$section->...
```
### Expected Behavior
A clear and concise description of what you expected to happen.
### Current Behavior
What is the current behavior?
### Context
Please fill in your environment information:
- PHP Version:
- PHPWord Version:

View File

@@ -1,22 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
labels: Change Request
---
### Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
### Describe the solution you'd like
A clear and concise description of what you want to happen.
### Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
### Additional context
Add any other context or screenshots about the feature request here.

View File

@@ -1,14 +0,0 @@
---
name: How to Use PHPWord
about: Find out how to use PHPWord
labels: WontFix
---
***Please do not use the issue tracker to ask how to use PHPWord.***
Documentation is available on [Read the Docs](https://phpword.readthedocs.io/en/latest/).
Sample code is in the [`/samples/` directory](https://github.com/PHPOffice/PHPWord/tree/develop/samples).
Usage questions belong on [Stack Overflow](https://stackoverflow.com/questions/tagged/phpword).

View File

@@ -1,11 +0,0 @@
### Description
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context.
Fixes # (issue)
### Checklist:
- [ ] I have run `composer run-script check --timeout=0` and no errors were reported
- [ ] The new code is covered by unit tests (check build/coverage for coverage report)
- [ ] I have updated the documentation to describe the changes

View File

@@ -1,8 +0,0 @@
version: 2
updates:
- package-ecosystem: composer
directory: "/"
schedule:
interval: monthly
time: "11:00"
open-pull-requests-limit: 10

View File

@@ -1,15 +0,0 @@
# 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

View File

@@ -1,122 +0,0 @@
name: CI
on:
- push
- pull_request
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
php-version:
- "7.1"
- "7.2"
- "7.3"
- "7.4"
- "8.0"
- "8.1"
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: Install dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- 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 --no-coverage
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: Composer Install
run: composer global require friendsofphp/php-cs-fixer
- name: Add environment path
run: export PATH="$PATH:$HOME/.composer/vendor/bin"
- name: Code style with PHP-CS-Fixer
run: php-cs-fixer fix --dry-run --diff
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

View File

@@ -1,29 +0,0 @@
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

@@ -1,32 +0,0 @@
name: 'Close stale issues and PRs'
on:
schedule:
- cron: '30 1 * * *'
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v5
with:
days-before-stale: 90
days-before-close: 60
exempt-issue-labels: 'pinned,security'
exempt-pr-labels: 'pinned,security'
stale-issue-message: 'This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs.
If this is still an issue for you, please try to help by debugging it
further and sharing your results.
Thank you for your contributions.'
stale-pr-message: 'This PR has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs.
If this is still an issue for you, please try to complete the PR by adding tests and making sure that the CI is green.
Thank you for your contributions.'

View File

@@ -1,741 +0,0 @@
# Changelog
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [1.0.0](https://github.com/PHPOffice/PHPWord/tree/1.0.0) (2022-11-15)
[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.18.3...1.0.0)
### BREAKING CHANGE
Most deprecated things were dropped. See details in
https://github.com/PHPOffice/PHPWord/commit/b9f1151bc6f90c276153c3c9dca10a5fc7f355fb.
#### Dropped classes:
- `PhpOffice\PhpWord\Template`
#### Dropped constants:
- `PhpOffice\PhpWord\Style\Font::UNDERLINE_DOTHASH`
- `PhpOffice\PhpWord\Style\Font::UNDERLINE_DOTHASHHEAVY`
- `PhpOffice\PhpWord\Style\Cell::VALIGN_TOP`
- `PhpOffice\PhpWord\Style\Cell::VALIGN_CENTER`
- `PhpOffice\PhpWord\Style\Cell::VALIGN_BOTTOM`
- `PhpOffice\PhpWord\Style\Cell::VALIGN_BOTH`
- `PhpOffice\PhpWord\Style\TOC::TABLEADER_DOT`
- `PhpOffice\PhpWord\Style\TOC::TABLEADER_UNDERSCORE`
- `PhpOffice\PhpWord\Style\TOC::TABLEADER_LINE`
- `PhpOffice\PhpWord\Style\TOC::TABLEADER_NONE`
- `PhpOffice\PhpWord\Style\Table::WIDTH_AUTO`
- `PhpOffice\PhpWord\Style\Table::WIDTH_PERCENT`
- `PhpOffice\PhpWord\Style\Table::WIDTH_TWIP`
- `PhpOffice\PhpWord\PhpWord::DEFAULT_FONT_NAME`
- `PhpOffice\PhpWord\PhpWord::DEFAULT_FONT_SIZE`
- `PhpOffice\PhpWord\PhpWord::DEFAULT_FONT_COLOR`
- `PhpOffice\PhpWord\PhpWord::DEFAULT_FONT_CONTENT_TYPE`
-
#### Dropped methods:
- `PhpOffice\PhpWord\Ekement\AbstractContainer::createTextRun()`
- `PhpOffice\PhpWord\Ekement\AbstractContainer::createFootnote()`
- `PhpOffice\PhpWord\Ekement\Footnote::getReferenceId()`
- `PhpOffice\PhpWord\Ekement\Footnote::setReferenceId()`
- `PhpOffice\PhpWord\Ekement\Image::getIsWatermark()`
- `PhpOffice\PhpWord\Ekement\Image::getIsMemImage()`
- `PhpOffice\PhpWord\Ekement\Link::getTarget()`
- `PhpOffice\PhpWord\Ekement\Link::getLinkSrc()`
- `PhpOffice\PhpWord\Ekement\Link::getLinkName()`
- `PhpOffice\PhpWord\Ekement\OLEObject::getObjectId()`
- `PhpOffice\PhpWord\Ekement\OLEObject::setObjectId()`
- `PhpOffice\PhpWord\Ekement\Section::getFootnotePropoperties()`
- `PhpOffice\PhpWord\Ekement\Section::setSettings()`
- `PhpOffice\PhpWord\Ekement\Section::getSettings()`
- `PhpOffice\PhpWord\Ekement\Section::createHeader()`
- `PhpOffice\PhpWord\Ekement\Section::createFooter()`
- `PhpOffice\PhpWord\Ekement\Section::getFooter()`
- `PhpOffice\PhpWord\Media::addSectionMediaElement()`
- `PhpOffice\PhpWord\Media::addSectionLinkElement()`
- `PhpOffice\PhpWord\Media::getSectionMediaElements()`
- `PhpOffice\PhpWord\Media::countSectionMediaElements()`
- `PhpOffice\PhpWord\Media::addHeaderMediaElement()`
- `PhpOffice\PhpWord\Media::countHeaderMediaElements()`
- `PhpOffice\PhpWord\Media::getHeaderMediaElements()`
- `PhpOffice\PhpWord\Media::addFooterMediaElement()`
- `PhpOffice\PhpWord\Media::countFooterMediaElements()`
- `PhpOffice\PhpWord\Media::getFooterMediaElements()`
- `PhpOffice\PhpWord\PhpWord::getProtection()`
- `PhpOffice\PhpWord\PhpWord::loadTemplate()`
- `PhpOffice\PhpWord\PhpWord::createSection()`
- `PhpOffice\PhpWord\PhpWord::getDocumentProperties()`
- `PhpOffice\PhpWord\PhpWord::setDocumentProperties()`
- `PhpOffice\PhpWord\Reader\AbstractReader::getReadDataOnly()`
- `PhpOffice\PhpWord\Settings::getCompatibility()`
- `PhpOffice\PhpWord\Style\AbstractStyle::setArrayStyle()`
- `PhpOffice\PhpWord\Style\Cell::getDefaultBorderColor()`
- `PhpOffice\PhpWord\Style\Font::getBold()`
- `PhpOffice\PhpWord\Style\Font::getItalic()`
- `PhpOffice\PhpWord\Style\Font::getSuperScript()`
- `PhpOffice\PhpWord\Style\Font::getSubScript()`
- `PhpOffice\PhpWord\Style\Font::getStrikethrough()`
- `PhpOffice\PhpWord\Style\Font::getParagraphStyle()`
- `PhpOffice\PhpWord\Style\Frame::getAlign()`
- `PhpOffice\PhpWord\Style\Frame::setAlign()`
- `PhpOffice\PhpWord\Style\NumberingLevel::getAlign()`
- `PhpOffice\PhpWord\Style\NumberingLevel::setAlign()`
- `PhpOffice\PhpWord\Style\Paragraph::getAlign()`
- `PhpOffice\PhpWord\Style\Paragraph::setAlign()`
- `PhpOffice\PhpWord\Style\Paragraph::getWidowControl()`
- `PhpOffice\PhpWord\Style\Paragraph::getKeepNext()`
- `PhpOffice\PhpWord\Style\Paragraph::getKeepLines()`
- `PhpOffice\PhpWord\Style\Paragraph::getPageBreakBefore()`
- `PhpOffice\PhpWord\Style\Row::getTblHeader()`
- `PhpOffice\PhpWord\Style\Row::isTblHeader()`
- `PhpOffice\PhpWord\Style\Row::getCantSplit()`
- `PhpOffice\PhpWord\Style\Row::getExactHeight()`
- `PhpOffice\PhpWord\Style\Spacing::getRule()`
- `PhpOffice\PhpWord\Style\Spacing::setRule()`
- `PhpOffice\PhpWord\Style\Table::getAlign()`
- `PhpOffice\PhpWord\Style\Table::setAlign()`
- `PhpOffice\PhpWord\Writer\AbstractWriter::getUseDiskCaching()`
- `PhpOffice\PhpWord\Writer\HTML::writeDocument()`
### Bug fixes
- Multiple PHP 8.1 fixes
- `loadConfig` returns config that was actually applied
- HTML Reader : Override inline style on HTML attribute for table
- HTML Reader : Use `border` attribute for tables
- HTML Reader : Style page-break-after in paragraph
- HTML Reader : Heading in Text Run is not allowed
-
### Miscellaneous
- Drop support for PHP 7.0 and older
## [0.18.3](https://github.com/PHPOffice/PHPWord/tree/0.18.3) (2022-02-17)
[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.18.2...0.18.3)
### Bug fixes
- PHP 8.1 compatibility
## [0.18.2](https://github.com/PHPOffice/PHPWord/tree/0.18.2) (2021-06-04)
[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.18.1...0.18.2)
### Bug fixes
- when adding image to relationship first check that the generated RID is actually unique [\#2063](https://github.com/PHPOffice/PHPWord/pull/2063) ([tpv-ebben](https://github.com/tpv-ebben))
- Update chart, don't write 'c:overlap' if grouping is 'clustered' [\#2052](https://github.com/PHPOffice/PHPWord/pull/2052) ([dfsd534](https://github.com/dfsd534))
- Update Html parser to accept line-height:normal [\#2041](https://github.com/PHPOffice/PHPWord/pull/2041) ([joelgo](https://github.com/joelgo))
- Fix image border in Word2007 Writer for LibreOffice 7 [\#2021](https://github.com/PHPOffice/PHPWord/pull/2021) ([kamilmmach](https://github.com/kamilmmach))
### Miscellaneous
- Corrected namespace for Language class in docs. [\#2087](https://github.com/PHPOffice/PHPWord/pull/2087) ([MegaChriz](https://github.com/MegaChriz))
- Added support for Garamond font [\#2078](https://github.com/PHPOffice/PHPWord/pull/2078) ([artemkolotilkin](https://github.com/artemkolotilkin))
- Add BorderStyle for Cell Style to documentation [\#2090](https://github.com/PHPOffice/PHPWord/pull/2090) ([DShkrabak](https://github.com/DShkrabak))
## [0.18.1](https://github.com/PHPOffice/PHPWord/tree/0.18.1) (2021-03-08)
[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/0.18.0...0.18.1)
### Bug fixes
- Fix BC break in #1946. This package does not replace laminas/laminas-zendframework-bridge [\#2032](https://github.com/PHPOffice/PHPWord/pull/2032) ([mussbach](https://github.com/mussbach))
## [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
- Add methods setValuesFromArray and cloneRowFromArray to the TemplateProcessor @geraldb-nicat #670
- Set complex type in template @troosan #1565
- implement support for section vAlign @troosan #1569
- ParseStyle for border-color @Gllrm0 #1551
- Html writer auto invert text color @SailorMax #1387
- Add RightToLeft table presentation. @troosan #1550
- Add support for page vertical alignment. @troosan #672 #1569
- Adding setNumId method for ListItem style @eweso #1329
- Add support for basic fields in RTF writer. @Samuel-BF #1717
### Fixed
- Fix HTML border-color parsing. @troosan #1551 #1570
- Language::validateLocale should pass with locale 'zxx'. @efpapado #1558
- can't align center vertically with the text @ter987 #672
- fix parsing of border-color and add test @troosan #1570
- TrackChange doesn't handle all return types of \DateTime::createFromFormat(...) @superhaggis #1584
- To support PreserveText inside sub container @bhattnishant #1637
- No nested w:pPr elements in ListItemRun. @waltertamboer #1628
- Ensure that entity_loader disable variable is re-set back to the original setting @seamuslee001 #1585
### Miscellaneous
- Use embedded http server to test loading of remote images @troosan #1544
- Change private to protected to be able extending class Html @SpinyMan #1646
- Fix apt-get crash in Travis CI for PHP 5.3 @mdupont #1707
v0.16.0 (30 dec 2018)
----------------------
### Added
- Add getVariableCount method in TemplateProcessor. @nicoder #1272
- Add setting Chart Title and Legend visibility @Tom-Magill #1433
- Add ability to pass a Style object in Section constructor @ndench #1416
- Add support for hidden text @Alexmg86 #1527
- Add support for setting images in TemplateProcessor @SailorMax #1170
- Add "Plain Text" type to SDT (Structured Document Tags) @morrisdj #1541
- Added possibility to index variables inside cloned block in TemplateProcessor @JPBetley #817
- Added possibility to replace variables inside cloned block with values in TemplateProcessor @DIDoS #1392
### Fixed
- Fix regex in `cloneBlock` function @nicoder #1269
- HTML Title Writer loses text when Title contains a TextRun instead a string. @begnini #1436
- Fix regex in fixBrokenMacros, make it less greedy @MuriloSo @brainwood @yurii-sio2 #1502 #1345
- 240 twips are being added to line spacing, should not happen when using lineRule fixed @troosan #1509 #1505
- Adding table layout to the generated HTML @aarangara #1441
- Fix loading of Sharepoint document @Garrcomm #1498
- RTF writer: Round getPageSizeW and getPageSizeH to avoid decimals @Patrick64 #1493
- Fix parsing of Office 365 documents @Timanx #1485
- For RTF writers, sizes should should never have decimals @Samuel-BF #1536
- Style Name Parsing fails if document generated by a non-english word version @begnini #1434
### Miscellaneous
- Get rid of duplicated code in TemplateProcessor @abcdmitry #1161
v0.15.0 (14 Jul 2018)
----------------------
### Added
- Parsing of `align` HTML attribute - @troosan #1231
- Parse formatting inside HTML lists - @troosan @samimussbach #1239 #945 #1215 #508
- Parsing of CSS `direction` instruction, HTML `lang` attribute, formatting inside table cell - @troosan #1273 #1252 #1254
- Add support for Track changes @Cip @troosan #354 #1262
- Add support for fixed Table Layout @aoloe @ekopach @troosan #841 #1276
- Add support for Cell Spacing @dox07 @troosan #1040
- Add parsing of formatting inside lists @atomicalnet @troosan #594
- Added support for Vertically Raised or Lowered Text (w:position) @anrikun @troosan #640
- Add support for MACROBUTTON field @phryneas @troosan #1021
- Add support for Hyphenation @Trainmaster #1282 (Document: `autoHyphenation`, `consecutiveHyphenLimit`, `hyphenationZone`, `doNotHyphenateCaps`, Paragraph: `suppressAutoHyphens`)
- Added support for Floating Table Positioning (tblpPr) @anrikun #639
- Added support for Image text wrapping distance @troosan #1310
- Added parsing of CSS line-height and text-indent in HTML reader @troosan #1316
- Added the ability to enable gridlines and axislabels on charts @FrankMeyer #576
- Add support for table indent (tblInd) @Trainmaster #1343
- Added parsing of internal links in HTML reader @lalop #1336
- Several improvements to charts @JAEK-S #1332
- Add parsing of html image in base64 format @jgpATs2w #1382
- Added Support for Indentation & Tabs on RTF Writer. @smaug1985 #1405
- Allows decimal numbers in HTML line-height style @jgpATs2w #1413
### Fixed
- Fix reading of docx default style - @troosan #1238
- Fix the size unit of when parsing html images - @troosan #1254
- Fixed HTML parsing of nested lists - @troosan #1265
- Save PNG alpha information when using remote images. @samsullivan #779
- Fix parsing of `<w:br/>` tag. @troosan #1274
- Bookmark are not writton as internal link in html writer @troosan #1263
- It should be possible to add a Footnote in a ListItemRun @troosan #1287 #1287
- Fix colspan and rowspan for tables in HTML Writer @mattbolt #1292
- Fix parsing of Heading and Title formating @troosan @gthomas2 #465
- Fix Dateformat typo, fix hours casing, add Month-Day-Year formats @ComputerTinker #591
- Support reading of w:drawing for documents produced by word 2011+ @gthomas2 #464 #1324
- Fix missing column width in ODText writer @potofcoffee #413
- Disable entity loader before parsing XML to avoid XXE injection @Tom4t0 #1427
### Changed
- Remove zend-stdlib dependency @Trainmaster #1284
- The default unit for `\PhpOffice\PhpWord\Style\Image` changed from `px` to `pt`.
### Miscellaneous
- Drop GitHub pages, switch to coveralls for code coverage analysis @czosel #1360
v0.14.0 (29 Dec 2017)
----------------------
This release fixes several bugs and adds some new features.
This version brings compatibility with PHP 7.0 & 7.1
### Added
- Possibility to control the footnote numbering - @troosan #1068
- Image creation from string - @troosan #937
- Introduced the `\PhpOffice\PhpWord\SimpleType\NumberFormat` simple type. - @troosan
- Support for ContextualSpacing - @postHawk #1088
- Possiblity to hide spelling and/or grammatical errors - @troosan #542
- Possiblity to set default document language as well as changing the language for each text element - @troosan #1108
- Support for Comments - @troosan #1067
- Support for paragraph textAlignment - @troosan #1165
- Add support for HTML underline tag <u> in addHtml - @zNightFalLz #1186
- Add support for HTML <br> in addHtml - @anrikun @troosan #659
- Allow to change cell width unit - guillaume-ro-fr #986
- Allow to change the line height rule @troosan
- Implement PageBreak for odt writer @cookiekiller #863 #824
- Allow to force an update of all fields on opening a document - @troosan #951
- Allow adding a CheckBox in a TextRun - @irond #727
- Add support for HTML img tag - @srggroup #934
- Add support for password protection for docx - @mariahaubner #1019
### Fixed
- Loosen dependency to Zend
- Images are not being printed when generating PDF - @hubertinio #1074 #431
- Fixed some PHP 7 warnings - @ likeuntomurphy #927
- Fixed PHP 7.2 compatibility (renamed `Object` class names to `ObjectElement`) - @SailorMax #1185
- Fixed Word 97 reader - @alsofronie @Benpxpx @mario-rivera #912 #920 #892
- Fixed image loading over https - @troosan #988
- Impossibility to set different even and odd page headers - @troosan #981
- Fixed Word2007 reader where unnecessary paragraphs were being created - @donghaobo #1043 #620
- Fixed Word2007 reader where margins were not being read correctly - @slowprog #885 #1008
- Impossible to add element PreserveText in Section - @rvanlaak #452
- Added missing options for numbering format - @troosan #1041
- Fixed impossibility to set a different footer for first page - @ctrlaltca #1116, @aoloe #875
- Fixed styles not being applied by HTML writer, better pdf output - @sarke #1047 #500 #1139
- Fixed read docx error when document contains image from remote url - @FBnil #1173 #1176
- Padded the $args array to remove error - @kaigoh #1150, @reformed #870
- Fix incorrect image size between windows and mac - @bskrtich #874
- Fix adding HTML table to document - @mogilvie @arivanbastos #324
- Fix parsing on/off values (w:val="true|false|1|0|on|off") - @troosan #1221 #1219
- Fix error on Empty Dropdown Entry - @ComputerTinker #592
### Deprecated
- PhpWord->getProtection(), get it from the settings instead PhpWord->getSettings()->getDocumentProtection();
v0.13.0 (31 July 2016)
-------------------
This release brings several improvements in `TemplateProcessor`, automatic output escaping feature for OOXML, ODF, HTML, and RTF (turned off, by default).
It also introduces constants for horizontal alignment options, and resolves some issues with PHP 7.
Manual installation feature has been dropped since the release. Please, use [Composer](https://getcomposer.org/) to install PHPWord.
### Added
- Introduced the `\PhpOffice\PhpWord\SimpleType\Jc` simple type. - @RomanSyroeshko
- Introduced the `\PhpOffice\PhpWord\SimpleType\JcTable` simple type. - @RomanSyroeshko
- Introduced writer for the "Paragraph Alignment" element (see `\PhpOffice\PhpWord\Writer\Word2007\Element\ParagraphAlignment`). - @RomanSyroeshko
- Introduced writer for the "Table Alignment" element (see `\PhpOffice\PhpWord\Writer\Word2007\Element\TableAlignment`). - @RomanSyroeshko
- Supported indexed arrays in arguments of `TemplateProcessor::setValue()`. - @RomanSyroeshko #618
- Introduced automatic output escaping for OOXML, ODF, HTML, and RTF. To turn the feature on use `phpword.ini` or `\PhpOffice\PhpWord\Settings`. - @RomanSyroeshko #483
- Supported processing of headers and footers in `TemplateProcessor::applyXslStyleSheet()`. - @RomanSyroeshko #335
### Changed
- Improved error message for the case when `autoload.php` is not found. - @RomanSyroeshko #371
- Renamed the `align` option of `NumberingLevel`, `Frame`, `Table`, and `Paragraph` styles into `alignment`. - @RomanSyroeshko
- Improved performance of `TemplateProcessor::setValue()`. - @kazitanvirahsan #614, #617
- Fixed some HTML tags not rendering any output (p, header & table) - #257, #324 - @twmobius and @garethellis
### Deprecated
- `getAlign` and `setAlign` methods of `NumberingLevel`, `Frame`, `Table`, and `Paragraph` styles.
Use the correspondent `getAlignment` and `setAlignment` methods instead. - @RomanSyroeshko
- `left`, `right`, and `justify` alignment options for paragraphs (now are mapped to `Jc::START`, `Jc::END`, and `Jc::BOTH`). - @RomanSyroeshko
- `left`, `right`, and `justify` alignment options for tables (now are mapped to `Jc::START`, `Jc::END`, and `Jc::CENTER`). - @RomanSyroeshko
- `TCPDF` due to its limited HTML support. Use `DomPDF` or `MPDF` writer instead. - @RomanSyroeshko #399
### Removed
- `\PhpOffice\PhpWord\Style\Alignment`. Style properties, which previously stored instances of this class, now deal with strings.
In each case set of available string values is defined by the correspondent simple type. - @RomanSyroeshko
- Manual installation support. Since the release we have dependencies on third party libraries,
so installation via ZIP-archive download is not an option anymore. To install PHPWord use [Composer](https://getcomposer.org/).
We also removed `\PhpOffice\PhpWord\Autoloader`, because the latter change made it completely useless.
Autoloaders provided by Composer are in use now (see `bootstrap.php`). - @RomanSyroeshko
- `\PhpOffice\PhpWord\Shared\Drawing` replaced by `\PhpOffice\Common\Drawing`. - @Progi1984 #658
- `\PhpOffice\PhpWord\Shared\Font`. - @Progi1984 #658
- `\PhpOffice\PhpWord\Shared\String` replaced by `\PhpOffice\Common\Text`. - @Progi1984 @RomanSyroeshko #658
- `\PhpOffice\PhpWord\Shared\XMLReader` replaced by `\PhpOffice\Common\XMLReader`. - @Progi1984 #658
- `\PhpOffice\PhpWord\Shared\XMLWriter` replaced by `\PhpOffice\Common\XMLWriter`. - @Progi1984 @RomanSyroeshko #658
- `AbstractContainer::addMemoryImage()`. Use `AbstractContainer::addImage()` instead.
### Fixed
- `Undefined property` error while reading MS-DOC documents. - @jaberu #610
- Corrupted OOXML template issue in case when its names is broken immediately after `$` sign.
That case wasn't taken into account in implementation of `TemplateProcessor::fixBrokenMacros()`. - @RomanSyroeshko @d-damien #548
v0.12.1 (30 August 2015)
-----------------------
Maintenance release. This release is focused primarily on `TemplateProcessor`.
### Changes
- Changed visibility of all private properties and methods of `TemplateProcessor` to `protected`. - @RomanSyroeshko #498
- Improved performance of `TemplateProcessor::setValue()`. - @RomanSyroeshko @nicoSWD #513
### Bugfixes
- Fixed issue with "Access denied" message while opening `Sample_07_TemplateCloneRow.docx` and `Sample_23_TemplateBlock.docx` result files on Windows platform. - @RomanSyroeshko @AshSat #532
- Fixed `PreserveText` element alignment in footer (see `Sample_12_HeaderFooter.php`). - @RomanSyroeshko @SSchwaiger #495
v0.12.0 (3 January 2015)
-----------------------
This release added form fields (textinput, checkbox, and dropdown), drawing shapes (arc, curve, line, polyline, rect, oval), and basic 2D chart (pie, doughnut, bar, line, area, scatter, radar) elements along with some new styles. Basic MsDoc reader is introduced.
### Features
- Element: Ability to add drawing shapes (arc, curve, line, polyline, rect, oval) using new `Shape` element - @ivanlanin #123
- Font: New `scale`, `spacing`, and `kerning` property of font style - @ivanlanin
- Paragraph: Added shading to the paragraph style for full width shading - @lrobert #264
- RTF Writer: Support for sections, margins, and borders - @ivanlanin #249
- Section: Ability to set paper size, e.g. A4, A3, and Legal - @ivanlanin #249
- General: New `PhpWord::save()` method to encapsulate `IOFactory` - @ivanlanin
- General: New `Shared\Converter` static class - @ivanlanin
- Chart: Basic 2D chart (pie, doughnut, bar, line, area, scatter, radar) - @ivanlanin #278
- Chart: 3D charts and ability to set width and height - @ivanlanin
- FormField: Ability to add textinput, checkbox, and dropdown form elements - @ivanlanin #266
- Setting: Ability to define document protection (readOnly, comments, trackedChanges, forms) - @ivanlanin
- Setting: Ability to remove [Compatibility Mode] text in the MS Word title bar - @ivanlanin
- SDT: Ability to add structured document tag elements (comboBox, dropDownList, date) - @ivanlanin
- Paragraph: Support for paragraph with borders - @ivanlanin #294
- Word2007 Writer : Support for RTL - @Progi1984 #331
- MsDOC Reader: Basic MsDOC Reader - @Progi1984 #23, #287
- "absolute" horizontal and vertical positioning of Frame - @basjan #302
- Add new-page function for PDF generation. For multiple PDF-backends - @chc88 #426
- Report style options enumerated when style unknown - @h6w
### Bugfixes
- Fix rare PclZip/realpath/PHP version problem - @andrew-kzoo #261
- `addHTML` encoding and ampersand fixes for PHP 5.3 - @bskrtich #270
- Page breaks on titles and tables - @ivanlanin #274
- Table inside vertical border does not rendered properly - @ivanlanin #280
- `add<elementName>` of container should be case insensitive, e.g. `addToc` should be accepted, not only `addTOC` - @ivanlanin #294
- Fix specific borders (and margins) were not written correctly in word2007 writer - @pscheit #327
- "HTML is not a valid writer" exception while running "Sample_36_RTL.php" - @RomanSyroeshko #340
- "addShape()" magic method in AbstractContainer is mistakenly named as "addObject()" - @GMTA #356
- `Element\Section::setPageSizeW()` and `Element\Section::setPageSizeH()` were mentioned in the docs but not implemented.
- Special Characters (ampersand) in Title break docx output - @RomanSyroeshko #401
- `<th>` tag is closed with `</td>` tag: - @franzholz #438
### Deprecated
- `Element\Link::getTarget()` replaced by `Element\Link::getSource()`
- `Element\Section::getSettings()` and `Element\Section::setSettings()` replaced by `Element\Section::getStyle()` and `Element\Section::setStyle()`
- `Shared\Drawing` and `Shared\Font` merged into `Shared\Converter`
- `DocumentProperties` replaced by `Metadata\DocInfo`
- `Template` replaced by `TemplateProcessor`
- `PhpWord->loadTemplate($filename)`
### Miscellaneous
- Docs: Add known issue on `README` about requirement for temporary folder to be writable and update `samples/index.php` for this requirement check - @ivanlanin #238
- Docs: Correct elements.rst about Line - @chrissharkman #292
- PclZip: Remove temporary file after used - @andrew-kzoo #265
- Autoloader: Add the ability to set the autoloader options - @bskrtich #267
- Element: Refactor elements to move set relation Id from container to element - @ivanlanin
- Introduced CreateTemporaryFileException, CopyFileException - @RomanSyroeshko
- Settings: added method to set user defined temporary directory - @RomanSyroeshko #310
- Renamed `Template` into `TemplateProcessor` - @RomanSyroeshko #216
- Reverted #51. All text escaping must be performed out of the library - @RomanSyroeshko #51
v0.11.1 (2 June 2014)
--------------------
This is an immediate bugfix release for HTML reader.
- HTML Reader: `<p>` and header tags puts no output - @canyildiz @ivanlanin #257
v0.11.0 (1 June 2014)
--------------------
This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3. Four new elements were added: TextBox, ListItemRun, Field, and Line. Relative and absolute positioning for images and textboxes were added. Writer classes were refactored into parts, elements, and styles. ODT and RTF features were enhanced. Ability to add elements to PHPWord object via HTML were implemented. RTF and HTML reader were initiated.
### Features
- Image: Ability to define relative and absolute positioning - @basjan #217
- Footer: Conform footer with header by adding firstPage, evenPage and by inheritance - @basjan @ivanlanin #219
- Element: New `TextBox` element - @basjan @ivanlanin #228, #229, #231
- HTML: Ability to add elements to PHPWord object via html - @basjan #231
- Element: New `ListItemRun` element that can add a list item with inline formatting like a textrun - @basjan #235
- Table: Ability to add table inside a cell (nested table) - @ivanlanin #149
- RTF Writer: UTF8 support for RTF: Internal UTF8 text is converted to Unicode before writing - @ivanlanin #158
- Table: Ability to define table width (in percent and twip) and position - @ivanlanin #237
- RTF Writer: Ability to add links and page breaks in RTF - @ivanlanin #196
- ListItemRun: Remove fontStyle parameter because ListItemRun is inherited from TextRun and TextRun doesn't have fontStyle - @ivanlanin
- Config: Ability to use a config file to store various common settings - @ivanlanin #200
- ODT Writer: Enable inline font style in TextRun - @ivanlanin
- ODT Writer: Enable underline, strike/doublestrike, smallcaps/allcaps, superscript/subscript font style - @ivanlanin
- ODT Writer: Enable section and column - @ivanlanin
- PDF Writer: Add TCPDF and mPDF as optional PDF renderer library - @ivanlanin
- ODT Writer: Enable title element and custom document properties - @ivanlanin
- ODT Reader: Ability to read standard and custom document properties - @ivanlanin
- Word2007 Writer: Enable the missing custom document properties writer - @ivanlanin
- Image: Enable "image float left" - @ivanlanin #244
- RTF Writer: Ability to write document properties - @ivanlanin
- RTF Writer: Ability to write image - @ivanlanin
- Element: New `Field` element - @basjan #251
- RTF Reader: Basic RTF reader - @ivanlanin #72, #252
- Element: New `Line` element - @basjan #253
- Title: Ability to apply numbering in heading - @ivanlanin #193
- HTML Reader: Basic HTML reader - @ivanlanin #80, #254
- RTF Writer: Basic table writing - @ivanlanin #245
### Bugfixes
- Header: All images added to the second header were assigned to the first header - @basjan #222
- Conversion: Fix conversion from cm to pixel, pixel to cm, and pixel to point - @basjan #233, #234
- PageBreak: Page break adds new line in the beginning of the new page - @ivanlanin #150
- Image: `marginLeft` and `marginTop` cannot accept float value - @ivanlanin #248
- Title: Orphan `w:fldChar` caused OpenOffice to crash when opening DOCX - @ivanlanin #236
### Deprecated
- Static classes `Footnotes`, `Endnotes`, and `TOC`
- `Writer\Word2007\Part`: `Numbering::writeNumbering()`, `Settings::writeSettings()`, `WebSettings::writeWebSettings()`, `ContentTypes::writeContentTypes()`, `Styles::writeStyles()`, `Document::writeDocument()` all changed into `write()`
- `Writer\Word2007\Part\DocProps`: Split into `Writer\Word2007\Part\DocPropsCore` and `Writer\Word2007\Part\DocPropsApp`
- `Element\Title::getBookmarkId()` replaced by `Element\Title::getRelationId()`
- `Writer\HTML::writeDocument`: Replaced by `Writer\HTML::getContent`
### Miscellaneous
- License: Change the project license from LGPL 2.1 into LGPL 3.0 - #211
- Word2007 Writer: New `Style\Image` class - @ivanlanin
- Refactor: Replace static classes `Footnotes`, `Endnotes`, and `TOC` with `Collections` - @ivanlanin #206
- QA: Reactivate `phpcpd` and `phpmd` on Travis - @ivanlanin
- Refactor: PHPMD recommendation: Change all `get...` method that returns `boolean` into `is...` or `has...` - @ivanlanin
- Docs: Create gh-pages branch for API documentation - @Progi1984 #154
- QA: Add `.scrutinizer.yml` and include `composer.lock` for preparation to Scrutinizer - @ivanlanin #186
- Writer: Refactor writer parts using composite pattern - @ivanlanin
- Docs: Show code quality and test code coverage badge on README
- Style: Change behaviour of `set...` function of boolean properties; when none is defined, assumed true - @ivanlanin
- Shared: Unify PHP ZipArchive and PCLZip features into PhpWord ZipArchive - @ivanlanin
- Docs: Create VERSION file - @ivanlanin
- QA: Improve dan update requirement check in `samples` folder - @ivanlanin
v0.10.1 (21 May 2014)
--------------------
This is a bugfix release for `php-zip` requirement in Composer.
- Change Composer requirements for php-zip from `require` to `suggest` - @bskrtich #246
v0.10.0 (4 May 2014)
-------------------
This release marked heavy refactorings on internal code structure with the creation of some abstract classes to reduce code duplication. `Element` subnamespace is introduced in this release to replace `Section`. Word2007 reader capability is greatly enhanced. Endnote is introduced. List numbering is now customizable. Basic HTML and PDF writing support is enabled. Basic ODText reader is introduced.
### Features
- Image: Get image dimensions without EXIF extension - @andrew-kzoo #184
- Table: Add `tblGrid` element for Libre/Open Office table sizing - @gianis6 #183
- Footnote: Ability to insert textbreak in footnote `$footnote->addTextBreak()` - @ivanlanin
- Footnote: Ability to style footnote reference mark by using `FootnoteReference` style - @ivanlanin
- Font: Add `bgColor` to font style to define background using HEX color - @jcarignan #168
- Table: Add `exactHeight` to row style to define whether row height should be exact or atLeast - @jcarignan #168
- Element: New `CheckBox` element for sections and table cells - @ozilion #156
- Settings: Ability to use PCLZip as alternative to ZipArchive - @bskrtich @ivanlanin #106, #140, #185
- Template: Ability to find & replace variables in headers & footers - @dgudgeon #190
- Template: Ability to clone & delete block of text using `cloneBlock` and `deleteBlock` - @diego-vieira #191
- TOC: Ability to have two or more TOC in one document and to set min and max depth for TOC - @Pyreweb #189
- Table: Ability to add footnote in table cell - @ivanlanin #187
- Footnote: Ability to add image in footnote - @ivanlanin #187
- ListItem: Ability to add list item in header/footer - @ivanlanin #187
- CheckBox: Ability to add checkbox in header/footer - @ivanlanin #187
- Link: Ability to add link in header/footer - @ivanlanin #187
- Object: Ability to add object in header, footer, textrun, and footnote - @ivanlanin #187
- Media: Add `Media::resetElements()` to reset all media data - @juzi #19
- General: Add `Style::resetStyles()` - @ivanlanin #187
- DOCX Reader: Ability to read header, footer, footnotes, link, preservetext, textbreak, pagebreak, table, list, image, and title - @ivanlanin
- Endnote: Ability to add endnotes - @ivanlanin
- ListItem: Ability to create custom list and reset list number - @ivanlanin #10, #198
- ODT Writer: Basic table writing support - @ivanlanin
- Image: Keep image aspect ratio if only 1 dimension styled - @japonicus #194
- HTML Writer: Basic HTML writer: text, textrun, link, title, textbreak, table, image (as Base64), footnote, endnote - @ivanlanin #203, #67, #147
- PDF Writer: Basic PDF writer using DomPDF: All HTML element except image - @ivanlanin #68
- DOCX Writer: Change `docProps/app.xml` `Application` to `PHPWord` - @ivanlanin
- DOCX Writer: Create `word/settings.xml` and `word/webSettings.xml` dynamically - @ivanlanin
- ODT Writer: Basic image writing - @ivanlanin
- ODT Writer: Link writing - @ivanlanin
- ODT Reader: Basic ODText Reader - @ivanlanin #71
- Section: Ability to define gutter and line numbering - @ivanlanin
- Font: Small caps, all caps, and double strikethrough - @ivanlanin #151
- Settings: Ability to use measurement unit other than twips with `setMeasurementUnit` - @ivanlanin #199
- Style: Remove `bgColor` from `Font`, `Table`, and `Cell` and put it into the new `Shading` style - @ivanlanin
- Style: New `Indentation` and `Spacing` style - @ivanlanin
- Paragraph: Ability to define first line and right indentation - @ivanlanin
### Bugfixes
- Footnote: Footnote content doesn't show footnote reference number - @ivanlanin #170
- Documentation: Error in a function - @theBeerNut #195
### Deprecated
- `createTextRun` replaced by `addTextRun`
- `createFootnote` replaced by `addFootnote`
- `createHeader` replaced by `addHeader`
- `createFooter` replaced by `addFooter`
- `createSection` replaced by `addSection`
- `Element\Footnote::getReferenceId` replaced by `Element\AbstractElement::getRelationId`
- `Element\Footnote::setReferenceId` replaced by `Element\AbstractElement::setRelationId`
- `Footnote::addFootnoteLinkElement` replaced by `Media::addElement`
- `Footnote::getFootnoteLinkElements` replaced by `Media::getElements`
- All current methods on `Media`
- `Element\Link::getLinkSrc` replaced by `Element\Link::getTarget`
- `Element\Link::getLinkName` replaced by `Element\Link::getText`
- `Style\Cell::getDefaultBorderColor`
### Miscellaneous
- Documentation: Simplify page level docblock - @ivanlanin #179
- Writer: Refactor writer classes and create a new `Write\AbstractWriter` abstract class - @ivanlanin #160
- General: Refactor folders: `Element` and `Exception` - @ivanlanin #187
- General: Remove legacy `HashTable` and `Shared\ZipStreamWrapper` and all related properties/methods - @ivanlanin #187
- Element: New `AbstractElement` abstract class - @ivanlanin #187
- Media: Refactor media class to use one method for all docPart (section, header, footer, footnote) - @ivanlanin #187
- General: Remove underscore prefix from all private properties name - @ivanlanin #187
- General: Move Section `Settings` to `Style\Section` - @ivanlanin #187
- General: Give `Abstract` prefix and `Interface` suffix for all abstract classes and interfaces as per [PHP-FIG recommendation](https://github.com/php-fig/fig-standards/blob/master/bylaws/002-psr-naming-conventions.md) - @ivanlanin #187
- Style: New `Style\AbstractStyle` abstract class - @ivanlanin #187
- Writer: New 'ODText\Base` class - @ivanlanin #187
- General: Rename `Footnote` to `Footnotes` to reflect the nature of collection - @ivanlanin
- General: Add some unit tests for Shared & Element (100%!) - @Progi1984
- Test: Add some samples and tests for image wrapping style - @brunocasado #59
- Refactor: Remove Style\Tabs - @ivanlanin
- Refactor: Apply composite pattern for writers - @ivanlanin
- Refactor: Split `AbstractContainer` from `AbstractElement` - @ivanlanin
- Refactor: Apply composite pattern for Word2007 reader - @ivanlanin
v0.9.1 (27 Mar 2014)
-------------------
This is a bugfix release for PSR-4 compatibility.
- Fixed PSR-4 composer autoloader - @AntonTyutin
v0.9.0 (26 Mar 2014)
-------------------
This release marked the transformation to namespaces (PHP 5.3+).
### Features
- Image: Ability to use remote or GD images using `addImage()` on sections, headers, footer, cells, and textruns - @ivanlanin
- Header: Ability to use remote or GD images using `addWatermark()` - @ivanlanin
### Bugfixes
- Preserve text doesn't render correctly when the text is not the first word, e.g. 'Page {PAGE}' - @ivanlanin
### Miscellaneous
- Move documentation to [Read The Docs](http://phpword.readthedocs.org/en/develop/) - @Progi1984 @ivanlanin #82
- Reorganize and redesign samples folder - @ivanlanin #137
- Use `PhpOffice\PhpWord` namespace for PSR compliance - @RomanSyroeshko @gabrielbull #159, #58
- Restructure folders and change folder name `Classes` to `src` and `Tests` to `test` for PSR compliance - @RomanSyroeshko @gabrielbull
- Compliance to phpDocumentor - @ivanlanin
- Merge Style\TableFull into Style\Table. Style\TableFull is deprecated - @ivanlanin #160
- Merge Section\MemoryImage into Section\Image. Section\Image is deprecated - @ivanlanin #160
v0.8.1 (17 Mar 2014)
-------------------
This is a bugfix release for image detection functionality.
- Added fallback for computers that do not have exif_imagetype - @bskrtich, @gabrielbull
v0.8.0 (15 Mar 2014)
-------------------
This release merged a lot of improvements from the community. Unit tests introduced in this release and has reached 90% code coverage.
### Features
- Template: Permit to save a template generated as a file (PHPWord_Template::saveAs()) - @RomanSyroeshko #56, #57
- Word2007: Support sections page numbering - @gabrielbull
- Word2007: Added line height methods to mirror the line height settings in Word in the paragraph styling - @gabrielbull
- Word2007: Added support for page header & page footer height - @JillElaine #5
- General: Add ability to manage line breaks after image insertion - @bskrtich #6, #66, #84
- Template: Ability to limit number of replacements performed by setValue() method of Template class - @RomanSyroeshko #52, #53, #85
- Table row: Repeat as header row & allow row to break across pages - @ivanlanin #48, #86
- Table: Table width in percentage - @ivanlanin #48, #86
- Font: Superscript and subscript - @ivanlanin #48, #86
- Paragraph: Hanging paragraph - @ivanlanin #48, #86
- Section: Multicolumn and section break - @ivanlanin #48, #86
- Template: Ability to apply XSL style sheet to Template - @RomanSyroeshko #46, #47, #83
- General: PHPWord_Shared_Font::pointSizeToTwips() converter - @ivanlanin #87
- Paragraph: Ability to define normal paragraph style with PHPWord::setNormalStyle() - @ivanlanin #87
- Paragraph: Ability to define parent style (basedOn) and style for following paragraph (next) - @ivanlanin #87
- Clone table rows on the fly when using a template document - @jeroenmoors #44, #88
- Initial addition of basic footnote support - @deds #16
- Paragraph: Ability to define paragraph pagination: widow control, keep next, keep lines, and page break before - @ivanlanin #92
- General: PHPWord_Style_Font refactoring - @ivanlanin #93
- Font: Use points instead of halfpoints internally. Conversion to halfpoints done during XML Writing. - @ivanlanin #93
- Paragraph: setTabs() function - @ivanlanin #92
- General: Basic support for TextRun on ODT and RTF - @ivanlanin #99
- Reader: Basic Reader for Word2007 - @ivanlanin #104
- TextRun: Allow Text Break in Text Run - @bskrtich #109
- General: Support for East Asian fontstyle - @jhfangying #111, #118
- Image: Use exif_imagetype to check image format instead of extension name - @gabrielbull #114
- General: Setting for XMLWriter Compatibility option - @bskrtich #103
- MemoryImage: Allow remote image when allow_url_open = on - @ivanlanin #122
- TextBreak: Allow font and paragraph style for text break - @ivanlanin #18
### Bugfixes
- Fixed bug with cell styling - @gabrielbull
- Fixed bug list items inside of cells - @gabrielbull
- Adding a value that contains "&" in a template breaks it - @SiebelsTim #51
- Example in README.md is broken - @Progi1984 #89
- General: PHPWord_Shared_Drawing::centimetersToPixels() conversion - @ivanlanin #94
- Footnote: Corrupt DOCX reported by MS Word when sections > 1 and not every sections have footnote - @ivanlanin #125
### Miscellaneous
- UnitTests - @Progi1984
v0.7.0 (28 Jan 2014)
-------------------
This is the first release after a long development hiatus in [CodePlex](https://phpword.codeplex.com/). This release initialized ODT and RTF Writer, along with some other new features for the existing Word2007 Writer, e.g. tab, multiple header, rowspan and colspan. [Composer](https://packagist.org/packages/phpoffice/phpword) and [Travis](https://travis-ci.org/PHPOffice/PHPWord) were added.
### Features
- Implement RTF Writer - @Progi1984 #1
- Implement ODT Writer - @Progi1984 #2
- Word2007: Add rowspan and colspan to cells - @kaystrobach
- Word2007: Support for tab stops - @RLovelett
- Word2007: Support Multiple headers - @RLovelett
- Word2007: Wrapping Styles to Images - @gabrielbull
- Added support for image wrapping style - @gabrielbull
### Bugfixes
- "Warning: Invalid error type specified in ...\PHPWord.php on line 226" is thrown when the specified template file is not found - @RomanSyroeshko #32
- PHPWord_Shared_String.IsUTF8 returns FALSE for Cyrillic UTF-8 input - @RomanSyroeshko #34
- Temporary files naming logic in PHPWord_Template can lead to a collision - @RomanSyroeshko #38
### Miscellaneous
- Add superscript/subscript styling in Excel2007 Writer - @MarkBaker
- add indentation support to paragraphs - @deds
- Support for Composer - @Progi1984 #27
- Basic CI with Travis - @Progi1984
- Added PHPWord_Exception and exception when could not copy the template - @Progi1984
- IMPROVED: Moved examples out of Classes directory - @Progi1984
- IMPROVED: Advanced string replace in setValue for Template - @Esmeraldo [#49](http://phpword.codeplex.com/workitem/49)

View File

@@ -1,23 +1,15 @@
# ![PHPWord](https://rawgit.com/PHPOffice/PHPWord/develop/docs/images/phpword.svg "PHPWord")
Master:
[![Latest Stable Version](https://poser.pugx.org/phpoffice/phpword/v/stable.png)](https://packagist.org/packages/phpoffice/phpword)
[![Build Status](https://travis-ci.org/PHPOffice/PHPWord.svg?branch=master)](https://travis-ci.org/PHPOffice/PHPWord)
[![Code Quality](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/)
[![Coverage Status](https://coveralls.io/repos/github/PHPOffice/PHPWord/badge.svg?branch=master)](https://coveralls.io/github/PHPOffice/PHPWord?branch=master)
[![Total Downloads](https://poser.pugx.org/phpoffice/phpword/downloads.png)](https://packagist.org/packages/phpoffice/phpword)
[![License](https://poser.pugx.org/phpoffice/phpword/license.png)](https://packagist.org/packages/phpoffice/phpword)
[![CI](https://github.com/PHPOffice/PHPWord/actions/workflows/ci.yml/badge.svg)](https://github.com/PHPOffice/PHPWord/actions/workflows/ci.yml)
[![Join the chat at https://gitter.im/PHPOffice/PHPWord](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/PHPOffice/PHPWord)
Develop:
[![Latest Development Version](https://img.shields.io/badge/unstable-dev--develop-orange.svg)](https://packagist.org/packages/phpoffice/phpword#dev-develop)
[![Build Status](https://travis-ci.org/PHPOffice/PHPWord.svg?branch=develop)](https://travis-ci.org/PHPOffice/PHPWord/branches)
[![Code Quality](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/badges/quality-score.png?b=develop)](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/?branch=develop)
[![Coverage Status](https://coveralls.io/repos/github/PHPOffice/PHPWord/badge.svg?branch=develop)](https://coveralls.io/github/PHPOffice/PHPWord?branch=develop)
PHPWord is a library written in pure PHP that provides a set of classes to write to and read from different document file formats. The current version of PHPWord supports Microsoft [Office Open XML](http://en.wikipedia.org/wiki/Office_Open_XML) (OOXML or OpenXML), OASIS [Open Document Format for Office Applications](http://en.wikipedia.org/wiki/OpenDocument) (OpenDocument or ODF), [Rich Text Format](http://en.wikipedia.org/wiki/Rich_Text_Format) (RTF), HTML, and PDF.
PHPWord is an open source project licensed under the terms of [LGPL version 3](COPYING.LESSER). PHPWord is aimed to be a high quality software product by incorporating [continuous integration](https://travis-ci.org/PHPOffice/PHPWord) and [unit testing](http://phpoffice.github.io/PHPWord/coverage/develop/). You can learn more about PHPWord by reading the [Developers' Documentation](http://phpword.readthedocs.org/).
PHPWord is an open source project licensed under the terms of [LGPL version 3](COPYING.LESSER). PHPWord is aimed to be a high quality software product by incorporating [continuous integration](https://github.com/PHPOffice/PHPWord/actions) and unit testing. You can learn more about PHPWord by reading the [Developers' Documentation](https://phpoffice.github.io/PHPWord/).
If you have any questions, please ask on [StackOverFlow](https://stackoverflow.com/questions/tagged/phpword)
@@ -28,7 +20,7 @@ Read more about PHPWord:
- [Installation](#installation)
- [Getting started](#getting-started)
- [Contributing](#contributing)
- [Developers' Documentation](http://phpword.readthedocs.org/)
- [Developers' Documentation](https://phpoffice.github.io/PHPWord/)
## Features
@@ -78,9 +70,9 @@ Run the following to use the latest stable version
```sh
composer require phpoffice/phpword
```
or if you want the latest develop version
or if you want the latest unreleased version
```sh
composer require phpoffice/phpword:dev-develop
composer require phpoffice/phpword:dev-master
```
## Getting started
@@ -158,13 +150,13 @@ $objWriter->save('helloWorld.html');
```
More examples are provided in the [samples folder](samples/). For an easy access to those samples launch `php -S localhost:8000` in the samples directory then browse to [http://localhost:8000](http://localhost:8000) to view the samples.
You can also read the [Developers' Documentation](http://phpword.readthedocs.org/) for more detail.
You can also read the [Developers' Documentation](https://phpoffice.github.io/PHPWord/) for more detail.
## Contributing
We welcome everyone to contribute to PHPWord. Below are some of the things that you can do to contribute.
- Read [our contributing guide](CONTRIBUTING.md).
- [Fork us](https://github.com/PHPOffice/PHPWord/fork) and [request a pull](https://github.com/PHPOffice/PHPWord/pulls) to the [develop](https://github.com/PHPOffice/PHPWord/tree/develop) branch.
- [Fork us](https://github.com/PHPOffice/PHPWord/fork) and [request a pull](https://github.com/PHPOffice/PHPWord/pulls) to the [master](https://github.com/PHPOffice/PHPWord/tree/master) branch.
- Submit [bug reports or feature requests](https://github.com/PHPOffice/PHPWord/issues) to GitHub.
- Follow [@PHPWord](https://twitter.com/PHPWord) and [@PHPOffice](https://twitter.com/PHPOffice) on Twitter.
- Follow [@PHPOffice](https://twitter.com/PHPOffice) on Twitter.

View File

@@ -6,7 +6,7 @@
"docx", "OOXML", "OpenXML", "Office Open XML", "ISO IEC 29500", "WordprocessingML",
"RTF", "Rich Text Format", "doc", "odt", "ODF", "OpenDocument", "PDF", "HTML"
],
"homepage": "https://phpword.readthedocs.io/",
"homepage": "https://phpoffice.github.io/PHPWord/",
"type": "library",
"license": "LGPL-3.0",
"authors": [
@@ -45,7 +45,8 @@
"php-cs-fixer fix --ansi --dry-run --diff",
"phpcs --report-width=200 --report-summary --report-full samples/ src/ tests/ --ignore=src/PhpWord/Shared/PCLZip --standard=PSR2 -n",
"phpmd src/,tests/ text ./phpmd.xml.dist --exclude pclzip.lib.php",
"@test-no-coverage"
"@test-no-coverage",
"phpstan analyse --ansi"
],
"fix": [
"php-cs-fixer fix --ansi"
@@ -57,12 +58,17 @@
"check": "Runs PHP CheckStyle and PHP Mess detector",
"fix": "Fixes issues found by PHP-CS"
},
"config": {
"platform": {
"php": "8.0"
}
},
"require": {
"php": "^7.1|^8.0",
"ext-dom": "*",
"ext-json": "*",
"ext-xml": "*",
"laminas/laminas-escaper": ">=2.6"
"phpoffice/math": "^0.1"
},
"require-dev": {
"ext-zip": "*",
@@ -70,11 +76,12 @@
"ext-libxml": "*",
"dompdf/dompdf": "^2.0",
"mpdf/mpdf": "^8.1",
"php-coveralls/php-coveralls": "^2.5",
"phpmd/phpmd": "^2.13",
"phpunit/phpunit": ">=7.0",
"tecnickcom/tcpdf": "^6.5",
"symfony/process": "^4.4"
"symfony/process": "^4.4 || ^5.0",
"friendsofphp/php-cs-fixer": "^3.3",
"phpstan/phpstan-phpunit": "@stable"
},
"suggest": {
"ext-zip": "Allows writing OOXML and ODF",
@@ -92,10 +99,5 @@
"psr-4": {
"PhpOffice\\PhpWordTests\\": "tests/PhpWordTests"
}
},
"extra": {
"branch-alias": {
"dev-develop": "0.19-dev"
}
}
}

117
vendor/phpoffice/phpword/mkdocs.yml vendored Normal file
View File

@@ -0,0 +1,117 @@
site_name: PHPWord
site_url: https://phpoffice.github.io/PHPWord
repo_url: https://github.com/PHPOffice/PHPWord
repo_name: PHPOffice/PHPWord
edit_uri: edit/develop/docs/
## Theme
theme:
name: material
palette:
primary: indigo
features:
- search.highlight
- search.suggest
## Plugins
plugins:
- search
- autolink_references:
autolinks:
- reference_prefix: GP-
target_url: https://github.com/<num>
- reference_prefix: GH-
target_url: https://github.com/PHPOffice/PHPWord/issues/<num>
- reference_prefix: CP-
target_url: https://archive.codeplex.com/?p=phpword&<num>
## Config
extra:
generator: false
markdown_extensions:
## Syntax highlighting
- pymdownx.highlight
- pymdownx.superfences
## Support for emojis
- pymdownx.emoji:
emoji_index: !!python/name:materialx.emoji.twemoji
emoji_generator: !!python/name:materialx.emoji.to_svg
## Support for call-outs
- admonition
- pymdownx.details
use_directory_urls: false
## Navigation
nav:
- Introduction: 'index.md'
- Install: 'install.md'
- Usage:
- Introduction: 'usage/introduction.md'
- Containers: 'usage/containers.md'
- Elements:
- Introduction: 'usage/elements/index.md'
- Chart: 'usage/elements/chart.md'
- Checkbox: 'usage/elements/checkbox.md'
- Comment: 'usage/elements/comment.md'
- Field: 'usage/elements/field.md'
- Footnote & Endnote: 'usage/elements/note.md'
- Formula: 'usage/elements/formula.md'
- Image: 'usage/elements/image.md'
- Line: 'usage/elements/line.md'
- Link: 'usage/elements/link.md'
- List: 'usage/elements/list.md'
- OLE Object: 'usage/elements/oleobject.md'
- Page Break: 'usage/elements/pagebreak.md'
- Preserve Text: 'usage/elements/preservetext.md'
- Text: 'usage/elements/text.md'
- TextBox: 'usage/elements/textbox.md'
- Text Break: 'usage/elements/textbreak.md'
- Table: 'usage/elements/table.md'
- Table of contents: 'usage/elements/toc.md'
- Title: 'usage/elements/title.md'
- Track Changes: 'usage/elements/trackchanges.md'
- Watermark: 'usage/elements/watermark.md'
- Styles:
- Chart: 'usage/styles/chart.md'
- Font: 'usage/styles/font.md'
- Image: 'usage/styles/image.md'
- Numbering Level: 'usage/styles/numberinglevel.md'
- Paragraph: 'usage/styles/paragraph.md'
- Section: 'usage/styles/section.md'
- Table: 'usage/styles/table.md'
- Template Processing: 'usage/template.md'
- Readers: 'usage/readers.md'
- Writers: 'usage/writers.md'
- FAQ: 'faq.md'
- How to: 'howto.md'
- Credits: 'credits.md'
- Releases:
- '1.x':
- '1.2.0 (WIP)': 'changes/1.x/1.2.0.md'
- '1.1.0': 'changes/1.x/1.1.0.md'
- '1.0.0': 'changes/1.x/1.0.0.md'
- '0.x':
- '0.18.3': 'changes/0.x/0.18.3.md'
- '0.18.2': 'changes/0.x/0.18.2.md'
- '0.18.1': 'changes/0.x/0.18.1.md'
- '0.18.0': 'changes/0.x/0.18.0.md'
- '0.17.0': 'changes/0.x/0.17.0.md'
- '0.16.0': 'changes/0.x/0.16.0.md'
- '0.15.0': 'changes/0.x/0.15.0.md'
- '0.14.0': 'changes/0.x/0.14.0.md'
- '0.13.0': 'changes/0.x/0.13.0.md'
- '0.12.1': 'changes/0.x/0.12.1.md'
- '0.12.0': 'changes/0.x/0.12.0.md'
- '0.11.1': 'changes/0.x/0.11.1.md'
- '0.11.0': 'changes/0.x/0.11.0.md'
- '0.10.1': 'changes/0.x/0.10.1.md'
- '0.10.0': 'changes/0.x/0.10.0.md'
- '0.9.1': 'changes/0.x/0.9.1.md'
- '0.9.0': 'changes/0.x/0.9.0.md'
- '0.8.1': 'changes/0.x/0.8.1.md'
- '0.8.0': 'changes/0.x/0.8.0.md'
- '0.7.0': 'changes/0.x/0.7.0.md'
- Developers:
- 'Coveralls': 'https://coveralls.io/github/PHPOffice/PHPWord'
- 'Code Coverage': 'coverage/index.html'
- 'PHPDoc': 'docs/index.html'

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +0,0 @@
# must be unique in a given SonarQube instance
sonar.projectKey=phpoffice:phpword
# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.
sonar.projectName=PHPWord
sonar.projectVersion=0.16
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
# This property is optional if sonar.modules is set.
sonar.sources=src
sonar.tests=tests
sonar.php.coverage.reportPaths=build/logs/clover.xml
sonar.php.tests.reportPath=build/logs/logfile.xml
# Encoding of the source code. Default is default system encoding
#sonar.sourceEncoding=UTF-8
sonar.host.url=http://localhost:9000

View File

@@ -46,7 +46,7 @@ abstract class AbstractCollection
*
* @param int $index
*
* @return \PhpOffice\PhpWord\Element\AbstractContainer
* @return ?\PhpOffice\PhpWord\Element\AbstractContainer
*/
public function getItem($index)
{
@@ -61,7 +61,7 @@ abstract class AbstractCollection
* Set item.
*
* @param int $index
* @param \PhpOffice\PhpWord\Element\AbstractContainer $item
* @param ?\PhpOffice\PhpWord\Element\AbstractContainer $item
*/
public function setItem($index, $item): void
{
@@ -79,7 +79,7 @@ abstract class AbstractCollection
*/
public function addItem($item)
{
$index = $this->countItems() + 1;
$index = $this->countItems();
$this->items[$index] = $item;
return $index;

View File

@@ -72,7 +72,7 @@ final class TrackChangesView
/**
* Set Display Visual Indicator Of Markup Area.
*
* @param bool $markup
* @param ?bool $markup
* Set to true to show markup
*/
public function setMarkup($markup): void
@@ -93,7 +93,7 @@ final class TrackChangesView
/**
* Set Display Comments.
*
* @param bool $comments
* @param ?bool $comments
* Set to true to show comments
*/
public function setComments($comments): void
@@ -114,7 +114,7 @@ final class TrackChangesView
/**
* Set Display Content Revisions.
*
* @param bool $insDel
* @param ?bool $insDel
* Set to true to show content revisions
*/
public function setInsDel($insDel): void
@@ -156,7 +156,7 @@ final class TrackChangesView
/**
* Set Display Ink Annotations.
*
* @param bool $inkAnnotations
* @param ?bool $inkAnnotations
* Set to true to show ink annotations
*/
public function setInkAnnotations($inkAnnotations): void

View File

@@ -18,6 +18,7 @@
namespace PhpOffice\PhpWord\Element;
use BadMethodCallException;
use PhpOffice\Math\Math;
use ReflectionClass;
/**
@@ -34,7 +35,7 @@ use ReflectionClass;
* @method Footnote addFootnote(mixed $pStyle = null)
* @method Endnote addEndnote(mixed $pStyle = null)
* @method CheckBox addCheckBox(string $name, $text, mixed $fStyle = null, mixed $pStyle = null)
* @method Title addTitle(mixed $text, int $depth = 1)
* @method Title addTitle(mixed $text, int $depth = 1, int $pageNumber = null)
* @method TOC addTOC(mixed $fontStyle = null, mixed $tocStyle = null, int $minDepth = 1, int $maxDepth = 9)
* @method PageBreak addPageBreak()
* @method Table addTable(mixed $style = null)
@@ -47,6 +48,7 @@ use ReflectionClass;
* @method Chart addChart(string $type, array $categories, array $values, array $style = null, $seriesName = null)
* @method FormField addFormField(string $type, mixed $fStyle = null, mixed $pStyle = null)
* @method SDT addSDT(string $type)
* @method Formula addFormula(Math $math)
* @method \PhpOffice\PhpWord\Element\OLEObject addObject(string $source, mixed $style = null) deprecated, use addOLEObject instead
*
* @since 0.10.0
@@ -88,6 +90,7 @@ abstract class AbstractContainer extends AbstractElement
'Footnote', 'Endnote', 'CheckBox', 'TextBox', 'Field',
'Line', 'Shape', 'Title', 'TOC', 'PageBreak',
'Chart', 'FormField', 'SDT', 'Comment',
'Formula',
];
$functions = [];
foreach ($elements as $element) {

View File

@@ -32,7 +32,7 @@ abstract class AbstractElement
/**
* PhpWord object.
*
* @var \PhpOffice\PhpWord\PhpWord
* @var ?\PhpOffice\PhpWord\PhpWord
*/
protected $phpWord;
@@ -147,7 +147,7 @@ abstract class AbstractElement
/**
* Get PhpWord.
*
* @return \PhpOffice\PhpWord\PhpWord
* @return ?\PhpOffice\PhpWord\PhpWord
*/
public function getPhpWord()
{
@@ -156,8 +156,6 @@ abstract class AbstractElement
/**
* Set PhpWord as reference.
*
* @param \PhpOffice\PhpWord\PhpWord $phpWord
*/
public function setPhpWord(?PhpWord $phpWord = null): void
{
@@ -347,8 +345,6 @@ abstract class AbstractElement
* Set parent container.
*
* Passed parameter should be a container, except for Table (contain Row) and Row (contain Cell)
*
* @param \PhpOffice\PhpWord\Element\AbstractElement $container
*/
public function setParentContainer(self $container): void
{
@@ -432,7 +428,7 @@ abstract class AbstractElement
* Set new style value.
*
* @param mixed $styleObject Style object
* @param mixed $styleValue Style value
* @param null|array|\PhpOffice\PhpWord\Style|string $styleValue Style value
* @param bool $returnObject Always return object
*
* @return mixed

View File

@@ -32,21 +32,21 @@ class Cell extends AbstractContainer
/**
* Cell width.
*
* @var int
* @var ?int
*/
private $width;
/**
* Cell style.
*
* @var \PhpOffice\PhpWord\Style\Cell
* @var ?\PhpOffice\PhpWord\Style\Cell
*/
private $style;
/**
* Create new instance.
*
* @param int $width
* @param null|int $width
* @param array|\PhpOffice\PhpWord\Style\Cell $style
*/
public function __construct($width = null, $style = null)
@@ -58,7 +58,7 @@ class Cell extends AbstractContainer
/**
* Get cell style.
*
* @return \PhpOffice\PhpWord\Style\Cell
* @return ?\PhpOffice\PhpWord\Style\Cell
*/
public function getStyle()
{
@@ -68,7 +68,7 @@ class Cell extends AbstractContainer
/**
* Get cell width.
*
* @return int
* @return ?int
*/
public function getWidth()
{

View File

@@ -50,7 +50,7 @@ class Chart extends AbstractElement
/**
* Chart style.
*
* @var \PhpOffice\PhpWord\Style\Chart
* @var ?\PhpOffice\PhpWord\Style\Chart
*/
private $style;
@@ -120,7 +120,7 @@ class Chart extends AbstractElement
/**
* Get chart style.
*
* @return \PhpOffice\PhpWord\Style\Chart
* @return ?\PhpOffice\PhpWord\Style\Chart
*/
public function getStyle()
{

View File

@@ -79,8 +79,6 @@ class Comment extends TrackChange
/**
* Sets the element where this comment starts.
*
* @param \PhpOffice\PhpWord\Element\AbstractElement $value
*/
public function setStartElement(AbstractElement $value): void
{
@@ -102,8 +100,6 @@ class Comment extends TrackChange
/**
* Sets the element where this comment ends.
*
* @param \PhpOffice\PhpWord\Element\AbstractElement $value
*/
public function setEndElement(AbstractElement $value): void
{

View File

@@ -85,6 +85,12 @@ class Field extends AbstractElement
'properties' => ['StyleIdentifier' => ''],
'options' => ['PreserveFormat'],
],
'FILENAME' => [
'properties' => [
'format' => ['Upper', 'Lower', 'FirstCap', 'Caps'],
],
'options' => ['Path', 'PreserveFormat'],
],
];
/**
@@ -268,7 +274,7 @@ class Field extends AbstractElement
/**
* Set Field text.
*
* @param string|TextRun $text
* @param null|string|TextRun $text
*
* @return null|string|TextRun
*/

View File

@@ -29,7 +29,7 @@ class Footnote extends AbstractContainer
/**
* Paragraph style.
*
* @var \PhpOffice\PhpWord\Style\Paragraph|string
* @var null|\PhpOffice\PhpWord\Style\Paragraph|string
*/
protected $paragraphStyle;
@@ -54,7 +54,7 @@ class Footnote extends AbstractContainer
/**
* Get paragraph style.
*
* @return \PhpOffice\PhpWord\Style\Paragraph|string
* @return null|\PhpOffice\PhpWord\Style\Paragraph|string
*/
public function getParagraphStyle()
{

View File

@@ -35,7 +35,7 @@ class FormField extends Text
/**
* Form field name.
*
* @var bool|int|string
* @var ?string
*/
private $name;
@@ -53,7 +53,7 @@ class FormField extends Text
/**
* Value.
*
* @var bool|int|string
* @var null|bool|int|string
*/
private $value;
@@ -105,7 +105,7 @@ class FormField extends Text
/**
* Get name.
*
* @return string
* @return ?string
*/
public function getName()
{
@@ -115,7 +115,7 @@ class FormField extends Text
/**
* Set name.
*
* @param bool|int|string $value
* @param ?string $value
*
* @return self
*/
@@ -153,7 +153,7 @@ class FormField extends Text
/**
* Get value.
*
* @return bool|int|string
* @return null|bool|int|string
*/
public function getValue()
{
@@ -163,7 +163,7 @@ class FormField extends Text
/**
* Set value.
*
* @param bool|int|string $value
* @param null|bool|int|string $value
*
* @return self
*/

View File

@@ -0,0 +1,53 @@
<?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
*
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
declare(strict_types=1);
namespace PhpOffice\PhpWord\Element;
use PhpOffice\Math\Math;
/**
* Formula element.
*/
class Formula extends AbstractElement
{
/**
* @var Math
*/
protected $math;
/**
* Create a new Formula Element.
*/
public function __construct(Math $math)
{
$this->setMath($math);
}
public function setMath(Math $math): self
{
$this->math = $math;
return $this;
}
public function getMath(): Math
{
return $this->math;
}
}

View File

@@ -54,7 +54,7 @@ class Image extends AbstractElement
/**
* Image style.
*
* @var ImageStyle
* @var ?ImageStyle
*/
private $style;
@@ -89,7 +89,7 @@ class Image extends AbstractElement
/**
* Image function.
*
* @var string
* @var null|callable(resource): void
*/
private $imageFunc;
@@ -100,6 +100,16 @@ class Image extends AbstractElement
*/
private $imageExtension;
/**
* Image quality.
*
* Functions imagepng() and imagejpeg() have an optional parameter for
* quality.
*
* @var null|int
*/
private $imageQuality;
/**
* Is memory image.
*
@@ -149,7 +159,7 @@ class Image extends AbstractElement
/**
* Get Image style.
*
* @return ImageStyle
* @return ?ImageStyle
*/
public function getStyle()
{
@@ -249,13 +259,21 @@ class Image extends AbstractElement
/**
* Get image function.
*
* @return string
* @return null|callable(resource): void
*/
public function getImageFunction()
public function getImageFunction(): ?callable
{
return $this->imageFunc;
}
/**
* Get image quality.
*/
public function getImageQuality(): ?int
{
return $this->imageQuality;
}
/**
* Get image extension.
*
@@ -317,20 +335,13 @@ class Image extends AbstractElement
}
/**
* Get image string data.
*
* @param bool $base64
*
* @return null|string
*
* @since 0.11.0
* Get image string.
*/
public function getImageStringData($base64 = false)
public function getImageString(): ?string
{
$source = $this->source;
$actualSource = null;
$imageBinary = null;
$imageData = null;
$isTemp = false;
// Get actual source from archive image or other source
@@ -367,7 +378,8 @@ class Image extends AbstractElement
imagesavealpha($imageResource, true);
}
ob_start();
call_user_func($this->imageFunc, $imageResource);
$callback = $this->imageFunc;
$callback($imageResource);
$imageBinary = ob_get_contents();
ob_end_clean();
} elseif ($this->sourceType == self::SOURCE_STRING) {
@@ -379,20 +391,36 @@ class Image extends AbstractElement
fclose($fileHandle);
}
}
if ($imageBinary !== null) {
if ($base64) {
$imageData = chunk_split(base64_encode($imageBinary));
} else {
$imageData = chunk_split(bin2hex($imageBinary));
}
}
// Delete temporary file if necessary
if ($isTemp === true) {
@unlink($actualSource);
}
return $imageData;
return $imageBinary;
}
/**
* Get image string data.
*
* @param bool $base64
*
* @return null|string
*
* @since 0.11.0
*/
public function getImageStringData($base64 = false)
{
$imageBinary = $this->getImageString();
if ($imageBinary === null) {
return null;
}
if ($base64) {
return base64_encode($imageBinary);
}
return bin2hex($imageBinary);
}
/**
@@ -503,31 +531,45 @@ class Image extends AbstractElement
switch ($this->imageType) {
case 'image/png':
$this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefrompng';
$this->imageFunc = 'imagepng';
$this->imageFunc = function ($resource): void {
imagepng($resource, null, $this->imageQuality);
};
$this->imageExtension = 'png';
$this->imageQuality = -1;
break;
case 'image/gif':
$this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefromgif';
$this->imageFunc = 'imagegif';
$this->imageFunc = function ($resource): void {
imagegif($resource);
};
$this->imageExtension = 'gif';
$this->imageQuality = null;
break;
case 'image/jpeg':
case 'image/jpg':
$this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefromjpeg';
$this->imageFunc = 'imagejpeg';
$this->imageFunc = function ($resource): void {
imagejpeg($resource, null, $this->imageQuality);
};
$this->imageExtension = 'jpg';
$this->imageQuality = 100;
break;
case 'image/bmp':
case 'image/x-ms-bmp':
$this->imageType = 'image/bmp';
$this->imageFunc = null;
$this->imageExtension = 'bmp';
$this->imageQuality = null;
break;
case 'image/tiff':
$this->imageType = 'image/tiff';
$this->imageFunc = null;
$this->imageExtension = 'tif';
$this->imageQuality = null;
break;
}

View File

@@ -27,7 +27,7 @@ class Line extends AbstractElement
/**
* Line style.
*
* @var \PhpOffice\PhpWord\Style\Line
* @var ?\PhpOffice\PhpWord\Style\Line
*/
private $style;
@@ -44,7 +44,7 @@ class Line extends AbstractElement
/**
* Get line style.
*
* @return \PhpOffice\PhpWord\Style\Line
* @return ?\PhpOffice\PhpWord\Style\Line
*/
public function getStyle()
{

View File

@@ -43,14 +43,14 @@ class Link extends AbstractElement
/**
* Font style.
*
* @var \PhpOffice\PhpWord\Style\Font|string
* @var null|\PhpOffice\PhpWord\Style\Font|string
*/
private $fontStyle;
/**
* Paragraph style.
*
* @var \PhpOffice\PhpWord\Style\Paragraph|string
* @var null|\PhpOffice\PhpWord\Style\Paragraph|string
*/
private $paragraphStyle;
@@ -109,7 +109,7 @@ class Link extends AbstractElement
/**
* Get Text style.
*
* @return \PhpOffice\PhpWord\Style\Font|string
* @return null|\PhpOffice\PhpWord\Style\Font|string
*/
public function getFontStyle()
{
@@ -119,7 +119,7 @@ class Link extends AbstractElement
/**
* Get Paragraph style.
*
* @return \PhpOffice\PhpWord\Style\Paragraph|string
* @return null|\PhpOffice\PhpWord\Style\Paragraph|string
*/
public function getParagraphStyle()
{

View File

@@ -28,7 +28,7 @@ class ListItem extends AbstractElement
/**
* Element style.
*
* @var \PhpOffice\PhpWord\Style\ListItem
* @var ?\PhpOffice\PhpWord\Style\ListItem
*/
private $style;
@@ -71,7 +71,7 @@ class ListItem extends AbstractElement
/**
* Get style.
*
* @return \PhpOffice\PhpWord\Style\ListItem
* @return ?\PhpOffice\PhpWord\Style\ListItem
*/
public function getStyle()
{

View File

@@ -32,7 +32,7 @@ class ListItemRun extends TextRun
/**
* ListItem Style.
*
* @var \PhpOffice\PhpWord\Style\ListItem
* @var ?\PhpOffice\PhpWord\Style\ListItem
*/
private $style;
@@ -66,7 +66,7 @@ class ListItemRun extends TextRun
/**
* Get ListItem style.
*
* @return \PhpOffice\PhpWord\Style\ListItem
* @return ?\PhpOffice\PhpWord\Style\ListItem
*/
public function getStyle()
{

View File

@@ -35,7 +35,7 @@ class OLEObject extends AbstractElement
/**
* Image Style.
*
* @var \PhpOffice\PhpWord\Style\Image
* @var ?\PhpOffice\PhpWord\Style\Image
*/
private $style;
@@ -100,7 +100,7 @@ class OLEObject extends AbstractElement
/**
* Get object style.
*
* @return \PhpOffice\PhpWord\Style\Image
* @return ?\PhpOffice\PhpWord\Style\Image
*/
public function getStyle()
{

View File

@@ -29,21 +29,21 @@ class PreserveText extends AbstractElement
/**
* Text content.
*
* @var array|string
* @var null|array|string
*/
private $text;
/**
* Text style.
*
* @var \PhpOffice\PhpWord\Style\Font|string
* @var null|\PhpOffice\PhpWord\Style\Font|string
*/
private $fontStyle;
/**
* Paragraph style.
*
* @var \PhpOffice\PhpWord\Style\Paragraph|string
* @var null|\PhpOffice\PhpWord\Style\Paragraph|string
*/
private $paragraphStyle;
@@ -69,7 +69,7 @@ class PreserveText extends AbstractElement
/**
* Get Text style.
*
* @return \PhpOffice\PhpWord\Style\Font|string
* @return null|\PhpOffice\PhpWord\Style\Font|string
*/
public function getFontStyle()
{
@@ -79,7 +79,7 @@ class PreserveText extends AbstractElement
/**
* Get Paragraph style.
*
* @return \PhpOffice\PhpWord\Style\Paragraph|string
* @return null|\PhpOffice\PhpWord\Style\Paragraph|string
*/
public function getParagraphStyle()
{
@@ -89,7 +89,7 @@ class PreserveText extends AbstractElement
/**
* Get Text content.
*
* @return array|string
* @return null|array|string
*/
public function getText()
{

View File

@@ -29,14 +29,14 @@ class Row extends AbstractElement
/**
* Row height.
*
* @var int
* @var ?int
*/
private $height;
/**
* Row style.
*
* @var \PhpOffice\PhpWord\Style\Row
* @var ?\PhpOffice\PhpWord\Style\Row
*/
private $style;
@@ -89,7 +89,7 @@ class Row extends AbstractElement
/**
* Get row style.
*
* @return \PhpOffice\PhpWord\Style\Row
* @return ?\PhpOffice\PhpWord\Style\Row
*/
public function getStyle()
{
@@ -99,7 +99,7 @@ class Row extends AbstractElement
/**
* Get row height.
*
* @return int
* @return ?int
*/
public function getHeight()
{

View File

@@ -34,7 +34,7 @@ class SDT extends Text
/**
* Value.
*
* @var bool|int|string
* @var null|bool|int|string
*/
private $value;
@@ -100,7 +100,7 @@ class SDT extends Text
/**
* Get value.
*
* @return bool|int|string
* @return null|bool|int|string
*/
public function getValue()
{
@@ -110,7 +110,7 @@ class SDT extends Text
/**
* Set value.
*
* @param bool|int|string $value
* @param null|bool|int|string $value
*
* @return self
*/

View File

@@ -31,7 +31,7 @@ class Section extends AbstractContainer
/**
* Section style.
*
* @var \PhpOffice\PhpWord\Style\Section
* @var ?\PhpOffice\PhpWord\Style\Section
*/
private $style;
@@ -60,7 +60,7 @@ class Section extends AbstractContainer
* Create new instance.
*
* @param int $sectionCount
* @param null|array|\PhpOffice\PhpWord\Style $style
* @param null|array|\PhpOffice\PhpWord\Style|string $style
*/
public function __construct($sectionCount, $style = null)
{
@@ -87,7 +87,7 @@ class Section extends AbstractContainer
/**
* Get section style.
*
* @return \PhpOffice\PhpWord\Style\Section
* @return ?\PhpOffice\PhpWord\Style\Section
*/
public function getStyle()
{
@@ -154,8 +154,6 @@ class Section extends AbstractContainer
/**
* Set the footnote properties.
*
* @param FootnoteProperties $footnoteProperties
*/
public function setFootnoteProperties(?FootnoteProperties $footnoteProperties = null): void
{

View File

@@ -36,7 +36,7 @@ class Shape extends AbstractElement
/**
* Shape style.
*
* @var \PhpOffice\PhpWord\Style\Shape
* @var ?\PhpOffice\PhpWord\Style\Shape
*/
private $style;
@@ -80,7 +80,7 @@ class Shape extends AbstractElement
/**
* Get shape style.
*
* @return \PhpOffice\PhpWord\Style\Shape
* @return ?\PhpOffice\PhpWord\Style\Shape
*/
public function getStyle()
{

View File

@@ -27,7 +27,7 @@ class Table extends AbstractElement
/**
* Table style.
*
* @var \PhpOffice\PhpWord\Style\Table
* @var ?\PhpOffice\PhpWord\Style\Table
*/
private $style;
@@ -41,7 +41,7 @@ class Table extends AbstractElement
/**
* Table width.
*
* @var int
* @var ?int
*/
private $width;
@@ -102,7 +102,7 @@ class Table extends AbstractElement
/**
* Get table style.
*
* @return \PhpOffice\PhpWord\Style\Table
* @return null|\PhpOffice\PhpWord\Style\Table|string
*/
public function getStyle()
{
@@ -112,7 +112,7 @@ class Table extends AbstractElement
/**
* Get table width.
*
* @return int
* @return ?int
*/
public function getWidth()
{

View File

@@ -29,7 +29,7 @@ class Text extends AbstractElement
/**
* Text content.
*
* @var string
* @var ?string
*/
protected $text;
@@ -147,7 +147,7 @@ class Text extends AbstractElement
/**
* Get Text content.
*
* @return string
* @return ?string
*/
public function getText()
{

View File

@@ -34,7 +34,7 @@ class TextBox extends AbstractContainer
/**
* TextBox style.
*
* @var \PhpOffice\PhpWord\Style\TextBox
* @var ?\PhpOffice\PhpWord\Style\TextBox
*/
private $style;
@@ -51,7 +51,7 @@ class TextBox extends AbstractContainer
/**
* Get textbox style.
*
* @return \PhpOffice\PhpWord\Style\TextBox
* @return ?\PhpOffice\PhpWord\Style\TextBox
*/
public function getStyle()
{

View File

@@ -28,14 +28,14 @@ class TextBreak extends AbstractElement
/**
* Paragraph style.
*
* @var \PhpOffice\PhpWord\Style\Paragraph|string
* @var null|\PhpOffice\PhpWord\Style\Paragraph|string
*/
private $paragraphStyle;
/**
* Text style.
*
* @var \PhpOffice\PhpWord\Style\Font|string
* @var null|\PhpOffice\PhpWord\Style\Font|string
*/
private $fontStyle;
@@ -82,7 +82,7 @@ class TextBreak extends AbstractElement
/**
* Get Text style.
*
* @return \PhpOffice\PhpWord\Style\Font|string
* @return null|\PhpOffice\PhpWord\Style\Font|string
*/
public function getFontStyle()
{
@@ -113,7 +113,7 @@ class TextBreak extends AbstractElement
/**
* Get Paragraph style.
*
* @return \PhpOffice\PhpWord\Style\Paragraph|string
* @return null|\PhpOffice\PhpWord\Style\Paragraph|string
*/
public function getParagraphStyle()
{

View File

@@ -78,4 +78,16 @@ class TextRun extends AbstractContainer
return $this->paragraphStyle;
}
public function getText(): string
{
$outstr = '';
foreach ($this->getElements() as $element) {
if ($element instanceof Text) {
$outstr .= $element->getText();
}
}
return $outstr;
}
}

View File

@@ -43,7 +43,7 @@ class Title extends AbstractElement
/**
* Name of the heading style, e.g. 'Heading1'.
*
* @var string
* @var ?string
*/
private $style;
@@ -54,13 +54,20 @@ class Title extends AbstractElement
*/
protected $collectionRelation = true;
/**
* Page number.
*
* @var int
*/
private $pageNumber;
/**
* Create a new Title Element.
*
* @param string|TextRun $text
* @param int $depth
*/
public function __construct($text, $depth = 1)
public function __construct($text, $depth = 1, ?int $pageNumber = null)
{
if (is_string($text)) {
$this->text = SharedText::toUTF8($text);
@@ -75,12 +82,16 @@ class Title extends AbstractElement
if (array_key_exists($styleName, Style::getStyles())) {
$this->style = str_replace('_', '', $styleName);
}
if ($pageNumber !== null) {
$this->pageNumber = $pageNumber;
}
}
/**
* Get Title Text content.
*
* @return string
* @return string|TextRun
*/
public function getText()
{
@@ -100,10 +111,18 @@ class Title extends AbstractElement
/**
* Get Title style.
*
* @return string
* @return ?string
*/
public function getStyle()
{
return $this->style;
}
/**
* Get page number.
*/
public function getPageNumber(): ?int
{
return $this->pageNumber;
}
}

View File

@@ -25,7 +25,7 @@ namespace PhpOffice\PhpWord\Escaper;
abstract class AbstractEscaper implements EscaperInterface
{
/**
* @param string $input
* @param ?string $input
*
* @return string
*/

View File

@@ -47,7 +47,7 @@ class Rtf extends AbstractEscaper
/**
* @see http://www.randomchaos.com/documents/?source=php_and_unicode
*
* @param string $input
* @param ?string $input
*/
protected function escapeSingleValue($input)
{

View File

@@ -41,7 +41,6 @@ class Media
* @param string $container section|headerx|footerx|footnote|endnote
* @param string $mediaType image|object|link
* @param string $source
* @param \PhpOffice\PhpWord\Element\Image $image
*
* @return int
*/
@@ -74,8 +73,7 @@ class Media
$mediaData['imageType'] = $image->getImageType();
if ($isMemImage) {
$mediaData['isMemImage'] = true;
$mediaData['createFunction'] = $image->getImageCreateFunction();
$mediaData['imageFunction'] = $image->getImageFunction();
$mediaData['imageString'] = $image->getImageString();
}
$target = "{$container}_image{$mediaTypeCount}.{$extension}";
$image->setTarget($target);

View File

@@ -441,7 +441,7 @@ class DocInfo
*
* @param string $propertyName
*
* @return string
* @return ?string
*/
public function getCustomPropertyType($propertyName)
{

View File

@@ -114,7 +114,7 @@ class Settings
/**
* Theme Font Languages.
*
* @var Language
* @var ?Language
*/
private $themeFontLang;
@@ -149,7 +149,7 @@ class Settings
/**
* The allowed amount of whitespace before hyphenation is applied.
*
* @var null|float
* @var null|float|int
*/
private $hyphenationZone;
@@ -160,6 +160,13 @@ class Settings
*/
private $doNotHyphenateCaps;
/**
* Enable or disable book-folded printing.
*
* @var bool
*/
private $bookFoldPrinting = false;
/**
* @return Protection
*/
@@ -213,7 +220,7 @@ class Settings
/**
* Hide spelling errors.
*
* @param bool $hideSpellingErrors
* @param ?bool $hideSpellingErrors
*/
public function setHideSpellingErrors($hideSpellingErrors): void
{
@@ -233,7 +240,7 @@ class Settings
/**
* Hide grammatical errors.
*
* @param bool $hideGrammaticalErrors
* @param ?bool $hideGrammaticalErrors
*/
public function setHideGrammaticalErrors($hideGrammaticalErrors): void
{
@@ -249,7 +256,7 @@ class Settings
}
/**
* @param bool $evenAndOddHeaders
* @param ?bool $evenAndOddHeaders
*/
public function setEvenAndOddHeaders($evenAndOddHeaders): void
{
@@ -268,8 +275,6 @@ class Settings
/**
* Set the Visibility of Annotation Types.
*
* @param TrackChangesView $trackChangesView
*/
public function setRevisionView(?TrackChangesView $trackChangesView = null): void
{
@@ -285,7 +290,7 @@ class Settings
}
/**
* @param bool $trackRevisions
* @param ?bool $trackRevisions
*/
public function setTrackRevisions($trackRevisions): void
{
@@ -301,7 +306,7 @@ class Settings
}
/**
* @param bool $doNotTrackMoves
* @param ?bool $doNotTrackMoves
*/
public function setDoNotTrackMoves($doNotTrackMoves): void
{
@@ -317,7 +322,7 @@ class Settings
}
/**
* @param bool $doNotTrackFormatting
* @param ?bool $doNotTrackFormatting
*/
public function setDoNotTrackFormatting($doNotTrackFormatting): void
{
@@ -364,22 +369,20 @@ class Settings
/**
* Returns the Language.
*
* @return Language
*/
public function getThemeFontLang()
public function getThemeFontLang(): ?Language
{
return $this->themeFontLang;
}
/**
* sets the Language for this document.
*
* @param Language $themeFontLang
* Sets the Language for this document.
*/
public function setThemeFontLang($themeFontLang): void
public function setThemeFontLang(Language $themeFontLang): self
{
$this->themeFontLang = $themeFontLang;
return $this;
}
/**
@@ -391,7 +394,7 @@ class Settings
}
/**
* @param bool $updateFields
* @param ?bool $updateFields
*/
public function setUpdateFields($updateFields): void
{
@@ -451,7 +454,7 @@ class Settings
}
/**
* @return null|float
* @return null|float|int
*/
public function getHyphenationZone()
{
@@ -459,7 +462,7 @@ class Settings
}
/**
* @param float $hyphenationZone Measurement unit is twip
* @param null|float|int $hyphenationZone Measurement unit is twip
*/
public function setHyphenationZone($hyphenationZone): void
{
@@ -481,4 +484,16 @@ class Settings
{
$this->doNotHyphenateCaps = (bool) $doNotHyphenateCaps;
}
public function hasBookFoldPrinting(): bool
{
return $this->bookFoldPrinting;
}
public function setBookFoldPrinting(bool $bookFoldPrinting): self
{
$this->bookFoldPrinting = $bookFoldPrinting;
return $this;
}
}

View File

@@ -77,6 +77,7 @@ class PhpWord
// Reset Media and styles
Media::resetElements();
Style::resetStyles();
Settings::setDefaultRtl(null);
// Collection
$collections = ['Bookmarks', 'Titles', 'Footnotes', 'Endnotes', 'Charts', 'Comments'];
@@ -211,7 +212,7 @@ class PhpWord
/**
* Create new section.
*
* @param array $style
* @param null|array|string $style
*
* @return \PhpOffice\PhpWord\Element\Section
*/
@@ -325,4 +326,52 @@ class PhpWord
return true;
}
/**
* Create new section.
*
* @deprecated 0.10.0
*
* @param array $settings
*
* @return \PhpOffice\PhpWord\Element\Section
*
* @codeCoverageIgnore
*/
public function createSection($settings = null)
{
return $this->addSection($settings);
}
/**
* Get document properties object.
*
* @deprecated 0.12.0
*
* @return \PhpOffice\PhpWord\Metadata\DocInfo
*
* @codeCoverageIgnore
*/
public function getDocumentProperties()
{
return $this->getDocInfo();
}
/**
* Set document properties object.
*
* @deprecated 0.12.0
*
* @param \PhpOffice\PhpWord\Metadata\DocInfo $documentProperties
*
* @return self
*
* @codeCoverageIgnore
*/
public function setDocumentProperties($documentProperties)
{
$this->metadata['Document'] = $documentProperties;
return $this;
}
}

View File

@@ -42,6 +42,13 @@ abstract class AbstractReader implements ReaderInterface
*/
protected $fileHandle;
/**
* Load images.
*
* @var bool
*/
protected $imageLoading = true;
/**
* Read data only?
*
@@ -67,6 +74,18 @@ abstract class AbstractReader implements ReaderInterface
return $this;
}
public function hasImageLoading(): bool
{
return $this->imageLoading;
}
public function setImageLoading(bool $value): self
{
$this->imageLoading = $value;
return $this;
}
/**
* Open file for reading.
*

View File

@@ -82,6 +82,12 @@ class MsDoc extends AbstractReader implements ReaderInterface
*/
private $arraySections = [];
/** @var string */
private $summaryInformation;
/** @var string */
private $documentSummaryInformation;
const VERSION_97 = '97';
const VERSION_2000 = '2000';
const VERSION_2002 = '2002';
@@ -150,9 +156,9 @@ class MsDoc extends AbstractReader implements ReaderInterface
// Get Data stream
$this->dataObjectPool = $ole->getStream($ole->wrkObjectPool);
// Get Summary Information data
$this->_SummaryInformation = $ole->getStream($ole->summaryInformation);
$this->summaryInformation = $ole->getStream($ole->summaryInformation);
// Get Document Summary Information data
$this->_DocumentSummaryInformation = $ole->getStream($ole->docSummaryInfos);
$this->documentSummaryInformation = $ole->getStream($ole->docSummaryInfos);
}
private function getNumInLcb($lcb, $iSize)
@@ -1131,7 +1137,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
/**
* Section and information about them.
*
* @see : http://msdn.microsoft.com/en-us/library/dd924458%28v=office.12%29.aspx
* @see http://msdn.microsoft.com/en-us/library/dd924458%28v=office.12%29.aspx
*/
private function readRecordPlcfSed(): void
{
@@ -1145,7 +1151,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
$posMem += 4;
// PlcfSed : aSed
//@see : http://msdn.microsoft.com/en-us/library/dd950194%28v=office.12%29.aspx
//@see http://msdn.microsoft.com/en-us/library/dd950194%28v=office.12%29.aspx
$numSed = $this->getNumInLcb($this->arrayFib['lcbPlcfSed'], 12);
$aSed = [];
@@ -1177,7 +1183,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
/**
* Specifies the fonts that are used in the document.
*
* @see : http://msdn.microsoft.com/en-us/library/dd943880%28v=office.12%29.aspx
* @see http://msdn.microsoft.com/en-us/library/dd943880%28v=office.12%29.aspx
*/
private function readRecordSttbfFfn(): void
{
@@ -1468,7 +1474,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
$offset = $offsetBase;
// ChpxFkp
// @see : http://msdn.microsoft.com/en-us/library/dd910989%28v=office.12%29.aspx
// @see http://msdn.microsoft.com/en-us/library/dd910989%28v=office.12%29.aspx
$numRGFC = self::getInt1d($this->dataWorkDocument, $offset + 511);
$arrayRGFC = [];
for ($inc = 0; $inc <= $numRGFC; ++$inc) {
@@ -1491,7 +1497,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
if ($rgb > 0) {
// Chp Structure
// @see : http://msdn.microsoft.com/en-us/library/dd772849%28v=office.12%29.aspx
// @see http://msdn.microsoft.com/en-us/library/dd772849%28v=office.12%29.aspx
$posRGB = $offsetBase + $rgb * 2;
$cb = self::getInt1d($this->dataWorkDocument, $posRGB);
@@ -1926,12 +1932,13 @@ class MsDoc extends AbstractReader implements ReaderInterface
// $operand = self::getInt2d($data, $pos);
$pos += 2;
$cbNum -= 2;
// $ipat = ($operand >> 0) && bindec('111111');
// $icoBack = ($operand >> 6) && bindec('11111');
// $icoFore = ($operand >> 11) && bindec('11111');
break;
// sprmCCv
//@see : http://msdn.microsoft.com/en-us/library/dd952824%28v=office.12%29.aspx
//@see http://msdn.microsoft.com/en-us/library/dd952824%28v=office.12%29.aspx
case 0x70:
$red = str_pad(dechex(self::getInt1d($this->dataWorkDocument, $pos)), 2, '0', STR_PAD_LEFT);
++$pos;
@@ -2042,7 +2049,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
// HFD > clsid
$sprmCPicLocation += 16;
// HFD > hyperlink
//@see : http://msdn.microsoft.com/en-us/library/dd909835%28v=office.12%29.aspx
//@see http://msdn.microsoft.com/en-us/library/dd909835%28v=office.12%29.aspx
$streamVersion = self::getInt4d($this->dataData, $sprmCPicLocation);
$sprmCPicLocation += 4;
$data = self::getInt4d($this->dataData, $sprmCPicLocation);
@@ -2110,8 +2117,8 @@ class MsDoc extends AbstractReader implements ReaderInterface
}*/
} else {
// Pictures
//@see : http://msdn.microsoft.com/en-us/library/dd925458%28v=office.12%29.aspx
//@see : http://msdn.microsoft.com/en-us/library/dd926136%28v=office.12%29.aspx
//@see http://msdn.microsoft.com/en-us/library/dd925458%28v=office.12%29.aspx
//@see http://msdn.microsoft.com/en-us/library/dd926136%28v=office.12%29.aspx
// PICF : lcb
$sprmCPicLocation += 4;
// PICF : cbHeader
@@ -2198,13 +2205,13 @@ class MsDoc extends AbstractReader implements ReaderInterface
$sprmCPicLocation += $shapeRH['recLen'];
}
// picture : rgfb
//@see : http://msdn.microsoft.com/en-us/library/dd950560%28v=office.12%29.aspx
//@see http://msdn.microsoft.com/en-us/library/dd950560%28v=office.12%29.aspx
$fileBlockRH = $this->loadRecordHeader($this->dataData, $sprmCPicLocation);
while ($fileBlockRH['recType'] == 0xF007 || ($fileBlockRH['recType'] >= 0xF018 && $fileBlockRH['recType'] <= 0xF117)) {
$sprmCPicLocation += 8;
switch ($fileBlockRH['recType']) {
// OfficeArtFBSE
//@see : http://msdn.microsoft.com/en-us/library/dd944923%28v=office.12%29.aspx
//@see http://msdn.microsoft.com/en-us/library/dd944923%28v=office.12%29.aspx
case 0xF007:
// btWin32
++$sprmCPicLocation;
@@ -2239,7 +2246,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
}
}
// embeddedBlip
//@see : http://msdn.microsoft.com/en-us/library/dd910081%28v=office.12%29.aspx
//@see http://msdn.microsoft.com/en-us/library/dd910081%28v=office.12%29.aspx
$embeddedBlipRH = $this->loadRecordHeader($this->dataData, $sprmCPicLocation);
switch ($embeddedBlipRH['recType']) {
case self::OFFICEARTBLIPJPG:

View File

@@ -53,13 +53,8 @@ class ODText extends AbstractReader implements ReaderInterface
/**
* Read document part.
*
* @param array $relationships
* @param string $partName
* @param string $docFile
* @param string $xmlFile
*/
private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile, $xmlFile): void
private function readPart(PhpWord $phpWord, array $relationships, string $partName, string $docFile, string $xmlFile): void
{
$partClass = "PhpOffice\\PhpWord\\Reader\\ODText\\{$partName}";
if (class_exists($partClass)) {
@@ -72,12 +67,8 @@ class ODText extends AbstractReader implements ReaderInterface
/**
* Read all relationship files.
*
* @param string $docFile
*
* @return array
*/
private function readRelationships($docFile)
private function readRelationships(string $docFile): array
{
$rels = [];
$xmlFile = 'META-INF/manifest.xml';

View File

@@ -18,6 +18,10 @@
namespace PhpOffice\PhpWord\Reader\ODText;
use DateTime;
use DOMElement;
use DOMNodeList;
use PhpOffice\Math\Reader\MathML;
use PhpOffice\PhpWord\Element\Section;
use PhpOffice\PhpWord\Element\TrackChange;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLReader;
@@ -29,6 +33,9 @@ use PhpOffice\PhpWord\Shared\XMLReader;
*/
class Content extends AbstractPart
{
/** @var ?Section */
private $section;
/**
* Read content.xml.
*/
@@ -40,48 +47,112 @@ class Content extends AbstractPart
$trackedChanges = [];
$nodes = $xmlReader->getElements('office:body/office:text/*');
$this->section = null;
$this->processNodes($nodes, $xmlReader, $phpWord);
$this->section = null;
}
/** @param DOMNodeList<DOMElement> $nodes */
public function processNodes(DOMNodeList $nodes, XMLReader $xmlReader, PhpWord $phpWord): void
{
if ($nodes->length > 0) {
$section = $phpWord->addSection();
foreach ($nodes as $node) {
// $styleName = $xmlReader->getAttribute('text:style-name', $node);
switch ($node->nodeName) {
case 'text:h': // Heading
$depth = $xmlReader->getAttribute('text:outline-level', $node);
$section->addTitle($node->nodeValue, $depth);
$this->getSection($phpWord)->addTitle($node->nodeValue, $depth);
break;
case 'text:p': // Paragraph
$children = $node->childNodes;
foreach ($children as $child) {
switch ($child->nodeName) {
case 'text:change-start':
$changeId = $child->getAttribute('text:change-id');
if (isset($trackedChanges[$changeId])) {
$changed = $trackedChanges[$changeId];
}
break;
case 'text:change-end':
unset($changed);
break;
case 'text:change':
$changeId = $child->getAttribute('text:change-id');
if (isset($trackedChanges[$changeId])) {
$changed = $trackedChanges[$changeId];
}
break;
}
$styleName = $xmlReader->getAttribute('text:style-name', $node);
if (substr($styleName, 0, 2) === 'SB') {
break;
}
$element = $xmlReader->getElement('draw:frame/draw:object', $node);
if ($element) {
$mathFile = str_replace('./', '', $element->getAttribute('xlink:href')) . '/content.xml';
$element = $section->addText($node->nodeValue);
if (isset($changed) && is_array($changed)) {
$element->setTrackChange($changed['changed']);
if (isset($changed['textNodes'])) {
foreach ($changed['textNodes'] as $changedNode) {
$element = $section->addText($changedNode->nodeValue);
$element->setTrackChange($changed['changed']);
$xmlReaderObject = new XMLReader();
$mathElement = $xmlReaderObject->getDomFromZip($this->docFile, $mathFile);
if ($mathElement) {
$mathXML = $mathElement->saveXML($mathElement);
if (is_string($mathXML)) {
$reader = new MathML();
$math = $reader->read($mathXML);
$this->getSection($phpWord)->addFormula($math);
}
}
} else {
$children = $node->childNodes;
$spans = false;
/** @var DOMElement $child */
foreach ($children as $child) {
switch ($child->nodeName) {
case 'text:change-start':
$changeId = $child->getAttribute('text:change-id');
if (isset($trackedChanges[$changeId])) {
$changed = $trackedChanges[$changeId];
}
break;
case 'text:change-end':
unset($changed);
break;
case 'text:change':
$changeId = $child->getAttribute('text:change-id');
if (isset($trackedChanges[$changeId])) {
$changed = $trackedChanges[$changeId];
}
break;
case 'text:span':
$spans = true;
break;
}
}
if ($spans) {
$element = $this->getSection($phpWord)->addTextRun();
foreach ($children as $child) {
switch ($child->nodeName) {
case 'text:span':
/** @var DOMElement $child2 */
foreach ($child->childNodes as $child2) {
switch ($child2->nodeName) {
case '#text':
$element->addText($child2->nodeValue);
break;
case 'text:tab':
$element->addText("\t");
break;
case 'text:s':
$spaces = (int) $child2->getAttribute('text:c') ?: 1;
$element->addText(str_repeat(' ', $spaces));
break;
}
}
break;
}
}
} else {
$element = $this->getSection($phpWord)->addText($node->nodeValue);
}
if (isset($changed) && is_array($changed)) {
$element->setTrackChange($changed['changed']);
if (isset($changed['textNodes'])) {
foreach ($changed['textNodes'] as $changedNode) {
$element = $this->getSection($phpWord)->addText($changedNode->nodeValue);
$element->setTrackChange($changed['changed']);
}
}
}
}
@@ -91,7 +162,7 @@ class Content extends AbstractPart
$listItems = $xmlReader->getElements('text:list-item/text:p', $node);
foreach ($listItems as $listItem) {
// $listStyleName = $xmlReader->getAttribute('text:style-name', $listItem);
$section->addListItem($listItem->nodeValue, 0);
$this->getSection($phpWord)->addListItem($listItem->nodeValue, 0);
}
break;
@@ -110,9 +181,26 @@ class Content extends AbstractPart
$trackedChanges[$changedRegion->getAttribute('text:id')] = ['changed' => $changed, 'textNodes' => $textNodes];
}
break;
case 'text:section': // Section
// $sectionStyleName = $xmlReader->getAttribute('text:style-name', $listItem);
$this->section = $phpWord->addSection();
$children = $node->childNodes;
$this->processNodes($children, $xmlReader, $phpWord);
break;
}
}
}
}
private function getSection(PhpWord $phpWord): Section
{
$section = $this->section;
if ($section === null) {
$section = $this->section = $phpWord->addSection();
}
return $section;
}
}

View File

@@ -17,7 +17,10 @@
namespace PhpOffice\PhpWord\Reader;
use Exception;
use PhpOffice\PhpWord\Element\AbstractElement;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Reader\Word2007\AbstractPart;
use PhpOffice\PhpWord\Shared\XMLReader;
use PhpOffice\PhpWord\Shared\ZipArchive;
@@ -42,23 +45,34 @@ class Word2007 extends AbstractReader implements ReaderInterface
{
$phpWord = new PhpWord();
$relationships = $this->readRelationships($docFile);
$commentRefs = [];
$steps = [
['stepPart' => 'document', 'stepItems' => [
'styles' => 'Styles',
'numbering' => 'Numbering',
]],
['stepPart' => 'main', 'stepItems' => [
'officeDocument' => 'Document',
'core-properties' => 'DocPropsCore',
'extended-properties' => 'DocPropsApp',
'custom-properties' => 'DocPropsCustom',
]],
['stepPart' => 'document', 'stepItems' => [
'endnotes' => 'Endnotes',
'footnotes' => 'Footnotes',
'settings' => 'Settings',
]],
[
'stepPart' => 'document',
'stepItems' => [
'styles' => 'Styles',
'numbering' => 'Numbering',
],
],
[
'stepPart' => 'main',
'stepItems' => [
'officeDocument' => 'Document',
'core-properties' => 'DocPropsCore',
'extended-properties' => 'DocPropsApp',
'custom-properties' => 'DocPropsCustom',
],
],
[
'stepPart' => 'document',
'stepItems' => [
'endnotes' => 'Endnotes',
'footnotes' => 'Footnotes',
'settings' => 'Settings',
'comments' => 'Comments',
],
],
];
foreach ($steps as $step) {
@@ -72,7 +86,8 @@ class Word2007 extends AbstractReader implements ReaderInterface
if (isset($stepItems[$relType])) {
$partName = $stepItems[$relType];
$xmlFile = $relItem['target'];
$this->readPart($phpWord, $relationships, $partName, $docFile, $xmlFile);
$part = $this->readPart($phpWord, $relationships, $commentRefs, $partName, $docFile, $xmlFile);
$commentRefs = $part->getCommentReferences();
}
}
}
@@ -83,20 +98,23 @@ class Word2007 extends AbstractReader implements ReaderInterface
/**
* Read document part.
*
* @param array $relationships
* @param string $partName
* @param string $docFile
* @param string $xmlFile
* @param array<string, array<string, null|AbstractElement>> $commentRefs
*/
private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile, $xmlFile): void
private function readPart(PhpWord $phpWord, array $relationships, array $commentRefs, string $partName, string $docFile, string $xmlFile): AbstractPart
{
$partClass = "PhpOffice\\PhpWord\\Reader\\Word2007\\{$partName}";
if (class_exists($partClass)) {
/** @var \PhpOffice\PhpWord\Reader\Word2007\AbstractPart $part Type hint */
$part = new $partClass($docFile, $xmlFile);
$part->setRels($relationships);
$part->read($phpWord);
if (!class_exists($partClass)) {
throw new Exception(sprintf('The part "%s" doesn\'t exist', $partClass));
}
/** @var AbstractPart $part Type hint */
$part = new $partClass($docFile, $xmlFile);
$part->setImageLoading($this->hasImageLoading());
$part->setRels($relationships);
$part->setCommentReferences($commentRefs);
$part->read($phpWord);
return $part;
}
/**

View File

@@ -19,8 +19,11 @@ namespace PhpOffice\PhpWord\Reader\Word2007;
use DateTime;
use DOMElement;
use InvalidArgumentException;
use PhpOffice\Math\Reader\OfficeMathML;
use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType;
use PhpOffice\PhpWord\Element\AbstractContainer;
use PhpOffice\PhpWord\Element\AbstractElement;
use PhpOffice\PhpWord\Element\TextRun;
use PhpOffice\PhpWord\Element\TrackChange;
use PhpOffice\PhpWord\PhpWord;
@@ -67,6 +70,20 @@ abstract class AbstractPart
*/
protected $rels = [];
/**
* Comment references.
*
* @var array<string, array<string, AbstractElement>>
*/
protected $commentRefs = [];
/**
* Image Loading.
*
* @var bool
*/
protected $imageLoading = true;
/**
* Read part.
*/
@@ -94,6 +111,74 @@ abstract class AbstractPart
$this->rels = $value;
}
public function setImageLoading(bool $value): self
{
$this->imageLoading = $value;
return $this;
}
public function hasImageLoading(): bool
{
return $this->imageLoading;
}
/**
* Get comment references.
*
* @return array<string, array<string, null|AbstractElement>>
*/
public function getCommentReferences(): array
{
return $this->commentRefs;
}
/**
* Set comment references.
*
* @param array<string, array<string, null|AbstractElement>> $commentRefs
*/
public function setCommentReferences(array $commentRefs): self
{
$this->commentRefs = $commentRefs;
return $this;
}
/**
* Set comment reference.
*/
private function setCommentReference(string $type, string $id, AbstractElement $element): self
{
if (!in_array($type, ['start', 'end'])) {
throw new InvalidArgumentException('Type must be "start" or "end"');
}
if (!array_key_exists($id, $this->commentRefs)) {
$this->commentRefs[$id] = [
'start' => null,
'end' => null,
];
}
$this->commentRefs[$id][$type] = $element;
return $this;
}
/**
* Get comment reference.
*
* @return array<string, null|AbstractElement>
*/
protected function getCommentReference(string $id): array
{
if (!array_key_exists($id, $this->commentRefs)) {
throw new InvalidArgumentException(sprintf('Comment with id %s isn\'t referenced in document', $id));
}
return $this->commentRefs[$id];
}
/**
* Read w:p.
*
@@ -105,12 +190,7 @@ abstract class AbstractPart
protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $parent, $docPart = 'document'): void
{
// Paragraph style
$paragraphStyle = null;
$headingDepth = null;
if ($xmlReader->elementExists('w:pPr', $domNode)) {
$paragraphStyle = $this->readParagraphStyle($xmlReader, $domNode);
$headingDepth = $this->getHeadingDepth($paragraphStyle);
}
$paragraphStyle = $xmlReader->elementExists('w:pPr', $domNode) ? $this->readParagraphStyle($xmlReader, $domNode) : null;
// PreserveText
if ($xmlReader->elementExists('w:r/w:instrText', $domNode)) {
@@ -137,8 +217,27 @@ abstract class AbstractPart
}
}
$parent->addPreserveText(htmlspecialchars($textContent, ENT_QUOTES, 'UTF-8'), $fontStyle, $paragraphStyle);
} elseif ($xmlReader->elementExists('w:pPr/w:numPr', $domNode)) {
// List item
return;
}
// Formula
$xmlReader->registerNamespace('m', 'http://schemas.openxmlformats.org/officeDocument/2006/math');
if ($xmlReader->elementExists('m:oMath', $domNode)) {
$mathElement = $xmlReader->getElement('m:oMath', $domNode);
$mathXML = $mathElement->ownerDocument->saveXML($mathElement);
if (is_string($mathXML)) {
$reader = new OfficeMathML();
$math = $reader->read($mathXML);
$parent->addFormula($math);
}
return;
}
// List item
if ($xmlReader->elementExists('w:pPr/w:numPr', $domNode)) {
$numId = $xmlReader->getAttribute('w:val', $domNode, 'w:pPr/w:numPr/w:numId');
$levelId = $xmlReader->getAttribute('w:val', $domNode, 'w:pPr/w:numPr/w:ilvl');
$nodes = $xmlReader->getElements('*', $domNode);
@@ -148,10 +247,15 @@ abstract class AbstractPart
foreach ($nodes as $node) {
$this->readRun($xmlReader, $node, $listItemRun, $docPart, $paragraphStyle);
}
} elseif ($headingDepth !== null) {
// Heading or Title
return;
}
// Heading or Title
$headingDepth = $xmlReader->elementExists('w:pPr', $domNode) ? $this->getHeadingDepth($paragraphStyle) : null;
if ($headingDepth !== null) {
$textContent = null;
$nodes = $xmlReader->getElements('w:r', $domNode);
$nodes = $xmlReader->getElements('w:r|w:hyperlink', $domNode);
if ($nodes->length === 1) {
$textContent = htmlspecialchars($xmlReader->getValue('w:t', $nodes->item(0)), ENT_QUOTES, 'UTF-8');
} else {
@@ -161,17 +265,19 @@ abstract class AbstractPart
}
}
$parent->addTitle($textContent, $headingDepth);
return;
}
// Text and TextRun
$textRunContainers = $xmlReader->countElements('w:r|w:ins|w:del|w:hyperlink|w:smartTag|w:commentReference|w:commentRangeStart|w:commentRangeEnd', $domNode);
if (0 === $textRunContainers) {
$parent->addTextBreak(null, $paragraphStyle);
} else {
// Text and TextRun
$textRunContainers = $xmlReader->countElements('w:r|w:ins|w:del|w:hyperlink|w:smartTag', $domNode);
if (0 === $textRunContainers) {
$parent->addTextBreak(null, $paragraphStyle);
} else {
$nodes = $xmlReader->getElements('*', $domNode);
$paragraph = $parent->addTextRun($paragraphStyle);
foreach ($nodes as $node) {
$this->readRun($xmlReader, $node, $paragraph, $docPart, $paragraphStyle);
}
$nodes = $xmlReader->getElements('*', $domNode);
$paragraph = $parent->addTextRun($paragraphStyle);
foreach ($nodes as $node) {
$this->readRun($xmlReader, $node, $paragraph, $docPart, $paragraphStyle);
}
}
}
@@ -179,8 +285,6 @@ abstract class AbstractPart
/**
* Returns the depth of the Heading, returns 0 for a Title.
*
* @param array $paragraphStyle
*
* @return null|number
*/
private function getHeadingDepth(?array $paragraphStyle = null)
@@ -211,7 +315,7 @@ abstract class AbstractPart
*/
protected function readRun(XMLReader $xmlReader, DOMElement $domNode, $parent, $docPart, $paragraphStyle = null): void
{
if (in_array($domNode->nodeName, ['w:ins', 'w:del', 'w:smartTag', 'w:hyperlink'])) {
if (in_array($domNode->nodeName, ['w:ins', 'w:del', 'w:smartTag', 'w:hyperlink', 'w:commentReference'])) {
$nodes = $xmlReader->getElements('*', $domNode);
foreach ($nodes as $node) {
$this->readRun($xmlReader, $node, $parent, $docPart, $paragraphStyle);
@@ -223,6 +327,17 @@ abstract class AbstractPart
$this->readRunChild($xmlReader, $node, $parent, $docPart, $paragraphStyle, $fontStyle);
}
}
if ($xmlReader->elementExists('.//*["commentReference"=local-name()]', $domNode)) {
$node = iterator_to_array($xmlReader->getElements('.//*["commentReference"=local-name()]', $domNode))[0];
$attributeIdentifier = $node->attributes->getNamedItem('id');
if ($attributeIdentifier) {
$id = $attributeIdentifier->nodeValue;
$this->setCommentReference('start', $id, $parent->getElement($parent->countElements() - 1));
$this->setCommentReference('end', $id, $parent->getElement($parent->countElements() - 1));
}
}
}
/**
@@ -249,7 +364,7 @@ abstract class AbstractPart
// Image
$rId = $xmlReader->getAttribute('r:id', $node, 'v:shape/v:imagedata');
$target = $this->getMediaTarget($docPart, $rId);
if (null !== $target) {
if ($this->hasImageLoading() && null !== $target) {
if ('External' == $this->getTargetMode($docPart, $rId)) {
$imageSource = $target;
} else {
@@ -271,7 +386,7 @@ abstract class AbstractPart
$embedId = $xmlReader->getAttribute('r:embed', $node, 'wp:anchor/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip');
}
$target = $this->getMediaTarget($docPart, $embedId);
if (null !== $target) {
if ($this->hasImageLoading() && null !== $target) {
$imageSource = "zip://{$this->docFile}#{$target}";
$parent->addImage($imageSource, null, false, $name);
}
@@ -320,9 +435,12 @@ abstract class AbstractPart
$type = ($runParent->nodeName == 'w:del') ? TrackChange::DELETED : TrackChange::INSERTED;
$author = $runParent->getAttribute('w:author');
$date = DateTime::createFromFormat('Y-m-d\TH:i:s\Z', $runParent->getAttribute('w:date'));
$date = $date instanceof DateTime ? $date : null;
$element->setChangeInfo($type, $author, $date);
}
}
} elseif ($node->nodeName == 'w:softHyphen') {
$element = $parent->addText("\u{200c}", $fontStyle, $paragraphStyle);
}
}
@@ -364,9 +482,8 @@ abstract class AbstractPart
} elseif ('w:tc' == $rowNode->nodeName) { // Cell
$cellWidth = $xmlReader->getAttribute('w:w', $rowNode, 'w:tcPr/w:tcW');
$cellStyle = null;
$cellStyleNode = $xmlReader->getElement('w:tcPr', $rowNode);
if (null !== $cellStyleNode) {
$cellStyle = $this->readCellStyle($xmlReader, $cellStyleNode);
if ($xmlReader->elementExists('w:tcPr', $rowNode)) {
$cellStyle = $this->readCellStyle($xmlReader, $rowNode);
}
$cell = $row->addCell($cellWidth, $cellStyle);
@@ -374,6 +491,8 @@ abstract class AbstractPart
foreach ($cellNodes as $cellNode) {
if ('w:p' == $cellNode->nodeName) { // Paragraph
$this->readParagraph($xmlReader, $cellNode, $cell, $docPart);
} elseif ($cellNode->nodeName == 'w:tbl') { // Table
$this->readTable($xmlReader, $cellNode, $cell, $docPart);
}
}
}
@@ -550,7 +669,7 @@ abstract class AbstractPart
/**
* Read w:tcPr.
*
* @return array
* @return null|array
*/
private function readCellStyle(XMLReader $xmlReader, DOMElement $domNode)
{
@@ -558,11 +677,28 @@ abstract class AbstractPart
'valign' => [self::READ_VALUE, 'w:vAlign'],
'textDirection' => [self::READ_VALUE, 'w:textDirection'],
'gridSpan' => [self::READ_VALUE, 'w:gridSpan'],
'vMerge' => [self::READ_VALUE, 'w:vMerge'],
'vMerge' => [self::READ_VALUE, 'w:vMerge', null, null, 'continue'],
'bgColor' => [self::READ_VALUE, 'w:shd', 'w:fill'],
'noWrap' => [self::READ_VALUE, 'w:noWrap', null, null, true],
];
$style = null;
return $this->readStyleDefs($xmlReader, $domNode, $styleDefs);
if ($xmlReader->elementExists('w:tcPr', $domNode)) {
$styleNode = $xmlReader->getElement('w:tcPr', $domNode);
$borders = ['top', 'left', 'bottom', 'right'];
foreach ($borders as $side) {
$ucfSide = ucfirst($side);
$styleDefs['border' . $ucfSide . 'Size'] = [self::READ_VALUE, 'w:tcBorders/w:' . $side, 'w:sz'];
$styleDefs['border' . $ucfSide . 'Color'] = [self::READ_VALUE, 'w:tcBorders/w:' . $side, 'w:color'];
$styleDefs['border' . $ucfSide . 'Style'] = [self::READ_VALUE, 'w:tcBorders/w:' . $side, 'w:val'];
}
$style = $this->readStyleDefs($xmlReader, $styleNode, $styleDefs);
}
return $style;
}
/**
@@ -614,7 +750,6 @@ abstract class AbstractPart
/**
* Read style definition.
*
* @param DOMElement $parentNode
* @param array $styleDefs
*
* @ignoreScrutinizerPatch
@@ -626,7 +761,7 @@ abstract class AbstractPart
$styles = [];
foreach ($styleDefs as $styleProp => $styleVal) {
[$method, $element, $attribute, $expected] = array_pad($styleVal, 4, null);
[$method, $element, $attribute, $expected, $default] = array_pad($styleVal, 5, null);
$element = $this->findPossibleElement($xmlReader, $parentNode, $element);
if ($element === null) {
@@ -640,7 +775,7 @@ abstract class AbstractPart
// Use w:val as default if no attribute assigned
$attribute = ($attribute === null) ? 'w:val' : $attribute;
$attributeValue = $xmlReader->getAttribute($attribute, $node);
$attributeValue = $xmlReader->getAttribute($attribute, $node) ?? $default;
$styleValue = $this->readStyleDef($method, $attributeValue, $expected);
if ($styleValue !== null) {

View File

@@ -0,0 +1,56 @@
<?php
namespace PhpOffice\PhpWord\Reader\Word2007;
use DateTime;
use PhpOffice\PhpWord\Element\Comment;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Shared\XMLReader;
class Comments extends AbstractPart
{
/**
* Collection name comments.
*
* @var string
*/
protected $collection = 'comments';
/**
* Read settings.xml.
*/
public function read(PhpWord $phpWord): void
{
$xmlReader = new XMLReader();
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
$comments = $phpWord->getComments();
$nodes = $xmlReader->getElements('*');
foreach ($nodes as $node) {
$name = str_replace('w:', '', $node->nodeName);
$author = $xmlReader->getAttribute('w:author', $node);
$date = $xmlReader->getAttribute('w:date', $node);
$initials = $xmlReader->getAttribute('w:initials', $node);
$element = new Comment($author, new DateTime($date), $initials);
$range = $this->getCommentReference($xmlReader->getAttribute('w:id', $node));
if ($range['start']) {
$range['start']->setCommentRangeStart($element);
}
if ($range['end']) {
$range['end']->setCommentRangeEnd($element);
}
$pNodes = $xmlReader->getElements('w:p/w:r', $node);
foreach ($pNodes as $pNode) {
$this->readRun($xmlReader, $pNode, $element, $this->collection);
}
$phpWord->getComments()->addItem($element);
}
}
}

View File

@@ -30,7 +30,10 @@ use PhpOffice\PhpWord\Style\Language;
*/
class Settings extends AbstractPart
{
private static $booleanProperties = [
/**
* @var array<string>
*/
private $booleanProperties = [
'mirrorMargins',
'hideSpellingErrors',
'hideGrammaticalErrors',
@@ -41,6 +44,7 @@ class Settings extends AbstractPart
'updateFields',
'autoHyphenation',
'doNotHyphenateCaps',
'bookFoldPrinting',
];
/**
@@ -60,12 +64,8 @@ class Settings extends AbstractPart
$value = $xmlReader->getAttribute('w:val', $node);
$method = 'set' . $name;
if (in_array($name, $this::$booleanProperties)) {
if ($value == 'false') {
$docSettings->$method(false);
} else {
$docSettings->$method(true);
}
if (in_array($name, $this->booleanProperties)) {
$docSettings->$method($value !== 'false');
} elseif (method_exists($this, $method)) {
$this->$method($xmlReader, $phpWord, $node);
} elseif (method_exists($docSettings, $method)) {

View File

@@ -39,14 +39,16 @@ class Styles extends AbstractPart
$fontDefaults = $xmlReader->getElement('w:docDefaults/w:rPrDefault');
if ($fontDefaults !== null) {
$fontDefaultStyle = $this->readFontStyle($xmlReader, $fontDefaults);
if (array_key_exists('name', $fontDefaultStyle)) {
$phpWord->setDefaultFontName($fontDefaultStyle['name']);
}
if (array_key_exists('size', $fontDefaultStyle)) {
$phpWord->setDefaultFontSize($fontDefaultStyle['size']);
}
if (array_key_exists('lang', $fontDefaultStyle)) {
$phpWord->getSettings()->setThemeFontLang(new Language($fontDefaultStyle['lang']));
if ($fontDefaultStyle) {
if (array_key_exists('name', $fontDefaultStyle)) {
$phpWord->setDefaultFontName($fontDefaultStyle['name']);
}
if (array_key_exists('size', $fontDefaultStyle)) {
$phpWord->setDefaultFontSize($fontDefaultStyle['size']);
}
if (array_key_exists('lang', $fontDefaultStyle)) {
$phpWord->getSettings()->setThemeFontLang(new Language($fontDefaultStyle['lang']));
}
}
}

View File

@@ -2,10 +2,8 @@
/**
* 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.
@@ -29,48 +27,46 @@ class Settings
*
* @const string
*/
const ZIPARCHIVE = 'ZipArchive';
const PCLZIP = 'PclZip';
const OLD_LIB = \PhpOffice\PhpWord\Shared\ZipArchive::class; // @deprecated 0.11
public const ZIPARCHIVE = 'ZipArchive';
public const PCLZIP = 'PclZip';
public const OLD_LIB = \PhpOffice\PhpWord\Shared\ZipArchive::class; // @deprecated 0.11
/**
* PDF rendering libraries.
*
* @const string
*/
const PDF_RENDERER_DOMPDF = 'DomPDF';
const PDF_RENDERER_TCPDF = 'TCPDF';
const PDF_RENDERER_MPDF = 'MPDF';
public const PDF_RENDERER_DOMPDF = 'DomPDF';
public const PDF_RENDERER_TCPDF = 'TCPDF';
public const PDF_RENDERER_MPDF = 'MPDF';
/**
* Measurement units multiplication factor.
*
* Applied to:
* - Section: margins, header/footer height, gutter, column spacing
* - Tab: position
* - Indentation: left, right, firstLine, hanging
* - Spacing: before, after
* - Spacing: before, after.
*
* @const string
*/
const UNIT_TWIP = 'twip'; // = 1/20 point
const UNIT_CM = 'cm';
const UNIT_MM = 'mm';
const UNIT_INCH = 'inch';
const UNIT_POINT = 'point'; // = 1/72 inch
const UNIT_PICA = 'pica'; // = 1/6 inch = 12 points
public const UNIT_TWIP = 'twip'; // = 1/20 point
public const UNIT_CM = 'cm';
public const UNIT_MM = 'mm';
public const UNIT_INCH = 'inch';
public const UNIT_POINT = 'point'; // = 1/72 inch
public const UNIT_PICA = 'pica'; // = 1/6 inch = 12 points
/**
* Default font settings.
*
* OOXML defined font size values in halfpoints, i.e. twice of what PhpWord
* use, and the conversion will be conducted during XML writing.
*/
const DEFAULT_FONT_NAME = 'Arial';
const DEFAULT_FONT_SIZE = 10;
const DEFAULT_FONT_COLOR = '000000';
const DEFAULT_FONT_CONTENT_TYPE = 'default'; // default|eastAsia|cs
const DEFAULT_PAPER = 'A4';
public const DEFAULT_FONT_NAME = 'Arial';
public const DEFAULT_FONT_SIZE = 10;
public const DEFAULT_FONT_COLOR = '000000';
public const DEFAULT_FONT_CONTENT_TYPE = 'default'; // default|eastAsia|cs
public const DEFAULT_PAPER = 'A4';
/**
* Compatibility option for XMLWriter.
@@ -89,21 +85,28 @@ class Settings
/**
* Name of the external Library used for rendering PDF files.
*
* @var string
* @var null|string
*/
private static $pdfRendererName;
/**
* Options used for rendering PDF files.
*
* @var array
*/
private static $pdfRendererOptions = [];
/**
* Directory Path to the external Library used for rendering PDF files.
*
* @var string
* @var null|string
*/
private static $pdfRendererPath;
/**
* Measurement unit.
*
* @var float|int
* @var string
*/
private static $measurementUnit = self::UNIT_TWIP;
@@ -117,7 +120,7 @@ class Settings
/**
* Default font size.
*
* @var int
* @var float|int
*/
private static $defaultFontSize = self::DEFAULT_FONT_SIZE;
@@ -128,6 +131,13 @@ class Settings
*/
private static $defaultPaper = self::DEFAULT_PAPER;
/**
* Is RTL by default ?
*
* @var ?bool
*/
private static $defaultRtl;
/**
* The user defined temporary directory.
*
@@ -148,23 +158,17 @@ class Settings
*
* @return bool Compatibility
*/
public static function hasCompatibility()
public static function hasCompatibility(): bool
{
return self::$xmlWriterCompatibility;
}
/**
* Set the compatibility option used by the XMLWriter.
*
* This sets the setIndent and setIndentString for better compatibility
*
* @param bool $compatibility
*
* @return bool
* This sets the setIndent and setIndentString for better compatibility.
*/
public static function setCompatibility($compatibility)
public static function setCompatibility(bool $compatibility): bool
{
$compatibility = (bool) $compatibility;
self::$xmlWriterCompatibility = $compatibility;
return true;
@@ -172,22 +176,16 @@ class Settings
/**
* Get zip handler class.
*
* @return string
*/
public static function getZipClass()
public static function getZipClass(): string
{
return self::$zipClass;
}
/**
* Set zip handler class.
*
* @param string $zipClass
*
* @return bool
*/
public static function setZipClass($zipClass)
public static function setZipClass(string $zipClass): bool
{
if (in_array($zipClass, [self::PCLZIP, self::ZIPARCHIVE, self::OLD_LIB])) {
self::$zipClass = $zipClass;
@@ -201,12 +199,9 @@ class Settings
/**
* Set details of the external library for rendering PDF files.
*
* @param string $libraryName
* @param string $libraryBaseDir
*
* @return bool Success or failure
*/
public static function setPdfRenderer($libraryName, $libraryBaseDir)
public static function setPdfRenderer(string $libraryName, string $libraryBaseDir): bool
{
if (!self::setPdfRendererName($libraryName)) {
return false;
@@ -217,22 +212,16 @@ class Settings
/**
* Return the PDF Rendering Library.
*
* @return string
*/
public static function getPdfRendererName()
public static function getPdfRendererName(): ?string
{
return self::$pdfRendererName;
}
/**
* Identify the external library to use for rendering PDF files.
*
* @param string $libraryName
*
* @return bool
*/
public static function setPdfRendererName($libraryName)
public static function setPdfRendererName(?string $libraryName): bool
{
$pdfRenderers = [self::PDF_RENDERER_DOMPDF, self::PDF_RENDERER_TCPDF, self::PDF_RENDERER_MPDF];
if (!in_array($libraryName, $pdfRenderers)) {
@@ -245,22 +234,36 @@ class Settings
/**
* Return the directory path to the PDF Rendering Library.
*
* @return string
*/
public static function getPdfRendererPath()
public static function getPdfRendererPath(): ?string
{
return self::$pdfRendererPath;
}
/**
* Set options of the external library for rendering PDF files.
*/
public static function setPdfRendererOptions(array $options): void
{
self::$pdfRendererOptions = $options;
}
/**
* Return the PDF Rendering Options.
*/
public static function getPdfRendererOptions(): array
{
return self::$pdfRendererOptions;
}
/**
* Location of external library to use for rendering PDF files.
*
* @param string $libraryBaseDir Directory path to the library's base folder
* @param null|string $libraryBaseDir Directory path to the library's base folder
*
* @return bool Success or failure
*/
public static function setPdfRendererPath($libraryBaseDir)
public static function setPdfRendererPath(?string $libraryBaseDir): bool
{
if (!$libraryBaseDir || false === file_exists($libraryBaseDir) || false === is_readable($libraryBaseDir)) {
return false;
@@ -272,25 +275,25 @@ class Settings
/**
* Get measurement unit.
*
* @return string
*/
public static function getMeasurementUnit()
public static function getMeasurementUnit(): string
{
return self::$measurementUnit;
}
/**
* Set measurement unit.
*
* @param string $value
*
* @return bool
*/
public static function setMeasurementUnit($value)
public static function setMeasurementUnit(string $value): bool
{
$units = [self::UNIT_TWIP, self::UNIT_CM, self::UNIT_MM, self::UNIT_INCH,
self::UNIT_POINT, self::UNIT_PICA, ];
$units = [
self::UNIT_TWIP,
self::UNIT_CM,
self::UNIT_MM,
self::UNIT_INCH,
self::UNIT_POINT,
self::UNIT_PICA,
];
if (!in_array($value, $units)) {
return false;
}
@@ -302,11 +305,11 @@ class Settings
/**
* Sets the user defined path to temporary directory.
*
* @since 0.12.0
*
* @param string $tempDir The user defined path to temporary directory
*
* @since 0.12.0
*/
public static function setTempDir($tempDir): void
public static function setTempDir(string $tempDir): void
{
self::$tempDir = $tempDir;
}
@@ -315,10 +318,8 @@ class Settings
* Returns path to temporary directory.
*
* @since 0.12.0
*
* @return string
*/
public static function getTempDir()
public static function getTempDir(): string
{
if (!empty(self::$tempDir)) {
$tempDir = self::$tempDir;
@@ -331,44 +332,34 @@ class Settings
/**
* @since 0.13.0
*
* @return bool
*/
public static function isOutputEscapingEnabled()
public static function isOutputEscapingEnabled(): bool
{
return self::$outputEscapingEnabled;
}
/**
* @since 0.13.0
*
* @param bool $outputEscapingEnabled
*/
public static function setOutputEscapingEnabled($outputEscapingEnabled): void
public static function setOutputEscapingEnabled(bool $outputEscapingEnabled): void
{
self::$outputEscapingEnabled = $outputEscapingEnabled;
}
/**
* Get default font name.
*
* @return string
*/
public static function getDefaultFontName()
public static function getDefaultFontName(): string
{
return self::$defaultFontName;
}
/**
* Set default font name.
*
* @param string $value
*
* @return bool
*/
public static function setDefaultFontName($value)
public static function setDefaultFontName(string $value): bool
{
if (is_string($value) && trim($value) !== '') {
if (trim($value) !== '') {
self::$defaultFontName = $value;
return true;
@@ -380,7 +371,7 @@ class Settings
/**
* Get default font size.
*
* @return int
* @return float|int
*/
public static function getDefaultFontSize()
{
@@ -390,14 +381,11 @@ class Settings
/**
* Set default font size.
*
* @param int $value
*
* @return bool
* @param null|float|int $value
*/
public static function setDefaultFontSize($value)
public static function setDefaultFontSize($value): bool
{
$value = (int) $value;
if ($value > 0) {
if ((is_int($value) || is_float($value)) && (int) $value > 0) {
self::$defaultFontSize = $value;
return true;
@@ -406,14 +394,20 @@ class Settings
return false;
}
public static function setDefaultRtl(?bool $defaultRtl): void
{
self::$defaultRtl = $defaultRtl;
}
public static function isDefaultRtl(): ?bool
{
return self::$defaultRtl;
}
/**
* Load setting from phpword.yml or phpword.yml.dist.
*
* @param string $filename
*
* @return array
*/
public static function loadConfig($filename = null)
public static function loadConfig(?string $filename = null): array
{
// Get config file
$configFile = null;
@@ -455,24 +449,18 @@ class Settings
/**
* Get default paper.
*
* @return string
*/
public static function getDefaultPaper()
public static function getDefaultPaper(): string
{
return self::$defaultPaper;
}
/**
* Set default paper.
*
* @param string $value
*
* @return bool
*/
public static function setDefaultPaper($value)
public static function setDefaultPaper(string $value): bool
{
if (is_string($value) && trim($value) !== '') {
if (trim($value) !== '') {
self::$defaultPaper = $value;
return true;

View File

@@ -374,7 +374,7 @@ class Converter
*
* @param string $value
*
* @return float
* @return ?float
*/
public static function cssToPoint($value)
{

View File

@@ -0,0 +1,80 @@
<?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
*
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
declare(strict_types=1);
namespace PhpOffice\PhpWord\Shared;
class Css
{
/**
* @var string
*/
private $cssContent;
/**
* @var array<string, array<string, string>>
*/
private $styles = [];
public function __construct(string $cssContent)
{
$this->cssContent = $cssContent;
}
public function process(): void
{
$cssContent = str_replace(["\r", "\n"], '', $this->cssContent);
preg_match_all('/(.+?)\s?\{\s?(.+?)\s?\}/', $cssContent, $cssExtracted);
// Check the number of extracted
if (count($cssExtracted) != 3) {
return;
}
// Check if there are x selectors and x rules
if (count($cssExtracted[1]) != count($cssExtracted[2])) {
return;
}
foreach ($cssExtracted[1] as $key => $selector) {
$rules = trim($cssExtracted[2][$key]);
$rules = explode(';', $rules);
foreach ($rules as $rule) {
if (empty($rule)) {
continue;
}
[$key, $value] = explode(':', trim($rule));
$this->styles[$this->sanitize($selector)][$this->sanitize($key)] = $this->sanitize($value);
}
}
}
public function getStyles(): array
{
return $this->styles;
}
public function getStyle(string $selector): array
{
$selector = $this->sanitize($selector);
return $this->styles[$selector] ?? [];
}
private function sanitize(string $value): string
{
return addslashes(trim($value));
}
}

View File

@@ -43,6 +43,11 @@ class Html
protected static $options;
/**
* @var Css
*/
protected static $css;
/**
* Add HTML parts.
*
@@ -61,7 +66,7 @@ class Html
* @todo parse $stylesheet for default styles. Should result in an array based on id, class and element,
* which could be applied when such an element occurs in the parseNode function.
*/
self::$options = $options;
static::$options = $options;
// Preprocess: remove all line ends, decode HTML entity,
// fix ampersand and angle brackets and add body tag for HTML fragments
@@ -82,10 +87,10 @@ class Html
$dom = new DOMDocument();
$dom->preserveWhiteSpace = $preserveWhiteSpace;
$dom->loadXML($html);
self::$xpath = new DOMXPath($dom);
static::$xpath = new DOMXPath($dom);
$node = $dom->getElementsByTagName('body');
self::parseNode($node->item(0), $element);
static::parseNode($node->item(0), $element);
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($orignalLibEntityLoader);
}
@@ -104,11 +109,12 @@ class Html
if (XML_ELEMENT_NODE == $node->nodeType) {
$attributes = $node->attributes; // get all the attributes(eg: id, class)
$bidi = ($attributes['dir'] ?? '') === 'rtl';
foreach ($attributes as $attribute) {
$val = $attribute->value;
switch (strtolower($attribute->name)) {
case 'align':
$styles['alignment'] = self::mapAlign(trim($val));
$styles['alignment'] = self::mapAlign(trim($val), $bidi);
break;
case 'lang':
@@ -149,6 +155,19 @@ class Html
}
}
$attributeIdentifier = $attributes->getNamedItem('id');
if ($attributeIdentifier && self::$css) {
$styles = self::parseStyleDeclarations(self::$css->getStyle('#' . $attributeIdentifier->value), $styles);
}
$attributeClass = $attributes->getNamedItem('class');
if ($attributeClass) {
if (self::$css) {
$styles = self::parseStyleDeclarations(self::$css->getStyle('.' . $attributeClass->value), $styles);
}
$styles['className'] = $attributeClass->value;
}
$attributeStyle = $attributes->getNamedItem('style');
if ($attributeStyle) {
$styles = self::parseStyle($attributeStyle, $styles);
@@ -168,6 +187,13 @@ class Html
*/
protected static function parseNode($node, $element, $styles = [], $data = []): void
{
if ($node->nodeName == 'style') {
self::$css = new Css($node->textContent);
self::$css->process();
return;
}
// Populate styles array
$styleTypes = ['font', 'paragraph', 'list', 'table', 'row', 'cell'];
foreach ($styleTypes as $styleType) {
@@ -246,7 +272,7 @@ class Html
* Parse child nodes.
*
* @param DOMNode $node
* @param \PhpOffice\PhpWord\Element\AbstractContainer $element
* @param \PhpOffice\PhpWord\Element\AbstractContainer|Row|Table $element
* @param array $styles
* @param array $data
*/
@@ -389,6 +415,11 @@ class Html
$newElement = $element->addTable($elementStyles);
// Add style name from CSS Class
if (isset($elementStyles['className'])) {
$newElement->getStyle()->setStyleName($elementStyles['className']);
}
$attributes = $node->attributes;
if ($attributes->getNamedItem('border') !== null) {
$border = (int) $attributes->getNamedItem('border')->value;
@@ -414,7 +445,11 @@ class Html
$rowStyles['tblHeader'] = true;
}
return $element->addRow(null, $rowStyles);
// set cell height to control row heights
$height = $rowStyles['height'] ?? null;
unset($rowStyles['height']); // would not apply
return $element->addRow($height, $rowStyles);
}
/**
@@ -635,13 +670,22 @@ class Html
{
$properties = explode(';', trim($attribute->value, " \t\n\r\0\x0B;"));
$selectors = [];
foreach ($properties as $property) {
[$cKey, $cValue] = array_pad(explode(':', $property, 2), 2, null);
$cValue = trim($cValue ?? '');
$cKey = strtolower(trim($cKey));
switch ($cKey) {
$selectors[strtolower(trim($cKey))] = trim($cValue ?? '');
}
return self::parseStyleDeclarations($selectors, $styles);
}
protected static function parseStyleDeclarations(array $selectors, array $styles)
{
$bidi = ($selectors['direction'] ?? '') === 'rtl';
foreach ($selectors as $property => $value) {
switch ($property) {
case 'text-decoration':
switch ($cValue) {
switch ($value) {
case 'underline':
$styles['underline'] = 'single';
@@ -654,44 +698,45 @@ class Html
break;
case 'text-align':
$styles['alignment'] = self::mapAlign($cValue);
$styles['alignment'] = self::mapAlign($value, $bidi);
break;
case 'display':
$styles['hidden'] = $cValue === 'none' || $cValue === 'hidden';
$styles['hidden'] = $value === 'none' || $value === 'hidden';
break;
case 'direction':
$styles['rtl'] = $cValue === 'rtl';
$styles['rtl'] = $value === 'rtl';
$styles['bidi'] = $value === 'rtl';
break;
case 'font-size':
$styles['size'] = Converter::cssToPoint($cValue);
$styles['size'] = Converter::cssToPoint($value);
break;
case 'font-family':
$cValue = array_map('trim', explode(',', $cValue));
$styles['name'] = ucwords($cValue[0]);
$value = array_map('trim', explode(',', $value));
$styles['name'] = ucwords($value[0]);
break;
case 'color':
$styles['color'] = trim($cValue, '#');
$styles['color'] = trim($value, '#');
break;
case 'background-color':
$styles['bgColor'] = trim($cValue, '#');
$styles['bgColor'] = trim($value, '#');
break;
case 'line-height':
$matches = [];
if ($cValue === 'normal') {
if ($value === 'normal') {
$spacingLineRule = \PhpOffice\PhpWord\SimpleType\LineSpacingRule::AUTO;
$spacing = 0;
} elseif (preg_match('/([0-9]+\.?[0-9]*[a-z]+)/', $cValue, $matches)) {
} elseif (preg_match('/([0-9]+\.?[0-9]*[a-z]+)/', $value, $matches)) {
//matches number with a unit, e.g. 12px, 15pt, 20mm, ...
$spacingLineRule = \PhpOffice\PhpWord\SimpleType\LineSpacingRule::EXACT;
$spacing = Converter::cssToTwip($matches[1]);
} elseif (preg_match('/([0-9]+)%/', $cValue, $matches)) {
} elseif (preg_match('/([0-9]+)%/', $value, $matches)) {
//matches percentages
$spacingLineRule = \PhpOffice\PhpWord\SimpleType\LineSpacingRule::AUTO;
//we are subtracting 1 line height because the Spacing writer is adding one line
@@ -700,23 +745,23 @@ class Html
//any other, wich is a multiplier. E.g. 1.2
$spacingLineRule = \PhpOffice\PhpWord\SimpleType\LineSpacingRule::AUTO;
//we are subtracting 1 line height because the Spacing writer is adding one line
$spacing = ($cValue * Paragraph::LINE_HEIGHT) - Paragraph::LINE_HEIGHT;
$spacing = ($value * Paragraph::LINE_HEIGHT) - Paragraph::LINE_HEIGHT;
}
$styles['spacingLineRule'] = $spacingLineRule;
$styles['line-spacing'] = $spacing;
break;
case 'letter-spacing':
$styles['letter-spacing'] = Converter::cssToTwip($cValue);
$styles['letter-spacing'] = Converter::cssToTwip($value);
break;
case 'text-indent':
$styles['indentation']['firstLine'] = Converter::cssToTwip($cValue);
$styles['indentation']['firstLine'] = Converter::cssToTwip($value);
break;
case 'font-weight':
$tValue = false;
if (preg_match('#bold#', $cValue)) {
if (preg_match('#bold#', $value)) {
$tValue = true; // also match bolder
}
$styles['bold'] = $tValue;
@@ -724,52 +769,65 @@ class Html
break;
case 'font-style':
$tValue = false;
if (preg_match('#(?:italic|oblique)#', $cValue)) {
if (preg_match('#(?:italic|oblique)#', $value)) {
$tValue = true;
}
$styles['italic'] = $tValue;
break;
case 'font-variant':
$tValue = false;
if (preg_match('#small-caps#', $value)) {
$tValue = true;
}
$styles['smallCaps'] = $tValue;
break;
case 'margin':
$cValue = Converter::cssToTwip($cValue);
$styles['spaceBefore'] = $cValue;
$styles['spaceAfter'] = $cValue;
$value = Converter::cssToTwip($value);
$styles['spaceBefore'] = $value;
$styles['spaceAfter'] = $value;
break;
case 'margin-top':
// BC change: up to ver. 0.17.0 incorrectly converted to points - Converter::cssToPoint($cValue)
$styles['spaceBefore'] = Converter::cssToTwip($cValue);
// BC change: up to ver. 0.17.0 incorrectly converted to points - Converter::cssToPoint($value)
$styles['spaceBefore'] = Converter::cssToTwip($value);
break;
case 'margin-bottom':
// BC change: up to ver. 0.17.0 incorrectly converted to points - Converter::cssToPoint($cValue)
$styles['spaceAfter'] = Converter::cssToTwip($cValue);
// BC change: up to ver. 0.17.0 incorrectly converted to points - Converter::cssToPoint($value)
$styles['spaceAfter'] = Converter::cssToTwip($value);
break;
case 'border-color':
self::mapBorderColor($styles, $cValue);
self::mapBorderColor($styles, $value);
break;
case 'border-width':
$styles['borderSize'] = Converter::cssToPoint($cValue);
$styles['borderSize'] = Converter::cssToPoint($value);
break;
case 'border-style':
$styles['borderStyle'] = self::mapBorderStyle($cValue);
$styles['borderStyle'] = self::mapBorderStyle($value);
break;
case 'width':
if (preg_match('/([0-9]+[a-z]+)/', $cValue, $matches)) {
if (preg_match('/([0-9]+[a-z]+)/', $value, $matches)) {
$styles['width'] = Converter::cssToTwip($matches[1]);
$styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::TWIP;
} elseif (preg_match('/([0-9]+)%/', $cValue, $matches)) {
} elseif (preg_match('/([0-9]+)%/', $value, $matches)) {
$styles['width'] = $matches[1] * 50;
$styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::PERCENT;
} elseif (preg_match('/([0-9]+)/', $cValue, $matches)) {
} elseif (preg_match('/([0-9]+)/', $value, $matches)) {
$styles['width'] = $matches[1];
$styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::AUTO;
}
break;
case 'height':
$styles['height'] = Converter::cssToTwip($value);
$styles['exactHeight'] = true;
break;
case 'border':
case 'border-top':
@@ -778,9 +836,9 @@ class Html
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);
if (preg_match('/([0-9]+[^0-9]*)\s+(\#[a-fA-F0-9]+|[a-zA-Z]+)\s+([a-z]+)/', $value, $matches)) {
if (false !== strpos($property, '-')) {
$tmp = explode('-', $property);
$which = $tmp[1];
$which = ucfirst($which); // e.g. bottom -> Bottom
} else {
@@ -803,13 +861,13 @@ class Html
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)) {
if (preg_match('#(?:top|bottom|middle|sub|baseline)#i', $value, $matches)) {
$styles['valign'] = self::mapAlignVertical($matches[0]);
}
break;
case 'page-break-after':
if ($cValue == 'always') {
if ($value == 'always') {
$styles['isPageBreak'] = true;
}
@@ -910,7 +968,10 @@ class Html
$tmpDir = Settings::getTempDir() . '/';
$match = [];
preg_match('/.+\.(\w+)$/', $src, $match);
$src = $tmpDir . uniqid() . '.' . $match[1];
$src = $tmpDir . uniqid();
if (isset($match[1])) {
$src .= '.' . $match[1];
}
$ifp = fopen($src, 'wb');
@@ -968,20 +1029,21 @@ class Html
* Transforms a HTML/CSS alignment into a \PhpOffice\PhpWord\SimpleType\Jc.
*
* @param string $cssAlignment
* @param bool $bidi
*
* @return null|string
*/
protected static function mapAlign($cssAlignment)
protected static function mapAlign($cssAlignment, $bidi)
{
switch ($cssAlignment) {
case 'right':
return Jc::END;
return $bidi ? Jc::START : Jc::END;
case 'center':
return Jc::CENTER;
case 'justify':
return Jc::BOTH;
default:
return Jc::START;
return $bidi ? Jc::END : Jc::START;
}
}

View File

@@ -61,6 +61,17 @@ class OLERead
public $wrkObjectPool = null;
public $summaryInformation = null;
public $docSummaryInfos = null;
public $numBigBlockDepotBlocks = null;
public $rootStartBlock = null;
public $sbdStartBlock = null;
public $extensionBlock = null;
public $numExtensionBlocks = null;
public $bigBlockChain = null;
public $smallBlockChain = null;
public $entry = null;
public $rootentry = null;
public $wrkObjectPoolelseif = null;
public $props = array();
/**
* Read the file

View File

@@ -1597,7 +1597,7 @@ class PclZip
if (is_string($p_options_list[$i + 1])) {
// ----- Remove spaces
$p_options_list[$i + 1] = strtr($p_options_list[$i + 1], ' ', '');
$p_options_list[$i + 1] = str_replace(' ', '', $p_options_list[$i + 1]);
// ----- Parse items
$v_work_list = explode(",", $p_options_list[$i + 1]);

View File

@@ -138,14 +138,15 @@ class Text
/**
* Return UTF8 encoded value.
*
* @param string $value
* @param null|string $value
*
* @return string
* @return ?string
*/
public static function toUTF8($value = '')
{
if (null !== $value && !self::isUTF8($value)) {
$value = utf8_encode($value);
// PHP8.2 : utf8_encode is deprecated, but mb_convert_encoding always usable
$value = (function_exists('mb_convert_encoding')) ? mb_convert_encoding($value, 'UTF-8', 'ISO-8859-1') : utf8_encode($value);
}
return $value;

View File

@@ -0,0 +1,76 @@
<?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
*
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
declare(strict_types=1);
namespace PhpOffice\PhpWord\Shared;
class Validate
{
public const CSS_WHITESPACE = [
'pre-wrap',
'normal',
'nowrap',
'pre',
'pre-line',
'initial',
'inherit',
];
public const CSS_GENERICFONT = [
'serif',
'sans-serif',
'monospace',
'cursive',
'fantasy',
'system-ui',
'math',
'emoji',
'fangsong',
];
/**
* Validate html css white-space value. It is expected that only pre-wrap and normal (default) are useful.
*
* @param string $value CSS White space
*
* @return string value if valid, empty string if not
*/
public static function validateCSSWhiteSpace(?string $value): string
{
if (in_array($value, self::CSS_WHITESPACE)) {
return $value;
}
return '';
}
/**
* Validate generic font for fallback for html.
*
* @param string $value Generic font name
*
* @return string Value if legitimate, empty string if not
*/
public static function validateCSSGenericFont(?string $value): string
{
if (in_array($value, self::CSS_GENERICFONT)) {
return $value;
}
return '';
}
}

View File

@@ -62,7 +62,7 @@ class XMLReader
$zip = new ZipArchive();
$zip->open($zipFile);
$content = $zip->getFromName($xmlFile);
$content = $zip->getFromName(ltrim($xmlFile, '/'));
$zip->close();
if ($content === false) {
@@ -97,24 +97,21 @@ class XMLReader
* Get elements.
*
* @param string $path
* @param DOMElement $contextNode
*
* @return DOMNodeList
* @return DOMNodeList<DOMElement>
*/
public function getElements($path, ?DOMElement $contextNode = null)
{
if ($this->dom === null) {
return [];
return new DOMNodeList(); // @phpstan-ignore-line
}
if ($this->xpath === null) {
$this->xpath = new DOMXpath($this->dom);
}
if (null === $contextNode) {
return $this->xpath->query($path);
}
$result = @$this->xpath->query($path, $contextNode);
return $this->xpath->query($path, $contextNode);
return empty($result) ? new DOMNodeList() : $result; // @phpstan-ignore-line
}
/**
@@ -141,7 +138,6 @@ class XMLReader
* Get element.
*
* @param string $path
* @param DOMElement $contextNode
*
* @return null|DOMElement
*/
@@ -159,7 +155,6 @@ class XMLReader
* Get element attribute.
*
* @param string $attribute
* @param DOMElement $contextNode
* @param string $path
*
* @return null|string
@@ -187,7 +182,6 @@ class XMLReader
* Get element value.
*
* @param string $path
* @param DOMElement $contextNode
*
* @return null|string
*/
@@ -205,7 +199,6 @@ class XMLReader
* Count elements.
*
* @param string $path
* @param DOMElement $contextNode
*
* @return int
*/
@@ -220,7 +213,6 @@ class XMLReader
* Element exists.
*
* @param string $path
* @param DOMElement $contextNode
*
* @return bool
*/

View File

@@ -30,8 +30,8 @@ use PhpOffice\PhpWord\Settings;
*
* @method bool addFile(string $filename, string $localname = null)
* @method bool addFromString(string $localname, string $contents)
* @method string getNameIndex(int $index)
* @method int locateName(string $name)
* @method false|string getNameIndex(int $index)
* @method false|int locateName(string $name)
*
* @since 0.10.0
*/
@@ -396,7 +396,7 @@ class ZipArchive
*
* @param string $filename Filename for the file in zip archive
*
* @return int
* @return false|int
*/
public function pclzipLocateName($filename)
{

View File

@@ -39,7 +39,7 @@ class Style
* Add paragraph style.
*
* @param string $styleName
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styles
* @param AbstractStyle|array $styles
*
* @return \PhpOffice\PhpWord\Style\Paragraph
*/
@@ -52,8 +52,8 @@ class Style
* Add font style.
*
* @param string $styleName
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $fontStyle
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $paragraphStyle
* @param AbstractStyle|array $fontStyle
* @param AbstractStyle|array $paragraphStyle
*
* @return \PhpOffice\PhpWord\Style\Font
*/
@@ -66,7 +66,7 @@ class Style
* Add link style.
*
* @param string $styleName
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styles
* @param AbstractStyle|array $styles
*
* @return \PhpOffice\PhpWord\Style\Font
*/
@@ -79,7 +79,7 @@ class Style
* Add numbering style.
*
* @param string $styleName
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styleValues
* @param AbstractStyle|array $styleValues
*
* @return \PhpOffice\PhpWord\Style\Numbering
*
@@ -94,8 +94,8 @@ class Style
* Add title style.
*
* @param null|int $depth Provide null to set title font
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $fontStyle
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $paragraphStyle
* @param AbstractStyle|array $fontStyle
* @param AbstractStyle|array $paragraphStyle
*
* @return \PhpOffice\PhpWord\Style\Font
*/
@@ -149,7 +149,7 @@ class Style
/**
* Set default paragraph style.
*
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styles Paragraph style definition
* @param AbstractStyle|array $styles Paragraph style definition
*
* @return \PhpOffice\PhpWord\Style\Paragraph
*/
@@ -161,7 +161,7 @@ class Style
/**
* Get all styles.
*
* @return \PhpOffice\PhpWord\Style\AbstractStyle[]
* @return AbstractStyle[]
*/
public static function getStyles()
{
@@ -173,7 +173,7 @@ class Style
*
* @param string $styleName
*
* @return \PhpOffice\PhpWord\Style\AbstractStyle Paragraph|Font|Table|Numbering
* @return ?AbstractStyle Paragraph|Font|Table|Numbering
*/
public static function getStyle($styleName)
{
@@ -190,10 +190,10 @@ class Style
* The $styleValues could be an array or object
*
* @param string $name
* @param \PhpOffice\PhpWord\Style\AbstractStyle $style
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $value
* @param AbstractStyle $style
* @param AbstractStyle|array $value
*
* @return \PhpOffice\PhpWord\Style\AbstractStyle
* @return AbstractStyle
*/
private static function setStyleValues($name, $style, $value = null)
{

View File

@@ -30,7 +30,7 @@ abstract class AbstractStyle
/**
* Style name.
*
* @var string
* @var ?string
*/
protected $styleName;
@@ -62,7 +62,7 @@ abstract class AbstractStyle
/**
* Get style name.
*
* @return string
* @return ?string
*/
public function getStyleName()
{
@@ -161,7 +161,7 @@ abstract class AbstractStyle
* Check if the set method is exists. Throws an exception?
*
* @param string $key
* @param string $value
* @param array|int|string $value
*
* @return self
*/
@@ -202,10 +202,10 @@ abstract class AbstractStyle
/**
* Set default for null and empty value.
*
* @param string $value (was: mixed)
* @param string $default (was: mixed)
* @param ?string $value
* @param string $default
*
* @return string (was: mixed)
* @return string
*/
protected function setNonEmptyVal($value, $default)
{
@@ -253,7 +253,7 @@ abstract class AbstractStyle
/**
* Set integer value: Convert string that contains only numeric into integer.
*
* @param null|int $value
* @param null|float|int|string $value
* @param null|int $default
*
* @return null|int

View File

@@ -22,6 +22,8 @@ namespace PhpOffice\PhpWord\Style;
*/
class Border extends AbstractStyle
{
const DEFAULT_MARGIN = 1440; // In twips.
/**
* Border Top Size.
*
@@ -106,6 +108,34 @@ class Border extends AbstractStyle
*/
protected $borderBottomStyle;
/**
* Top margin spacing.
*
* @var float|int
*/
protected $marginTop = self::DEFAULT_MARGIN;
/**
* Left margin spacing.
*
* @var float|int
*/
protected $marginLeft = self::DEFAULT_MARGIN;
/**
* Right margin spacing.
*
* @var float|int
*/
protected $marginRight = self::DEFAULT_MARGIN;
/**
* Bottom margin spacing.
*
* @var float|int
*/
protected $marginBottom = self::DEFAULT_MARGIN;
/**
* Get border size.
*
@@ -501,4 +531,100 @@ class Border extends AbstractStyle
return $borders !== array_filter($borders, 'is_null');
}
/**
* Get Margin Top.
*
* @return float|int
*/
public function getMarginTop()
{
return $this->marginTop;
}
/**
* Set Margin Top.
*
* @param float|int $value
*
* @return self
*/
public function setMarginTop($value = null)
{
$this->marginTop = $this->setNumericVal($value, self::DEFAULT_MARGIN);
return $this;
}
/**
* Get Margin Left.
*
* @return float|int
*/
public function getMarginLeft()
{
return $this->marginLeft;
}
/**
* Set Margin Left.
*
* @param float|int $value
*
* @return self
*/
public function setMarginLeft($value = null)
{
$this->marginLeft = $this->setNumericVal($value, self::DEFAULT_MARGIN);
return $this;
}
/**
* Get Margin Right.
*
* @return float|int
*/
public function getMarginRight()
{
return $this->marginRight;
}
/**
* Set Margin Right.
*
* @param float|int $value
*
* @return self
*/
public function setMarginRight($value = null)
{
$this->marginRight = $this->setNumericVal($value, self::DEFAULT_MARGIN);
return $this;
}
/**
* Get Margin Bottom.
*
* @return float|int
*/
public function getMarginBottom()
{
return $this->marginBottom;
}
/**
* Set Margin Bottom.
*
* @param float|int $value
*
* @return self
*/
public function setMarginBottom($value = null)
{
$this->marginBottom = $this->setNumericVal($value, self::DEFAULT_MARGIN);
return $this;
}
}

View File

@@ -107,7 +107,7 @@ class Cell extends Border
/**
* Width.
*
* @var int
* @var ?int
*/
private $width;
@@ -118,6 +118,13 @@ class Cell extends Border
*/
private $unit = TblWidth::TWIP;
/**
* Prevent text from wrapping in the cell.
*
* @var bool
*/
private $noWrap = true;
/**
* Get vertical align.
*
@@ -162,7 +169,14 @@ class Cell extends Border
*/
public function setTextDirection($value = null)
{
$enum = [self::TEXT_DIR_BTLR, self::TEXT_DIR_TBRL];
$enum = [
self::TEXT_DIR_BTLR,
self::TEXT_DIR_TBRL,
self::TEXT_DIR_LRTB,
self::TEXT_DIR_LRTBV,
self::TEXT_DIR_TBRLV,
self::TEXT_DIR_TBLRV,
];
$this->textDirection = $this->setEnumVal($value, $enum, $this->textDirection);
return $this;
@@ -270,7 +284,7 @@ class Cell extends Border
/**
* Get cell width.
*
* @return int
* @return ?int
*/
public function getWidth()
{
@@ -286,7 +300,7 @@ class Cell extends Border
*/
public function setWidth($value)
{
$this->setIntVal($value);
$this->width = $this->setIntVal($value);
return $this;
}
@@ -312,4 +326,22 @@ class Cell extends Border
return $this;
}
/**
* Set noWrap.
*/
public function setNoWrap(bool $value): self
{
$this->noWrap = $this->setBoolVal($value, true);
return $this;
}
/**
* Get noWrap.
*/
public function getNoWrap(): bool
{
return $this->noWrap;
}
}

View File

@@ -17,6 +17,9 @@
namespace PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Shared\Validate;
/**
* Font style.
*/
@@ -230,7 +233,7 @@ class Font extends AbstractStyle
/**
* Right to left languages.
*
* @var bool
* @var ?bool
*/
private $rtl;
@@ -245,7 +248,7 @@ class Font extends AbstractStyle
/**
* Languages.
*
* @var \PhpOffice\PhpWord\Style\Language
* @var null|\PhpOffice\PhpWord\Style\Language
*/
private $lang;
@@ -267,6 +270,20 @@ class Font extends AbstractStyle
*/
private $position;
/**
* Preservation of white space in html.
*
* @var string Value used for css white-space
*/
private $whiteSpace = '';
/**
* Generic font as fallback for html.
*
* @var string generic font name
*/
private $fallbackFont = '';
/**
* Create new font style.
*
@@ -288,7 +305,7 @@ class Font extends AbstractStyle
*/
public function getStyleValues()
{
$styles = [
return [
'name' => $this->getStyleName(),
'basic' => [
'name' => $this->getName(),
@@ -319,9 +336,9 @@ class Font extends AbstractStyle
'rtl' => $this->isRTL(),
'shading' => $this->getShading(),
'lang' => $this->getLang(),
'whiteSpace' => $this->getWhiteSpace(),
'fallbackFont' => $this->getFallbackFont(),
];
return $styles;
}
/**
@@ -827,17 +844,17 @@ class Font extends AbstractStyle
/**
* Get rtl.
*
* @return bool
* @return ?bool
*/
public function isRTL()
{
return $this->rtl;
return $this->rtl ?? Settings::isDefaultRtl();
}
/**
* Set rtl.
*
* @param bool $value
* @param ?bool $value
*
* @return self
*/
@@ -875,7 +892,7 @@ class Font extends AbstractStyle
/**
* Get language.
*
* @return \PhpOffice\PhpWord\Style\Language
* @return null|\PhpOffice\PhpWord\Style\Language
*/
public function getLang()
{
@@ -946,4 +963,44 @@ class Font extends AbstractStyle
return $this;
}
/**
* Set html css white-space value. It is expected that only pre-wrap and normal (default) are useful.
*
* @param null|string $value Should be one of pre-wrap, normal, nowrap, pre, pre-line, initial, inherit
*/
public function setWhiteSpace(?string $value): self
{
$this->whiteSpace = Validate::validateCSSWhiteSpace($value);
return $this;
}
/**
* Get html css white-space value.
*/
public function getWhiteSpace(): string
{
return $this->whiteSpace;
}
/**
* Set generic font for fallback for html.
*
* @param string $value generic font name
*/
public function setFallbackFont(?string $value): self
{
$this->fallbackFont = Validate::validateCSSGenericFont($value);
return $this;
}
/**
* Get html fallback generic font.
*/
public function getFallbackFont(): string
{
return $this->fallbackFont;
}
}

View File

@@ -44,7 +44,7 @@ class Indentation extends AbstractStyle
*
* @var float|int
*/
private $firstLine;
private $firstLine = 0;
/**
* Indentation removed from first line (twip).
@@ -80,7 +80,7 @@ class Indentation extends AbstractStyle
*
* @return self
*/
public function setLeft($value = null)
public function setLeft($value)
{
$this->left = $this->setNumericVal($value, $this->left);
@@ -104,7 +104,7 @@ class Indentation extends AbstractStyle
*
* @return self
*/
public function setRight($value = null)
public function setRight($value)
{
$this->right = $this->setNumericVal($value, $this->right);
@@ -128,7 +128,7 @@ class Indentation extends AbstractStyle
*
* @return self
*/
public function setFirstLine($value = null)
public function setFirstLine($value)
{
$this->firstLine = $this->setNumericVal($value, $this->firstLine);

View File

@@ -40,18 +40,27 @@ final class Language extends AbstractStyle
const FR_BE = 'fr-BE';
const FR_BE_ID = 2060;
const FR_CH = 'fr-CH';
const FR_CH_ID = 4108;
const ES_ES = 'es-ES';
const ES_ES_ID = 3082;
const DE_DE = 'de-DE';
const DE_DE_ID = 1031;
const DE_CH = 'de-CH';
const DE_CH_ID = 2055;
const HE_IL = 'he-IL';
const HE_IL_ID = 1037;
const IT_IT = 'it-IT';
const IT_IT_ID = 1040;
const IT_CH = 'it-CH';
const IT_CH_ID = 2064;
const JA_JP = 'ja-JP';
const JA_JP_ID = 1041;
@@ -70,6 +79,9 @@ final class Language extends AbstractStyle
const NL_NL = 'nl-NL';
const NL_NL_ID = 1043;
const SV_SE = 'sv-SE';
const SV_SE_ID = 1053;
const UK_UA = 'uk-UA';
const UK_UA_ID = 1058;
@@ -244,7 +256,9 @@ final class Language extends AbstractStyle
if ($locale !== null && strlen($locale) === 2) {
return strtolower($locale) . '-' . strtoupper($locale);
}
if ($locale === 'und') {
return 'en-EN';
}
if ($locale !== null && $locale !== 'zxx' && strstr($locale, '-') === false) {
throw new InvalidArgumentException($locale . ' is not a valid language code');
}

View File

@@ -18,6 +18,7 @@
namespace PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Exception\InvalidStyleException;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Shared\Text;
use PhpOffice\PhpWord\SimpleType\Jc;
use PhpOffice\PhpWord\SimpleType\TextAlignment;
@@ -99,7 +100,7 @@ class Paragraph extends Border
/**
* Text line height.
*
* @var int
* @var null|float|int
*/
private $lineHeight;
@@ -169,9 +170,9 @@ class Paragraph extends Border
/**
* Right to Left Paragraph Layout.
*
* @var bool
* @var ?bool
*/
private $bidi = false;
private $bidi;
/**
* Vertical Character Alignment on Line.
@@ -321,9 +322,9 @@ class Paragraph extends Border
}
/**
* Get shading.
* Get indentation.
*
* @return \PhpOffice\PhpWord\Style\Indentation
* @return null|\PhpOffice\PhpWord\Style\Indentation
*/
public function getIndentation()
{
@@ -419,7 +420,7 @@ class Paragraph extends Border
/**
* Get space before paragraph.
*
* @return int
* @return null|float|int
*/
public function getSpaceBefore()
{
@@ -429,7 +430,7 @@ class Paragraph extends Border
/**
* Set space before paragraph.
*
* @param int $value
* @param null|float|int $value
*
* @return self
*/
@@ -441,7 +442,7 @@ class Paragraph extends Border
/**
* Get space after paragraph.
*
* @return int
* @return null|float|int
*/
public function getSpaceAfter()
{
@@ -451,7 +452,7 @@ class Paragraph extends Border
/**
* Set space after paragraph.
*
* @param int $value
* @param null|float|int $value
*
* @return self
*/
@@ -463,7 +464,7 @@ class Paragraph extends Border
/**
* Get spacing between lines.
*
* @return float|int
* @return null|float|int
*/
public function getSpacing()
{
@@ -473,7 +474,7 @@ class Paragraph extends Border
/**
* Set spacing between lines.
*
* @param float|int $value
* @param null|float|int $value
*
* @return self
*/
@@ -507,7 +508,7 @@ class Paragraph extends Border
/**
* Get line height.
*
* @return float|int
* @return null|float|int
*/
public function getLineHeight()
{
@@ -759,17 +760,17 @@ class Paragraph extends Border
/**
* Get bidirectional.
*
* @return bool
* @return ?bool
*/
public function isBidi()
{
return $this->bidi;
return $this->bidi ?? Settings::isDefaultRtl();
}
/**
* Set bidi.
*
* @param bool $bidi
* @param ?bool $bidi
* Set to true to write from right to left
*
* @return self

View File

@@ -40,7 +40,6 @@ class Section extends Border
*/
const DEFAULT_WIDTH = 11905.511811024; // In twips.
const DEFAULT_HEIGHT = 16837.79527559; // In twips.
const DEFAULT_MARGIN = 1440; // In twips.
const DEFAULT_GUTTER = 0; // In twips.
const DEFAULT_HEADER_HEIGHT = 720; // In twips.
const DEFAULT_FOOTER_HEIGHT = 720; // In twips.
@@ -77,34 +76,6 @@ class Section extends Border
*/
private $pageSizeH = self::DEFAULT_HEIGHT;
/**
* Top margin spacing.
*
* @var float|int
*/
private $marginTop = self::DEFAULT_MARGIN;
/**
* Left margin spacing.
*
* @var float|int
*/
private $marginLeft = self::DEFAULT_MARGIN;
/**
* Right margin spacing.
*
* @var float|int
*/
private $marginRight = self::DEFAULT_MARGIN;
/**
* Bottom margin spacing.
*
* @var float|int
*/
private $marginBottom = self::DEFAULT_MARGIN;
/**
* Page gutter spacing.
*
@@ -159,7 +130,7 @@ class Section extends Border
* - evenPage: Even page section break
* - oddPage: Odd page section break
*
* @var string
* @var ?string
*/
private $breakType;
@@ -176,7 +147,7 @@ class Section extends Border
* Vertical Text Alignment on Page
* One of \PhpOffice\PhpWord\SimpleType\VerticalJc.
*
* @var string
* @var ?string
*/
private $vAlign;
@@ -224,7 +195,7 @@ class Section extends Border
* Set Setting Value.
*
* @param string $key
* @param string $value
* @param array|int|string $value
*
* @return self
*/
@@ -344,102 +315,6 @@ class Section extends Border
return $this;
}
/**
* Get Margin Top.
*
* @return float|int
*/
public function getMarginTop()
{
return $this->marginTop;
}
/**
* Set Margin Top.
*
* @param float|int $value
*
* @return self
*/
public function setMarginTop($value = null)
{
$this->marginTop = $this->setNumericVal($value, self::DEFAULT_MARGIN);
return $this;
}
/**
* Get Margin Left.
*
* @return float|int
*/
public function getMarginLeft()
{
return $this->marginLeft;
}
/**
* Set Margin Left.
*
* @param float|int $value
*
* @return self
*/
public function setMarginLeft($value = null)
{
$this->marginLeft = $this->setNumericVal($value, self::DEFAULT_MARGIN);
return $this;
}
/**
* Get Margin Right.
*
* @return float|int
*/
public function getMarginRight()
{
return $this->marginRight;
}
/**
* Set Margin Right.
*
* @param float|int $value
*
* @return self
*/
public function setMarginRight($value = null)
{
$this->marginRight = $this->setNumericVal($value, self::DEFAULT_MARGIN);
return $this;
}
/**
* Get Margin Bottom.
*
* @return float|int
*/
public function getMarginBottom()
{
return $this->marginBottom;
}
/**
* Set Margin Bottom.
*
* @param float|int $value
*
* @return self
*/
public function setMarginBottom($value = null)
{
$this->marginBottom = $this->setNumericVal($value, self::DEFAULT_MARGIN);
return $this;
}
/**
* Get gutter.
*
@@ -587,7 +462,7 @@ class Section extends Border
/**
* Get Break Type.
*
* @return string
* @return ?string
*/
public function getBreakType()
{
@@ -635,7 +510,7 @@ class Section extends Border
/**
* Get vertical alignment.
*
* @return string
* @return ?string
*/
public function getVAlign()
{

View File

@@ -30,21 +30,21 @@ class Spacing extends AbstractStyle
/**
* Spacing above paragraph (twip).
*
* @var float|int
* @var null|float|int
*/
private $before;
/**
* Spacing below paragraph (twip).
*
* @var float|int
* @var null|float|int
*/
private $after;
/**
* Spacing between lines in paragraph (twip).
*
* @var float|int
* @var null|float|int
*/
private $line;
@@ -68,7 +68,7 @@ class Spacing extends AbstractStyle
/**
* Get before.
*
* @return float|int
* @return null|float|int
*/
public function getBefore()
{
@@ -78,7 +78,7 @@ class Spacing extends AbstractStyle
/**
* Set before.
*
* @param float|int $value
* @param null|float|int $value
*
* @return self
*/
@@ -92,7 +92,7 @@ class Spacing extends AbstractStyle
/**
* Get after.
*
* @return float|int
* @return null|float|int
*/
public function getAfter()
{
@@ -102,7 +102,7 @@ class Spacing extends AbstractStyle
/**
* Set after.
*
* @param float|int $value
* @param null|float|int $value
*
* @return self
*/
@@ -116,7 +116,7 @@ class Spacing extends AbstractStyle
/**
* Get line.
*
* @return float|int
* @return null|float|int
*/
public function getLine()
{
@@ -126,7 +126,7 @@ class Spacing extends AbstractStyle
/**
* Set distance.
*
* @param float|int $value
* @param null|float|int $value
*
* @return self
*/

View File

@@ -18,9 +18,11 @@
namespace PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\SimpleType\Jc;
use PhpOffice\PhpWord\SimpleType\JcTable;
use PhpOffice\PhpWord\SimpleType\TblWidth;
use PhpOffice\PhpWord\Style;
class Table extends Border
{
@@ -131,7 +133,7 @@ class Table extends Border
private $unit = TblWidth::AUTO;
/**
* @var float|int cell spacing value
* @var null|float|int cell spacing value
*/
protected $cellSpacing;
@@ -143,7 +145,7 @@ class Table extends Border
/**
* Position.
*
* @var \PhpOffice\PhpWord\Style\TablePosition
* @var ?\PhpOffice\PhpWord\Style\TablePosition
*/
private $position;
@@ -162,9 +164,9 @@ class Table extends Border
*
* @see http://www.datypic.com/sc/ooxml/e-w_bidiVisual-1.html
*
* @var bool
* @var ?bool
*/
private $bidiVisual = false;
private $bidiVisual;
/**
* Create new table style.
@@ -188,7 +190,7 @@ class Table extends Border
}
/**
* @param float|int $cellSpacing
* @param null|float|int $cellSpacing
*/
public function setCellSpacing($cellSpacing = null): void
{
@@ -196,7 +198,7 @@ class Table extends Border
}
/**
* @return float|int
* @return null|float|int
*/
public function getCellSpacing()
{
@@ -216,7 +218,7 @@ class Table extends Border
/**
* Get background.
*
* @return string
* @return ?string
*/
public function getBgColor()
{
@@ -704,7 +706,7 @@ class Table extends Border
/**
* Get position.
*
* @return \PhpOffice\PhpWord\Style\TablePosition
* @return ?\PhpOffice\PhpWord\Style\TablePosition
*/
public function getPosition()
{
@@ -726,7 +728,7 @@ class Table extends Border
}
/**
* @return TblWidthComplexType
* @return ?TblWidthComplexType
*/
public function getIndent()
{
@@ -768,17 +770,17 @@ class Table extends Border
/**
* Get bidiVisual.
*
* @return bool
* @return ?bool
*/
public function isBidiVisual()
{
return $this->bidiVisual;
return $this->bidiVisual ?? Settings::isDefaultRtl();
}
/**
* Set bidiVisual.
*
* @param bool $bidi
* @param ?bool $bidi
* Set to true to visually present table as Right to Left
*
* @return self

View File

@@ -2,10 +2,8 @@
/**
* 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.
@@ -27,121 +25,128 @@ class TextBox extends Image
/**
* margin top.
*
* @var int
* @var null|int
*/
private $innerMarginTop;
/**
* margin left.
*
* @var int
* @var null|int
*/
private $innerMarginLeft;
/**
* margin right.
*
* @var int
* @var null|int
*/
private $innerMarginRight;
/**
* Cell margin bottom.
*
* @var int
* @var null|int
*/
private $innerMarginBottom;
/**
* border size.
*
* @var int
* @var null|int
*/
private $borderSize;
/**
* border color.
*
* @var string
* @var null|string
*/
private $borderColor;
/**
* Set margin top.
* background color.
*
* @param int $value
* @var null|string
*/
public function setInnerMarginTop($value = null): void
private $bgColor;
/**
* Set background color.
*/
public function setBgColor(?string $value = null): void
{
$this->bgColor = $value;
}
/**
* Get background color.
*/
public function getBgColor(): ?string
{
return $this->bgColor;
}
/**
* Set margin top.
*/
public function setInnerMarginTop(?int $value = null): void
{
$this->innerMarginTop = $value;
}
/**
* Get margin top.
*
* @return int
*/
public function getInnerMarginTop()
public function getInnerMarginTop(): ?int
{
return $this->innerMarginTop;
}
/**
* Set margin left.
*
* @param int $value
*/
public function setInnerMarginLeft($value = null): void
public function setInnerMarginLeft(?int $value = null): void
{
$this->innerMarginLeft = $value;
}
/**
* Get margin left.
*
* @return int
*/
public function getInnerMarginLeft()
public function getInnerMarginLeft(): ?int
{
return $this->innerMarginLeft;
}
/**
* Set margin right.
*
* @param int $value
*/
public function setInnerMarginRight($value = null): void
public function setInnerMarginRight(?int $value = null): void
{
$this->innerMarginRight = $value;
}
/**
* Get margin right.
*
* @return int
*/
public function getInnerMarginRight()
public function getInnerMarginRight(): ?int
{
return $this->innerMarginRight;
}
/**
* Set margin bottom.
*
* @param int $value
*/
public function setInnerMarginBottom($value = null): void
public function setInnerMarginBottom(?int $value = null): void
{
$this->innerMarginBottom = $value;
}
/**
* Get margin bottom.
*
* @return int
*/
public function getInnerMarginBottom()
public function getInnerMarginBottom(): ?int
{
return $this->innerMarginBottom;
}
@@ -149,9 +154,9 @@ class TextBox extends Image
/**
* Set TLRB cell margin.
*
* @param int $value Margin in twips
* @param null|int $value Margin in twips
*/
public function setInnerMargin($value = null): void
public function setInnerMargin(?int $value = null): void
{
$this->setInnerMarginTop($value);
$this->setInnerMarginLeft($value);
@@ -164,17 +169,15 @@ class TextBox extends Image
*
* @return int[]
*/
public function getInnerMargin()
public function getInnerMargin(): array
{
return [$this->innerMarginLeft, $this->innerMarginTop, $this->innerMarginRight, $this->innerMarginBottom];
}
/**
* Has inner margin?
*
* @return bool
*/
public function hasInnerMargins()
public function hasInnerMargins(): bool
{
$hasInnerMargins = false;
$margins = $this->getInnerMargin();
@@ -191,39 +194,33 @@ class TextBox extends Image
/**
* Set border size.
*
* @param int $value Size in points
* @param null|int $value Size in points
*/
public function setBorderSize($value = null): void
public function setBorderSize(?int $value = null): void
{
$this->borderSize = $value;
}
/**
* Get border size.
*
* @return int
*/
public function getBorderSize()
public function getBorderSize(): ?int
{
return $this->borderSize;
}
/**
* Set border color.
*
* @param string $value
*/
public function setBorderColor($value = null): void
public function setBorderColor(?string $value = null): void
{
$this->borderColor = $value;
}
/**
* Get border color.
*
* @return string
*/
public function getBorderColor()
public function getBorderColor(): ?string
{
return $this->borderColor;
}

View File

@@ -27,6 +27,7 @@ use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Shared\Text;
use PhpOffice\PhpWord\Shared\XMLWriter;
use PhpOffice\PhpWord\Shared\ZipArchive;
use Throwable;
use XSLTProcessor;
class TemplateProcessor
@@ -94,6 +95,10 @@ class TemplateProcessor
*/
protected $tempDocumentNewImages = [];
protected static $macroOpeningChars = '${';
protected static $macroClosingChars = '}';
/**
* @since 0.12.0 Throws CreateTemporaryFileException and CopyFileException instead of Exception
*
@@ -131,6 +136,30 @@ class TemplateProcessor
$this->tempDocumentContentTypes = $this->zipClass->getFromName($this->getDocumentContentTypesName());
}
public function __destruct()
{
// ZipClass
if ($this->zipClass) {
try {
$this->zipClass->close();
} catch (Throwable $e) {
// Nothing to do here.
}
}
// Temporary file
if ($this->tempDocumentFilename && file_exists($this->tempDocumentFilename)) {
unlink($this->tempDocumentFilename);
}
}
public function __wakeup(): void
{
$this->tempDocumentFilename = '';
$this->zipClass = null;
throw new Exception('unserialize not permitted for this class');
}
/**
* Expose zip class.
*
@@ -238,30 +267,25 @@ class TemplateProcessor
*/
protected static function ensureMacroCompleted($macro)
{
if (substr($macro, 0, 2) !== '${' && substr($macro, -1) !== '}') {
$macro = '${' . $macro . '}';
if (substr($macro, 0, 2) !== self::$macroOpeningChars && substr($macro, -1) !== self::$macroClosingChars) {
$macro = self::$macroOpeningChars . $macro . self::$macroClosingChars;
}
return $macro;
}
/**
* @param string $subject
* @param ?string $subject
*
* @return string
*/
protected static function ensureUtf8Encoded($subject)
{
if (!Text::isUTF8($subject) && null !== $subject) {
$subject = utf8_encode($subject);
}
return (null !== $subject) ? $subject : '';
return $subject ? Text::toUTF8($subject) : '';
}
/**
* @param string $search
* @param \PhpOffice\PhpWord\Element\AbstractElement $complexType
*/
public function setComplexValue($search, Element\AbstractElement $complexType): void
{
@@ -289,7 +313,6 @@ class TemplateProcessor
/**
* @param string $search
* @param \PhpOffice\PhpWord\Element\AbstractElement $complexType
*/
public function setComplexBlock($search, Element\AbstractElement $complexType): void
{
@@ -349,6 +372,27 @@ class TemplateProcessor
}
}
public function setCheckbox(string $search, bool $checked): void
{
$search = static::ensureMacroCompleted($search);
$blockType = 'w:sdt';
$where = $this->findContainingXmlBlockForMacro($search, $blockType);
if (!is_array($where)) {
return;
}
$block = $this->getSlice($where['start'], $where['end']);
$val = $checked ? '1' : '0';
$block = preg_replace('/(<w14:checked w14:val=)".*?"(\/>)/', '$1"' . $val . '"$2', $block);
$text = $checked ? '☒' : '☐';
$block = preg_replace('/(<w:t>).*?(<\/w:t>)/', '$1' . $text . '$2', $block);
$this->replaceXmlBlock($search, $block, $blockType);
}
/**
* @param string $search
*/
@@ -433,7 +477,7 @@ class TemplateProcessor
if (null === $value && isset($inlineValue)) {
$value = $inlineValue;
}
if (!preg_match('/^([0-9]*(cm|mm|in|pt|pc|px|%|em|ex|)|auto)$/i', $value ?? '')) {
if (!preg_match('/^([0-9\.]*(cm|mm|in|pt|pc|px|%|em|ex|)|auto)$/i', $value ?? '')) {
$value = null;
}
if (null === $value) {
@@ -759,6 +803,70 @@ class TemplateProcessor
$this->tempDocumentMainPart = $result;
}
/**
* Delete a table row in a template document.
*/
public function deleteRow(string $search): void
{
if ('${' !== substr($search, 0, 2) && '}' !== substr($search, -1)) {
$search = '${' . $search . '}';
}
$tagPos = strpos($this->tempDocumentMainPart, $search);
if (!$tagPos) {
throw new Exception(sprintf('Can not delete row %s, template variable not found or variable contains markup.', $search));
}
$tableStart = $this->findTableStart($tagPos);
$tableEnd = $this->findTableEnd($tagPos);
$xmlTable = $this->getSlice($tableStart, $tableEnd);
if (substr_count($xmlTable, '<w:tr') === 1) {
$this->tempDocumentMainPart = $this->getSlice(0, $tableStart) . $this->getSlice($tableEnd);
return;
}
$rowStart = $this->findRowStart($tagPos);
$rowEnd = $this->findRowEnd($tagPos);
$xmlRow = $this->getSlice($rowStart, $rowEnd);
$this->tempDocumentMainPart = $this->getSlice(0, $rowStart) . $this->getSlice($rowEnd);
// Check if there's a cell spanning multiple rows.
if (preg_match('#<w:vMerge w:val="restart"/>#', $xmlRow)) {
$extraRowStart = $rowStart;
while (true) {
$extraRowStart = $this->findRowStart($extraRowStart + 1);
$extraRowEnd = $this->findRowEnd($extraRowStart + 1);
// If extraRowEnd is lower then 7, there was no next row found.
if ($extraRowEnd < 7) {
break;
}
// If tmpXmlRow doesn't contain continue, this row is no longer part of the spanned row.
$tmpXmlRow = $this->getSlice($extraRowStart, $extraRowEnd);
if (!preg_match('#<w:vMerge/>#', $tmpXmlRow) &&
!preg_match('#<w:vMerge w:val="continue" />#', $tmpXmlRow)
) {
break;
}
$tableStart = $this->findTableStart($extraRowEnd + 1);
$tableEnd = $this->findTableEnd($extraRowEnd + 1);
$xmlTable = $this->getSlice($tableStart, $tableEnd);
if (substr_count($xmlTable, '<w:tr') === 1) {
$this->tempDocumentMainPart = $this->getSlice(0, $tableStart) . $this->getSlice($tableEnd);
return;
}
$this->tempDocumentMainPart = $this->getSlice(0, $extraRowStart) . $this->getSlice($extraRowEnd);
}
}
}
/**
* Clones a table row and populates it's values from a two-dimensional array in a template document.
*
@@ -792,8 +900,12 @@ class TemplateProcessor
{
$xmlBlock = null;
$matches = [];
$escapedMacroOpeningChars = self::$macroOpeningChars;
$escapedMacroClosingChars = self::$macroClosingChars;
preg_match(
'/(.*((?s)<w:p\b(?:(?!<w:p\b).)*?\${' . $blockname . '}<\/w:.*?p>))(.*)((?s)<w:p\b(?:(?!<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',
'/(.*((?s)<w:p\b(?:(?!<w:p\b).)*?\\' . $escapedMacroOpeningChars . $blockname . $escapedMacroClosingChars . '<\/w:.*?p>))(.*)((?s)<w:p\b(?:(?!<w:p\b).)[^$]*?\\' . $escapedMacroOpeningChars . '\/' . $blockname . $escapedMacroClosingChars . '<\/w:.*?p>)/is',
//'/(.*((?s)<w:p\b(?:(?!<w:p\b).)*?\\'. $escapedMacroOpeningChars . $blockname . '}<\/w:.*?p>))(.*)((?s)<w:p\b(?:(?!<w:p\b).)[^$]*?\\'.$escapedMacroOpeningChars.'\/' . $blockname . '}<\/w:.*?p>)/is',
$this->tempDocumentMainPart,
$matches
);
@@ -832,8 +944,10 @@ class TemplateProcessor
public function replaceBlock($blockname, $replacement): void
{
$matches = [];
$escapedMacroOpeningChars = preg_quote(self::$macroOpeningChars);
$escapedMacroClosingChars = preg_quote(self::$macroClosingChars);
preg_match(
'/(<\?xml.*)(<w:p.*>\${' . $blockname . '}<\/w:.*?p>)(.*)(<w:p.*\${\/' . $blockname . '}<\/w:.*?p>)/is',
'/(<\?xml.*)(<w:p.*>' . $escapedMacroOpeningChars . $blockname . $escapedMacroClosingChars . '<\/w:.*?p>)(.*)(<w:p.*' . $escapedMacroOpeningChars . '\/' . $blockname . $escapedMacroClosingChars . '<\/w:.*?p>)/is',
$this->tempDocumentMainPart,
$matches
);
@@ -949,8 +1063,12 @@ class TemplateProcessor
*/
protected function fixBrokenMacros($documentPart)
{
$brokenMacroOpeningChars = substr(self::$macroOpeningChars, 0, 1);
$endMacroOpeningChars = substr(self::$macroOpeningChars, 1);
$macroClosingChars = self::$macroClosingChars;
return preg_replace_callback(
'/\$(?:\{|[^{$]*\>\{)[^}$]*\}/U',
'/\\' . $brokenMacroOpeningChars . '(?:\\' . $endMacroOpeningChars . '|[^{$]*\>\{)[^' . $macroClosingChars . '$]*\}/U',
function ($match) {
return strip_tags($match[0]);
},
@@ -963,7 +1081,7 @@ class TemplateProcessor
*
* @param mixed $search
* @param mixed $replace
* @param string $documentPartXML
* @param array<int, string>|string $documentPartXML
* @param int $limit
*
* @return string
@@ -989,7 +1107,10 @@ class TemplateProcessor
protected function getVariablesForPart($documentPartXML)
{
$matches = [];
preg_match_all('/\$\{(.*?)}/i', $documentPartXML, $matches);
$escapedMacroOpeningChars = preg_quote(self::$macroOpeningChars);
$escapedMacroClosingChars = preg_quote(self::$macroClosingChars);
preg_match_all("/$escapedMacroOpeningChars(.*?)$escapedMacroClosingChars/i", $documentPartXML, $matches);
return $matches[1];
}
@@ -1079,6 +1200,39 @@ class TemplateProcessor
return '[Content_Types].xml';
}
/**
* Find the start position of the nearest table before $offset.
*/
private function findTableStart(int $offset): int
{
$rowStart = strrpos(
$this->tempDocumentMainPart,
'<w:tbl ',
((strlen($this->tempDocumentMainPart) - $offset) * -1)
);
if (!$rowStart) {
$rowStart = strrpos(
$this->tempDocumentMainPart,
'<w:tbl>',
((strlen($this->tempDocumentMainPart) - $offset) * -1)
);
}
if (!$rowStart) {
throw new Exception('Can not find the start position of the table.');
}
return $rowStart;
}
/**
* Find the end position of the nearest table row after $offset.
*/
private function findTableEnd(int $offset): int
{
return strpos($this->tempDocumentMainPart, '</w:tbl>', $offset) + 7;
}
/**
* Find the start position of the nearest table row before $offset.
*
@@ -1141,15 +1295,18 @@ class TemplateProcessor
protected function indexClonedVariables($count, $xmlBlock)
{
$results = [];
$escapedMacroOpeningChars = preg_quote(self::$macroOpeningChars);
$escapedMacroClosingChars = preg_quote(self::$macroClosingChars);
for ($i = 1; $i <= $count; ++$i) {
$results[] = preg_replace('/\$\{([^:]*?)(:.*?)?\}/', '\${\1#' . $i . '\2}', $xmlBlock);
$results[] = preg_replace("/$escapedMacroOpeningChars([^:]*?)(:.*?)?$escapedMacroClosingChars/", self::$macroOpeningChars . '\1#' . $i . '\2' . self::$macroClosingChars, $xmlBlock);
}
return $results;
}
/**
* Raplaces variables with values from array, array keys are the variable names.
* Replaces variables with values from array, array keys are the variable names.
*
* @param array $variableReplacements
* @param string $xmlBlock
@@ -1297,7 +1454,7 @@ class TemplateProcessor
}
$unformattedText = preg_replace('/>\s+</', '><', $text);
$result = str_replace(['${', '}'], ['</w:t></w:r><w:r>' . $extractedStyle . '<w:t xml:space="preserve">${', '}</w:t></w:r><w:r>' . $extractedStyle . '<w:t xml:space="preserve">'], $unformattedText);
$result = str_replace([self::$macroOpeningChars, self::$macroClosingChars], ['</w:t></w:r><w:r>' . $extractedStyle . '<w:t xml:space="preserve">' . self::$macroOpeningChars, self::$macroClosingChars . '</w:t></w:r><w:r>' . $extractedStyle . '<w:t xml:space="preserve">'], $unformattedText);
return str_replace(['<w:r>' . $extractedStyle . '<w:t xml:space="preserve"></w:t></w:r>', '<w:r><w:t xml:space="preserve"></w:t></w:r>', '<w:t>'], ['', '', '<w:t xml:space="preserve">'], $result);
}
@@ -1311,6 +1468,25 @@ class TemplateProcessor
*/
protected function textNeedsSplitting($text)
{
return preg_match('/[^>]\${|}[^<]/i', $text) == 1;
$escapedMacroOpeningChars = preg_quote(self::$macroOpeningChars);
$escapedMacroClosingChars = preg_quote(self::$macroClosingChars);
return 1 === preg_match('/[^>]' . $escapedMacroOpeningChars . '|' . $escapedMacroClosingChars . '[^<]/i', $text);
}
public function setMacroOpeningChars(string $macroOpeningChars): void
{
self::$macroOpeningChars = $macroOpeningChars;
}
public function setMacroClosingChars(string $macroClosingChars): void
{
self::$macroClosingChars = $macroClosingChars;
}
public function setMacroChars(string $macroOpeningChars, string $macroClosingChars): void
{
self::$macroOpeningChars = $macroOpeningChars;
self::$macroClosingChars = $macroClosingChars;
}
}

View File

@@ -347,17 +347,8 @@ abstract class AbstractWriter implements WriterInterface
// Retrive GD image content or get local media
if (isset($element['isMemImage']) && $element['isMemImage']) {
$image = call_user_func($element['createFunction'], $element['source']);
if ($element['imageType'] === 'image/png') {
// PNG images need to preserve alpha channel information
imagesavealpha($image, true);
}
ob_start();
call_user_func($element['imageFunction'], $image);
$imageContents = ob_get_contents();
ob_end_clean();
$imageContents = $element['imageString'];
$zip->addFromString($target, $imageContents);
imagedestroy($image);
} else {
$this->addFileToPackage($zip, $element['source'], $target);
}

View File

@@ -18,6 +18,9 @@
namespace PhpOffice\PhpWord\Writer;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Shared\Validate;
use PhpOffice\PhpWord\Style\Font;
/**
* HTML writer.
@@ -42,6 +45,27 @@ class HTML extends AbstractWriter implements WriterInterface
*/
protected $notes = [];
/**
* Callback for editing generated html.
*
* @var null|callable
*/
private $editCallback;
/**
* Default generic name for default font for html.
*
* @var string
*/
private $defaultGenericFont = '';
/**
* Default white space style for html.
*
* @var string
*/
private $defaultWhiteSpace = '';
/**
* Create new instance.
*/
@@ -63,10 +87,8 @@ class HTML extends AbstractWriter implements WriterInterface
/**
* Save PhpWord to file.
*
* @param string $filename
*/
public function save($filename = null): void
public function save(string $filename): void
{
$this->writeFile($this->openFile($filename), $this->getContent());
}
@@ -84,14 +106,56 @@ class HTML extends AbstractWriter implements WriterInterface
$content .= '<!DOCTYPE html>' . PHP_EOL;
$content .= '<!-- Generated by PHPWord -->' . PHP_EOL;
$content .= '<html>' . PHP_EOL;
$langtext = '';
$phpWord = $this->getPhpWord();
$lang = $phpWord->getSettings()->getThemeFontLang();
if (!empty($lang)) {
$lang2 = $lang->getLatin();
if (!$lang2) {
$lang2 = $lang->getEastAsia();
}
if (!$lang2) {
$lang2 = $lang->getBidirectional();
}
if ($lang2) {
$langtext = " lang='" . $lang2 . "'";
}
}
$content .= "<html$langtext>" . PHP_EOL;
$content .= $this->getWriterPart('Head')->write();
$content .= $this->getWriterPart('Body')->write();
$content .= '</html>' . PHP_EOL;
// Trigger a callback for editing the entire HTML
$callback = $this->editCallback;
if ($callback !== null) {
$content = $callback($content);
}
return $content;
}
/**
* Return the callback to edit the entire HTML.
*/
public function getEditCallback(): ?callable
{
return $this->editCallback;
}
/**
* Set a callback to edit the entire HTML.
*
* The callback must accept the HTML as string as first parameter,
* and it must return the edited HTML as string.
*/
public function setEditCallback(?callable $callback): self
{
$this->editCallback = $callback;
return $this;
}
/**
* Get is PDF.
*
@@ -122,4 +186,52 @@ class HTML extends AbstractWriter implements WriterInterface
{
$this->notes[$noteId] = $noteMark;
}
/**
* Get generic name for default font for html.
*/
public function getDefaultGenericFont(): string
{
return $this->defaultGenericFont;
}
/**
* Set generic name for default font for html.
*/
public function setDefaultGenericFont(string $value): self
{
$this->defaultGenericFont = Validate::validateCSSGenericFont($value);
return $this;
}
/**
* Get default white space style for html.
*/
public function getDefaultWhiteSpace(): string
{
return $this->defaultWhiteSpace;
}
/**
* Set default white space style for html.
*/
public function setDefaultWhiteSpace(string $value): self
{
$this->defaultWhiteSpace = Validate::validateCSSWhiteSpace($value);
return $this;
}
/**
* Escape string or not depending on setting.
*/
public function escapeHTML(string $txt): string
{
if (Settings::isOutputEscapingEnabled()) {
return htmlspecialchars($txt, ENT_QUOTES | (defined('ENT_SUBSTITUTE') ? ENT_SUBSTITUTE : 0), 'UTF-8');
}
return $txt;
}
}

View File

@@ -17,9 +17,8 @@
namespace PhpOffice\PhpWord\Writer\HTML\Element;
use Laminas\Escaper\Escaper;
use PhpOffice\PhpWord\Element\AbstractElement as Element;
use PhpOffice\PhpWord\Writer\AbstractWriter;
use PhpOffice\PhpWord\Writer\HTML;
/**
* Abstract HTML element writer.
@@ -31,7 +30,7 @@ abstract class AbstractElement
/**
* Parent writer.
*
* @var \PhpOffice\PhpWord\Writer\AbstractWriter
* @var HTML
*/
protected $parentWriter;
@@ -49,11 +48,6 @@ abstract class AbstractElement
*/
protected $withoutP = false;
/**
* @var \Laminas\Escaper\Escaper|\PhpOffice\PhpWord\Escaper\AbstractEscaper
*/
protected $escaper;
/**
* Write element.
*/
@@ -64,12 +58,11 @@ abstract class AbstractElement
*
* @param bool $withoutP
*/
public function __construct(AbstractWriter $parentWriter, Element $element, $withoutP = false)
public function __construct(HTML $parentWriter, Element $element, $withoutP = false)
{
$this->parentWriter = $parentWriter;
$this->element = $element;
$this->withoutP = $withoutP;
$this->escaper = new Escaper();
}
/**

View File

@@ -17,7 +17,7 @@
namespace PhpOffice\PhpWord\Writer\HTML\Element;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Writer\HTML;
/**
* Link element HTML writer.
@@ -39,11 +39,11 @@ class Link extends Text
$prefix = $this->element->isInternal() ? '#' : '';
$content = $this->writeOpening();
if (Settings::isOutputEscapingEnabled()) {
$content .= "<a href=\"{$prefix}{$this->escaper->escapeHtmlAttr($this->element->getSource())}\">{$this->escaper->escapeHtml($this->element->getText())}</a>";
} else {
$content .= "<a href=\"{$prefix}{$this->element->getSource()}\">{$this->element->getText()}</a>";
}
$content .= "<a href=\"{$prefix}"
. $this->parentWriter->escapeHTML($this->element->getSource())
. '">'
. $this->parentWriter->escapeHTML($this->element->getText())
. '</a>';
$content .= $this->writeClosing();
return $content;

View File

@@ -17,7 +17,7 @@
namespace PhpOffice\PhpWord\Writer\HTML\Element;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Writer\HTML;
/**
* ListItem element HTML writer.
@@ -37,11 +37,7 @@ class ListItem extends AbstractElement
return '';
}
if (Settings::isOutputEscapingEnabled()) {
$content = '<p>' . $this->escaper->escapeHtml($this->element->getTextObject()->getText()) . '</p>' . PHP_EOL;
} else {
$content = '<p>' . $this->element->getTextObject()->getText() . '</p>' . PHP_EOL;
}
$content = '<p>' . $this->parentWriter->escapeHTML($this->element->getTextObject()->getText()) . '</p>' . PHP_EOL;
return $content;
}

View File

@@ -17,6 +17,8 @@
namespace PhpOffice\PhpWord\Writer\HTML\Element;
use PhpOffice\PhpWord\Writer\PDF\TCPDF;
/**
* PageBreak element HTML writer.
*
@@ -35,10 +37,13 @@ class PageBreak extends TextBreak
{
/** @var \PhpOffice\PhpWord\Writer\HTML $parentWriter Type hint */
$parentWriter = $this->parentWriter;
if ($parentWriter instanceof TCPDF) {
return '<br pagebreak="true"/>';
}
if ($parentWriter->isPdf()) {
return '<pagebreak style="page-break-before: always;" pagebreak="true"></pagebreak>';
}
return '';
return '<div style="page-break-before: always; height: 0; margin: 0; padding: 0; overflow: hidden;">&#160;</div>' . PHP_EOL;
}
}

View File

@@ -17,6 +17,8 @@
namespace PhpOffice\PhpWord\Writer\HTML\Element;
use PhpOffice\PhpWord\Writer\HTML\Style\Table as TableStyleWriter;
/**
* Table element HTML writer.
*
@@ -39,7 +41,7 @@ class Table extends AbstractElement
$rows = $this->element->getRows();
$rowCount = count($rows);
if ($rowCount > 0) {
$content .= '<table' . self::getTableStyle($this->element->getStyle()) . '>' . PHP_EOL;
$content .= '<table' . $this->getTableStyle($this->element->getStyle()) . '>' . PHP_EOL;
for ($i = 0; $i < $rowCount; ++$i) {
/** @var \PhpOffice\PhpWord\Element\Row $row Type hint */
@@ -51,10 +53,10 @@ class Table extends AbstractElement
$rowCellCount = count($rowCells);
for ($j = 0; $j < $rowCellCount; ++$j) {
$cellStyle = $rowCells[$j]->getStyle();
$cellStyleCss = $this->getTableStyle($cellStyle);
$cellBgColor = $cellStyle->getBgColor();
$cellBgColor === 'auto' && $cellBgColor = null; // auto cannot be parsed to hexadecimal number
$cellFgColor = null;
if ($cellBgColor) {
if ($cellBgColor && $cellBgColor !== 'auto') {
$red = hexdec(substr($cellBgColor, 0, 2));
$green = hexdec(substr($cellBgColor, 2, 2));
$blue = hexdec(substr($cellBgColor, 4, 2));
@@ -67,12 +69,8 @@ class Table extends AbstractElement
if ($cellVMerge === 'restart') {
for ($k = $i + 1; $k < $rowCount; ++$k) {
$kRowCells = $rows[$k]->getCells();
if (isset($kRowCells[$j])) {
if ($kRowCells[$j]->getStyle()->getVMerge() === 'continue') {
++$cellRowSpan;
} else {
break;
}
if (isset($kRowCells[$j]) && $kRowCells[$j]->getStyle()->getVMerge() === 'continue') {
++$cellRowSpan;
} else {
break;
}
@@ -83,22 +81,18 @@ class Table extends AbstractElement
$cellTag = $tblHeader ? 'th' : 'td';
$cellColSpanAttr = (is_numeric($cellColSpan) && ($cellColSpan > 1) ? " colspan=\"{$cellColSpan}\"" : '');
$cellRowSpanAttr = ($cellRowSpan > 1 ? " rowspan=\"{$cellRowSpan}\"" : '');
$cellBgColorAttr = (null === $cellBgColor ? '' : " bgcolor=\"#{$cellBgColor}\"");
$cellFgColorAttr = (null === $cellFgColor ? '' : " color=\"#{$cellFgColor}\"");
$content .= "<{$cellTag}{$cellColSpanAttr}{$cellRowSpanAttr}{$cellBgColorAttr}{$cellFgColorAttr}>" . PHP_EOL;
$cellBgColorAttr = (empty($cellBgColor) ? '' : " bgcolor=\"#{$cellBgColor}\"");
$cellFgColorAttr = (empty($cellFgColor) ? '' : " color=\"#{$cellFgColor}\"");
$content .= "<{$cellTag}{$cellStyleCss}{$cellColSpanAttr}{$cellRowSpanAttr}{$cellBgColorAttr}{$cellFgColorAttr}>" . PHP_EOL;
$writer = new Container($this->parentWriter, $rowCells[$j]);
$content .= $writer->write();
if ($cellRowSpan > 1) {
// There shouldn't be any content in the subsequent merged cells, but lets check anyway
for ($k = $i + 1; $k < $rowCount; ++$k) {
$kRowCells = $rows[$k]->getCells();
if (isset($kRowCells[$j])) {
if ($kRowCells[$j]->getStyle()->getVMerge() === 'continue') {
$writer = new Container($this->parentWriter, $kRowCells[$j]);
$content .= $writer->write();
} else {
break;
}
if (isset($kRowCells[$j]) && $kRowCells[$j]->getStyle()->getVMerge() === 'continue') {
$writer = new Container($this->parentWriter, $kRowCells[$j]);
$content .= $writer->write();
} else {
break;
}
@@ -118,26 +112,25 @@ class Table extends AbstractElement
/**
* Translates Table style in CSS equivalent.
*
* @param null|\PhpOffice\PhpWord\Style\Table|string $tableStyle
*
* @return string
* @param null|\PhpOffice\PhpWord\Style\Cell|\PhpOffice\PhpWord\Style\Table|string $tableStyle
*/
private function getTableStyle($tableStyle = null)
private function getTableStyle($tableStyle = null): string
{
if ($tableStyle == null) {
return '';
}
if (is_string($tableStyle)) {
$style = ' class="' . $tableStyle;
} else {
$style = ' style="';
if ($tableStyle->getLayout() == \PhpOffice\PhpWord\Style\Table::LAYOUT_FIXED) {
$style .= 'table-layout: fixed;';
} elseif ($tableStyle->getLayout() == \PhpOffice\PhpWord\Style\Table::LAYOUT_AUTO) {
$style .= 'table-layout: auto;';
}
return $style . '"';
}
return $style . '"';
$styleWriter = new TableStyleWriter($tableStyle);
$style = $styleWriter->write();
if ($style === '') {
return '';
}
return ' style="' . $style . '"';
}
}

View File

@@ -18,9 +18,10 @@
namespace PhpOffice\PhpWord\Writer\HTML\Element;
use PhpOffice\PhpWord\Element\TrackChange;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Style\Paragraph;
use PhpOffice\PhpWord\Writer\HTML;
use PhpOffice\PhpWord\Writer\HTML\Style\Font as FontStyleWriter;
use PhpOffice\PhpWord\Writer\HTML\Style\Paragraph as ParagraphStyleWriter;
@@ -66,19 +67,21 @@ class Text extends AbstractElement
*/
public function write()
{
$this->processFontStyle();
/** @var \PhpOffice\PhpWord\Element\Text $element Type hint */
$element = $this->element;
$this->getFontStyle();
$text = $this->parentWriter->escapeHTML($element->getText());
if (!$this->withoutP && !trim($text)) {
$text = '&nbsp;';
}
$content = '';
$content .= $this->writeOpening();
$content .= $this->openingText;
$content .= $this->openingTags;
if (Settings::isOutputEscapingEnabled()) {
$content .= $this->escaper->escapeHtml($element->getText());
} else {
$content .= $element->getText();
}
$content .= $text;
$content .= $this->closingTags;
$content .= $this->closingText;
$content .= $this->writeClosing();
@@ -115,10 +118,7 @@ class Text extends AbstractElement
{
$content = '';
if (!$this->withoutP) {
$style = '';
if (method_exists($this->element, 'getParagraphStyle')) {
$style = $this->getParagraphStyle();
}
$style = $this->getParagraphStyle();
$content .= "<p{$style}>";
}
@@ -141,12 +141,7 @@ class Text extends AbstractElement
$content .= $this->writeTrackChangeClosing();
if (!$this->withoutP) {
if (Settings::isOutputEscapingEnabled()) {
$content .= $this->escaper->escapeHtml($this->closingText);
} else {
$content .= $this->closingText;
}
$content .= $this->parentWriter->escapeHTML($this->closingText);
$content .= '</p>' . PHP_EOL;
}
@@ -228,6 +223,7 @@ class Text extends AbstractElement
$pStyleIsObject = ($paragraphStyle instanceof Paragraph);
if ($pStyleIsObject) {
$styleWriter = new ParagraphStyleWriter($paragraphStyle);
$styleWriter->setParentWriter($this->parentWriter);
$style = $styleWriter->write();
} elseif (is_string($paragraphStyle)) {
$style = $paragraphStyle;
@@ -243,22 +239,50 @@ class Text extends AbstractElement
/**
* Get font style.
*/
private function getFontStyle(): void
private function processFontStyle(): void
{
/** @var \PhpOffice\PhpWord\Element\Text $element Type hint */
$element = $this->element;
$style = '';
$attributeStyle = $attributeLang = '';
$lang = null;
$fontStyle = $element->getFontStyle();
$fStyleIsObject = ($fontStyle instanceof Font);
if ($fStyleIsObject) {
if ($fontStyle instanceof Font) {
// Attribute style
$styleWriter = new FontStyleWriter($fontStyle);
$style = $styleWriter->write();
} elseif (is_string($fontStyle)) {
$style = $fontStyle;
$fontCSS = $styleWriter->write();
if ($fontCSS) {
$attributeStyle = ' style="' . $fontCSS . '"';
}
// Attribute Lang
$lang = $fontStyle->getLang();
} elseif (!empty($fontStyle)) {
// Attribute class
$attributeStyle = ' class="' . $fontStyle . '"';
// Attribute Lang
/** @var Font $cssClassStyle */
$cssClassStyle = Style::getStyle($fontStyle);
if ($cssClassStyle !== null && method_exists($cssClassStyle, 'getLang')) {
$lang = $cssClassStyle->getLang();
}
}
if ($style) {
$attribute = $fStyleIsObject ? 'style' : 'class';
$this->openingTags = "<span {$attribute}=\"{$style}\">";
if ($lang) {
$attributeLang = $lang->getLatin();
if (!$attributeLang) {
$attributeLang = $lang->getEastAsia();
}
if (!$attributeLang) {
$attributeLang = $lang->getBidirectional();
}
if ($attributeLang) {
$attributeLang = " lang='$attributeLang'";
}
}
if ($attributeStyle || $attributeLang) {
$this->openingTags = "<span$attributeLang$attributeStyle>";
$this->closingTags = '</span>';
}
}

View File

@@ -17,7 +17,7 @@
namespace PhpOffice\PhpWord\Writer\HTML\Element;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Writer\HTML;
/**
* TextRun element HTML writer.
@@ -41,10 +41,8 @@ class Title extends AbstractElement
$text = $this->element->getText();
if (is_string($text)) {
if (Settings::isOutputEscapingEnabled()) {
$text = $this->escaper->escapeHtml($text);
}
} elseif ($text instanceof \PhpOffice\PhpWord\Element\AbstractContainer) {
$text = $this->parentWriter->escapeHTML($text);
} else {
$writer = new Container($this->parentWriter, $text);
$text = $writer->write();
}

View File

@@ -17,9 +17,8 @@
namespace PhpOffice\PhpWord\Writer\HTML\Part;
use Laminas\Escaper\Escaper;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Writer\AbstractWriter;
use PhpOffice\PhpWord\Writer\HTML;
/**
* @since 0.11.0
@@ -27,35 +26,22 @@ use PhpOffice\PhpWord\Writer\AbstractWriter;
abstract class AbstractPart
{
/**
* @var \PhpOffice\PhpWord\Writer\AbstractWriter
* @var ?HTML
*/
private $parentWriter;
/**
* @var \Laminas\Escaper\Escaper
*/
protected $escaper;
public function __construct()
{
$this->escaper = new Escaper();
}
/**
* @return string
*/
abstract public function write();
/**
* @param \PhpOffice\PhpWord\Writer\AbstractWriter $writer
*/
public function setParentWriter(?AbstractWriter $writer = null): void
public function setParentWriter(?HTML $writer = null): void
{
$this->parentWriter = $writer;
}
/**
* @return \PhpOffice\PhpWord\Writer\AbstractWriter
* @return HTML
*/
public function getParentWriter()
{

View File

@@ -19,6 +19,7 @@ namespace PhpOffice\PhpWord\Writer\HTML\Part;
use PhpOffice\PhpWord\Writer\HTML\Element\Container;
use PhpOffice\PhpWord\Writer\HTML\Element\TextRun as TextRunWriter;
use PhpOffice\PhpWord\Writer\PDF\TCPDF;
/**
* RTF body part writer.
@@ -40,9 +41,18 @@ class Body extends AbstractPart
$content .= '<body>' . PHP_EOL;
$sections = $phpWord->getSections();
$secno = 0;
$isTCPDFWriter = $this->getParentWriter() instanceof TCPDF;
foreach ($sections as $section) {
++$secno;
if ($isTCPDFWriter && $secno > 1) {
$content .= "<div style=\"page: page$secno; page-break-before:always;\">" . PHP_EOL;
} else {
$content .= "<div style='page: page$secno'>" . PHP_EOL;
}
$writer = new Container($this->getParentWriter(), $section);
$content .= $writer->write();
$content .= '</div>' . PHP_EOL;
}
$content .= $this->writeNotes();

View File

@@ -18,12 +18,15 @@
namespace PhpOffice\PhpWord\Writer\HTML\Part;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Shared\Converter;
use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Style\Paragraph;
use PhpOffice\PhpWord\Style\Table;
use PhpOffice\PhpWord\Writer\HTML\Style\Font as FontStyleWriter;
use PhpOffice\PhpWord\Writer\HTML\Style\Generic as GenericStyleWriter;
use PhpOffice\PhpWord\Writer\HTML\Style\Paragraph as ParagraphStyleWriter;
use PhpOffice\PhpWord\Writer\HTML\Style\Table as TableStyleWriter;
/**
* RTF head part writer.
@@ -63,8 +66,10 @@ class Head extends AbstractPart
$method = 'get' . $key;
if ($docProps->$method() != '') {
$content .= '<meta name="' . $value . '"'
. ' content="' . (Settings::isOutputEscapingEnabled() ? $this->escaper->escapeHtmlAttr($docProps->$method()) : $docProps->$method()) . '"'
. ' />' . PHP_EOL;
. ' content="'
. $this->getParentWriter()->escapeHTML($docProps->$method())
. '"'
. ' />' . PHP_EOL;
}
}
$content .= $this->writeStyles();
@@ -75,19 +80,27 @@ class Head extends AbstractPart
/**
* Get styles.
*
* @return string
*/
private function writeStyles()
private function writeStyles(): string
{
$css = '<style>' . PHP_EOL;
// Default styles
$defaultStyles = [
'*' => [
'font-family' => Settings::getDefaultFontName(),
'font-size' => Settings::getDefaultFontSize() . 'pt',
],
$astarray = [
'font-family' => $this->getFontFamily(Settings::getDefaultFontName(), $this->getParentWriter()->getDefaultGenericFont()),
'font-size' => Settings::getDefaultFontSize() . 'pt',
];
// Mpdf sometimes needs separate tag for body; doesn't harm others.
$bodyarray = $astarray;
$defaultWhiteSpace = $this->getParentWriter()->getDefaultWhiteSpace();
if ($defaultWhiteSpace) {
$astarray['white-space'] = $defaultWhiteSpace;
}
foreach ([
'body' => $bodyarray,
'*' => $astarray,
'a.NoteRef' => [
'text-decoration' => 'none',
],
@@ -106,8 +119,7 @@ class Head extends AbstractPart
'td' => [
'border' => '1px solid black',
],
];
foreach ($defaultStyles as $selector => $style) {
] as $selector => $style) {
$styleWriter = new GenericStyleWriter($style);
$css .= $selector . ' {' . $styleWriter->write() . '}' . PHP_EOL;
}
@@ -116,23 +128,81 @@ class Head extends AbstractPart
$customStyles = Style::getStyles();
if (is_array($customStyles)) {
foreach ($customStyles as $name => $style) {
$styleParagraph = null;
if ($style instanceof Font) {
$styleWriter = new FontStyleWriter($style);
if ($style->getStyleType() == 'title') {
$name = str_replace('Heading_', 'h', $name);
$styleParagraph = $style->getParagraph();
$style = $styleParagraph;
} else {
$name = '.' . $name;
}
$css .= "{$name} {" . $styleWriter->write() . '}' . PHP_EOL;
} elseif ($style instanceof Paragraph) {
}
if ($style instanceof Paragraph) {
$styleWriter = new ParagraphStyleWriter($style);
$name = '.' . $name;
$styleWriter->setParentWriter($this->getParentWriter());
if (!$styleParagraph) {
$name = '.' . $name;
}
if ($name === '.Normal') {
$name = "p, $name";
}
$css .= "{$name} {" . $styleWriter->write() . '}' . PHP_EOL;
}
if ($style instanceof Table) {
$styleWriter = new TableStyleWriter($style);
$css .= ".{$name} {" . $styleWriter->write() . '}' . PHP_EOL;
}
}
}
$css .= 'body > div + div {page-break-before: always;}' . PHP_EOL;
$css .= 'div > *:first-child {page-break-before: auto;}' . PHP_EOL;
$sectionNum = 0;
foreach ($this->getParentWriter()->getPhpWord()->getSections() as $section) {
++$sectionNum;
$css .= "@page page$sectionNum {";
$paperSize = $section->getStyle()->getPaperSize();
$orientation = $section->getStyle()->getOrientation();
if ($this->getParentWriter()->isPdf()) {
if ($orientation === 'landscape') {
$paperSize .= '-L';
}
$css .= "sheet-size: $paperSize; ";
} else {
$css .= "size: $paperSize $orientation; ";
}
$css .= 'margin-right: ' . (string) ($section->getStyle()->getMarginRight() / Converter::INCH_TO_TWIP) . 'in; ';
$css .= 'margin-left: ' . (string) ($section->getStyle()->getMarginLeft() / Converter::INCH_TO_TWIP) . 'in; ';
$css .= 'margin-top: ' . (string) ($section->getStyle()->getMarginTop() / Converter::INCH_TO_TWIP) . 'in; ';
$css .= 'margin-bottom: ' . (string) ($section->getStyle()->getMarginBottom() / Converter::INCH_TO_TWIP) . 'in; ';
$css .= '}' . PHP_EOL;
}
$css .= '</style>' . PHP_EOL;
return $css;
}
/**
* Set font and alternates for css font-family.
*/
private function getFontFamily(string $font, string $genericFont): string
{
if (empty($font)) {
return '';
}
$fontfamily = "'" . htmlspecialchars($font, ENT_QUOTES, 'UTF-8') . "'";
if (!empty($genericFont)) {
$fontfamily .= ", $genericFont";
}
return $fontfamily;
}
}

View File

@@ -17,7 +17,8 @@
namespace PhpOffice\PhpWord\Writer\HTML\Style;
use PhpOffice\PhpWord\Style\AbstractStyle as Style;
use PhpOffice\PhpWord\Style\AbstractStyle as StyleAbstract;
use PhpOffice\PhpWord\Writer\HTML;
/**
* Style writer.
@@ -29,26 +30,28 @@ abstract class AbstractStyle
/**
* Parent writer.
*
* @var \PhpOffice\PhpWord\Writer\AbstractWriter
* @var HTML
*/
private $parentWriter;
/**
* Style.
*
* @var array|\PhpOffice\PhpWord\Style\AbstractStyle
* @var null|array|StyleAbstract
*/
private $style;
/**
* Write style.
*
* @return mixed
*/
abstract public function write();
/**
* Create new instance.
*
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $style
* @param array|StyleAbstract $style
*/
public function __construct($style = null)
{
@@ -58,7 +61,7 @@ abstract class AbstractStyle
/**
* Set parent writer.
*
* @param \PhpOffice\PhpWord\Writer\AbstractWriter $writer
* @param HTML $writer
*/
public function setParentWriter($writer): void
{
@@ -68,7 +71,7 @@ abstract class AbstractStyle
/**
* Get parent writer.
*
* @return \PhpOffice\PhpWord\Writer\AbstractWriter
* @return HTML
*/
public function getParentWriter()
{
@@ -78,11 +81,11 @@ abstract class AbstractStyle
/**
* Get style.
*
* @return array|\PhpOffice\PhpWord\Style\AbstractStyle $style
* @return null|array|string|StyleAbstract
*/
public function getStyle()
{
if (!$this->style instanceof Style && !is_array($this->style)) {
if (!$this->style instanceof StyleAbstract && !is_array($this->style)) {
return '';
}

View File

@@ -39,14 +39,14 @@ class Font extends AbstractStyle
}
$css = [];
$font = $style->getName();
$font = $this->getFontFamily($style->getName(), $style->getFallbackFont());
$size = $style->getSize();
$color = $style->getColor();
$fgColor = $style->getFgColor();
$underline = $style->getUnderline() != FontStyle::UNDERLINE_NONE;
$lineThrough = $style->isStrikethrough() || $style->isDoubleStrikethrough();
$css['font-family'] = $this->getValueIf($font !== null, "'{$font}'");
$css['font-family'] = $this->getValueIf(!empty($font), $font);
$css['font-size'] = $this->getValueIf($size !== null, "{$size}pt");
$css['color'] = $this->getValueIf($color !== null, "#{$color}");
$css['background'] = $this->getValueIf($fgColor != '', $fgColor);
@@ -61,10 +61,35 @@ class Font extends AbstractStyle
$css['text-transform'] = $this->getValueIf($style->isAllCaps(), 'uppercase');
$css['font-variant'] = $this->getValueIf($style->isSmallCaps(), 'small-caps');
$css['display'] = $this->getValueIf($style->isHidden(), 'none');
$whitespace = $style->getWhiteSpace();
if ($whitespace) {
$css['white-space'] = $whitespace;
}
$spacing = $style->getSpacing();
$css['letter-spacing'] = $this->getValueIf(null !== $spacing, ($spacing / 20) . 'pt');
if ($style->isRTL()) {
$css['direction'] = 'rtl';
} elseif ($style->isRTL() === false) {
$css['direction'] = 'ltr';
}
return $this->assembleCss($css);
}
/**
* Set font and alternates for css font-family.
*/
private function getFontFamily(?string $font, string $genericFont): string
{
if (empty($font)) {
return '';
}
$fontfamily = "'" . htmlspecialchars($font, ENT_QUOTES, 'UTF-8') . "'";
if (!empty($genericFont)) {
$fontfamily .= ", $genericFont";
}
return $fontfamily;
}
}

View File

@@ -17,7 +17,9 @@
namespace PhpOffice\PhpWord\Writer\HTML\Style;
use PhpOffice\PhpWord\Shared\Converter;
use PhpOffice\PhpWord\SimpleType\Jc;
use PhpOffice\PhpWord\Writer\PDF\TCPDF;
/**
* Paragraph style HTML writer.
@@ -49,6 +51,9 @@ class Paragraph extends AbstractStyle
break;
case Jc::END:
$textAlign = $style->isBidi() ? 'left' : 'right';
break;
case Jc::MEDIUM_KASHIDA:
case Jc::HIGH_KASHIDA:
case Jc::LOW_KASHIDA:
@@ -63,9 +68,13 @@ class Paragraph extends AbstractStyle
$textAlign = 'justify';
break;
default: //all others, align left
case Jc::LEFT:
$textAlign = 'left';
break;
default: //all others, including Jc::START
$textAlign = $style->isBidi() ? 'right' : 'left';
break;
}
@@ -79,9 +88,32 @@ class Paragraph extends AbstractStyle
$after = $spacing->getAfter();
$css['margin-top'] = $this->getValueIf(null !== $before, ($before / 20) . 'pt');
$css['margin-bottom'] = $this->getValueIf(null !== $after, ($after / 20) . 'pt');
} else {
$css['margin-top'] = '0';
$css['margin-bottom'] = '0';
}
// Line Height
$lineHeight = $style->getLineHeight();
if (!empty($lineHeight)) {
$css['line-height'] = $lineHeight;
}
// Indentation (Margin)
$indentation = $style->getIndentation();
if ($indentation) {
$inches = $indentation->getLeft() * 1.0 / Converter::INCH_TO_TWIP;
$css[$this->getParentWriter() instanceof TCPDF ? 'text-indent' : 'margin-left'] = ((string) $inches) . 'in';
$inches = $indentation->getRight() * 1.0 / Converter::INCH_TO_TWIP;
$css['margin-right'] = ((string) $inches) . 'in';
}
// Page Break Before
if ($style->hasPageBreakBefore()) {
$css['page-break-before'] = 'always';
}
// Bidirectional
if ($style->isBidi()) {
$css['direction'] = 'rtl';
}
return $this->assembleCss($css);

View File

@@ -0,0 +1,82 @@
<?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
*
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
declare(strict_types=1);
namespace PhpOffice\PhpWord\Writer\HTML\Style;
use PhpOffice\PhpWord\Style\Cell as StyleCell;
use PhpOffice\PhpWord\Style\Table as StyleTable;
class Table extends AbstractStyle
{
/**
* @return string
*/
public function write()
{
$style = $this->getStyle();
if (!$style instanceof StyleTable && !$style instanceof StyleCell) {
return '';
}
$css = [];
if (is_object($style) && method_exists($style, 'getLayout')) {
if ($style->getLayout() == StyleTable::LAYOUT_FIXED) {
$css['table-layout'] = 'fixed';
} elseif ($style->getLayout() == StyleTable::LAYOUT_AUTO) {
$css['table-layout'] = 'auto';
}
}
if (is_object($style) && method_exists($style, 'isBidiVisual')) {
if ($style->isBidiVisual()) {
$css['direction'] = 'rtl';
}
}
foreach (['Top', 'Left', 'Bottom', 'Right'] as $direction) {
$method = 'getBorder' . $direction . 'Style';
if (method_exists($style, $method)) {
$outval = $style->{$method}();
if ($outval === 'single') {
$outval = 'solid';
}
if (is_string($outval) && 1 == preg_match('/^[a-z]+$/', $outval)) {
$css['border-' . lcfirst($direction) . '-style'] = $outval;
}
}
$method = 'getBorder' . $direction . 'Color';
if (method_exists($style, $method)) {
$outval = $style->{$method}();
if (is_string($outval) && 1 == preg_match('/^[a-z]+$/', $outval)) {
$css['border-' . lcfirst($direction) . '-color'] = $outval;
}
}
$method = 'getBorder' . $direction . 'Size';
if (method_exists($style, $method)) {
$outval = $style->{$method}();
if (is_numeric($outval)) {
// size is in twips - divide by 20 to get points
$css['border-' . lcfirst($direction) . '-width'] = ((string) ($outval / 20)) . 'pt';
}
}
}
return $this->assembleCss($css);
}
}

View File

@@ -17,8 +17,12 @@
namespace PhpOffice\PhpWord\Writer;
use PhpOffice\Math\Writer\MathML;
use PhpOffice\PhpWord\Element\AbstractElement;
use PhpOffice\PhpWord\Element\Formula;
use PhpOffice\PhpWord\Media;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Writer\ODText\Part\AbstractPart;
/**
* ODText writer.
@@ -27,10 +31,13 @@ use PhpOffice\PhpWord\PhpWord;
*/
class ODText extends AbstractWriter implements WriterInterface
{
/**
* @var AbstractElement[]
*/
protected $objects = [];
/**
* Create new ODText writer.
*
* @param \PhpOffice\PhpWord\PhpWord $phpWord
*/
public function __construct(?PhpWord $phpWord = null)
{
@@ -61,10 +68,8 @@ class ODText extends AbstractWriter implements WriterInterface
/**
* Save PhpWord to file.
*
* @param string $filename
*/
public function save($filename = null): void
public function save(string $filename): void
{
$filename = $this->getTempFile($filename);
$zip = $this->getZipArchive($filename);
@@ -77,8 +82,28 @@ class ODText extends AbstractWriter implements WriterInterface
// Write parts
foreach ($this->parts as $partName => $fileName) {
if ($fileName != '') {
$zip->addFromString($fileName, $this->getWriterPart($partName)->write());
if ($fileName === '') {
continue;
}
$part = $this->getWriterPart($partName);
if (!$part instanceof AbstractPart) {
continue;
}
$part->setObjects($this->objects);
$zip->addFromString($fileName, $part->write());
$this->objects = $part->getObjects();
}
// Write objects charts
if (!empty($this->objects)) {
$writer = new MathML();
foreach ($this->objects as $idxObject => $object) {
if ($object instanceof Formula) {
$zip->addFromString('Formula' . $idxObject . '/content.xml', $writer->write($object->getMath()));
}
}
}

View File

@@ -15,7 +15,7 @@
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
// Not fully implemented
// - supports only PAGE and NUMPAGES
// - supports only PAGE, NUMPAGES, DATE and FILENAME
// - supports only default formats and options
// - supports style only if specified by name
// - spaces before and after field may be dropped
@@ -44,6 +44,7 @@ class Field extends Text
case 'date':
case 'page':
case 'numpages':
case 'filename':
$this->writeDefault($element, $type);
break;
@@ -78,6 +79,18 @@ class Field extends Text
$xmlWriter->startElement('text:page-count');
$xmlWriter->endElement();
break;
case 'filename':
$xmlWriter->startElement('text:file-name');
$xmlWriter->writeAttribute('text:fixed', 'false');
$options = $element->getOptions();
if ($options != null && in_array('Path', $options)) {
$xmlWriter->writeAttribute('text:display', 'full');
} else {
$xmlWriter->writeAttribute('text:display', 'name');
}
$xmlWriter->endElement();
break;
}
$xmlWriter->endElement(); // text:span

View File

@@ -0,0 +1,74 @@
<?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
*
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Writer\ODText\Element;
use PhpOffice\PhpWord\Element\Formula as ElementFormula;
use PhpOffice\PhpWord\Shared\Converter;
use PhpOffice\PhpWord\Writer\ODText\Part\AbstractPart;
/**
* Formula element writer.
*
* @since 0.10.0
*/
class Formula extends AbstractElement
{
/**
* Write element.
*/
public function write(): void
{
$xmlWriter = $this->getXmlWriter();
$element = $this->getElement();
if (!$element instanceof ElementFormula) {
return;
}
$part = $this->getPart();
if (!$part instanceof AbstractPart) {
return;
}
$objectIdx = $part->addObject($element);
//$style = $element->getStyle();
//$width = Converter::pixelToCm($style->getWidth());
//$height = Converter::pixelToCm($style->getHeight());
$xmlWriter->startElement('text:p');
$xmlWriter->writeAttribute('text:style-name', 'OB' . $objectIdx);
$xmlWriter->startElement('draw:frame');
$xmlWriter->writeAttribute('draw:name', $element->getElementId());
$xmlWriter->writeAttribute('text:anchor-type', 'as-char');
//$xmlWriter->writeAttribute('svg:width', $width . 'cm');
//$xmlWriter->writeAttribute('svg:height', $height . 'cm');
//$xmlWriter->writeAttribute('draw:z-index', $mediaIndex);
$xmlWriter->startElement('draw:object');
$xmlWriter->writeAttribute('xlink:href', 'Formula' . $objectIdx);
$xmlWriter->writeAttribute('xlink:type', 'simple');
$xmlWriter->writeAttribute('xlink:show', 'embed');
$xmlWriter->writeAttribute('xlink:actuate', 'onLoad');
$xmlWriter->endElement(); // draw:object
$xmlWriter->endElement(); // draw:frame
$xmlWriter->endElement(); // text:p
}
}

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