diff --git a/.gitignore b/.gitignore index 810a7b0a..e5deb643 100644 --- a/.gitignore +++ b/.gitignore @@ -4,12 +4,16 @@ .Trashes Thumbs.db Desktop.ini -composer.phar +.idea +_build phpunit.xml +composer.lock +composer.phar +vendor +/report +/samples/resources +/samples/results +/.settings phpword.ini /.buildpath -/.idea -/.project -/.settings -/build -/vendor +/.project \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 73dd68ec..22f45d9b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: php php: - - 5.3.3 - 5.3 - 5.4 - 5.5 @@ -10,6 +9,7 @@ php: matrix: allow_failures: + - php: 5.2 - php: hhvm env: @@ -23,17 +23,6 @@ before_script: ## Composer - composer self-update - composer install --prefer-source --dev - ## PHP Copy/Paste Detector - - curl -o phpcpd.phar https://phar.phpunit.de/phpcpd.phar - ## PHP Mess Detector - - pear config-set preferred_state beta - - printf "\n" | pecl install imagick - - pear channel-discover pear.phpmd.org - - pear channel-discover pear.pdepend.org - - pear install --alldeps phpmd/PHP_PMD - - phpenv rehash - ## PHPLOC - #- curl -o phploc.phar https://phar.phpunit.de/phploc.phar ## PHPDocumentor - mkdir -p build/docs - mkdir -p build/coverage @@ -42,15 +31,15 @@ script: ## PHP_CodeSniffer - ./vendor/bin/phpcs src/ tests/ --standard=PSR2 -n --ignore=src/PhpWord/Shared/PCLZip ## PHP Copy/Paste Detector - - php phpcpd.phar src/ tests/ --verbose + - ./vendor/bin/phpcpd src/ tests/ --verbose ## PHP Mess Detector - - phpmd src/,tests/ text ./phpmd.xml.dist --exclude pclzip.lib.php - ## PHPLOC - #- php phploc.phar src/ + - ./vendor/bin/phpmd src/,tests/ text ./phpmd.xml.dist --exclude pclzip.lib.php ## PHPUnit - - phpunit -c ./ --coverage-text --coverage-html ./build/coverage + - ./vendor/bin/phpunit -c ./ --coverage-text --coverage-html ./build/coverage + ## PHPLOC + - ./vendor/bin/phploc src/ ## PHPDocumentor - - vendor/bin/phpdoc.php -q -d ./src -t ./build/docs --ignore "*/src/PhpWord/Shared/*/*" --template="responsive-twig" + - ./vendor/bin/phpdoc -q -d ./src -t ./build/docs --ignore "*/src/PhpWord/Shared/*/*" --template="responsive-twig" after_script: ## PHPDocumentor diff --git a/CHANGELOG.md b/CHANGELOG.md index 59cbba6c..93ab0127 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,72 @@ This is the changelog between releases of PHPWord. Releases are listed in reverse chronological order with the latest version listed on top, while additions/changes in each release are listed in chronological order. Changes in each release are divided into three parts: added or change features, bugfixes, and miscellaneous improvements. Each line contains short information about the change made, the person who made it, and the related issue number(s) in GitHub. +## 0.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` 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 +- `` tag is closed with `` 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 + ## 0.11.1 - 2 June 2014 This is an immediate bugfix release for HTML reader. -- HTML Reader: `

` and header tags puts no output - @canyildiz @ivanlanin GH-257 +- HTML Reader: `

` and header tags puts no output - @canyildiz @ivanlanin #257 ## 0.11.0 - 1 June 2014 @@ -14,17 +75,17 @@ This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3. Four ### Features -- Image: Ability to define relative and absolute positioning - @basjan GH-217 -- Footer: Conform footer with header by adding firstPage, evenPage and by inheritance - @basjan @ivanlanin GH-219 -- Element: New `TextBox` element - @basjan @ivanlanin GH-228 GH-229 GH-231 -- HTML: Ability to add elements to PHPWord object via html - @basjan GH-231 -- Element: New `ListItemRun` element that can add a list item with inline formatting like a textrun - @basjan GH-235 -- Table: Ability to add table inside a cell (nested table) - @ivanlanin GH-149 -- RTF Writer: UTF8 support for RTF: Internal UTF8 text is converted to Unicode before writing - @ivanlanin GH-158 -- Table: Ability to define table width (in percent and twip) and position - @ivanlanin GH-237 -- RTF Writer: Ability to add links and page breaks in RTF - @ivanlanin GH-196 +- 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 GH-200 +- 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 @@ -32,23 +93,23 @@ This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3. Four - 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 GH-244 +- 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 GH-251 -- RTF Reader: Basic RTF reader - @ivanlanin GH-72 GH-252 -- Element: New `Line` element - @basjan GH-253 -- Title: Ability to apply numbering in heading - @ivanlanin GH-193 -- HTML Reader: Basic HTML reader - @ivanlanin GH-80 GH-254 -- RTF Writer: Basic table writing - @ivanlanin GH-245 +- 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 GH-222 -- Conversion: Fix conversion from cm to pixel, pixel to cm, and pixel to point - @basjan GH-233 GH-234 -- PageBreak: Page break adds new line in the beginning of the new page - @ivanlanin GH-150 -- Image: `marginLeft` and `marginTop` cannot accept float value - @ivanlanin GH-248 -- Title: Orphan `w:fldChar` caused OpenOffice to crash when opening DOCX - @ivanlanin GH-236 +- 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 @@ -60,13 +121,13 @@ This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3. Four ### Miscellaneous -- License: Change the project license from LGPL 2.1 into LGPL 3.0 - GH-211 +- 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 GH-206 +- 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 GH-154 -- QA: Add `.scrutinizer.yml` and include `composer.lock` for preparation to Scrutinizer - @ivanlanin GH-186 +- 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 @@ -79,7 +140,7 @@ This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3. Four This is a bugfix release for `php-zip` requirement in Composer. -- Change Composer requirements for php-zip from `require` to `suggest` - @bskrtich GH-246 +- Change Composer requirements for php-zip from `require` to `suggest` - @bskrtich #246 ## 0.10.0 - 4 May 2014 @@ -87,48 +148,48 @@ This release marked heavy refactorings on internal code structure with the creat ### Features -- Image: Get image dimensions without EXIF extension - @andrew-kzoo GH-184 -- Table: Add `tblGrid` element for Libre/Open Office table sizing - @gianis6 GH-183 +- 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 GH-168 -- Table: Add `exactHeight` to row style to define whether row height should be exact or atLeast - @jcarignan GH-168 -- Element: New `CheckBox` element for sections and table cells - @ozilion GH-156 -- Settings: Ability to use PCLZip as alternative to ZipArchive - @bskrtich @ivanlanin GH-106 GH-140 GH-185 -- Template: Ability to find & replace variables in headers & footers - @dgudgeon GH-190 -- Template: Ability to clone & delete block of text using `cloneBlock` and `deleteBlock` - @diego-vieira GH-191 -- TOC: Ability to have two or more TOC in one document and to set min and max depth for TOC - @Pyreweb GH-189 -- Table: Ability to add footnote in table cell - @ivanlanin GH-187 -- Footnote: Ability to add image in footnote - @ivanlanin GH-187 -- ListItem: Ability to add list item in header/footer - @ivanlanin GH-187 -- CheckBox: Ability to add checkbox in header/footer - @ivanlanin GH-187 -- Link: Ability to add link in header/footer - @ivanlanin GH-187 -- Object: Ability to add object in header, footer, textrun, and footnote - @ivanlanin GH-187 -- Media: Add `Media::resetElements()` to reset all media data - @juzi GH-19 -- General: Add `Style::resetStyles()` - @ivanlanin GH-187 +- 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 GH-10 GH-198 +- 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 GH-194 -- HTML Writer: Basic HTML writer: text, textrun, link, title, textbreak, table, image (as Base64), footnote, endnote - @ivanlanin GH-203 GH-67 GH-147 -- PDF Writer: Basic PDF writer using DomPDF: All HTML element except image - @ivanlanin GH-68 +- 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 GH-71 +- 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 GH-151 -- Settings: Ability to use measurement unit other than twips with `setMeasurementUnit` - @ivanlanin GH-199 +- 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 GH-170 -- Documentation: Error in a function - @theBeerNut GH-195 +- Footnote: Footnote content doesn't show footnote reference number - @ivanlanin #170 +- Documentation: Error in a function - @theBeerNut #195 ### Deprecated @@ -148,20 +209,20 @@ This release marked heavy refactorings on internal code structure with the creat ### Miscellaneous -- Documentation: Simplify page level docblock - @ivanlanin GH-179 -- Writer: Refactor writer classes and create a new `Write\AbstractWriter` abstract class - @ivanlanin GH-160 -- General: Refactor folders: `Element` and `Exception` - @ivanlanin GH-187 -- General: Remove legacy `HashTable` and `Shared\ZipStreamWrapper` and all related properties/methods - @ivanlanin GH-187 -- Element: New `AbstractElement` abstract class - @ivanlanin GH-187 -- Media: Refactor media class to use one method for all docPart (section, header, footer, footnote) - @ivanlanin GH-187 -- General: Remove underscore prefix from all private properties name - @ivanlanin GH-187 -- General: Move Section `Settings` to `Style\Section` - @ivanlanin GH-187 -- General: Give `Abstract` prefix and `Interface` suffix for all abstract classes and interfaces as per [PHP-FIG recommendation](https://github.com/php-fig/fig-standards/blob/master/bylaws/002-psr-naming-conventions.md) - @ivanlanin GH-187 -- Style: New `Style\AbstractStyle` abstract class - @ivanlanin GH-187 -- Writer: New 'ODText\Base` class - @ivanlanin GH-187 +- 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 GH-59 +- 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 @@ -188,13 +249,13 @@ This release marked the transformation to namespaces (PHP 5.3+). ### Miscellaneous -- Move documentation to [Read The Docs](http://phpword.readthedocs.org/en/develop/) - @Progi1984 @ivanlanin GH-82 -- Reorganize and redesign samples folder - @ivanlanin GH-137 -- Use `PhpOffice\PhpWord` namespace for PSR compliance - @RomanSyroeshko @gabrielbull GH-159 GH-58 +- 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 GH-160 -- Merge Section\MemoryImage into Section\Image. Section\Image is deprecated - @ivanlanin GH-160 +- Merge Style\TableFull into Style\Table. Style\TableFull is deprecated - @ivanlanin #160 +- Merge Section\MemoryImage into Section\Image. Section\Image is deprecated - @ivanlanin #160 ## 0.8.1 - 17 Mar 2014 @@ -208,44 +269,44 @@ This release merged a lot of improvements from the community. Unit tests introdu ### Features -- Template: Permit to save a template generated as a file (PHPWord_Template::saveAs()) - @RomanSyroeshko GH-56 GH-57 +- 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 GH-5 -- General: Add ability to manage line breaks after image insertion - @bskrtich GH-6 GH-66 GH-84 -- Template: Ability to limit number of replacements performed by setValue() method of Template class - @RomanSyroeshko GH-52 GH-53 GH-85 -- Table row: Repeat as header row & allow row to break across pages - @ivanlanin GH-48 GH-86 -- Table: Table width in percentage - @ivanlanin GH-48 GH-86 -- Font: Superscript and subscript - @ivanlanin GH-48 GH-86 -- Paragraph: Hanging paragraph - @ivanlanin GH-48 GH-86 -- Section: Multicolumn and section break - @ivanlanin GH-48 GH-86 -- Template: Ability to apply XSL style sheet to Template - @RomanSyroeshko GH-46 GH-47 GH-83 -- General: PHPWord_Shared_Font::pointSizeToTwips() converter - @ivanlanin GH-87 -- Paragraph: Ability to define normal paragraph style with PHPWord::setNormalStyle() - @ivanlanin GH-87 -- Paragraph: Ability to define parent style (basedOn) and style for following paragraph (next) - @ivanlanin GH-87 -- Clone table rows on the fly when using a template document - @jeroenmoors GH-44 GH-88 -- Initial addition of basic footnote support - @deds GH-16 -- Paragraph: Ability to define paragraph pagination: widow control, keep next, keep lines, and page break before - @ivanlanin GH-92 -- General: PHPWord_Style_Font refactoring - @ivanlanin GH-93 -- Font: Use points instead of halfpoints internally. Conversion to halfpoints done during XML Writing. - @ivanlanin GH-93 -- Paragraph: setTabs() function - @ivanlanin GH-92 -- General: Basic support for TextRun on ODT and RTF - @ivanlanin GH-99 -- Reader: Basic Reader for Word2007 - @ivanlanin GH-104 -- TextRun: Allow Text Break in Text Run - @bskrtich GH-109 -- General: Support for East Asian fontstyle - @jhfangying GH-111 GH-118 -- Image: Use exif_imagetype to check image format instead of extension name - @gabrielbull GH-114 -- General: Setting for XMLWriter Compatibility option - @bskrtich GH-103 -- MemoryImage: Allow remote image when allow_url_open = on - @ivanlanin GH-122 -- TextBreak: Allow font and paragraph style for text break - @ivanlanin GH-18 +- 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 GH-51 -- Example in README.md is broken - @Progi1984 GH-89 -- General: PHPWord_Shared_Drawing::centimetersToPixels() conversion - @ivanlanin GH-94 -- Footnote: Corrupt DOCX reported by MS Word when sections > 1 and not every sections have footnote - @ivanlanin GH-125 +- 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 @@ -257,8 +318,8 @@ This is the first release after a long development hiatus in [CodePlex](https:// ### Features -- Implement RTF Writer - @Progi1984 GH-1 -- Implement ODT Writer - @Progi1984 GH-2 +- 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 @@ -267,16 +328,16 @@ This is the first release after a long development hiatus in [CodePlex](https:// ### Bugfixes -- "Warning: Invalid error type specified in ...\PHPWord.php on line 226" is thrown when the specified template file is not found - @RomanSyroeshko GH-32 -- PHPWord_Shared_String.IsUTF8 returns FALSE for Cyrillic UTF-8 input - @RomanSyroeshko GH-34 -- Temporary files naming logic in PHPWord_Template can lead to a collision - @RomanSyroeshko GH-38 +- "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 GH-27 +- 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 CP-49 +- IMPROVED: Advanced string replace in setValue for Template - @Esmeraldo [#49](http://phpword.codeplex.com/workitem/49) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 34985610..335ad2d5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,14 +1,14 @@ # Contributing to PHPWord -PHPWord is build by the crowd and for the crowd. Every contributions are welcomed; either by [submitting](https://github.com/PHPOffice/PHPWord/issues) bug issues or suggesting improvements, or in a more active form like [requesting](https://github.com/PHPOffice/PHPWord/pulls) a pull. +PHPWord is built by the crowd and for the crowd. Every contribution is welcome; either by [submitting](https://github.com/PHPOffice/PHPWord/issues) bug issues or suggesting improvements, or in a more active form like [requesting](https://github.com/PHPOffice/PHPWord/pulls) a pull. -We want to create a high quality document writer and reader library that people can use with more confidence and less bugs. We want to collaborate happily, code joyfully, and get a life merrily. Thus, below are some guidelines that we expect to be followed by each contributor. +We want to create a high quality document writer and reader library that people can use with more confidence and less bugs. We want to collaborate happily, code joyfully, and get alive merrily. Thus, below are some guidelines, that we expect to be followed by each contributor. -- **Be brief, but be bold**: State your issues briefly, but speak out your ideas loudly, even if you can't or don't know how to implement it right away. The world will be better with limitless innovations. -- **Code in PSR**: We use PHP Standards Recommendation (PSR) from as the PHP Framework Interoperability Group (PHP-FIG). If you're not familiar with this standard, please [familiarize yourself now](https://github.com/php-fig/fig-standards). Use [PHPCodeSniffer](http://pear.php.net/package/PHP_CodeSniffer/) to check your code against this standard. -- **Test your code**: Nobody else knows your code better than you. So, please, test your own code before submitting your pull request. PHPWord uses [PHPUnit](http://phpunit.de/) as our testing framework. -- **Request pull in separate branch**: Do not submit your request to the master branch, but create a separate branch named specifically for the issue that you addressed. Read [GitHub manual](https://help.github.com/articles/using-pull-requests) to find out more about this. If you are new to GitHub, read [this short manual](https://help.github.com/articles/fork-a-repo) to get you familiar with forks and how git works in general. +- **Be brief, but be bold**. State your issues briefly. But speak out your ideas loudly, even if you can't or don't know how to implement it right away. The world will be better with limitless innovations. +- **Follow PHP-FIG standards**. We follow PHP Standards Recommendations (PSRs) by [PHP Framework Interoperability Group](http://www.php-fig.org/). If you're not familiar with these standards, please, [familiarize yourself now](https://github.com/php-fig/fig-standards). Also, please, use [PHPCodeSniffer](http://pear.php.net/package/PHP_CodeSniffer/) to validate your code against PSRs. +- **Test your code**. Nobody else knows your code better than you. So, it's completely yours mission to test the changes you made before pull request submission. We use [PHPUnit](https://phpunit.de/) for our testing purposes and recommend you using this tool too. [Here](https://phpunit.de/presentations.html) you can find PHPUnit best practices and additional information on effective unit testing, which helps us making PHPWord better day to day. Do not hesitate to smoke it carefully. It's a great investment in quality of your work, and it saves you years of life. +- **Request pull in separate branch**. Do not submit your request to the master branch. But create a separate branch named specifically for the issue that you addressed. Read [GitHub manual](https://help.github.com/articles/using-pull-requests) to find out more about this. If you are new to GitHub, read [this short manual](https://help.github.com/articles/fork-a-repo) to get yourself familiar with forks and how git works in general. [This video](http://www.youtube.com/watch?v=-zvHQXnBO6c) explains how to synchronize your Github Fork with the Branch of PHPWord. That's it. Thank you for your interest in PHPWord, and welcome! -May the Force be with you. \ No newline at end of file +May the Force be with you. diff --git a/README.md b/README.md index ecbe1354..8f499a8e 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,16 @@ PHPWord is a library written in pure PHP that provides a set of classes to write PHPWord is an open source project licensed under the terms of [LGPL version 3](https://github.com/PHPOffice/PHPWord/blob/develop/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/) and the [API Documentation](http://phpoffice.github.io/PHPWord/docs/develop/). +Read more about PHPWord: + +- [Features](#features) +- [Requirements](#requirements) +- [Installation](#installation) +- [Getting started](#getting-started) +- [Contributing](#contributing) +- [Developers' Documentation](http://phpword.readthedocs.org/) +- [API Documentation](http://phpoffice.github.io/PHPWord/docs/master/) + ## Features With PHPWord, you can create DOCX, ODT, or RTF documents dynamically using your PHP 5.3+ scripts. Below are some of the things that you can do with PHPWord library: @@ -30,6 +40,9 @@ With PHPWord, you can create DOCX, ODT, or RTF documents dynamically using your - Insert list items as bulleted, numbered, or multilevel - Insert hyperlinks - Insert footnotes and endnotes +- Insert drawing shapes (arc, curve, line, polyline, rect, oval) +- Insert charts (pie, doughnut, bar, line, area, scatter, radar) +- Insert form fields (textinput, checkbox, and dropdown) - Create document from templates - Use XSL 1.0 style sheets to transform main document part of OOXML template - ... and many more features on progress @@ -67,55 +80,97 @@ require_once 'path/to/PhpWord/src/PhpWord/Autoloader.php'; \PhpOffice\PhpWord\Autoloader::register(); ``` -## Usages +## Getting started -The following is a basic example of the PHPWord library. More examples are provided in the [samples folder](samples/). +The following is a basic usage example of the PHPWord library. ```php +addSection(); +// Adding Text element to the Section having font styled by default... +$section->addText( + htmlspecialchars( + '"Learn from yesterday, live for today, hope for tomorrow. ' + . 'The important thing is not to stop questioning." ' + . '(Albert Einstein)' + ) +); -// After creating a section, you can append elements: -$section->addText('Hello world!'); +/* + * Note: it's possible to customize font style of the Text element you add in three ways: + * - inline; + * - using named font style (new font style object will be implicitly created); + * - using explicitly created font style object. + */ -// You can directly style your text by giving the addText function an array: -$section->addText('Hello world! I am formatted.', - array('name'=>'Tahoma', 'size'=>16, 'bold'=>true)); +// Adding Text element with font customized inline... +$section->addText( + htmlspecialchars( + '"Great achievement is usually born of great sacrifice, ' + . 'and is never the result of selfishness." ' + . '(Napoleon Hill)' + ), + array('name' => 'Tahoma', 'size' => 10) +); -// If you often need the same style again you can create a user defined style -// to the word document and give the addText function the name of the style: -$phpWord->addFontStyle('myOwnStyle', - array('name'=>'Verdana', 'size'=>14, 'color'=>'1B2232')); -$section->addText('Hello world! I am formatted by a user defined style', - 'myOwnStyle'); +// Adding Text element with font customized using named font style... +$fontStyleName = 'oneUserDefinedStyle'; +$phpWord->addFontStyle( + $fontStyleName, + array('name' => 'Tahoma', 'size' => 10, 'color' => '1B2232', 'bold' => true) +); +$section->addText( + htmlspecialchars( + '"The greatest accomplishment is not in never falling, ' + . 'but in rising again after you fall." ' + . '(Vince Lombardi)' + ), + $fontStyleName +); -// You can also put the appended element to local object like this: +// Adding Text element with font customized using explicitly created font style object... $fontStyle = new \PhpOffice\PhpWord\Style\Font(); $fontStyle->setBold(true); -$fontStyle->setName('Verdana'); -$fontStyle->setSize(22); -$myTextElement = $section->addText('Hello World!'); +$fontStyle->setName('Tahoma'); +$fontStyle->setSize(13); +$myTextElement = $section->addText( + htmlspecialchars('"Believe you can and you\'re halfway there." (Theodor Roosevelt)') +); $myTextElement->setFontStyle($fontStyle); -// Finally, write the document: +// Saving the document as OOXML file... $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007'); $objWriter->save('helloWorld.docx'); +// Saving the document as ODF file... $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'ODText'); $objWriter->save('helloWorld.odt'); -$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'RTF'); -$objWriter->save('helloWorld.rtf'); +// Saving the document as HTML file... +$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'HTML'); +$objWriter->save('helloWorld.html'); + +/* Note: we skip RTF, because it's not XML-based and requires a different example. */ +/* Note: we skip PDF, because "HTML-to-PDF" approach is used to create PDF documents. */ ``` +:warning: Escape any string you pass to OOXML/ODF/HTML document, otherwise it may get broken. + +More examples are provided in the [samples folder](samples/). You can also read the [Developers' Documentation](http://phpword.readthedocs.org/) and the [API Documentation](http://phpoffice.github.io/PHPWord/docs/master/) for more detail. ## Contributing -We welcome everyone to contribute to PHPWord. Below are some of the things that you can do to contribute: +We welcome everyone to contribute to PHPWord. Below are some of the things that you can do to contribute. -- Read [our contributing guide](https://github.com/PHPOffice/PHPWord/blob/master/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 -- 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 +- Read [our contributing guide](https://github.com/PHPOffice/PHPWord/blob/master/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. +- 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. diff --git a/VERSION b/VERSION index 027934ea..d33c3a21 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.11.1 \ No newline at end of file +0.12.0 \ No newline at end of file diff --git a/composer.json b/composer.json index 2f9a0915..b55d8340 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "phpoffice/phpword", "description": "PHPWord - A pure PHP library for reading and writing word processing documents (DOCX, ODT, RTF, HTML, PDF)", "keywords": [ - "PHP", "PhpOffice", "office", "PhpWord", "word", "template", "reader", "writer", + "PHP", "PhpOffice", "office", "PhpWord", "word", "template", "template processor", "reader", "writer", "docx", "OOXML", "OpenXML", "Office Open XML", "ISO IEC 29500", "WordprocessingML", "RTF", "Rich Text Format", "doc", "odt", "OpenDocument", "PDF", "HTML" ], @@ -39,6 +39,9 @@ "phpunit/phpunit": "3.7.*", "phpdocumentor/phpdocumentor":"2.*", "squizlabs/php_codesniffer": "1.*", + "phpmd/phpmd": "2.*", + "sebastian/phpcpd": "2.*", + "phploc/phploc": "2.*", "dompdf/dompdf":"0.6.*", "tecnick.com/tcpdf": "6.*", "mpdf/mpdf": "5.*" @@ -47,7 +50,7 @@ "ext-zip": "Used to write DOCX and ODT", "ext-gd2": "Used to add images", "ext-xmlwriter": "Used to write DOCX and ODT", - "ext-xsl": "Used to apply XSL style sheet to template part", + "ext-xsl": "Used to apply XSL style sheet to main document part of OOXML template", "dompdf/dompdf": "Used to write PDF" }, "autoload": { diff --git a/composer.lock b/composer.lock index 172e564e..47351b0e 100644 --- a/composer.lock +++ b/composer.lock @@ -1,12 +1,11 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" - ], - "hash": "91993ff980d11a416fcf3a7309a4044f", - "packages": [ - + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" ], + "hash": "1a31c30080e1b0b550cdb47b7f764ca6", + "packages": [], "packages-dev": [ { "name": "cilex/cilex", @@ -128,16 +127,16 @@ }, { "name": "doctrine/annotations", - "version": "v1.1.2", + "version": "v1.2.1", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "40db0c96985aab2822edbc4848b3bd2429e02670" + "reference": "6a6bec0670bb6e71a263b08bc1b98ea242928633" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/40db0c96985aab2822edbc4848b3bd2429e02670", - "reference": "40db0c96985aab2822edbc4848b3bd2429e02670", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/6a6bec0670bb6e71a263b08bc1b98ea242928633", + "reference": "6a6bec0670bb6e71a263b08bc1b98ea242928633", "shasum": "" }, "require": { @@ -145,12 +144,13 @@ "php": ">=5.3.2" }, "require-dev": { - "doctrine/cache": "1.*" + "doctrine/cache": "1.*", + "phpunit/phpunit": "4.*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { @@ -163,17 +163,6 @@ "MIT" ], "authors": [ - { - "name": "Jonathan H. Wage", - "email": "jonwage@gmail.com", - "homepage": "http://www.jwage.com/", - "role": "Creator" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com", - "homepage": "http://www.instaclick.com" - }, { "name": "Roman Borschel", "email": "roman@code-factory.org" @@ -183,10 +172,16 @@ "email": "kontakt@beberlei.de" }, { - "name": "Johannes M. Schmitt", - "email": "schmittjoh@gmail.com", - "homepage": "http://jmsyst.com", - "role": "Developer of wrapped JMSSerializerBundle" + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], "description": "Docblock Annotations Parser", @@ -196,7 +191,7 @@ "docblock", "parser" ], - "time": "2013-06-16 21:33:03" + "time": "2014-09-25 16:45:30" }, { "name": "doctrine/lexer", @@ -293,16 +288,16 @@ }, { "name": "erusev/parsedown", - "version": "0.9.4", + "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/erusev/parsedown.git", - "reference": "d29ff18299210b52a75a631a70963e7c8b35b04f" + "reference": "495e7ac73bb5fde6b857b88ff2bb1b5e79a4263a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/erusev/parsedown/zipball/d29ff18299210b52a75a631a70963e7c8b35b04f", - "reference": "d29ff18299210b52a75a631a70963e7c8b35b04f", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/495e7ac73bb5fde6b857b88ff2bb1b5e79a4263a", + "reference": "495e7ac73bb5fde6b857b88ff2bb1b5e79a4263a", "shasum": "" }, "type": "library", @@ -328,20 +323,139 @@ "markdown", "parser" ], - "time": "2014-02-06 12:16:14" + "time": "2014-11-29 02:29:14" }, { - "name": "jms/metadata", - "version": "1.5.0", + "name": "herrera-io/json", + "version": "1.0.3", "source": { "type": "git", - "url": "https://github.com/schmittjoh/metadata.git", - "reference": "88ffa28bc987e4c26229fc84a2e541b6ed4e1459" + "url": "https://github.com/herrera-io/php-json.git", + "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/88ffa28bc987e4c26229fc84a2e541b6ed4e1459", - "reference": "88ffa28bc987e4c26229fc84a2e541b6ed4e1459", + "url": "https://api.github.com/repos/herrera-io/php-json/zipball/60c696c9370a1e5136816ca557c17f82a6fa83f1", + "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1", + "shasum": "" + }, + "require": { + "ext-json": "*", + "justinrainbow/json-schema": ">=1.0,<2.0-dev", + "php": ">=5.3.3", + "seld/jsonlint": ">=1.0,<2.0-dev" + }, + "require-dev": { + "herrera-io/phpunit-test-case": "1.*", + "mikey179/vfsstream": "1.1.0", + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "files": [ + "src/lib/json_version.php" + ], + "psr-0": { + "Herrera\\Json": "src/lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kevin Herrera", + "email": "kevin@herrera.io", + "homepage": "http://kevin.herrera.io/", + "role": "Developer" + } + ], + "description": "A library for simplifying JSON linting and validation.", + "homepage": "http://herrera-io.github.com/php-json", + "keywords": [ + "json", + "lint", + "schema", + "validate" + ], + "time": "2013-10-30 16:51:34" + }, + { + "name": "herrera-io/phar-update", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/herrera-io/php-phar-update.git", + "reference": "00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/herrera-io/php-phar-update/zipball/00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b", + "reference": "00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b", + "shasum": "" + }, + "require": { + "herrera-io/json": "1.*", + "kherge/version": "1.*", + "php": ">=5.3.3" + }, + "require-dev": { + "herrera-io/phpunit-test-case": "1.*", + "mikey179/vfsstream": "1.1.0", + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "files": [ + "src/lib/constants.php" + ], + "psr-0": { + "Herrera\\Phar\\Update": "src/lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kevin Herrera", + "email": "kevin@herrera.io", + "homepage": "http://kevin.herrera.io/", + "role": "Developer" + } + ], + "description": "A library for self-updating Phars.", + "homepage": "http://herrera-io.github.com/php-phar-update", + "keywords": [ + "phar", + "update" + ], + "time": "2013-10-30 17:23:01" + }, + { + "name": "jms/metadata", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/metadata.git", + "reference": "22b72455559a25777cfd28c4ffda81ff7639f353" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/22b72455559a25777cfd28c4ffda81ff7639f353", + "reference": "22b72455559a25777cfd28c4ffda81ff7639f353", "shasum": "" }, "require": { @@ -367,9 +481,9 @@ ], "authors": [ { - "name": "Johannes M. Schmitt", + "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com", - "homepage": "http://jmsyst.com", + "homepage": "https://github.com/schmittjoh", "role": "Developer of wrapped JMSSerializerBundle" } ], @@ -380,7 +494,7 @@ "xml", "yaml" ], - "time": "2013-11-05 23:02:36" + "time": "2014-07-12 07:13:19" }, { "name": "jms/parser-lib", @@ -488,41 +602,97 @@ "time": "2014-03-18 08:39:00" }, { - "name": "knplabs/knp-menu", - "version": "v1.1.2", + "name": "justinrainbow/json-schema", + "version": "1.3.7", "source": { "type": "git", - "url": "https://github.com/KnpLabs/KnpMenu.git", - "reference": "f8e867268f63f561c1adadd6cbb5d8524f921873" + "url": "https://github.com/justinrainbow/json-schema.git", + "reference": "87b54b460febed69726c781ab67462084e97a105" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/KnpLabs/KnpMenu/zipball/f8e867268f63f561c1adadd6cbb5d8524f921873", - "reference": "f8e867268f63f561c1adadd6cbb5d8524f921873", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/87b54b460febed69726c781ab67462084e97a105", + "reference": "87b54b460febed69726c781ab67462084e97a105", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { - "pimple/pimple": "*", - "silex/silex": "1.0.*", - "twig/twig": ">=1.2,<2.0-dev" - }, - "suggest": { - "pimple/pimple": "for the built-in implementations of the menu provider and renderer provider", - "silex/silex": "for the integration with your silex application", - "twig/twig": "for the TwigRenderer and the integration with your templates" + "json-schema/json-schema-test-suite": "1.1.0", + "phpdocumentor/phpdocumentor": "~2", + "phpunit/phpunit": "~3.7" }, + "bin": [ + "bin/validate-json" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.4.x-dev" } }, "autoload": { "psr-0": { - "Knp\\Menu\\": "src/" + "JsonSchema": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" + }, + { + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com" + } + ], + "description": "A library to validate a json schema.", + "homepage": "https://github.com/justinrainbow/json-schema", + "keywords": [ + "json", + "schema" + ], + "time": "2014-08-25 02:48:14" + }, + { + "name": "kherge/version", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/kherge-unmaintained/Version.git", + "reference": "f07cf83f8ce533be8f93d2893d96d674bbeb7e30" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kherge-unmaintained/Version/zipball/f07cf83f8ce533be8f93d2893d96d674bbeb7e30", + "reference": "f07cf83f8ce533be8f93d2893d96d674bbeb7e30", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "KevinGH\\Version": "src/lib/" } }, "notification-url": "https://packagist.org/downloads/", @@ -531,51 +701,44 @@ ], "authors": [ { - "name": "Christophe Coevoet", - "email": "stof@notk.org" - }, - { - "name": "KnpLabs", - "homepage": "http://knplabs.com" - }, - { - "name": "Symfony Community", - "homepage": "https://github.com/KnpLabs/KnpMenu/contributors" + "name": "Kevin Herrera", + "email": "me@kevingh.com", + "homepage": "http://www.kevingh.com/" } ], - "description": "An object oriented menu library", - "homepage": "http://knplabs.com", - "keywords": [ - "menu", - "tree" - ], - "time": "2012-06-10 16:20:40" + "description": "A parsing and comparison library for semantic versioning.", + "homepage": "http://github.com/kherge/Version", + "time": "2012-08-16 17:13:03" }, { "name": "monolog/monolog", - "version": "1.9.1", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "65026b610f8c19e61d7242f600530677b0466aac" + "reference": "ec3961874c43840e96da3a8a1ed20d8c73d7e5aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/65026b610f8c19e61d7242f600530677b0466aac", - "reference": "65026b610f8c19e61d7242f600530677b0466aac", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/ec3961874c43840e96da3a8a1ed20d8c73d7e5aa", + "reference": "ec3961874c43840e96da3a8a1ed20d8c73d7e5aa", "shasum": "" }, "require": { "php": ">=5.3.0", "psr/log": "~1.0" }, + "provide": { + "psr/log-implementation": "1.0.0" + }, "require-dev": { "aws/aws-sdk-php": "~2.4, >2.4.8", "doctrine/couchdb": "~1.0@dev", "graylog2/gelf-php": "~1.0", "phpunit/phpunit": "~3.7.0", "raven/raven": "~0.5", - "ruflin/elastica": "0.90.*" + "ruflin/elastica": "0.90.*", + "videlalvaro/php-amqplib": "~2.4" }, "suggest": { "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", @@ -585,12 +748,13 @@ "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", "raven/raven": "Allow sending log messages to a Sentry server", "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "videlalvaro/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9.x-dev" + "dev-master": "1.11.x-dev" } }, "autoload": { @@ -606,8 +770,7 @@ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", - "homepage": "http://seld.be", - "role": "Developer" + "homepage": "http://seld.be" } ], "description": "Sends your logs to files, sockets, inboxes, databases and various web services", @@ -617,20 +780,20 @@ "logging", "psr-3" ], - "time": "2014-04-24 13:29:03" + "time": "2014-09-30 13:30:58" }, { "name": "mpdf/mpdf", - "version": "v5.7.2", + "version": "v5.7.3", "source": { "type": "git", "url": "https://github.com/finwe/mpdf.git", - "reference": "1627f9e7d2ef0f635a886f611079216ed2929717" + "reference": "ace190986978df40b9c416cf7ba8761945fc1758" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/finwe/mpdf/zipball/1627f9e7d2ef0f635a886f611079216ed2929717", - "reference": "1627f9e7d2ef0f635a886f611079216ed2929717", + "url": "https://api.github.com/repos/finwe/mpdf/zipball/ace190986978df40b9c416cf7ba8761945fc1758", + "reference": "ace190986978df40b9c416cf7ba8761945fc1758", "shasum": "" }, "require": { @@ -660,23 +823,24 @@ "php", "utf-8" ], - "time": "2014-05-16 07:18:10" + "time": "2014-08-24 08:33:20" }, { "name": "nikic/php-parser", - "version": "v0.9.4", + "version": "v0.9.5", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "1e5e280ae88a27effa2ae4aa2bd088494ed8594f" + "reference": "ef70767475434bdb3615b43c327e2cae17ef12eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1e5e280ae88a27effa2ae4aa2bd088494ed8594f", - "reference": "1e5e280ae88a27effa2ae4aa2bd088494ed8594f", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ef70767475434bdb3615b43c327e2cae17ef12eb", + "reference": "ef70767475434bdb3615b43c327e2cae17ef12eb", "shasum": "" }, "require": { + "ext-tokenizer": "*", "php": ">=5.2" }, "type": "library", @@ -704,7 +868,46 @@ "parser", "php" ], - "time": "2013-08-25 17:11:40" + "time": "2014-07-23 18:24:17" + }, + { + "name": "pdepend/pdepend", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/pdepend/pdepend.git", + "reference": "1b0acf162da4f30237987e61e177a57f78e3d87e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pdepend/pdepend/zipball/1b0acf162da4f30237987e61e177a57f78e3d87e", + "reference": "1b0acf162da4f30237987e61e177a57f78e3d87e", + "shasum": "" + }, + "require": { + "symfony/config": ">=2.4", + "symfony/dependency-injection": ">=2.4", + "symfony/filesystem": ">=2.4" + }, + "require-dev": { + "phpunit/phpunit": "4.*@stable", + "squizlabs/php_codesniffer": "@stable" + }, + "bin": [ + "src/bin/pdepend" + ], + "type": "library", + "autoload": { + "psr-0": { + "PDepend\\": "src/main/php/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Official version of pdepend to be handled with Composer", + "time": "2014-12-04 12:38:39" }, { "name": "phenx/php-font-lib", @@ -835,16 +1038,16 @@ }, { "name": "phpdocumentor/graphviz", - "version": "1.0.2", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/phpDocumentor/GraphViz.git", - "reference": "13595130b9bc185109f40f1b70f0b231f490f5fc" + "reference": "aa243118c8a055fc853c02802e8503c5435862f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/GraphViz/zipball/13595130b9bc185109f40f1b70f0b231f490f5fc", - "reference": "13595130b9bc185109f40f1b70f0b231f490f5fc", + "url": "https://api.github.com/repos/phpDocumentor/GraphViz/zipball/aa243118c8a055fc853c02802e8503c5435862f7", + "reference": "aa243118c8a055fc853c02802e8503c5435862f7", "shasum": "" }, "require": { @@ -872,28 +1075,28 @@ "email": "mike.vanriel@naenius.com" } ], - "time": "2014-02-26 17:45:01" + "time": "2014-07-19 06:52:59" }, { "name": "phpdocumentor/phpdocumentor", - "version": "v2.5.0", + "version": "v2.8.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/phpDocumentor2.git", - "reference": "bf9fa40f6d00412410025b2e16eb16c315eb0216" + "reference": "5920dd42a5a92e4486f342ba8ded979db149ceb2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/phpDocumentor2/zipball/bf9fa40f6d00412410025b2e16eb16c315eb0216", - "reference": "bf9fa40f6d00412410025b2e16eb16c315eb0216", + "url": "https://api.github.com/repos/phpDocumentor/phpDocumentor2/zipball/5920dd42a5a92e4486f342ba8ded979db149ceb2", + "reference": "5920dd42a5a92e4486f342ba8ded979db149ceb2", "shasum": "" }, "require": { "cilex/cilex": "~1.0", "dompdf/dompdf": "~0.6", - "erusev/parsedown": "~0.7", + "erusev/parsedown": "~1.0", + "herrera-io/phar-update": "1.0.3", "jms/serializer": "~0.12", - "knplabs/knp-menu": "~1.1", "monolog/monolog": "~1.6", "php": ">=5.3.3", "phpdocumentor/fileset": "~1.0", @@ -916,20 +1119,20 @@ "symfony/stopwatch": "~2.3", "symfony/validator": "~2.2", "twig/twig": "~1.3", - "zendframework/zend-cache": "2.1.*", - "zendframework/zend-config": "2.1.*", - "zendframework/zend-filter": "2.1.*", - "zendframework/zend-i18n": "2.1.*", - "zendframework/zend-serializer": "2.1.*", - "zendframework/zend-servicemanager": "2.1.*", - "zendframework/zend-stdlib": "2.1.*", + "zendframework/zend-cache": "~2.1", + "zendframework/zend-config": "~2.1", + "zendframework/zend-filter": "~2.1", + "zendframework/zend-i18n": "~2.1", + "zendframework/zend-serializer": "~2.1", + "zendframework/zend-servicemanager": "~2.1", + "zendframework/zend-stdlib": "~2.1", "zetacomponents/document": ">=1.3.1" }, "require-dev": { "behat/behat": "~2.4", "mikey179/vfsstream": "~1.2", - "mockery/mockery": ">=0.8.0", - "phpunit/phpunit": "~3.7", + "mockery/mockery": "~0.9@dev", + "phpunit/phpunit": "~4.0", "squizlabs/php_codesniffer": "~1.4", "symfony/expression-language": "~2.4" }, @@ -944,7 +1147,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-develop": "2.5-dev" + "dev-develop": "2.9-dev" } }, "autoload": { @@ -952,6 +1155,9 @@ "phpDocumentor": [ "src/", "tests/unit/" + ], + "Cilex\\Provider": [ + "src/" ] } }, @@ -968,34 +1174,39 @@ "documentation", "phpdoc" ], - "time": "2014-05-17 12:25:35" + "time": "2014-11-11 14:08:43" }, { "name": "phpdocumentor/reflection", - "version": "1.0.5", + "version": "1.0.7", "source": { "type": "git", "url": "https://github.com/phpDocumentor/Reflection.git", - "reference": "df82db631acd60739c8796b3c6d5e4da970808f3" + "reference": "fc40c3f604ac2287eb5c314174d5109b2c699372" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/df82db631acd60739c8796b3c6d5e4da970808f3", - "reference": "df82db631acd60739c8796b3c6d5e4da970808f3", + "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/fc40c3f604ac2287eb5c314174d5109b2c699372", + "reference": "fc40c3f604ac2287eb5c314174d5109b2c699372", "shasum": "" }, "require": { - "nikic/php-parser": "0.9.4", + "nikic/php-parser": "~0.9.4", "php": ">=5.3.3", - "phpdocumentor/reflection-docblock": "2.*", + "phpdocumentor/reflection-docblock": "~2.0", "psr/log": "~1.0" }, "require-dev": { "behat/behat": "~2.4", - "mockery/mockery": ">=0.7.0", - "phpunit/phpunit": "~3.7" + "mockery/mockery": "~0.8", + "phpunit/phpunit": "~4.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-0": { "phpDocumentor": [ @@ -1017,20 +1228,20 @@ "reflection", "static analysis" ], - "time": "2014-03-28 11:20:22" + "time": "2014-11-14 11:43:04" }, { "name": "phpdocumentor/reflection-docblock", - "version": "2.0.2", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "0bca477a34baea39add016af90046f002a175619" + "reference": "38743b677965c48a637097b2746a281264ae2347" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/0bca477a34baea39add016af90046f002a175619", - "reference": "0bca477a34baea39add016af90046f002a175619", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/38743b677965c48a637097b2746a281264ae2347", + "reference": "38743b677965c48a637097b2746a281264ae2347", "shasum": "" }, "require": { @@ -1066,24 +1277,23 @@ "email": "mike.vanriel@naenius.com" } ], - "time": "2014-03-28 09:21:30" + "time": "2014-08-09 10:27:07" }, { "name": "phpdocumentor/template-abstract", - "version": "1.2.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/template.abstract.git", - "reference": "43fa2db351d7a150803397721e778f9dd8a20b47" + "reference": "df1d11cf11cf5da433789e2be07f4d2d6e51aaca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/template.abstract/zipball/43fa2db351d7a150803397721e778f9dd8a20b47", - "reference": "43fa2db351d7a150803397721e778f9dd8a20b47", + "url": "https://api.github.com/repos/phpDocumentor/template.abstract/zipball/df1d11cf11cf5da433789e2be07f4d2d6e51aaca", + "reference": "df1d11cf11cf5da433789e2be07f4d2d6e51aaca", "shasum": "" }, "require": { - "ext-xsl": "*", "phpdocumentor/unified-asset-installer": "~1.1" }, "type": "phpdocumentor-template", @@ -1098,24 +1308,23 @@ "phpdoc", "template" ], - "time": "2013-08-02 06:11:13" + "time": "2014-06-04 19:32:56" }, { "name": "phpdocumentor/template-checkstyle", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/template.checkstyle.git", - "reference": "22a45684e737c8c3ec3f1a12edb7743b7a82ac8b" + "reference": "cfa86d19327b0d762332787ff2dda0d55226a2e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/template.checkstyle/zipball/22a45684e737c8c3ec3f1a12edb7743b7a82ac8b", - "reference": "22a45684e737c8c3ec3f1a12edb7743b7a82ac8b", + "url": "https://api.github.com/repos/phpDocumentor/template.checkstyle/zipball/cfa86d19327b0d762332787ff2dda0d55226a2e2", + "reference": "cfa86d19327b0d762332787ff2dda0d55226a2e2", "shasum": "" }, "require": { - "ext-xsl": "*", "phpdocumentor/unified-asset-installer": "~1.1" }, "type": "phpdocumentor-template", @@ -1130,20 +1339,20 @@ "phpdoc", "template" ], - "time": "2013-08-01 19:43:19" + "time": "2014-08-17 19:32:38" }, { "name": "phpdocumentor/template-clean", - "version": "1.0.4", + "version": "1.0.6", "source": { "type": "git", "url": "https://github.com/phpDocumentor/template.clean.git", - "reference": "78f2048c5ecd62f0b79dbac093687d78a66d1806" + "reference": "6fc0f7f6c55c1f94ac5b1c6fccde7aac77755e45" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/template.clean/zipball/78f2048c5ecd62f0b79dbac093687d78a66d1806", - "reference": "78f2048c5ecd62f0b79dbac093687d78a66d1806", + "url": "https://api.github.com/repos/phpDocumentor/template.clean/zipball/6fc0f7f6c55c1f94ac5b1c6fccde7aac77755e45", + "reference": "6fc0f7f6c55c1f94ac5b1c6fccde7aac77755e45", "shasum": "" }, "require": { @@ -1162,24 +1371,23 @@ "responsive", "template" ], - "time": "2014-03-29 08:22:15" + "time": "2014-08-15 21:45:34" }, { "name": "phpdocumentor/template-new-black", - "version": "1.3.1", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/template.new_black.git", - "reference": "be38beba2b2674be292f32f88efe8a60c658a139" + "reference": "d98f84633b94b279582735aecd91015c1e191d98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/template.new_black/zipball/be38beba2b2674be292f32f88efe8a60c658a139", - "reference": "be38beba2b2674be292f32f88efe8a60c658a139", + "url": "https://api.github.com/repos/phpDocumentor/template.new_black/zipball/d98f84633b94b279582735aecd91015c1e191d98", + "reference": "d98f84633b94b279582735aecd91015c1e191d98", "shasum": "" }, "require": { - "ext-xsl": "*", "phpdocumentor/template-abstract": "1.*", "phpdocumentor/unified-asset-installer": "~1.1" }, @@ -1195,24 +1403,23 @@ "phpdoc", "template" ], - "time": "2013-08-02 06:16:30" + "time": "2014-06-27 17:00:31" }, { "name": "phpdocumentor/template-old-ocean", - "version": "1.3.1", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/template.old_ocean.git", - "reference": "3a0e2bcced4045a694d53b4607aad04e99d78489" + "reference": "2fdb786038351c0ec88633d4e2aa103e4bbb8655" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/template.old_ocean/zipball/3a0e2bcced4045a694d53b4607aad04e99d78489", - "reference": "3a0e2bcced4045a694d53b4607aad04e99d78489", + "url": "https://api.github.com/repos/phpDocumentor/template.old_ocean/zipball/2fdb786038351c0ec88633d4e2aa103e4bbb8655", + "reference": "2fdb786038351c0ec88633d4e2aa103e4bbb8655", "shasum": "" }, "require": { - "ext-xsl": "*", "phpdocumentor/unified-asset-installer": "~1.1" }, "type": "phpdocumentor-template", @@ -1227,24 +1434,23 @@ "phpdoc", "template" ], - "time": "2013-08-02 06:21:07" + "time": "2014-06-27 16:59:35" }, { "name": "phpdocumentor/template-responsive", - "version": "1.3.3", + "version": "1.3.5", "source": { "type": "git", "url": "https://github.com/phpDocumentor/template.responsive.git", - "reference": "26f895a2ed3148e1686ae4d802f65a3ef04c04e1" + "reference": "949e742f350f70fc8ec7c945b3cf0070a4e1825e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/template.responsive/zipball/26f895a2ed3148e1686ae4d802f65a3ef04c04e1", - "reference": "26f895a2ed3148e1686ae4d802f65a3ef04c04e1", + "url": "https://api.github.com/repos/phpDocumentor/template.responsive/zipball/949e742f350f70fc8ec7c945b3cf0070a4e1825e", + "reference": "949e742f350f70fc8ec7c945b3cf0070a4e1825e", "shasum": "" }, "require": { - "ext-xsl": "*", "phpdocumentor/unified-asset-installer": "~1.1" }, "type": "phpdocumentor-template", @@ -1259,20 +1465,20 @@ "phpdoc", "template" ], - "time": "2014-03-29 08:55:54" + "time": "2014-08-05 20:47:53" }, { "name": "phpdocumentor/template-responsive-twig", - "version": "1.2.3", + "version": "1.2.5", "source": { "type": "git", "url": "https://github.com/phpDocumentor/template.responsive-twig.git", - "reference": "cd6d82be6a4626d865fd01d40aad170cea08db0a" + "reference": "493e204be607583efd2d75f1728cd5210e23cf96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/template.responsive-twig/zipball/cd6d82be6a4626d865fd01d40aad170cea08db0a", - "reference": "cd6d82be6a4626d865fd01d40aad170cea08db0a", + "url": "https://api.github.com/repos/phpDocumentor/template.responsive-twig/zipball/493e204be607583efd2d75f1728cd5210e23cf96", + "reference": "493e204be607583efd2d75f1728cd5210e23cf96", "shasum": "" }, "require": { @@ -1290,7 +1496,7 @@ "phpdoc", "template" ], - "time": "2014-03-30 21:02:00" + "time": "2014-07-30 20:00:37" }, { "name": "phpdocumentor/template-xml", @@ -1406,6 +1612,93 @@ ], "time": "2013-09-09 06:13:02" }, + { + "name": "phploc/phploc", + "version": "2.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phploc.git", + "reference": "322ad07c112d5c6832abed4269d648cacff5959b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phploc/zipball/322ad07c112d5c6832abed4269d648cacff5959b", + "reference": "322ad07c112d5c6832abed4269d648cacff5959b", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/finder-facade": "~1.1", + "sebastian/git": "~1.0", + "sebastian/version": "~1.0", + "symfony/console": "~2.2" + }, + "bin": [ + "phploc" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "A tool for quickly measuring the size of a PHP project.", + "homepage": "https://github.com/sebastianbergmann/phploc", + "time": "2014-06-25 08:11:02" + }, + { + "name": "phpmd/phpmd", + "version": "2.1.3", + "source": { + "type": "git", + "url": "https://github.com/phpmd/phpmd.git", + "reference": "1a485d9db869137af5e9678bd844568c92998b25" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpmd/phpmd/zipball/1a485d9db869137af5e9678bd844568c92998b25", + "reference": "1a485d9db869137af5e9678bd844568c92998b25", + "shasum": "" + }, + "require": { + "pdepend/pdepend": "2.0.*", + "php": ">=5.3.0", + "symfony/config": "2.5.*", + "symfony/dependency-injection": "2.5.*", + "symfony/filesystem": "2.5.*" + }, + "bin": [ + "src/bin/phpmd" + ], + "type": "library", + "autoload": { + "psr-0": { + "PHPMD\\": "src/main/php" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Official version of PHPMD handled with Composer.", + "time": "2014-09-25 15:56:22" + }, { "name": "phpoption/phpoption", "version": "1.4.0", @@ -1457,23 +1750,23 @@ }, { "name": "phpunit/php-code-coverage", - "version": "1.2.17", + "version": "1.2.18", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "6ef2bf3a1c47eca07ea95f0d8a902a6340390b34" + "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6ef2bf3a1c47eca07ea95f0d8a902a6340390b34", - "reference": "6ef2bf3a1c47eca07ea95f0d8a902a6340390b34", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", + "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", "shasum": "" }, "require": { "php": ">=5.3.3", "phpunit/php-file-iterator": ">=1.3.0@stable", "phpunit/php-text-template": ">=1.2.0@stable", - "phpunit/php-token-stream": ">=1.1.3@stable" + "phpunit/php-token-stream": ">=1.1.3,<1.3.0" }, "require-dev": { "phpunit/phpunit": "3.7.*@dev" @@ -1514,7 +1807,7 @@ "testing", "xunit" ], - "time": "2014-03-28 10:53:45" + "time": "2014-09-02 10:13:14" }, { "name": "phpunit/php-file-iterator", @@ -1701,16 +1994,16 @@ }, { "name": "phpunit/phpunit", - "version": "3.7.37", + "version": "3.7.38", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "ae6cefd7cc84586a5ef27e04bae11ee940ec63dc" + "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ae6cefd7cc84586a5ef27e04bae11ee940ec63dc", - "reference": "ae6cefd7cc84586a5ef27e04bae11ee940ec63dc", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/38709dc22d519a3d1be46849868aa2ddf822bcf6", + "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6", "shasum": "" }, "require": { @@ -1770,7 +2063,7 @@ "testing", "xunit" ], - "time": "2014-04-30 12:24:19" + "time": "2014-10-17 09:04:17" }, { "name": "phpunit/phpunit-mock-objects", @@ -1908,17 +2201,234 @@ "time": "2012-12-21 11:40:51" }, { - "name": "squizlabs/php_codesniffer", - "version": "1.5.3", + "name": "sebastian/finder-facade", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "396178ada8499ec492363587f037125bf7b07fcc" + "url": "https://github.com/sebastianbergmann/finder-facade.git", + "reference": "1e396fda3449fce9df032749fa4fa2619e0347e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/396178ada8499ec492363587f037125bf7b07fcc", - "reference": "396178ada8499ec492363587f037125bf7b07fcc", + "url": "https://api.github.com/repos/sebastianbergmann/finder-facade/zipball/1e396fda3449fce9df032749fa4fa2619e0347e0", + "reference": "1e396fda3449fce9df032749fa4fa2619e0347e0", + "shasum": "" + }, + "require": { + "symfony/finder": ">=2.2.0", + "theseer/fdomdocument": ">=1.3.1" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FinderFacade is a convenience wrapper for Symfony's Finder component.", + "homepage": "https://github.com/sebastianbergmann/finder-facade", + "time": "2013-05-28 06:10:03" + }, + { + "name": "sebastian/git", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/git.git", + "reference": "a99fbc102e982c1404041ef3e4d431562b29bcba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/git/zipball/a99fbc102e982c1404041ef3e4d431562b29bcba", + "reference": "a99fbc102e982c1404041ef3e4d431562b29bcba", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple wrapper for Git", + "homepage": "http://www.github.com/sebastianbergmann/git", + "keywords": [ + "git" + ], + "time": "2013-08-04 09:35:29" + }, + { + "name": "sebastian/phpcpd", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpcpd.git", + "reference": "a9462153f2dd90466a010179901d31fbff598365" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/a9462153f2dd90466a010179901d31fbff598365", + "reference": "a9462153f2dd90466a010179901d31fbff598365", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-timer": ">=1.0.4", + "sebastian/finder-facade": ">=1.1.0", + "sebastian/version": ">=1.0.3", + "symfony/console": ">=2.2.0", + "theseer/fdomdocument": "~1.4" + }, + "bin": [ + "phpcpd" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Copy/Paste Detector (CPD) for PHP code.", + "homepage": "https://github.com/sebastianbergmann/phpcpd", + "time": "2014-03-31 09:25:30" + }, + { + "name": "sebastian/version", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43", + "reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2014-03-07 15:35:33" + }, + { + "name": "seld/jsonlint", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/jsonlint.git", + "reference": "a7bc2ec9520ad15382292591b617c43bdb1fec35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/a7bc2ec9520ad15382292591b617c43bdb1fec35", + "reference": "a7bc2ec9520ad15382292591b617c43bdb1fec35", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "bin": [ + "bin/jsonlint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Seld\\JsonLint\\": "src/Seld/JsonLint/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "JSON Linter", + "keywords": [ + "json", + "linter", + "parser", + "validator" + ], + "time": "2014-09-05 15:36:20" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "1.5.6", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/6f3e42d311b882b25b4d409d23a289f4d3b803d5", + "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5", "shasum": "" }, "require": { @@ -1980,21 +2490,21 @@ "phpcs", "standards" ], - "time": "2014-05-01 03:07:07" + "time": "2014-12-04 22:32:15" }, { "name": "symfony/config", - "version": "v2.4.4", + "version": "v2.5.8", "target-dir": "Symfony/Component/Config", "source": { "type": "git", "url": "https://github.com/symfony/Config.git", - "reference": "2effc67af6f21a0d267210b72d0b0b691d113528" + "reference": "92f0b4c625b8c42d394b53f879d2795d84bb8c4f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Config/zipball/2effc67af6f21a0d267210b72d0b0b691d113528", - "reference": "2effc67af6f21a0d267210b72d0b0b691d113528", + "url": "https://api.github.com/repos/symfony/Config/zipball/92f0b4c625b8c42d394b53f879d2795d84bb8c4f", + "reference": "92f0b4c625b8c42d394b53f879d2795d84bb8c4f", "shasum": "" }, "require": { @@ -2004,7 +2514,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -2017,49 +2527,51 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony Config Component", "homepage": "http://symfony.com", - "time": "2014-04-22 08:11:06" + "time": "2014-12-02 20:15:53" }, { "name": "symfony/console", - "version": "v2.4.4", + "version": "v2.6.1", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "2e452005b1e1d003d23702d227e23614679eb5ca" + "reference": "ef825fd9f809d275926547c9e57cbf14968793e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/2e452005b1e1d003d23702d227e23614679eb5ca", - "reference": "2e452005b1e1d003d23702d227e23614679eb5ca", + "url": "https://api.github.com/repos/symfony/Console/zipball/ef825fd9f809d275926547c9e57cbf14968793e8", + "reference": "ef825fd9f809d275926547c9e57cbf14968793e8", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "symfony/event-dispatcher": "~2.1" + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.1", + "symfony/process": "~2.1" }, "suggest": { - "symfony/event-dispatcher": "" + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/process": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.6-dev" } }, "autoload": { @@ -2072,41 +2584,100 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony Console Component", "homepage": "http://symfony.com", - "time": "2014-04-27 13:34:57" + "time": "2014-12-02 20:19:20" }, { - "name": "symfony/event-dispatcher", - "version": "v2.4.4", - "target-dir": "Symfony/Component/EventDispatcher", + "name": "symfony/dependency-injection", + "version": "v2.5.8", + "target-dir": "Symfony/Component/DependencyInjection", "source": { "type": "git", - "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "e539602e5455aa086c0e81e604745af7789e4d8a" + "url": "https://github.com/symfony/DependencyInjection.git", + "reference": "b4afda3c24867a17f93237ac1fcce917cc9d7695" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/e539602e5455aa086c0e81e604745af7789e4d8a", - "reference": "e539602e5455aa086c0e81e604745af7789e4d8a", + "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/b4afda3c24867a17f93237ac1fcce917cc9d7695", + "reference": "b4afda3c24867a17f93237ac1fcce917cc9d7695", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "symfony/dependency-injection": "~2.0" + "symfony/config": "~2.2", + "symfony/expression-language": "~2.4", + "symfony/yaml": "~2.0" + }, + "suggest": { + "symfony/config": "", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\DependencyInjection\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony DependencyInjection Component", + "homepage": "http://symfony.com", + "time": "2014-12-02 21:48:32" + }, + { + "name": "symfony/event-dispatcher", + "version": "v2.6.1", + "target-dir": "Symfony/Component/EventDispatcher", + "source": { + "type": "git", + "url": "https://github.com/symfony/EventDispatcher.git", + "reference": "720fe9bca893df7ad1b4546649473b5afddf0216" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/720fe9bca893df7ad1b4546649473b5afddf0216", + "reference": "720fe9bca893df7ad1b4546649473b5afddf0216", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.0", + "symfony/dependency-injection": "~2.6", + "symfony/expression-language": "~2.6", + "symfony/stopwatch": "~2.2" }, "suggest": { "symfony/dependency-injection": "", @@ -2115,7 +2686,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.6-dev" } }, "autoload": { @@ -2128,34 +2699,32 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony EventDispatcher Component", "homepage": "http://symfony.com", - "time": "2014-04-16 10:34:31" + "time": "2014-12-02 20:19:20" }, { "name": "symfony/filesystem", - "version": "v2.4.4", + "version": "v2.5.8", "target-dir": "Symfony/Component/Filesystem", "source": { "type": "git", "url": "https://github.com/symfony/Filesystem.git", - "reference": "a3af8294bcce4a7c1b2892363b0c9d8109affad4" + "reference": "e5fc05a3a1dbb4ea0bed80fe7bd21ba3cab88c42" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/a3af8294bcce4a7c1b2892363b0c9d8109affad4", - "reference": "a3af8294bcce4a7c1b2892363b0c9d8109affad4", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/e5fc05a3a1dbb4ea0bed80fe7bd21ba3cab88c42", + "reference": "e5fc05a3a1dbb4ea0bed80fe7bd21ba3cab88c42", "shasum": "" }, "require": { @@ -2164,7 +2733,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -2177,34 +2746,32 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony Filesystem Component", "homepage": "http://symfony.com", - "time": "2014-04-16 10:34:31" + "time": "2014-12-02 20:15:53" }, { "name": "symfony/finder", - "version": "v2.4.4", + "version": "v2.6.1", "target-dir": "Symfony/Component/Finder", "source": { "type": "git", "url": "https://github.com/symfony/Finder.git", - "reference": "25e1e7d5e7376f8a92ae3b1d714d956edf33a730" + "reference": "0d3ef7f6ec55a7af5eca7914eaa0dacc04ccc721" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/25e1e7d5e7376f8a92ae3b1d714d956edf33a730", - "reference": "25e1e7d5e7376f8a92ae3b1d714d956edf33a730", + "url": "https://api.github.com/repos/symfony/Finder/zipball/0d3ef7f6ec55a7af5eca7914eaa0dacc04ccc721", + "reference": "0d3ef7f6ec55a7af5eca7914eaa0dacc04ccc721", "shasum": "" }, "require": { @@ -2213,7 +2780,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.6-dev" } }, "autoload": { @@ -2226,34 +2793,32 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony Finder Component", "homepage": "http://symfony.com", - "time": "2014-04-27 13:34:57" + "time": "2014-12-02 20:19:20" }, { "name": "symfony/process", - "version": "v2.4.4", + "version": "v2.6.1", "target-dir": "Symfony/Component/Process", "source": { "type": "git", "url": "https://github.com/symfony/Process.git", - "reference": "8721f1476d5d38a43c7d6ccb6435b351cf8f3bb7" + "reference": "bf0c9bd625f13b0b0bbe39919225cf145dfb935a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/8721f1476d5d38a43c7d6ccb6435b351cf8f3bb7", - "reference": "8721f1476d5d38a43c7d6ccb6435b351cf8f3bb7", + "url": "https://api.github.com/repos/symfony/Process/zipball/bf0c9bd625f13b0b0bbe39919225cf145dfb935a", + "reference": "bf0c9bd625f13b0b0bbe39919225cf145dfb935a", "shasum": "" }, "require": { @@ -2262,7 +2827,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.6-dev" } }, "autoload": { @@ -2275,94 +2840,32 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony Process Component", "homepage": "http://symfony.com", - "time": "2014-04-27 13:34:57" - }, - { - "name": "symfony/property-access", - "version": "v2.4.4", - "target-dir": "Symfony/Component/PropertyAccess", - "source": { - "type": "git", - "url": "https://github.com/symfony/PropertyAccess.git", - "reference": "0456222bc00c40c1365065b603f7c397fb9a7134" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/PropertyAccess/zipball/0456222bc00c40c1365065b603f7c397fb9a7134", - "reference": "0456222bc00c40c1365065b603f7c397fb9a7134", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.4-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\PropertyAccess\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - } - ], - "description": "Symfony PropertyAccess Component", - "homepage": "http://symfony.com", - "keywords": [ - "access", - "array", - "extraction", - "index", - "injection", - "object", - "property", - "property path", - "reflection" - ], - "time": "2014-04-18 20:37:09" + "time": "2014-12-02 20:19:20" }, { "name": "symfony/stopwatch", - "version": "v2.4.4", + "version": "v2.6.1", "target-dir": "Symfony/Component/Stopwatch", "source": { "type": "git", "url": "https://github.com/symfony/Stopwatch.git", - "reference": "343bcc0360f2c22f371884b8f6a9fee8d1aa431a" + "reference": "261abd360cfb6ac65ea93ffd82073e2011d034fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/343bcc0360f2c22f371884b8f6a9fee8d1aa431a", - "reference": "343bcc0360f2c22f371884b8f6a9fee8d1aa431a", + "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/261abd360cfb6ac65ea93ffd82073e2011d034fc", + "reference": "261abd360cfb6ac65ea93ffd82073e2011d034fc", "shasum": "" }, "require": { @@ -2371,7 +2874,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.6-dev" } }, "autoload": { @@ -2384,51 +2887,52 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony Stopwatch Component", "homepage": "http://symfony.com", - "time": "2014-04-18 20:37:09" + "time": "2014-12-02 20:19:20" }, { "name": "symfony/translation", - "version": "v2.4.4", + "version": "v2.6.1", "target-dir": "Symfony/Component/Translation", "source": { "type": "git", "url": "https://github.com/symfony/Translation.git", - "reference": "d2c73ffa4a5ba1fa0c5d93f43b68331dffe898c5" + "reference": "5b8bf84a43317021849813f556f26dc35968156b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Translation/zipball/d2c73ffa4a5ba1fa0c5d93f43b68331dffe898c5", - "reference": "d2c73ffa4a5ba1fa0c5d93f43b68331dffe898c5", + "url": "https://api.github.com/repos/symfony/Translation/zipball/5b8bf84a43317021849813f556f26dc35968156b", + "reference": "5b8bf84a43317021849813f556f26dc35968156b", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { + "psr/log": "~1.0", "symfony/config": "~2.0", + "symfony/intl": "~2.3", "symfony/yaml": "~2.2" }, "suggest": { + "psr/log": "To use logging capability in translator", "symfony/config": "", "symfony/yaml": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.6-dev" } }, "autoload": { @@ -2441,61 +2945,64 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony Translation Component", "homepage": "http://symfony.com", - "time": "2014-04-18 21:02:05" + "time": "2014-12-02 20:19:20" }, { "name": "symfony/validator", - "version": "v2.4.4", + "version": "v2.6.1", "target-dir": "Symfony/Component/Validator", "source": { "type": "git", "url": "https://github.com/symfony/Validator.git", - "reference": "5bbcdcc520bc7fb3826abb44020880f14c9c03a7" + "reference": "4583e0321f1bcdad14d93e265eaca1001035b5c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Validator/zipball/5bbcdcc520bc7fb3826abb44020880f14c9c03a7", - "reference": "5bbcdcc520bc7fb3826abb44020880f14c9c03a7", + "url": "https://api.github.com/repos/symfony/Validator/zipball/4583e0321f1bcdad14d93e265eaca1001035b5c4", + "reference": "4583e0321f1bcdad14d93e265eaca1001035b5c4", "shasum": "" }, "require": { "php": ">=5.3.3", - "symfony/property-access": "~2.2", "symfony/translation": "~2.0" }, "require-dev": { "doctrine/annotations": "~1.0", "doctrine/cache": "~1.0", + "egulias/email-validator": "~1.0", "symfony/config": "~2.2", + "symfony/expression-language": "~2.4", "symfony/http-foundation": "~2.1", "symfony/intl": "~2.3", + "symfony/property-access": "~2.2", "symfony/yaml": "~2.0" }, "suggest": { "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", - "doctrine/cache": "For using the default cached annotation reader", + "doctrine/cache": "For using the default cached annotation reader and metadata cache.", + "egulias/email-validator": "Strict (RFC compliant) email validation", "symfony/config": "", + "symfony/expression-language": "For using the 2.4 Expression validator", "symfony/http-foundation": "", "symfony/intl": "", + "symfony/property-access": "For using the 2.4 Validator API", "symfony/yaml": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.6-dev" } }, "autoload": { @@ -2508,34 +3015,32 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony Validator Component", "homepage": "http://symfony.com", - "time": "2014-04-27 13:34:57" + "time": "2014-12-02 20:19:20" }, { "name": "symfony/yaml", - "version": "v2.4.4", + "version": "v2.6.1", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "65539ecde838f9c0d18b006b2101e3deb4b5c9ff" + "reference": "3346fc090a3eb6b53d408db2903b241af51dcb20" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/65539ecde838f9c0d18b006b2101e3deb4b5c9ff", - "reference": "65539ecde838f9c0d18b006b2101e3deb4b5c9ff", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/3346fc090a3eb6b53d408db2903b241af51dcb20", + "reference": "3346fc090a3eb6b53d408db2903b241af51dcb20", "shasum": "" }, "require": { @@ -2544,7 +3049,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.6-dev" } }, "autoload": { @@ -2557,28 +3062,32 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony Yaml Component", "homepage": "http://symfony.com", - "time": "2014-04-18 20:37:09" + "time": "2014-12-02 20:19:20" }, { "name": "tecnick.com/tcpdf", - "version": "6.0.078", + "version": "6.2.0", "source": { "type": "git", - "url": "git://git.code.sf.net/p/tcpdf/code", - "reference": "e1cbda79b99f3cdc8fdf26b39eb4870d2cd9fbac" + "url": "https://github.com/tecnickcom/TCPDF.git", + "reference": "40662daa766bd3a6b5eafa44dfde680ee6661716" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/40662daa766bd3a6b5eafa44dfde680ee6661716", + "reference": "40662daa766bd3a6b5eafa44dfde680ee6661716", + "shasum": "" }, "require": { "php": ">=5.3.0" @@ -2616,7 +3125,7 @@ "homepage": "http://nicolaasuni.tecnick.com" } ], - "description": "TCPDF is a PHP class for generating PDF documents.", + "description": "TCPDF is a PHP class for generating PDF documents and barcodes.", "homepage": "http://www.tcpdf.org/", "keywords": [ "PDFD32000-2008", @@ -2627,20 +3136,60 @@ "pdf417", "qrcode" ], - "time": "2014-05-12 19:50:13" + "time": "2014-12-10 18:53:49" }, { - "name": "twig/twig", - "version": "v1.15.1", + "name": "theseer/fdomdocument", + "version": "1.6.0", "source": { "type": "git", - "url": "https://github.com/fabpot/Twig.git", - "reference": "1fb5784662f438d7d96a541e305e28b812e2eeed" + "url": "https://github.com/theseer/fDOMDocument.git", + "reference": "d08cf070350f884c63fc9078d27893c2ab6c7cef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fabpot/Twig/zipball/1fb5784662f438d7d96a541e305e28b812e2eeed", - "reference": "1fb5784662f438d7d96a541e305e28b812e2eeed", + "url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/d08cf070350f884c63fc9078d27893c2ab6c7cef", + "reference": "d08cf070350f884c63fc9078d27893c2ab6c7cef", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "lib-libxml": "*", + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "lead" + } + ], + "description": "The classes contained within this repository extend the standard DOM to use exceptions at all occasions of errors instead of PHP warnings or notices. They also add various custom methods and shortcuts for convenience and to simplify the usage of DOM.", + "homepage": "https://github.com/theseer/fDOMDocument", + "time": "2014-09-13 10:57:19" + }, + { + "name": "twig/twig", + "version": "v1.16.2", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "42f758d9fe2146d1f0470604fc05ee43580873fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/42f758d9fe2146d1f0470604fc05ee43580873fc", + "reference": "42f758d9fe2146d1f0470604fc05ee43580873fc", "shasum": "" }, "require": { @@ -2649,7 +3198,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.16-dev" } }, "autoload": { @@ -2669,7 +3218,7 @@ "role": "Lead Developer" }, { - "name": "Armin Ronacher2", + "name": "Armin Ronacher", "email": "armin.ronacher@active-4.com", "role": "Project Founder" }, @@ -2684,31 +3233,32 @@ "keywords": [ "templating" ], - "time": "2014-02-13 10:19:29" + "time": "2014-10-17 12:53:44" }, { "name": "zendframework/zend-cache", - "version": "2.1.6", + "version": "2.3.3", "target-dir": "Zend/Cache", "source": { "type": "git", "url": "https://github.com/zendframework/Component_ZendCache.git", - "reference": "560355160f06cdc3ef549a7eef843af3bead7e39" + "reference": "1966038a1568ebeaeeeaa78ce27bc7b340e30747" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/Component_ZendCache/zipball/560355160f06cdc3ef549a7eef843af3bead7e39", - "reference": "560355160f06cdc3ef549a7eef843af3bead7e39", + "url": "https://api.github.com/repos/zendframework/Component_ZendCache/zipball/1966038a1568ebeaeeeaa78ce27bc7b340e30747", + "reference": "1966038a1568ebeaeeeaa78ce27bc7b340e30747", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": ">=5.3.23", "zendframework/zend-eventmanager": "self.version", "zendframework/zend-servicemanager": "self.version", "zendframework/zend-stdlib": "self.version" }, "require-dev": { - "zendframework/zend-serializer": "self.version" + "zendframework/zend-serializer": "self.version", + "zendframework/zend-session": "self.version" }, "suggest": { "ext-apc": "APC >= 3.1.6 to use the APC storage adapter", @@ -2721,8 +3271,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev", - "dev-develop": "2.3-dev" + "dev-master": "2.3-dev", + "dev-develop": "2.4-dev" } }, "autoload": { @@ -2735,40 +3285,49 @@ "BSD-3-Clause" ], "description": "provides a generic way to cache any data", + "homepage": "https://github.com/zendframework/zf2", "keywords": [ "cache", "zf2" ], - "time": "2014-03-03 23:00:17" + "time": "2014-09-16 22:58:11" }, { "name": "zendframework/zend-config", - "version": "2.1.6", + "version": "2.3.3", "target-dir": "Zend/Config", "source": { "type": "git", "url": "https://github.com/zendframework/Component_ZendConfig.git", - "reference": "a31c3980cf7ec88418a931e9cf4ba21079f47a08" + "reference": "a9ad512e1482461a5b500ee3fcf2d06ec9c7c7e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/Component_ZendConfig/zipball/a31c3980cf7ec88418a931e9cf4ba21079f47a08", - "reference": "a31c3980cf7ec88418a931e9cf4ba21079f47a08", + "url": "https://api.github.com/repos/zendframework/Component_ZendConfig/zipball/a9ad512e1482461a5b500ee3fcf2d06ec9c7c7e8", + "reference": "a9ad512e1482461a5b500ee3fcf2d06ec9c7c7e8", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": ">=5.3.23", "zendframework/zend-stdlib": "self.version" }, + "require-dev": { + "zendframework/zend-filter": "self.version", + "zendframework/zend-i18n": "self.version", + "zendframework/zend-json": "self.version", + "zendframework/zend-servicemanager": "self.version" + }, "suggest": { + "zendframework/zend-filter": "Zend\\Filter component", + "zendframework/zend-i18n": "Zend\\I18n component", "zendframework/zend-json": "Zend\\Json to use the Json reader or writer classes", "zendframework/zend-servicemanager": "Zend\\ServiceManager for use with the Config Factory to retrieve reader and writer instances" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev", - "dev-develop": "2.3-dev" + "dev-master": "2.3-dev", + "dev-develop": "2.4-dev" } }, "autoload": { @@ -2781,36 +3340,37 @@ "BSD-3-Clause" ], "description": "provides a nested object property based user interface for accessing this configuration data within application code", + "homepage": "https://github.com/zendframework/zf2", "keywords": [ "config", "zf2" ], - "time": "2014-01-02 18:00:10" + "time": "2014-09-16 22:58:11" }, { "name": "zendframework/zend-eventmanager", - "version": "2.1.6", + "version": "2.3.3", "target-dir": "Zend/EventManager", "source": { "type": "git", "url": "https://github.com/zendframework/Component_ZendEventManager.git", - "reference": "89368704bb37303fba64c3ddd6bce0506aa7187c" + "reference": "4110fe64b10616b9bb71429a206d8e9e6d99e3ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/Component_ZendEventManager/zipball/89368704bb37303fba64c3ddd6bce0506aa7187c", - "reference": "89368704bb37303fba64c3ddd6bce0506aa7187c", + "url": "https://api.github.com/repos/zendframework/Component_ZendEventManager/zipball/4110fe64b10616b9bb71429a206d8e9e6d99e3ba", + "reference": "4110fe64b10616b9bb71429a206d8e9e6d99e3ba", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": ">=5.3.23", "zendframework/zend-stdlib": "self.version" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev", - "dev-develop": "2.3-dev" + "dev-master": "2.3-dev", + "dev-develop": "2.4-dev" } }, "autoload": { @@ -2822,45 +3382,48 @@ "license": [ "BSD-3-Clause" ], + "homepage": "https://github.com/zendframework/zf2", "keywords": [ "eventmanager", "zf2" ], - "time": "2014-01-04 13:00:14" + "time": "2014-09-16 22:58:11" }, { "name": "zendframework/zend-filter", - "version": "2.1.6", + "version": "2.3.3", "target-dir": "Zend/Filter", "source": { "type": "git", "url": "https://github.com/zendframework/Component_ZendFilter.git", - "reference": "8ceece474b29d079e86976dbd3efffe6064b3d72" + "reference": "98b8c2abfdc9009e4c0157e78c9f22bf2cebb693" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/Component_ZendFilter/zipball/8ceece474b29d079e86976dbd3efffe6064b3d72", - "reference": "8ceece474b29d079e86976dbd3efffe6064b3d72", + "url": "https://api.github.com/repos/zendframework/Component_ZendFilter/zipball/98b8c2abfdc9009e4c0157e78c9f22bf2cebb693", + "reference": "98b8c2abfdc9009e4c0157e78c9f22bf2cebb693", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": ">=5.3.23", "zendframework/zend-stdlib": "self.version" }, "require-dev": { - "zendframework/zend-crypt": "self.version" + "zendframework/zend-crypt": "self.version", + "zendframework/zend-servicemanager": "self.version", + "zendframework/zend-uri": "self.version" }, "suggest": { "zendframework/zend-crypt": "Zend\\Crypt component", "zendframework/zend-i18n": "Zend\\I18n component", - "zendframework/zend-uri": "Zend\\Uri component for UriNormalize filter", - "zendframework/zend-validator": "Zend\\Validator component" + "zendframework/zend-servicemanager": "Zend\\ServiceManager component", + "zendframework/zend-uri": "Zend\\Uri component for UriNormalize filter" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev", - "dev-develop": "2.3-dev" + "dev-master": "2.3-dev", + "dev-develop": "2.4-dev" } }, "autoload": { @@ -2873,44 +3436,57 @@ "BSD-3-Clause" ], "description": "provides a set of commonly needed data filters", + "homepage": "https://github.com/zendframework/zf2", "keywords": [ "filter", "zf2" ], - "time": "2014-03-03 21:00:06" + "time": "2014-09-16 22:58:11" }, { "name": "zendframework/zend-i18n", - "version": "2.1.6", + "version": "2.3.3", "target-dir": "Zend/I18n", "source": { "type": "git", "url": "https://github.com/zendframework/Component_ZendI18n.git", - "reference": "10f56e0869761d62699782e4dd04eb77262cc353" + "reference": "7939bd8eaa573f10fe33a799714199ed7c1fad5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/Component_ZendI18n/zipball/10f56e0869761d62699782e4dd04eb77262cc353", - "reference": "10f56e0869761d62699782e4dd04eb77262cc353", + "url": "https://api.github.com/repos/zendframework/Component_ZendI18n/zipball/7939bd8eaa573f10fe33a799714199ed7c1fad5c", + "reference": "7939bd8eaa573f10fe33a799714199ed7c1fad5c", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": ">=5.3.23", "zendframework/zend-stdlib": "self.version" }, + "require-dev": { + "zendframework/zend-cache": "self.version", + "zendframework/zend-config": "self.version", + "zendframework/zend-eventmanager": "self.version", + "zendframework/zend-filter": "self.version", + "zendframework/zend-servicemanager": "self.version", + "zendframework/zend-validator": "self.version", + "zendframework/zend-view": "self.version" + }, "suggest": { "ext-intl": "Required for most features of Zend\\I18n; included in default builds of PHP", + "zendframework/zend-cache": "Zend\\Cache component", + "zendframework/zend-config": "Zend\\Config component", "zendframework/zend-eventmanager": "You should install this package to use the events in the translator", "zendframework/zend-filter": "You should install this package to use the provided filters", "zendframework/zend-resources": "Translation resources", + "zendframework/zend-servicemanager": "Zend\\ServiceManager component", "zendframework/zend-validator": "You should install this package to use the provided validators", "zendframework/zend-view": "You should install this package to use the provided view helpers" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev", - "dev-develop": "2.3-dev" + "dev-master": "2.3-dev", + "dev-develop": "2.4-dev" } }, "autoload": { @@ -2922,39 +3498,45 @@ "license": [ "BSD-3-Clause" ], + "homepage": "https://github.com/zendframework/zf2", "keywords": [ "i18n", "zf2" ], - "time": "2014-01-04 13:00:19" + "time": "2014-09-16 22:58:11" }, { "name": "zendframework/zend-json", - "version": "2.1.6", + "version": "2.3.3", "target-dir": "Zend/Json", "source": { "type": "git", "url": "https://github.com/zendframework/Component_ZendJson.git", - "reference": "dd8a8239a7c08c7449a6ea219da3e2369bd90d92" + "reference": "4093e5a0a166a5d02532bac6e5671a7b21d203b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/Component_ZendJson/zipball/dd8a8239a7c08c7449a6ea219da3e2369bd90d92", - "reference": "dd8a8239a7c08c7449a6ea219da3e2369bd90d92", + "url": "https://api.github.com/repos/zendframework/Component_ZendJson/zipball/4093e5a0a166a5d02532bac6e5671a7b21d203b5", + "reference": "4093e5a0a166a5d02532bac6e5671a7b21d203b5", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": ">=5.3.23", "zendframework/zend-stdlib": "self.version" }, + "require-dev": { + "zendframework/zend-http": "self.version", + "zendframework/zend-server": "self.version" + }, "suggest": { + "zendframework/zend-http": "Zend\\Http component", "zendframework/zend-server": "Zend\\Server component" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev", - "dev-develop": "2.3-dev" + "dev-master": "2.3-dev", + "dev-develop": "2.4-dev" } }, "autoload": { @@ -2967,29 +3549,30 @@ "BSD-3-Clause" ], "description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP", + "homepage": "https://github.com/zendframework/zf2", "keywords": [ "json", "zf2" ], - "time": "2014-03-06 18:00:05" + "time": "2014-09-16 22:58:11" }, { "name": "zendframework/zend-math", - "version": "2.1.6", + "version": "2.3.3", "target-dir": "Zend/Math", "source": { "type": "git", "url": "https://github.com/zendframework/Component_ZendMath.git", - "reference": "b982ee2edafd4075b22372596ab2e2fdd0f6424e" + "reference": "a197ee44ade44a289f0f250c2aedb321b3618573" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/Component_ZendMath/zipball/b982ee2edafd4075b22372596ab2e2fdd0f6424e", - "reference": "b982ee2edafd4075b22372596ab2e2fdd0f6424e", + "url": "https://api.github.com/repos/zendframework/Component_ZendMath/zipball/a197ee44ade44a289f0f250c2aedb321b3618573", + "reference": "a197ee44ade44a289f0f250c2aedb321b3618573", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.23" }, "suggest": { "ext-bcmath": "If using the bcmath functionality", @@ -3000,8 +3583,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev", - "dev-develop": "2.3-dev" + "dev-master": "2.3-dev", + "dev-develop": "2.4-dev" } }, "autoload": { @@ -3013,41 +3596,45 @@ "license": [ "BSD-3-Clause" ], + "homepage": "https://github.com/zendframework/zf2", "keywords": [ "math", "zf2" ], - "time": "2014-03-05 18:00:06" + "time": "2014-09-16 22:58:11" }, { "name": "zendframework/zend-serializer", - "version": "2.1.6", + "version": "2.3.3", "target-dir": "Zend/Serializer", "source": { "type": "git", "url": "https://github.com/zendframework/Component_ZendSerializer.git", - "reference": "d76b931d3ffa842a496c9fa319bbe285b5ddfade" + "reference": "34ee4925e7e256bfa80c4c3dcc8e764d02a51edd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/Component_ZendSerializer/zipball/d76b931d3ffa842a496c9fa319bbe285b5ddfade", - "reference": "d76b931d3ffa842a496c9fa319bbe285b5ddfade", + "url": "https://api.github.com/repos/zendframework/Component_ZendSerializer/zipball/34ee4925e7e256bfa80c4c3dcc8e764d02a51edd", + "reference": "34ee4925e7e256bfa80c4c3dcc8e764d02a51edd", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": ">=5.3.23", "zendframework/zend-json": "self.version", "zendframework/zend-math": "self.version", "zendframework/zend-stdlib": "self.version" }, + "require-dev": { + "zendframework/zend-servicemanager": "self.version" + }, "suggest": { "zendframework/zend-servicemanager": "To support plugin manager support" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev", - "dev-develop": "2.3-dev" + "dev-master": "2.3-dev", + "dev-develop": "2.4-dev" } }, "autoload": { @@ -3060,29 +3647,33 @@ "BSD-3-Clause" ], "description": "provides an adapter based interface to simply generate storable representation of PHP types by different facilities, and recover", + "homepage": "https://github.com/zendframework/zf2", "keywords": [ "serializer", "zf2" ], - "time": "2014-01-02 18:00:26" + "time": "2014-09-16 22:58:11" }, { "name": "zendframework/zend-servicemanager", - "version": "2.1.6", + "version": "2.3.3", "target-dir": "Zend/ServiceManager", "source": { "type": "git", "url": "https://github.com/zendframework/Component_ZendServiceManager.git", - "reference": "de182a20dfdcf978c49570514103c7477ef16e4f" + "reference": "559403e4fd10db2516641f20f129a568d7e6a993" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/Component_ZendServiceManager/zipball/de182a20dfdcf978c49570514103c7477ef16e4f", - "reference": "de182a20dfdcf978c49570514103c7477ef16e4f", + "url": "https://api.github.com/repos/zendframework/Component_ZendServiceManager/zipball/559403e4fd10db2516641f20f129a568d7e6a993", + "reference": "559403e4fd10db2516641f20f129a568d7e6a993", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.23" + }, + "require-dev": { + "zendframework/zend-di": "self.version" }, "suggest": { "zendframework/zend-di": "Zend\\Di component" @@ -3090,8 +3681,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev", - "dev-develop": "2.3-dev" + "dev-master": "2.3-dev", + "dev-develop": "2.4-dev" } }, "autoload": { @@ -3103,39 +3694,46 @@ "license": [ "BSD-3-Clause" ], + "homepage": "https://github.com/zendframework/zf2", "keywords": [ "servicemanager", "zf2" ], - "time": "2014-03-03 21:00:04" + "time": "2014-09-16 22:58:11" }, { "name": "zendframework/zend-stdlib", - "version": "2.1.6", + "version": "2.3.3", "target-dir": "Zend/Stdlib", "source": { "type": "git", "url": "https://github.com/zendframework/Component_ZendStdlib.git", - "reference": "e646729f2274f4552b6a92e38d8e458efe08ebc5" + "reference": "fa33e6647f830d0d2a1cb451efcdfe1bb9a66c33" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/Component_ZendStdlib/zipball/e646729f2274f4552b6a92e38d8e458efe08ebc5", - "reference": "e646729f2274f4552b6a92e38d8e458efe08ebc5", + "url": "https://api.github.com/repos/zendframework/Component_ZendStdlib/zipball/fa33e6647f830d0d2a1cb451efcdfe1bb9a66c33", + "reference": "fa33e6647f830d0d2a1cb451efcdfe1bb9a66c33", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.23" + }, + "require-dev": { + "zendframework/zend-eventmanager": "self.version", + "zendframework/zend-serializer": "self.version", + "zendframework/zend-servicemanager": "self.version" }, "suggest": { "zendframework/zend-eventmanager": "To support aggregate hydrator usage", + "zendframework/zend-serializer": "Zend\\Serializer component", "zendframework/zend-servicemanager": "To support hydrator plugin manager usage" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev", - "dev-develop": "2.3-dev" + "dev-master": "2.3-dev", + "dev-develop": "2.4-dev" } }, "autoload": { @@ -3147,26 +3745,30 @@ "license": [ "BSD-3-Clause" ], + "homepage": "https://github.com/zendframework/zf2", "keywords": [ "stdlib", "zf2" ], - "time": "2014-01-04 13:00:28" + "time": "2014-09-16 22:58:11" }, { "name": "zetacomponents/base", - "version": "1.8", + "version": "1.9", "source": { "type": "git", "url": "https://github.com/zetacomponents/Base.git", - "reference": "52ca69c1de55f3fa4f595779e5bc831da7ee176c" + "reference": "f20df24e8de3e48b6b69b2503f917e457281e687" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zetacomponents/Base/zipball/52ca69c1de55f3fa4f595779e5bc831da7ee176c", - "reference": "52ca69c1de55f3fa4f595779e5bc831da7ee176c", + "url": "https://api.github.com/repos/zetacomponents/Base/zipball/f20df24e8de3e48b6b69b2503f917e457281e687", + "reference": "f20df24e8de3e48b6b69b2503f917e457281e687", "shasum": "" }, + "require-dev": { + "zetacomponents/unit-test": "*" + }, "type": "library", "autoload": { "classmap": [ @@ -3175,7 +3777,7 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "apache2" + "Apache-2.0" ], "authors": [ { @@ -3211,7 +3813,7 @@ ], "description": "The Base package provides the basic infrastructure that all packages rely on. Therefore every component relies on this package.", "homepage": "https://github.com/zetacomponents", - "time": "2009-12-21 12:14:16" + "time": "2014-09-19 03:28:34" }, { "name": "zetacomponents/document", @@ -3265,19 +3867,13 @@ "time": "2013-12-19 11:40:00" } ], - "aliases": [ - - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": [ - - ], + "stability-flags": [], + "prefer-stable": false, "platform": { "php": ">=5.3.3", - "ext-xml": "*", - "ext-zip": "*" + "ext-xml": "*" }, - "platform-dev": [ - - ] + "platform-dev": [] } diff --git a/docs/conf.py b/docs/conf.py index f5c38581..de645350 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -41,14 +41,14 @@ master_doc = 'index' # General information about the project. project = u'PhpWord' -copyright = u'2014, Progi1984' +copyright = u'2014, PHPWord Contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '0.9.0' +version = '0.12.0' # The full version, including alpha/beta/rc tags. release = version diff --git a/docs/containers.rst b/docs/containers.rst index 30566df6..f165a589 100644 --- a/docs/containers.rst +++ b/docs/containers.rst @@ -16,57 +16,24 @@ section, use the following code: .. code-block:: php - $section = $phpWord->addSection($sectionSettings); + $section = $phpWord->addSection($sectionStyle); -The ``$sectionSettings`` is an optional associative array that sets the +The ``$sectionStyle`` is an optional associative array that sets the section. Example: .. code-block:: php - $sectionSettings = array( + $sectionStyle = array( 'orientation' => 'landscape', 'marginTop' => 600, 'colsNum' => 2, ); -Section settings -~~~~~~~~~~~~~~~~ - -Below are the available settings for section: - -- ``orientation`` Page orientation, i.e. 'portrait' (default) or - 'landscape' -- ``marginTop`` Page margin top in twips -- ``marginLeft`` Page margin left in twips -- ``marginRight`` Page margin right in twips -- ``marginBottom`` Page margin bottom in twips -- ``borderTopSize`` Border top size in twips -- ``borderTopColor`` Border top color -- ``borderLeftSize`` Border left size in twips -- ``borderLeftColor`` Border left color -- ``borderRightSize`` Border right size in twips -- ``borderRightColor`` Border right color -- ``borderBottomSize`` Border bottom size in twips -- ``borderBottomColor`` Border bottom color -- ``headerHeight`` Spacing to top of header -- ``footerHeight`` Spacing to bottom of footer -- ``gutter`` Page gutter spacing -- ``colsNum`` Number of columns -- ``colsSpace`` Spacing between columns -- ``breakType`` Section break type (nextPage, nextColumn, continuous, - evenPage, oddPage) - -The following two settings are automatically set by the use of the -``orientation`` setting. You can alter them but that's not recommended. - -- ``pageSizeW`` Page width in twips -- ``pageSizeH`` Page height in twips - Page number ~~~~~~~~~~~ You can change a section page number by using the ``pageNumberingStart`` -property of the section. +style of the section. .. code-block:: php @@ -75,13 +42,13 @@ property of the section. // Method 2 $section = $phpWord->addSection(); - $section->getSettings()->setPageNumberingStart(1); + $section->getStyle()->setPageNumberingStart(1); Multicolumn ~~~~~~~~~~~ You can change a section layout to multicolumn (like in a newspaper) by -using the ``breakType`` and ``colsNum`` property of the section. +using the ``breakType`` and ``colsNum`` style of the section. .. code-block:: php @@ -90,14 +57,14 @@ using the ``breakType`` and ``colsNum`` property of the section. // Method 2 $section = $phpWord->addSection(); - $section->getSettings()->setBreakType('continuous'); - $section->getSettings()->setColsNum(2); + $section->getStyle()->setBreakType('continuous'); + $section->getStyle()->setColsNum(2); - -### Line numbering +Line numbering +~~~~~~~~~~~~~~ You can apply line numbering to a section by using the ``lineNumbering`` -property of the section. +style of the section. .. code-block:: php @@ -106,14 +73,15 @@ property of the section. // Method 2 $section = $phpWord->addSection(); - $section->getSettings()->setLineNumbering(array()); + $section->getStyle()->setLineNumbering(array()); Below are the properties of the line numbering style. - ``start`` Line numbering starting value - ``increment`` Line number increments - ``distance`` Distance between text and line numbering in twip -- ``restart`` Line numbering restart setting continuous|newPage|newSection +- ``restart`` Line numbering restart setting + continuous\|newPage\|newSection Headers ------- diff --git a/docs/faq.rst b/docs/faq.rst index ec158356..79652ae0 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -3,6 +3,12 @@ Frequently asked questions ========================== +How contribute to PHPWord ? +--------------------------- + +- Improve the documentation (`Sphinx Format `__) + + Is this the same with PHPWord that I found in CodePlex? ------------------------------------------------------- diff --git a/docs/general.rst b/docs/general.rst index f08e29ba..34d3af24 100644 --- a/docs/general.rst +++ b/docs/general.rst @@ -12,46 +12,82 @@ folder `__. .. code-block:: php + addSection(); + // Adding Text element to the Section having font styled by default... + $section->addText( + htmlspecialchars( + '"Learn from yesterday, live for today, hope for tomorrow. ' + . 'The important thing is not to stop questioning." ' + . '(Albert Einstein)' + ) + ); - // After creating a section, you can append elements: - $section->addText('Hello world!'); + /* + * Note: it's possible to customize font style of the Text element you add in three ways: + * - inline; + * - using named font style (new font style object will be implicitly created); + * - using explicitly created font style object. + */ - // You can directly style your text by giving the addText function an array: - $section->addText('Hello world! I am formatted.', - array('name'=>'Tahoma', 'size'=>16, 'bold'=>true)); + // Adding Text element with font customized inline... + $section->addText( + htmlspecialchars( + '"Great achievement is usually born of great sacrifice, ' + . 'and is never the result of selfishness." ' + . '(Napoleon Hill)' + ), + array('name' => 'Tahoma', 'size' => 10) + ); - // If you often need the same style again you can create a user defined style - // to the word document and give the addText function the name of the style: - $phpWord->addFontStyle('myOwnStyle', - array('name'=>'Verdana', 'size'=>14, 'color'=>'1B2232')); - $section->addText('Hello world! I am formatted by a user defined style', - 'myOwnStyle'); + // Adding Text element with font customized using named font style... + $fontStyleName = 'oneUserDefinedStyle'; + $phpWord->addFontStyle( + $fontStyleName, + array('name' => 'Tahoma', 'size' => 10, 'color' => '1B2232', 'bold' => true) + ); + $section->addText( + htmlspecialchars( + '"The greatest accomplishment is not in never falling, ' + . 'but in rising again after you fall." ' + . '(Vince Lombardi)' + ), + $fontStyleName + ); - // You can also put the appended element to local object like this: + // Adding Text element with font customized using explicitly created font style object... $fontStyle = new \PhpOffice\PhpWord\Style\Font(); $fontStyle->setBold(true); - $fontStyle->setName('Verdana'); - $fontStyle->setSize(22); - $myTextElement = $section->addText('Hello World!'); + $fontStyle->setName('Tahoma'); + $fontStyle->setSize(13); + $myTextElement = $section->addText( + htmlspecialchars('"Believe you can and you\'re halfway there." (Theodor Roosevelt)') + ); $myTextElement->setFontStyle($fontStyle); - // Finally, write the document: + // Saving the document as OOXML file... $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007'); $objWriter->save('helloWorld.docx'); + // Saving the document as ODF file... $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'ODText'); $objWriter->save('helloWorld.odt'); - $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'RTF'); - $objWriter->save('helloWorld.rtf'); + // Saving the document as HTML file... + $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'HTML'); + $objWriter->save('helloWorld.html'); + + /* Note: we skip RTF, because it's not XML-based and requires a different example. */ + /* Note: we skip PDF, because "HTML-to-PDF" approach is used to create PDF documents. */ Settings -------- @@ -79,11 +115,10 @@ during development to make the resulting XML file easier to read. Zip class ~~~~~~~~~ -By default, PHPWord uses PHP -`ZipArchive `__ to read or write -ZIP compressed archive and the files inside them. If you can't have -ZipArchive installed on your server, you can use pure PHP library -alternative, `PCLZip `__, which +By default, PHPWord uses `Zip extension `__ +to deal with ZIP compressed archives and files inside them. If you can't have +Zip extension installed on your server, you can use pure PHP library +alternative, `PclZip `__, which included with PHPWord. .. code-block:: php @@ -101,15 +136,15 @@ default font by using the following two functions: $phpWord->setDefaultFontName('Times New Roman'); $phpWord->setDefaultFontSize(12); -Document properties -------------------- +Document information +-------------------- -You can set the document properties such as title, creator, and company +You can set the document information such as title, creator, and company name. Use the following functions: .. code-block:: php - $properties = $phpWord->getDocumentProperties(); + $properties = $phpWord->getDocInfo(); $properties->setCreator('My name'); $properties->setCompany('My factory'); $properties->setTitle('My title'); @@ -134,13 +169,13 @@ points to twips. // Paragraph with 6 points space after $phpWord->addParagraphStyle('My Style', array( - 'spaceAfter' => \PhpOffice\PhpWord\Shared\Font::pointSizeToTwips(6)) + 'spaceAfter' => \PhpOffice\PhpWord\Shared\Converter::pointToTwip(6)) ); $section = $phpWord->addSection(); - $sectionStyle = $section->getSettings(); + $sectionStyle = $section->getStyle(); // half inch left margin - $sectionStyle->setMarginLeft(\PhpOffice\PhpWord\Shared\Font::inchSizeToTwips(.5)); + $sectionStyle->setMarginLeft(\PhpOffice\PhpWord\Shared\Converter::inchToTwip(.5)); // 2 cm right margin - $sectionStyle->setMarginRight(\PhpOffice\PhpWord\Shared\Font::centimeterSizeToTwips(2)); + $sectionStyle->setMarginRight(\PhpOffice\PhpWord\Shared\Converter::cmToTwip(2)); diff --git a/docs/index.rst b/docs/index.rst index fd3a3fa9..671c32a6 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -18,11 +18,12 @@ Format (RTF). :maxdepth: 2 intro - setup + installing general containers elements - templates + styles + templates-processing writersreaders recipes faq diff --git a/docs/setup.rst b/docs/installing.rst similarity index 62% rename from docs/setup.rst rename to docs/installing.rst index e5d61b4e..65995904 100644 --- a/docs/setup.rst +++ b/docs/installing.rst @@ -41,13 +41,32 @@ To install via Composer, add the following lines to your } } +If you are a developer or if you want to help us with testing then fetch the latest branch for developers. +Notice: All contributions must be done against the developer branch. + +.. code-block:: json + + { + "require": { + "phpoffice/phpword": "dev-develop" + } + } + + Manual install ~~~~~~~~~~~~~~ -To install manually, `download PHPWord package from -github `__. -Extract the package and put the contents to your machine. To use the -library, include ``src/PhpWord/Autoloader.php`` in your script and +To install manually, you change to the webserver directory of your file system . +Then you have 2 possibilities. + + 1. `download PHPWord package from github `__. + Extract the package and put the contents to your machine. + 2. Alternatively you can use Git to install it: + .. code-block:: console + + git clone https://github.com/PHPOffice/PHPWord.git + +To use the library, include ``src/PhpWord/Autoloader.php`` in your PHP script and invoke ``Autoloader::register``. .. code-block:: php @@ -55,6 +74,7 @@ invoke ``Autoloader::register``. require_once '/path/to/src/PhpWord/Autoloader.php'; \PhpOffice\PhpWord\Autoloader::register(); + Using samples ------------- diff --git a/docs/intro.rst b/docs/intro.rst index aca5b241..d2decd7c 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -37,6 +37,7 @@ Features run) that contains other elements - Insert titles (headers) and table of contents - Insert text breaks and page breaks +- Insert right-to-left text - Insert and format images, either local, remote, or as page watermarks - Insert binary OLE Objects such as Excel or Visio - Insert and format table with customized properties for each rows @@ -45,6 +46,9 @@ Features - Insert list items as bulleted, numbered, or multilevel - Insert hyperlinks - Insert footnotes and endnotes +- Insert drawing shapes (arc, curve, line, polyline, rect, oval) +- Insert charts (pie, doughnut, bar, line, area, scatter, radar) +- Insert form fields (textinput, checkbox, and dropdown) - Create document from templates - Use XSL 1.0 style sheets to transform main document part of OOXML template @@ -99,11 +103,11 @@ Writers +---------------------------+----------------------+--------+-------+-------+--------+-------+ | | Endnote | ✓ | | | ✓ | | +---------------------------+----------------------+--------+-------+-------+--------+-------+ -| **Graphs** | 2D basic graphs | | | | | | +| **Graphs** | 2D basic graphs | ✓ | | | | | +---------------------------+----------------------+--------+-------+-------+--------+-------+ | | 2D advanced graphs | | | | | | +---------------------------+----------------------+--------+-------+-------+--------+-------+ -| | 3D graphs | | | | | | +| | 3D graphs | ✓ | | | | | +---------------------------+----------------------+--------+-------+-------+--------+-------+ | **Math** | OMML support | | | | | | +---------------------------+----------------------+--------+-------+-------+--------+-------+ @@ -117,75 +121,75 @@ Writers Readers ~~~~~~~ -+---------------------------+----------------------+--------+-------+-------+-------+ -| Features | | DOCX | ODT | RTF | HTML | -+===========================+======================+========+=======+=======+=======+ -| **Document Properties** | Standard | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Custom | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| **Element Type** | Text | ✓ | ✓ | ✓ | ✓ | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Text Run | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Title | ✓ | ✓ | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Link | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Preserve Text | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Text Break | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Page Break | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | List | ✓ | ✓ | | ✓ | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Table | ✓ | | | ✓ | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Image | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Object | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Watermark | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Table of Contents | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Header | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Footer | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Footnote | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Endnote | ✓ | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| **Graphs** | 2D basic graphs | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | 2D advanced graphs | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | 3D graphs | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| **Math** | OMML support | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | MathML support | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| **Bonus** | Encryption | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ -| | Protection | | | | | -+---------------------------+----------------------+--------+-------+-------+-------+ ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| Features | | DOCX | DOC | ODT | RTF | HTML | ++===========================+======================+========+=======+=======+=======+=======+ +| **Document Properties** | Standard | ✓ | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Custom | ✓ | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| **Element Type** | Text | ✓ | ✓ | ✓ | ✓ | ✓ | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Text Run | ✓ | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Title | ✓ | | ✓ | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Link | ✓ | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Preserve Text | ✓ | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Text Break | ✓ | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Page Break | ✓ | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | List | ✓ | | ✓ | | ✓ | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Table | ✓ | | | | ✓ | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Image | ✓ | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Object | | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Watermark | | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Table of Contents | | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Header | ✓ | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Footer | ✓ | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Footnote | ✓ | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Endnote | ✓ | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| **Graphs** | 2D basic graphs | | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | 2D advanced graphs | | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | 3D graphs | | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| **Math** | OMML support | | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | MathML support | | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| **Bonus** | Encryption | | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Protection | | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ Contributing ------------ We welcome everyone to contribute to PHPWord. Below are some of the -things that you can do to contribute: +things that you can do to contribute. - Read `our contributing - guide `__ + guide `__. - `Fork us `__ and `request a pull `__ to the `develop `__ - branch + branch. - Submit `bug reports or feature - requests `__ to GitHub + requests `__ to GitHub. - Follow `@PHPWord `__ and - `@PHPOffice `__ on Twitter + `@PHPOffice `__ on Twitter. diff --git a/docs/recipes.rst b/docs/recipes.rst index d5678a52..0be6b4e0 100644 --- a/docs/recipes.rst +++ b/docs/recipes.rst @@ -65,3 +65,34 @@ Define a numbering style and title styles, and match the two styles (with ``pSty $section->addTitle('Heading 1', 1); $section->addTitle('Heading 2', 2); $section->addTitle('Heading 3', 3); + +Add a link within a title +------------------------- + +Apply 'HeadingN' paragraph style to TextRun or Link. Sample code: + +.. code-block:: php + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord->addTitleStyle(1, array('size' => 16, 'bold' => true)); + $phpWord->addTitleStyle(2, array('size' => 14, 'bold' => true)); + $phpWord->addFontStyle('Link', array('color' => '0000FF', 'underline' => 'single')); + + $section = $phpWord->addSection(); + + // Textrun + $textrun = $section->addTextRun('Heading1'); + $textrun->addText('The '); + $textrun->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord', 'Link'); + + // Link + $section->addLink('https://github.com/', 'GitHub', 'Link', 'Heading2'); + +Remove [Compatibility Mode] text in the MS Word title bar +--------------------------------------------------------- + +Use the ``Metadata\Compatibility\setOoxmlVersion(n)`` method with ``n`` is the version of Office (14 = Office 2010, 15 = Office 2013). + +.. code-block:: php + + $phpWord->getCompatibility()->setOoxmlVersion(15); diff --git a/docs/src/documentation.md b/docs/src/documentation.md index 84522c1b..1a59e942 100644 --- a/docs/src/documentation.md +++ b/docs/src/documentation.md @@ -36,7 +36,15 @@ Don't forget to change `code::` directive to `code-block::` in the resulting rst - [Textboxes](#textboxes) - [Fields](#fields) - [Lines](#lines) -- [Templates](#templates) + - [Shapes](#shapes) + - [Charts](#charts) + - [FormFields](#form-fields) +- [Styles](#styles) + - [Section](#section) + - [Font](#font) + - [Paragraph](#paragraph) + - [Table](#table) +- [Templates processing](#templates-processing) - [Writers & readers](#writers-readers) - [OOXML](#ooxml) - [OpenDocument](#opendocument) @@ -70,6 +78,9 @@ PHPWord is an open source project licensed under the terms of [LGPL version 3](h - Insert list items as bulleted, numbered, or multilevel - Insert hyperlinks - Insert footnotes and endnotes +- Insert drawing shapes (arc, curve, line, polyline, rect, oval) +- Insert charts (pie, doughnut, bar, line, area, scatter, radar) +- Insert form fields (textinput, checkbox, and dropdown) - Create document from templates - Use XSL 1.0 style sheets to transform main document part of OOXML template - ... and many more features on progress @@ -101,9 +112,9 @@ Below are the supported features for each file formats. | | Footer | ✓ | | | | | | | Footnote | ✓ | | | ✓ | | | | Endnote | ✓ | | | ✓ | | -| **Graphs** | 2D basic graphs | | | | | | +| **Graphs** | 2D basic graphs | ✓ | | | | | | | 2D advanced graphs | | | | | | -| | 3D graphs | | | | | | +| | 3D graphs | ✓ | | | | | | **Math** | OMML support | | | | | | | | MathML support | | | | | | | **Bonus** | Encryption | | | | | | @@ -201,46 +212,82 @@ After installation, you can browse and use the samples that we've provided, eith The following is a basic example of the PHPWord library. More examples are provided in the [samples folder](https://github.com/PHPOffice/PHPWord/tree/master/samples/). ```php +addSection(); +// Adding Text element to the Section having font styled by default... +$section->addText( + htmlspecialchars( + '"Learn from yesterday, live for today, hope for tomorrow. ' + . 'The important thing is not to stop questioning." ' + . '(Albert Einstein)' + ) +); -// After creating a section, you can append elements: -$section->addText('Hello world!'); +/* + * Note: it's possible to customize font style of the Text element you add in three ways: + * - inline; + * - using named font style (new font style object will be implicitly created); + * - using explicitly created font style object. + */ -// You can directly style your text by giving the addText function an array: -$section->addText('Hello world! I am formatted.', - array('name'=>'Tahoma', 'size'=>16, 'bold'=>true)); +// Adding Text element with font customized inline... +$section->addText( + htmlspecialchars( + '"Great achievement is usually born of great sacrifice, ' + . 'and is never the result of selfishness." ' + . '(Napoleon Hill)' + ), + array('name' => 'Tahoma', 'size' => 10) +); -// If you often need the same style again you can create a user defined style -// to the word document and give the addText function the name of the style: -$phpWord->addFontStyle('myOwnStyle', - array('name'=>'Verdana', 'size'=>14, 'color'=>'1B2232')); -$section->addText('Hello world! I am formatted by a user defined style', - 'myOwnStyle'); +// Adding Text element with font customized using named font style... +$fontStyleName = 'oneUserDefinedStyle'; +$phpWord->addFontStyle( + $fontStyleName, + array('name' => 'Tahoma', 'size' => 10, 'color' => '1B2232', 'bold' => true) +); +$section->addText( + htmlspecialchars( + '"The greatest accomplishment is not in never falling, ' + . 'but in rising again after you fall." ' + . '(Vince Lombardi)' + ), + $fontStyleName +); -// You can also put the appended element to local object like this: +// Adding Text element with font customized using explicitly created font style object... $fontStyle = new \PhpOffice\PhpWord\Style\Font(); $fontStyle->setBold(true); -$fontStyle->setName('Verdana'); -$fontStyle->setSize(22); -$myTextElement = $section->addText('Hello World!'); +$fontStyle->setName('Tahoma'); +$fontStyle->setSize(13); +$myTextElement = $section->addText( + htmlspecialchars('"Believe you can and you\'re halfway there." (Theodor Roosevelt)') +); $myTextElement->setFontStyle($fontStyle); -// Finally, write the document: +// Saving the document as OOXML file... $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007'); $objWriter->save('helloWorld.docx'); +// Saving the document as ODF file... $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'ODText'); $objWriter->save('helloWorld.odt'); -$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'RTF'); -$objWriter->save('helloWorld.rtf'); +// Saving the document as HTML file... +$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'HTML'); +$objWriter->save('helloWorld.html'); + +/* Note: we skip RTF, because it's not XML-based and requires a different example. */ +/* Note: we skip PDF, because "HTML-to-PDF" approach is used to create PDF documents. */ ``` ## Settings @@ -272,12 +319,12 @@ $phpWord->setDefaultFontName('Times New Roman'); $phpWord->setDefaultFontSize(12); ``` -## Document properties +## Document information -You can set the document properties such as title, creator, and company name. Use the following functions: +You can set the document information such as title, creator, and company name. Use the following functions: ```php -$properties = $phpWord->getDocumentProperties(); +$properties = $phpWord->getDocInfo(); $properties->setCreator('My name'); $properties->setCompany('My factory'); $properties->setTitle('My title'); @@ -299,15 +346,15 @@ You can use PHPWord helper functions to convert inches, centimeters, or points t ```php // Paragraph with 6 points space after $phpWord->addParagraphStyle('My Style', array( - 'spaceAfter' => \PhpOffice\PhpWord\Shared\Font::pointSizeToTwips(6)) + 'spaceAfter' => \PhpOffice\PhpWord\Shared\Converter::pointToTwip(6)) ); $section = $phpWord->addSection(); -$sectionStyle = $section->getSettings(); +$sectionStyle = $section->getStyle(); // half inch left margin -$sectionStyle->setMarginLeft(\PhpOffice\PhpWord\Shared\Font::inchSizeToTwips(.5)); +$sectionStyle->setMarginLeft(\PhpOffice\PhpWord\Shared\Converter::inchToTwip(.5)); // 2 cm right margin -$sectionStyle->setMarginRight(\PhpOffice\PhpWord\Shared\Font::centimeterSizeToTwips(2)); +$sectionStyle->setMarginRight(\PhpOffice\PhpWord\Shared\Converter::cmToTwip(2)); ``` # Containers @@ -319,51 +366,23 @@ Containers are objects where you can put elements (texts, lists, tables, etc). T Every visible element in word is placed inside of a section. To create a section, use the following code: ```php -$section = $phpWord->addSection($sectionSettings); +$section = $phpWord->addSection($sectionStyle); ``` -The `$sectionSettings` is an optional associative array that sets the section. Example: +The `$sectionStyle` is an optional associative array that sets the section. Example: ```php -$sectionSettings = array( +$sectionStyle = array( 'orientation' => 'landscape', 'marginTop' => 600, 'colsNum' => 2, ); ``` -### Section settings - -Below are the available settings for section: - -- `orientation` Page orientation, i.e. 'portrait' (default) or 'landscape' -- `marginTop` Page margin top in twips -- `marginLeft` Page margin left in twips -- `marginRight` Page margin right in twips -- `marginBottom` Page margin bottom in twips -- `borderTopSize` Border top size in twips -- `borderTopColor` Border top color -- `borderLeftSize` Border left size in twips -- `borderLeftColor` Border left color -- `borderRightSize` Border right size in twips -- `borderRightColor` Border right color -- `borderBottomSize` Border bottom size in twips -- `borderBottomColor` Border bottom color -- `headerHeight` Spacing to top of header -- `footerHeight` Spacing to bottom of footer -- `gutter` Page gutter spacing -- `colsNum` Number of columns -- `colsSpace` Spacing between columns -- `breakType` Section break type (nextPage, nextColumn, continuous, evenPage, oddPage) - -The following two settings are automatically set by the use of the `orientation` setting. You can alter them but that's not recommended. - -- `pageSizeW` Page width in twips -- `pageSizeH` Page height in twips ### Page number -You can change a section page number by using the `pageNumberingStart` property of the section. +You can change a section page number by using the `pageNumberingStart` style of the section. ```php // Method 1 @@ -371,12 +390,12 @@ $section = $phpWord->addSection(array('pageNumberingStart' => 1)); // Method 2 $section = $phpWord->addSection(); -$section->getSettings()->setPageNumberingStart(1); +$section->getStyle()->setPageNumberingStart(1); ``` ### Multicolumn -You can change a section layout to multicolumn (like in a newspaper) by using the `breakType` and `colsNum` property of the section. +You can change a section layout to multicolumn (like in a newspaper) by using the `breakType` and `colsNum` style of the section. ```php // Method 1 @@ -384,13 +403,13 @@ $section = $phpWord->addSection(array('breakType' => 'continuous', 'colsNum' => // Method 2 $section = $phpWord->addSection(); -$section->getSettings()->setBreakType('continuous'); -$section->getSettings()->setColsNum(2); +$section->getStyle()->setBreakType('continuous'); +$section->getStyle()->setColsNum(2); ``` ### Line numbering -You can apply line numbering to a section by using the `lineNumbering` property of the section. +You can apply line numbering to a section by using the `lineNumbering` style of the section. ```php // Method 1 @@ -398,7 +417,7 @@ $section = $phpWord->addSection(array('lineNumbering' => array())); // Method 2 $section = $phpWord->addSection(); -$section->getSettings()->setLineNumbering(array()); +$section->getStyle()->setLineNumbering(array()); ``` Below are the properties of the line numbering style. @@ -465,6 +484,9 @@ Below are the matrix of element availability in each container. The column shows | 17 | TextBox | v | v | v | v | - | - | | 18 | Field | v | v | v | v | v | v | | 19 | Line | v | v | v | v | v | v | +| 20 | Shape | v | v | v | v | v | v | +| 21 | Chart | v | - | - | - | - | - | +| 22 | Form Fields | v | v | v | v | v | v | Legend: @@ -483,8 +505,6 @@ $section->addText($text, [$fontStyle], [$paragraphStyle]); $textrun = $section->addTextRun([$paragraphStyle]); ``` -### Text styles - You can use the `$fontStyle` and `$paragraphStyle` variable to define text formatting. There are 2 options to style the inserted text elements, i.e. inline style by using array or defined style by adding style definition. Inline style examples: @@ -512,44 +532,6 @@ $phpWord->addParagraphStyle('pStyle', $paragraphStyle); $text = $section->addText('Hello world!', 'pStyle'); ``` -#### Font style - -Available font styles: - -- `name` Font name, e.g. *Arial* -- `size` Font size, e.g. *20*, *22*, -- `hint` Font content type, *default*, *eastAsia*, or *cs* -- `bold` Bold, *true* or *false* -- `italic` Italic, *true* or *false* -- `superScript` Superscript, *true* or *false* -- `subScript` Subscript, *true* or *false* -- `underline` Underline, *dash*, *dotted*, etc. -- `strikethrough` Strikethrough, *true* or *false* -- `doubleStrikethrough` Double strikethrough, *true* or *false* -- `color` Font color, e.g. *FF0000* -- `fgColor` Font highlight color, e.g. *yellow*, *green*, *blue* -- `bgColor` Font background color, e.g. *FF0000* -- `smallCaps` Small caps, *true* or *false* -- `allCaps` All caps, *true* or *false* - -#### Paragraph style - -Available paragraph styles: - -- `align` Paragraph alignment, *left*, *right* or *center* -- `spaceBefore` Space before paragraph -- `spaceAfter` Space after paragraph -- `indent` Indent by how much -- `hanging` Hanging by how much -- `basedOn` Parent style -- `next` Style for next paragraph -- `widowControl` Allow first/last line to display on a separate page, *true* or *false* -- `keepNext` Keep paragraph with next paragraph, *true* or *false* -- `keepLines` Keep all lines on one page, *true* or *false* -- `pageBreakBefore` Start paragraph on next page, *true* or *false* -- `lineHeight` text line height, e.g. *1.0*, *1.5*, ect... -- `tabs` Set of custom tab stops - ### Titles If you want to structure your document or build table of contents, you need titles or headings. To add a title to the document, use the `addTitleStyle` and `addTitle` method. @@ -600,9 +582,9 @@ $section->addTextBreak([$breakCount], [$fontStyle], [$paragraphStyle]); There are two ways to insert a page breaks, using the `addPageBreak` method or using the `pageBreakBefore` style of paragraph. -:: code-block:: php - -> \$section-\>addPageBreak(); +```php +$section->addPageBreak(); +``` ## Lists @@ -641,20 +623,6 @@ $section->addListItem('List Item I.b', 1, null, 'multilevel'); $section->addListItem('List Item II', 0, null, 'multilevel'); ``` -Level styles: - -- `start` Starting value -- `format` Numbering format bullet|decimal|upperRoman|lowerRoman|upperLetter|lowerLetter -- `restart` Restart numbering level symbol -- `suffix` Content between numbering symbol and paragraph text tab|space|nothing -- `text` Numbering level text e.g. %1 for nonbullet or bullet character -- `align` Numbering symbol align left|center|right|both -- `left` See paragraph style -- `hanging` See paragraph style -- `tabPos` See paragraph style -- `font` Font name -- `hint` See font style - ## Tables To add tables, rows, and cells, use the `addTable`, `addRow`, and `addCell` methods: @@ -678,33 +646,6 @@ $phpWord->addTableStyle('myTable', $tableStyle, $firstRowStyle); $table = $section->addTable('myTable'); ``` -### Table, row, and cell styles - -Table styles: - -- `width` Table width in percent -- `bgColor` Background color, e.g. '9966CC' -- `border(Top|Right|Bottom|Left)Size` Border size in twips -- `border(Top|Right|Bottom|Left)Color` Border color, e.g. '9966CC' -- `cellMargin(Top|Right|Bottom|Left)` Cell margin in twips - -Row styles: - -- `tblHeader` Repeat table row on every new page, *true* or *false* -- `cantSplit` Table row cannot break across pages, *true* or *false* -- `exactHeight` Row height is exact or at least - -Cell styles: - -- `width` Cell width in twips -- `valign` Vertical alignment, *top*, *center*, *both*, *bottom* -- `textDirection` Direction of text -- `bgColor` Background color, e.g. '9966CC' -- `border(Top|Right|Bottom|Left)Size` Border size in twips -- `border(Top|Right|Bottom|Left)Color` Border color, e.g. '9966CC' -- `gridSpan` Number of columns spanned -- `vMerge` *restart* or *continue* - ### Cell span You can span a cell on multiple columns by using `gridSpan` or multiple rows by using `vMerge`. @@ -747,17 +688,6 @@ $textrun = $section->addTextRun(); $textrun->addImage('http://php.net/logo.jpg'); ``` -### Image styles - -Available image styles: - -- `width` Width in pixels -- `height` Height in pixels -- `align` Image alignment, *left*, *right*, or *center* -- `marginTop` Top margin in inches, can be negative -- `marginLeft` Left margin in inches, can be negative -- `wrappingStyle` Wrapping style, *inline*, *square*, *tight*, *behind*, or *infront* - ### Watermarks To add a watermark (or page background image), your section needs a header reference. After creating a header, you can use the `addWatermark` method to add a watermark. @@ -850,21 +780,158 @@ To be completed. To be completed. -# Templates +## Shapes -You can create a docx template with included search-patterns that can be replaced by any value you wish. Only single-line values can be replaced. To load a template file, use the `loadTemplate` method. After loading the docx template, you can use the `setValue` method to change the value of a search pattern. The search-pattern model is: `${search-pattern}`. It is not possible to add new PHPWord elements to a loaded template file. +To be completed. + +## Charts + +To be completed. + +## Form fields + +To be completed. + +# Styles + +## Section + +Below are the available styles for section: + +- `orientation` Page orientation, i.e. 'portrait' (default) or 'landscape' +- `marginTop` Page margin top in twips +- `marginLeft` Page margin left in twips +- `marginRight` Page margin right in twips +- `marginBottom` Page margin bottom in twips +- `borderTopSize` Border top size in twips +- `borderTopColor` Border top color +- `borderLeftSize` Border left size in twips +- `borderLeftColor` Border left color +- `borderRightSize` Border right size in twips +- `borderRightColor` Border right color +- `borderBottomSize` Border bottom size in twips +- `borderBottomColor` Border bottom color +- `headerHeight` Spacing to top of header +- `footerHeight` Spacing to bottom of footer +- `gutter` Page gutter spacing +- `colsNum` Number of columns +- `colsSpace` Spacing between columns +- `breakType` Section break type (nextPage, nextColumn, continuous, evenPage, oddPage) + +The following two styles are automatically set by the use of the `orientation` style. You can alter them but that's not recommended. + +- `pageSizeW` Page width in twips +- `pageSizeH` Page height in twips + +## Font + +Available font styles: + +- `name` Font name, e.g. *Arial* +- `size` Font size, e.g. *20*, *22*, +- `hint` Font content type, *default*, *eastAsia*, or *cs* +- `bold` Bold, *true* or *false* +- `italic` Italic, *true* or *false* +- `superScript` Superscript, *true* or *false* +- `subScript` Subscript, *true* or *false* +- `underline` Underline, *dash*, *dotted*, etc. +- `strikethrough` Strikethrough, *true* or *false* +- `doubleStrikethrough` Double strikethrough, *true* or *false* +- `color` Font color, e.g. *FF0000* +- `fgColor` Font highlight color, e.g. *yellow*, *green*, *blue* +- `bgColor` Font background color, e.g. *FF0000* +- `smallCaps` Small caps, *true* or *false* +- `allCaps` All caps, *true* or *false* + +## Paragraph + +Available paragraph styles: + +- `align` Paragraph alignment, *left*, *right* or *center* +- `spaceBefore` Space before paragraph +- `spaceAfter` Space after paragraph +- `indent` Indent by how much +- `hanging` Hanging by how much +- `basedOn` Parent style +- `next` Style for next paragraph +- `widowControl` Allow first/last line to display on a separate page, *true* or *false* +- `keepNext` Keep paragraph with next paragraph, *true* or *false* +- `keepLines` Keep all lines on one page, *true* or *false* +- `pageBreakBefore` Start paragraph on next page, *true* or *false* +- `lineHeight` text line height, e.g. *1.0*, *1.5*, ect... +- `tabs` Set of custom tab stops + +## Table + +Table styles: + +- `width` Table width in percent +- `bgColor` Background color, e.g. '9966CC' +- `border(Top|Right|Bottom|Left)Size` Border size in twips +- `border(Top|Right|Bottom|Left)Color` Border color, e.g. '9966CC' +- `cellMargin(Top|Right|Bottom|Left)` Cell margin in twips + +Row styles: + +- `tblHeader` Repeat table row on every new page, *true* or *false* +- `cantSplit` Table row cannot break across pages, *true* or *false* +- `exactHeight` Row height is exact or at least + +Cell styles: + +- `width` Cell width in twips +- `valign` Vertical alignment, *top*, *center*, *both*, *bottom* +- `textDirection` Direction of text +- `bgColor` Background color, e.g. '9966CC' +- `border(Top|Right|Bottom|Left)Size` Border size in twips +- `border(Top|Right|Bottom|Left)Color` Border color, e.g. '9966CC' +- `gridSpan` Number of columns spanned +- `vMerge` *restart* or *continue* + +## Image + +Available image styles: + +- `width` Width in pixels +- `height` Height in pixels +- `align` Image alignment, *left*, *right*, or *center* +- `marginTop` Top margin in inches, can be negative +- `marginLeft` Left margin in inches, can be negative +- `wrappingStyle` Wrapping style, *inline*, *square*, *tight*, *behind*, or *infront* + +## Numbering level + +- `start` Starting value +- `format` Numbering format bullet|decimal|upperRoman|lowerRoman|upperLetter|lowerLetter +- `restart` Restart numbering level symbol +- `suffix` Content between numbering symbol and paragraph text tab|space|nothing +- `text` Numbering level text e.g. %1 for nonbullet or bullet character +- `align` Numbering symbol align left|center|right|both +- `left` See paragraph style +- `hanging` See paragraph style +- `tabPos` See paragraph style +- `font` Font name +- `hint` See font style + +# Templates processing + +You can create a .docx document template with included search-patterns which can be replaced by any value you wish. Only single-line values can be replaced. + +To deal with a template file, use `new TemplateProcessor` statement. After TemplateProcessor instance creation the document template is copied into the temporary directory. Then you can use `TemplateProcessor::setValue` method to change the value of a search pattern. The search-pattern model is: `${search-pattern}`. Example: ```php -$template = $phpWord->loadTemplate('Template.docx'); -$template->setValue('Name', 'Somebody someone'); -$template->setValue('Street', 'Coming-Undone-Street 32'); +$templateProcessor = new TemplateProcessor('Template.docx'); +$templateProcessor->setValue('Name', 'Somebody someone'); +$templateProcessor->setValue('Street', 'Coming-Undone-Street 32'); ``` -See `Sample_07_TemplateCloneRow.php` for example on how to create multirow from a single row in a template by using `cloneRow`. +It is not possible to directly add new OOXML elements to the template file being processed, but it is possible to transform main document part of the template using XSLT (see `TemplateProcessor::applyXslStyleSheet`). -See `Sample_23_TemplateBlock.php` for example on how to clone a block of text using `cloneBlock` and delete a block of text using `deleteBlock`. +See `Sample_07_TemplateCloneRow.php` for example on how to create multirow from a single row in a template by using `TemplateProcessor::cloneRow`. + +See `Sample_23_TemplateBlock.php` for example on how to clone a block of text using `TemplateProcessor::cloneBlock` and delete a block of text using `TemplateProcessor::deleteBlock`. # Writers & readers @@ -1009,6 +1076,35 @@ $section->addTitle('Heading 2', 2); $section->addTitle('Heading 3', 3); ``` +## Add a link within a title + +Apply 'HeadingN' paragraph style to TextRun or Link. Sample code: + +```php +$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord->addTitleStyle(1, array('size' => 16, 'bold' => true)); +$phpWord->addTitleStyle(2, array('size' => 14, 'bold' => true)); +$phpWord->addFontStyle('Link', array('color' => '0000FF', 'underline' => 'single')); + +$section = $phpWord->addSection(); + +// Textrun +$textrun = $section->addTextRun('Heading1'); +$textrun->addText('The '); +$textrun->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord', 'Link'); + +// Link +$section->addLink('https://github.com/', 'GitHub', 'Link', 'Heading2'); +``` + +## Remove [Compatibility Mode] text in the MS Word title bar + +Use the `Metadata\Compatibility\setOoxmlVersion(n)` method with `n` is the version of Office (14 = Office 2010, 15 = Office 2013). + +```php +$phpWord->getCompatibility()->setOoxmlVersion(15); +``` + # Frequently asked questions ## Is this the same with PHPWord that I found in CodePlex? diff --git a/docs/styles.rst b/docs/styles.rst new file mode 100644 index 00000000..f4c1e8eb --- /dev/null +++ b/docs/styles.rst @@ -0,0 +1,134 @@ +.. _styles: + +Styles +====== + +Section +------- + +Below are the available styles for section: + +- ``pageSizeW`` Page width in twips (the default is 11906/A4 size) +- ``pageSizeH`` Page height in twips (the default is 16838/A4 size) +- ``orientation`` Page orientation, i.e. 'portrait' (default) or + 'landscape' +- ``marginTop`` Page margin top in twips +- ``marginLeft`` Page margin left in twips +- ``marginRight`` Page margin right in twips +- ``marginBottom`` Page margin bottom in twips +- ``borderTopSize`` Border top size in twips +- ``borderTopColor`` Border top color +- ``borderLeftSize`` Border left size in twips +- ``borderLeftColor`` Border left color +- ``borderRightSize`` Border right size in twips +- ``borderRightColor`` Border right color +- ``borderBottomSize`` Border bottom size in twips +- ``borderBottomColor`` Border bottom color +- ``headerHeight`` Spacing to top of header +- ``footerHeight`` Spacing to bottom of footer +- ``gutter`` Page gutter spacing +- ``colsNum`` Number of columns +- ``colsSpace`` Spacing between columns +- ``breakType`` Section break type (nextPage, nextColumn, continuous, + evenPage, oddPage) + +Font +---- + +Available font styles: + +- ``name`` Font name, e.g. *Arial* +- ``size`` Font size, e.g. *20*, *22*, +- ``hint`` Font content type, *default*, *eastAsia*, or *cs* +- ``bold`` Bold, *true* or *false* +- ``italic`` Italic, *true* or *false* +- ``superScript`` Superscript, *true* or *false* +- ``subScript`` Subscript, *true* or *false* +- ``underline`` Underline, *dash*, *dotted*, etc. +- ``strikethrough`` Strikethrough, *true* or *false* +- ``doubleStrikethrough`` Double strikethrough, *true* or *false* +- ``color`` Font color, e.g. *FF0000* +- ``fgColor`` Font highlight color, e.g. *yellow*, *green*, *blue* +- ``bgColor`` Font background color, e.g. *FF0000* +- ``smallCaps`` Small caps, *true* or *false* +- ``allCaps`` All caps, *true* or *false* +- ``rtl`` Right to Left language, *true* or *false* + +Paragraph +--------- + +Available paragraph styles: + +- ``align`` Paragraph alignment, *left*, *right* or *center* +- ``spaceBefore`` Space before paragraph +- ``spaceAfter`` Space after paragraph +- ``indent`` Indent by how much +- ``hanging`` Hanging by how much +- ``basedOn`` Parent style +- ``next`` Style for next paragraph +- ``widowControl`` Allow first/last line to display on a separate page, + *true* or *false* +- ``keepNext`` Keep paragraph with next paragraph, *true* or *false* +- ``keepLines`` Keep all lines on one page, *true* or *false* +- ``pageBreakBefore`` Start paragraph on next page, *true* or *false* +- ``lineHeight`` text line height, e.g. *1.0*, *1.5*, ect... +- ``tabs`` Set of custom tab stops + +Table +----- + +Table styles: + +- ``width`` Table width in percent +- ``bgColor`` Background color, e.g. '9966CC' +- ``border(Top|Right|Bottom|Left)Size`` Border size in twips +- ``border(Top|Right|Bottom|Left)Color`` Border color, e.g. '9966CC' +- ``cellMargin(Top|Right|Bottom|Left)`` Cell margin in twips + +Row styles: + +- ``tblHeader`` Repeat table row on every new page, *true* or *false* +- ``cantSplit`` Table row cannot break across pages, *true* or *false* +- ``exactHeight`` Row height is exact or at least + +Cell styles: + +- ``width`` Cell width in twips +- ``valign`` Vertical alignment, *top*, *center*, *both*, *bottom* +- ``textDirection`` Direction of text +- ``bgColor`` Background color, e.g. '9966CC' +- ``border(Top|Right|Bottom|Left)Size`` Border size in twips +- ``border(Top|Right|Bottom|Left)Color`` Border color, e.g. '9966CC' +- ``gridSpan`` Number of columns spanned +- ``vMerge`` *restart* or *continue* + +Image +----- + +Available image styles: + +- ``width`` Width in pixels +- ``height`` Height in pixels +- ``align`` Image alignment, *left*, *right*, or *center* +- ``marginTop`` Top margin in inches, can be negative +- ``marginLeft`` Left margin in inches, can be negative +- ``wrappingStyle`` Wrapping style, *inline*, *square*, *tight*, + *behind*, or *infront* + +Numbering level +--------------- + +- ``start`` Starting value +- ``format`` Numbering format + bullet\|decimal\|upperRoman\|lowerRoman\|upperLetter\|lowerLetter +- ``restart`` Restart numbering level symbol +- ``suffix`` Content between numbering symbol and paragraph text + tab\|space\|nothing +- ``text`` Numbering level text e.g. %1 for nonbullet or bullet + character +- ``align`` Numbering symbol align left\|center\|right\|both +- ``left`` See paragraph style +- ``hanging`` See paragraph style +- ``tabPos`` See paragraph style +- ``font`` Font name +- ``hint`` See font style diff --git a/docs/templates-processing.rst b/docs/templates-processing.rst new file mode 100644 index 00000000..6a65ea0d --- /dev/null +++ b/docs/templates-processing.rst @@ -0,0 +1,25 @@ +.. _templates-processing: + +Templates processing +==================== + +You can create a .docx document template with included search-patterns which can be replaced by any value you wish. Only single-line values can be replaced. + +To deal with a template file, use ``new TemplateProcessor`` statement. After TemplateProcessor instance creation the document template is copied into the temporary directory. Then you can use ``TemplateProcessor::setValue`` method to change the value of a search pattern. The search-pattern model is: ``${search-pattern}``. + +Example: + +.. code-block:: php + + $templateProcessor = new TemplateProcessor('Template.docx'); + $templateProcessor->setValue('Name', 'Somebody someone'); + $templateProcessor->setValue('Street', 'Coming-Undone-Street 32'); + +It is not possible to directly add new OOXML elements to the template file being processed, but it is possible to transform main document part of the template using XSLT (see ``TemplateProcessor::applyXslStyleSheet``). + +See ``Sample_07_TemplateCloneRow.php`` for example on how to create +multirow from a single row in a template by using ``TemplateProcessor::cloneRow``. + +See ``Sample_23_TemplateBlock.php`` for example on how to clone a block +of text using ``TemplateProcessor::cloneBlock`` and delete a block of text using +``TemplateProcessor::deleteBlock``. diff --git a/docs/templates.rst b/docs/templates.rst deleted file mode 100644 index b1d9d205..00000000 --- a/docs/templates.rst +++ /dev/null @@ -1,27 +0,0 @@ -.. _templates: - -Templates -========= - -You can create a docx template with included search-patterns that can be -replaced by any value you wish. Only single-line values can be replaced. -To load a template file, use the ``loadTemplate`` method. After loading -the docx template, you can use the ``setValue`` method to change the -value of a search pattern. The search-pattern model is: -``${search-pattern}``. It is not possible to add new PHPWord elements to -a loaded template file. - -Example: - -.. code-block:: php - - $template = $phpWord->loadTemplate('Template.docx'); - $template->setValue('Name', 'Somebody someone'); - $template->setValue('Street', 'Coming-Undone-Street 32'); - -See ``Sample_07_TemplateCloneRow.php`` for example on how to create -multirow from a single row in a template by using ``cloneRow``. - -See ``Sample_23_TemplateBlock.php`` for example on how to clone a block -of text using ``cloneBlock`` and delete a block of text using -``deleteBlock``. diff --git a/phpmd.xml.dist b/phpmd.xml.dist index f0b62b2d..5eb348ec 100644 --- a/phpmd.xml.dist +++ b/phpmd.xml.dist @@ -18,7 +18,7 @@ - + diff --git a/phpword.ini.dist b/phpword.ini.dist index 4a51ee11..f8eafb6a 100644 --- a/phpword.ini.dist +++ b/phpword.ini.dist @@ -7,6 +7,7 @@ compatibility = true zipClass = ZipArchive pdfRendererName = DomPDF pdfRendererPath = +; tempDir = "C:\PhpWordTemp" [Font] diff --git a/samples/Sample_01_SimpleText.php b/samples/Sample_01_SimpleText.php index 311f3350..f7aaece3 100644 --- a/samples/Sample_01_SimpleText.php +++ b/samples/Sample_01_SimpleText.php @@ -2,7 +2,7 @@ include_once 'Sample_Header.php'; // New Word Document -echo date('H:i:s') , " Create new PhpWord object" , EOL; +echo date('H:i:s') , ' Create new PhpWord object' , EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); $phpWord->addFontStyle('rStyle', array('bold' => true, 'italic' => true, 'size' => 16, 'allCaps' => true, 'doubleStrikethrough' => true)); $phpWord->addParagraphStyle('pStyle', array('align' => 'center', 'spaceAfter' => 100)); @@ -12,36 +12,57 @@ $phpWord->addTitleStyle(1, array('bold' => true), array('spaceAfter' => 240)); $section = $phpWord->addSection(); // Simple text -$section->addTitle('Welcome to PhpWord', 1); -$section->addText('Hello World!'); +$section->addTitle(htmlspecialchars('Welcome to PhpWord'), 1); +$section->addText(htmlspecialchars('Hello World!')); // Two text break $section->addTextBreak(2); // Defined style -$section->addText('I am styled by a font style definition.', 'rStyle'); -$section->addText('I am styled by a paragraph style definition.', null, 'pStyle'); -$section->addText('I am styled by both font and paragraph style.', 'rStyle', 'pStyle'); +$section->addText(htmlspecialchars('I am styled by a font style definition.'), 'rStyle'); +$section->addText(htmlspecialchars('I am styled by a paragraph style definition.'), null, 'pStyle'); +$section->addText(htmlspecialchars('I am styled by both font and paragraph style.'), 'rStyle', 'pStyle'); -$section->addPageBreak(); +$section->addTextBreak(); // Inline font style $fontStyle['name'] = 'Times New Roman'; $fontStyle['size'] = 20; -$fontStyle['bold'] = true; -$fontStyle['italic'] = true; -$fontStyle['underline'] = 'dash'; -$fontStyle['strikethrough'] = true; -$fontStyle['superScript'] = true; -$fontStyle['color'] = 'FF0000'; -$fontStyle['fgColor'] = 'yellow'; -$fontStyle['smallCaps'] = true; -$section->addText('I am inline styled.', $fontStyle); -$section->addTextBreak(); +$textrun = $section->addTextRun(); +$textrun->addText(htmlspecialchars('I am inline styled '), $fontStyle); +$textrun->addText(htmlspecialchars('with ')); +$textrun->addText(htmlspecialchars('color'), array('color' => '996699')); +$textrun->addText(htmlspecialchars(', ')); +$textrun->addText(htmlspecialchars('bold'), array('bold' => true)); +$textrun->addText(htmlspecialchars(', ')); +$textrun->addText(htmlspecialchars('italic'), array('italic' => true)); +$textrun->addText(htmlspecialchars(', ')); +$textrun->addText(htmlspecialchars('underline'), array('underline' => 'dash')); +$textrun->addText(htmlspecialchars(', ')); +$textrun->addText(htmlspecialchars('strikethrough'), array('strikethrough' => true)); +$textrun->addText(htmlspecialchars(', ')); +$textrun->addText(htmlspecialchars('doubleStrikethrough'), array('doubleStrikethrough' => true)); +$textrun->addText(htmlspecialchars(', ')); +$textrun->addText(htmlspecialchars('superScript'), array('superScript' => true)); +$textrun->addText(htmlspecialchars(', ')); +$textrun->addText(htmlspecialchars('subScript'), array('subScript' => true)); +$textrun->addText(htmlspecialchars(', ')); +$textrun->addText(htmlspecialchars('smallCaps'), array('smallCaps' => true)); +$textrun->addText(htmlspecialchars(', ')); +$textrun->addText(htmlspecialchars('allCaps'), array('allCaps' => true)); +$textrun->addText(htmlspecialchars(', ')); +$textrun->addText(htmlspecialchars('fgColor'), array('fgColor' => 'yellow')); +$textrun->addText(htmlspecialchars(', ')); +$textrun->addText(htmlspecialchars('scale'), array('scale' => 200)); +$textrun->addText(htmlspecialchars(', ')); +$textrun->addText(htmlspecialchars('spacing'), array('spacing' => 120)); +$textrun->addText(htmlspecialchars(', ')); +$textrun->addText(htmlspecialchars('kerning'), array('kerning' => 10)); +$textrun->addText(htmlspecialchars('. ')); // Link -$section->addLink('http://www.google.com', 'Google'); +$section->addLink('http://www.google.com', htmlspecialchars('Google')); $section->addTextBreak(); // Image diff --git a/samples/Sample_02_TabStops.php b/samples/Sample_02_TabStops.php index d6e4cdbc..46d91cec 100644 --- a/samples/Sample_02_TabStops.php +++ b/samples/Sample_02_TabStops.php @@ -2,35 +2,36 @@ include_once 'Sample_Header.php'; // New Word Document -echo date('H:i:s') , ' Create new PhpWord object' , EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); // Ads styles -$phpWord->addParagraphStyle('multipleTab', array( - 'tabs' => array( - new \PhpOffice\PhpWord\Style\Tab('left', 1550), - new \PhpOffice\PhpWord\Style\Tab('center', 3200), - new \PhpOffice\PhpWord\Style\Tab('right', 5300) - ) -)); -$phpWord->addParagraphStyle('rightTab', array( - 'tabs' => array( - new \PhpOffice\PhpWord\Style\Tab('right', 9090) - ) -)); -$phpWord->addParagraphStyle('centerTab', array( - 'tabs' => array( - new \PhpOffice\PhpWord\Style\Tab('center', 4680) - ) -)); +$phpWord->addParagraphStyle( + 'multipleTab', + array( + 'tabs' => array( + new \PhpOffice\PhpWord\Style\Tab('left', 1550), + new \PhpOffice\PhpWord\Style\Tab('center', 3200), + new \PhpOffice\PhpWord\Style\Tab('right', 5300), + ) + ) +); +$phpWord->addParagraphStyle( + 'rightTab', + array('tabs' => array(new \PhpOffice\PhpWord\Style\Tab('right', 9090))) +); +$phpWord->addParagraphStyle( + 'centerTab', + array('tabs' => array(new \PhpOffice\PhpWord\Style\Tab('center', 4680))) +); // New portrait section $section = $phpWord->addSection(); // Add listitem elements -$section->addText("Multiple Tabs:\tOne\tTwo\tThree", null, 'multipleTab'); -$section->addText("Left Aligned\tRight Aligned", null, 'rightTab'); -$section->addText("\tCenter Aligned", null, 'centerTab'); +$section->addText(htmlspecialchars("Multiple Tabs:\tOne\tTwo\tThree"), null, 'multipleTab'); +$section->addText(htmlspecialchars("Left Aligned\tRight Aligned"), null, 'rightTab'); +$section->addText(htmlspecialchars("\tCenter Aligned"), null, 'centerTab'); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_03_Sections.php b/samples/Sample_03_Sections.php index bfbc84af..a95b15d6 100644 --- a/samples/Sample_03_Sections.php +++ b/samples/Sample_03_Sections.php @@ -2,28 +2,43 @@ include_once 'Sample_Header.php'; // New Word Document -echo date('H:i:s') , ' Create new PhpWord object' , EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); // New portrait section $section = $phpWord->addSection(array('borderColor' => '00FF00', 'borderSize' => 12)); -$section->addText('I am placed on a default section.'); +$section->addText(htmlspecialchars('I am placed on a default section.')); // New landscape section $section = $phpWord->addSection(array('orientation' => 'landscape')); -$section->addText('I am placed on a landscape section. Every page starting from this section will be landscape style.'); +$section->addText( + htmlspecialchars( + 'I am placed on a landscape section. Every page starting from this section will be landscape style.' + ) +); $section->addPageBreak(); $section->addPageBreak(); // New portrait section -$section = $phpWord->addSection(array('marginLeft' => 600, 'marginRight' => 600, 'marginTop' => 600, 'marginBottom' => 600)); -$section->addText('This section uses other margins.'); +$section = $phpWord->addSection( + array('paperSize' => 'Folio', 'marginLeft' => 600, 'marginRight' => 600, 'marginTop' => 600, 'marginBottom' => 600) +); +$section->addText(htmlspecialchars('This section uses other margins with folio papersize.')); // New portrait section with Header & Footer -$section = $phpWord->addSection(array('marginLeft' => 200, 'marginRight' => 200, 'marginTop' => 200, 'marginBottom' => 200, 'headerHeight' => 50, 'footerHeight' => 50,)); -$section->addText('This section and we play with header/footer height.'); -$section->addHeader()->addText('Header'); -$section->addFooter()->addText('Footer'); +$section = $phpWord->addSection( + array( + 'marginLeft' => 200, + 'marginRight' => 200, + 'marginTop' => 200, + 'marginBottom' => 200, + 'headerHeight' => 50, + 'footerHeight' => 50, + ) +); +$section->addText(htmlspecialchars('This section and we play with header/footer height.')); +$section->addHeader()->addText(htmlspecialchars('Header')); +$section->addFooter()->addText(htmlspecialchars('Footer')); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_04_Textrun.php b/samples/Sample_04_Textrun.php index e41f4ddb..7ebf6e33 100644 --- a/samples/Sample_04_Textrun.php +++ b/samples/Sample_04_Textrun.php @@ -2,14 +2,17 @@ include_once 'Sample_Header.php'; // New Word Document -echo date('H:i:s') , ' Create new PhpWord object' , EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); // Ads styles -$phpWord->addParagraphStyle('pStyle', array('spacing'=>100)); -$phpWord->addFontStyle('BoldText', array('bold'=>true)); -$phpWord->addFontStyle('ColoredText', array('color'=>'FF8080', 'bgColor' => 'FFFFCC')); -$phpWord->addLinkStyle('NLink', array('color'=>'0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE)); +$phpWord->addParagraphStyle('pStyle', array('spacing' => 100)); +$phpWord->addFontStyle('BoldText', array('bold' => true)); +$phpWord->addFontStyle('ColoredText', array('color' => 'FF8080', 'bgColor' => 'FFFFCC')); +$phpWord->addLinkStyle( + 'NLink', + array('color' => '0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE) +); // New portrait section $section = $phpWord->addSection(); @@ -17,21 +20,24 @@ $section = $phpWord->addSection(); // Add text run $textrun = $section->addTextRun('pStyle'); -$textrun->addText('Each textrun can contain native text, link elements or an image.'); -$textrun->addText(' No break is placed after adding an element.', 'BoldText'); -$textrun->addText(' Both '); -$textrun->addText('superscript', array('superScript' => true)); -$textrun->addText(' and '); -$textrun->addText('subscript', array('subScript' => true)); -$textrun->addText(' are also available.'); -$textrun->addText(' All elements are placed inside a paragraph with the optionally given p-Style.', 'ColoredText'); -$textrun->addText(' Sample Link: '); +$textrun->addText(htmlspecialchars('Each textrun can contain native text, link elements or an image.')); +$textrun->addText(htmlspecialchars(' No break is placed after adding an element.'), 'BoldText'); +$textrun->addText(htmlspecialchars(' Both ')); +$textrun->addText(htmlspecialchars('superscript'), array('superScript' => true)); +$textrun->addText(htmlspecialchars(' and ')); +$textrun->addText(htmlspecialchars('subscript'), array('subScript' => true)); +$textrun->addText(htmlspecialchars(' are also available.')); +$textrun->addText( + htmlspecialchars(' All elements are placed inside a paragraph with the optionally given p-Style.'), + 'ColoredText' +); +$textrun->addText(htmlspecialchars(' Sample Link: ')); $textrun->addLink('http://www.google.com', null, 'NLink'); -$textrun->addText(' Sample Image: '); +$textrun->addText(htmlspecialchars(' Sample Image: ')); $textrun->addImage('resources/_earth.jpg', array('width' => 18, 'height' => 18)); -$textrun->addText(' Sample Object: '); +$textrun->addText(htmlspecialchars(' Sample Object: ')); $textrun->addObject('resources/_sheet.xls'); -$textrun->addText(' Here is some more text. '); +$textrun->addText(htmlspecialchars(' Here is some more text. ')); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_05_Multicolumn.php b/samples/Sample_05_Multicolumn.php index f4737060..b93ab344 100644 --- a/samples/Sample_05_Multicolumn.php +++ b/samples/Sample_05_Multicolumn.php @@ -2,38 +2,44 @@ include_once 'Sample_Header.php'; // New Word Document -echo date('H:i:s') , " Create new PhpWord object" , EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); -$filler = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. ' . - 'Nulla fermentum, tortor id adipiscing adipiscing, tortor turpis commodo. ' . - 'Donec vulputate iaculis metus, vel luctus dolor hendrerit ac. ' . - 'Suspendisse congue congue leo sed pellentesque.'; +$filler = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. ' + . 'Nulla fermentum, tortor id adipiscing adipiscing, tortor turpis commodo. ' + . 'Donec vulputate iaculis metus, vel luctus dolor hendrerit ac. ' + . 'Suspendisse congue congue leo sed pellentesque.'; // Normal $section = $phpWord->addSection(); -$section->addText('Normal paragraph. ' . $filler); +$section->addText(htmlspecialchars("Normal paragraph. {$filler}")); // Two columns -$section = $phpWord->addSection(array( - 'colsNum' => 2, - 'colsSpace' => 1440, - 'breakType' => 'continuous')); -$section->addText('Two columns, one inch (1440 twips) spacing. ' . $filler); +$section = $phpWord->addSection( + array( + 'colsNum' => 2, + 'colsSpace' => 1440, + 'breakType' => 'continuous', + ) +); +$section->addText(htmlspecialchars("Two columns, one inch (1440 twips) spacing. {$filler}")); // Normal $section = $phpWord->addSection(array('breakType' => 'continuous')); -$section->addText('Normal paragraph again. ' . $filler); +$section->addText(htmlspecialchars("Normal paragraph again. {$filler}")); // Three columns -$section = $phpWord->addSection(array( - 'colsNum' => 3, - 'colsSpace' => 720, - 'breakType' => 'continuous')); -$section->addText('Three columns, half inch (720 twips) spacing. ' . $filler); +$section = $phpWord->addSection( + array( + 'colsNum' => 3, + 'colsSpace' => 720, + 'breakType' => 'continuous', + ) +); +$section->addText(htmlspecialchars("Three columns, half inch (720 twips) spacing. {$filler}")); // Normal $section = $phpWord->addSection(array('breakType' => 'continuous')); -$section->addText('Normal paragraph again.'); +$section->addText(htmlspecialchars('Normal paragraph again.')); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_06_Footnote.php b/samples/Sample_06_Footnote.php index 1bec44e4..c7f3d8c0 100644 --- a/samples/Sample_06_Footnote.php +++ b/samples/Sample_06_Footnote.php @@ -2,7 +2,7 @@ include_once 'Sample_Header.php'; // New Word Document -echo date('H:i:s') , " Create new PhpWord object" , EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); \PhpOffice\PhpWord\Settings::setCompatibility(false); @@ -10,32 +10,40 @@ $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); // Add style definitions -$phpWord->addParagraphStyle('pStyle', array('spacing'=>100)); -$phpWord->addFontStyle('BoldText', array('bold'=>true)); -$phpWord->addFontStyle('ColoredText', array('color'=>'FF8080')); -$phpWord->addLinkStyle('NLink', array('color'=>'0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE)); +$phpWord->addParagraphStyle('pStyle', array('spacing' => 100)); +$phpWord->addFontStyle('BoldText', array('bold' => true)); +$phpWord->addFontStyle('ColoredText', array('color' => 'FF8080')); +$phpWord->addLinkStyle( + 'NLink', + array('color' => '0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE) +); // Add text elements $textrun = $section->addTextRun('pStyle'); -$textrun->addText('This is some lead text in a paragraph with a following footnote. ','pStyle'); +$textrun->addText(htmlspecialchars('This is some lead text in a paragraph with a following footnote. '), 'pStyle'); $footnote = $textrun->addFootnote(); -$footnote->addText('Just like a textrun, a footnote can contain native texts. '); -$footnote->addText('No break is placed after adding an element. ', 'BoldText'); -$footnote->addText('All elements are placed inside a paragraph. ', 'ColoredText'); +$footnote->addText(htmlspecialchars('Just like a textrun, a footnote can contain native texts. ')); +$footnote->addText(htmlspecialchars('No break is placed after adding an element. '), 'BoldText'); +$footnote->addText(htmlspecialchars('All elements are placed inside a paragraph. '), 'ColoredText'); $footnote->addTextBreak(); -$footnote->addText('But you can insert a manual text break like above, '); -$footnote->addText('links like '); +$footnote->addText(htmlspecialchars('But you can insert a manual text break like above, ')); +$footnote->addText(htmlspecialchars('links like ')); $footnote->addLink('http://www.google.com', null, 'NLink'); -$footnote->addText(', image like '); +$footnote->addText(htmlspecialchars(', image like ')); $footnote->addImage('resources/_earth.jpg', array('width' => 18, 'height' => 18)); -$footnote->addText(', or object like '); +$footnote->addText(htmlspecialchars(', or object like ')); $footnote->addObject('resources/_sheet.xls'); -$footnote->addText('But you can only put footnote in section, not in header or footer.'); +$footnote->addText(htmlspecialchars('But you can only put footnote in section, not in header or footer.')); -$section->addText('You can also create the footnote directly from the section making it wrap in a paragraph like the footnote below this paragraph. But is is best used from within a textrun.'); +$section->addText( + htmlspecialchars( + 'You can also create the footnote directly from the section making it wrap in a paragraph ' + . 'like the footnote below this paragraph. But is is best used from within a textrun.' + ) +); $footnote = $section->addFootnote(); -$footnote->addText('The reference for this is wrapped in its own line'); +$footnote->addText(htmlspecialchars('The reference for this is wrapped in its own line')); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_07_TemplateCloneRow.php b/samples/Sample_07_TemplateCloneRow.php index 899bc82b..60edacb5 100644 --- a/samples/Sample_07_TemplateCloneRow.php +++ b/samples/Sample_07_TemplateCloneRow.php @@ -1,64 +1,60 @@ loadTemplate('resources/Sample_07_TemplateCloneRow.docx'); +// Template processor instance creation +echo date('H:i:s'), ' Creating new TemplateProcessor instance...', EOL; +$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('resources/Sample_07_TemplateCloneRow.docx'); // Variables on different parts of document -$document->setValue('weekday', date('l')); // On section/content -$document->setValue('time', date('H:i')); // On footer -$document->setValue('serverName', realpath(__DIR__)); // On header +$templateProcessor->setValue('weekday', htmlspecialchars(date('l'))); // On section/content +$templateProcessor->setValue('time', htmlspecialchars(date('H:i'))); // On footer +$templateProcessor->setValue('serverName', htmlspecialchars(realpath(__DIR__))); // On header // Simple table -$document->cloneRow('rowValue', 10); +$templateProcessor->cloneRow('rowValue', 10); -$document->setValue('rowValue#1', 'Sun'); -$document->setValue('rowValue#2', 'Mercury'); -$document->setValue('rowValue#3', 'Venus'); -$document->setValue('rowValue#4', 'Earth'); -$document->setValue('rowValue#5', 'Mars'); -$document->setValue('rowValue#6', 'Jupiter'); -$document->setValue('rowValue#7', 'Saturn'); -$document->setValue('rowValue#8', 'Uranus'); -$document->setValue('rowValue#9', 'Neptun'); -$document->setValue('rowValue#10', 'Pluto'); +$templateProcessor->setValue('rowValue#1', htmlspecialchars('Sun')); +$templateProcessor->setValue('rowValue#2', htmlspecialchars('Mercury')); +$templateProcessor->setValue('rowValue#3', htmlspecialchars('Venus')); +$templateProcessor->setValue('rowValue#4', htmlspecialchars('Earth')); +$templateProcessor->setValue('rowValue#5', htmlspecialchars('Mars')); +$templateProcessor->setValue('rowValue#6', htmlspecialchars('Jupiter')); +$templateProcessor->setValue('rowValue#7', htmlspecialchars('Saturn')); +$templateProcessor->setValue('rowValue#8', htmlspecialchars('Uranus')); +$templateProcessor->setValue('rowValue#9', htmlspecialchars('Neptun')); +$templateProcessor->setValue('rowValue#10', htmlspecialchars('Pluto')); -$document->setValue('rowNumber#1', '1'); -$document->setValue('rowNumber#2', '2'); -$document->setValue('rowNumber#3', '3'); -$document->setValue('rowNumber#4', '4'); -$document->setValue('rowNumber#5', '5'); -$document->setValue('rowNumber#6', '6'); -$document->setValue('rowNumber#7', '7'); -$document->setValue('rowNumber#8', '8'); -$document->setValue('rowNumber#9', '9'); -$document->setValue('rowNumber#10', '10'); +$templateProcessor->setValue('rowNumber#1', htmlspecialchars('1')); +$templateProcessor->setValue('rowNumber#2', htmlspecialchars('2')); +$templateProcessor->setValue('rowNumber#3', htmlspecialchars('3')); +$templateProcessor->setValue('rowNumber#4', htmlspecialchars('4')); +$templateProcessor->setValue('rowNumber#5', htmlspecialchars('5')); +$templateProcessor->setValue('rowNumber#6', htmlspecialchars('6')); +$templateProcessor->setValue('rowNumber#7', htmlspecialchars('7')); +$templateProcessor->setValue('rowNumber#8', htmlspecialchars('8')); +$templateProcessor->setValue('rowNumber#9', htmlspecialchars('9')); +$templateProcessor->setValue('rowNumber#10', htmlspecialchars('10')); // Table with a spanned cell -$document->cloneRow('userId', 3); +$templateProcessor->cloneRow('userId', 3); -$document->setValue('userId#1', '1'); -$document->setValue('userFirstName#1', 'James'); -$document->setValue('userName#1', 'Taylor'); -$document->setValue('userPhone#1', '+1 428 889 773'); +$templateProcessor->setValue('userId#1', htmlspecialchars('1')); +$templateProcessor->setValue('userFirstName#1', htmlspecialchars('James')); +$templateProcessor->setValue('userName#1', htmlspecialchars('Taylor')); +$templateProcessor->setValue('userPhone#1', htmlspecialchars('+1 428 889 773')); -$document->setValue('userId#2', '2'); -$document->setValue('userFirstName#2', 'Robert'); -$document->setValue('userName#2', 'Bell'); -$document->setValue('userPhone#2', '+1 428 889 774'); +$templateProcessor->setValue('userId#2', htmlspecialchars('2')); +$templateProcessor->setValue('userFirstName#2', htmlspecialchars('Robert')); +$templateProcessor->setValue('userName#2', htmlspecialchars('Bell')); +$templateProcessor->setValue('userPhone#2', htmlspecialchars('+1 428 889 774')); -$document->setValue('userId#3', '3'); -$document->setValue('userFirstName#3', 'Michael'); -$document->setValue('userName#3', 'Ray'); -$document->setValue('userPhone#3', '+1 428 889 775'); +$templateProcessor->setValue('userId#3', htmlspecialchars('3')); +$templateProcessor->setValue('userFirstName#3', htmlspecialchars('Michael')); +$templateProcessor->setValue('userName#3', htmlspecialchars('Ray')); +$templateProcessor->setValue('userPhone#3', htmlspecialchars('+1 428 889 775')); -$name = 'Sample_07_TemplateCloneRow.docx'; -echo date('H:i:s'), " Write to Word2007 format", EOL; -$document->saveAs($name); -rename($name, "results/{$name}"); +echo date('H:i:s'), ' Saving the result document...', EOL; +$templateProcessor->saveAs('results/Sample_07_TemplateCloneRow.docx'); echo getEndingNotes(array('Word2007' => 'docx')); if (!CLI) { diff --git a/samples/Sample_08_ParagraphPagination.php b/samples/Sample_08_ParagraphPagination.php index d3f0c1fb..dd364562 100644 --- a/samples/Sample_08_ParagraphPagination.php +++ b/samples/Sample_08_ParagraphPagination.php @@ -2,48 +2,75 @@ include_once 'Sample_Header.php'; // New Word document -echo date('H:i:s') , " Create new PhpWord object" , EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); -$phpWord->setDefaultParagraphStyle(array( - 'align' => 'both', - 'spaceAfter' => \PhpOffice\PhpWord\Shared\Font::pointSizeToTwips(12), - 'spacing' => 120, -)); +$phpWord->setDefaultParagraphStyle( + array( + 'align' => 'both', + 'spaceAfter' => \PhpOffice\PhpWord\Shared\Converter::pointToTwip(12), + 'spacing' => 120, + ) +); // Sample $section = $phpWord->addSection(); -$section->addText('Below are the samples on how to control your paragraph ' . - 'pagination. See "Line and Page Break" tab on paragraph properties ' . - 'window to see the attribute set by these controls.', - array('bold' => true), array('space' => array('before' => 360, 'after' => 480))); +$section->addText( + htmlspecialchars( + 'Below are the samples on how to control your paragraph ' + . 'pagination. See "Line and Page Break" tab on paragraph properties ' + . 'window to see the attribute set by these controls.' + ), + array('bold' => true), + array('space' => array('before' => 360, 'after' => 480)) +); -$section->addText('Paragraph with widowControl = false (default: true). ' . - 'A "widow" is the last line of a paragraph printed by itself at the top ' . - 'of a page. An "orphan" is the first line of a paragraph printed by ' . - 'itself at the bottom of a page. Set this option to "false" if you want ' . - 'to disable this automatic control.', - null, array('widowControl' => false, 'indentation' => array('left' => 240, 'right' => 120))); +$section->addText( + htmlspecialchars( + 'Paragraph with widowControl = false (default: true). ' + . 'A "widow" is the last line of a paragraph printed by itself at the top ' + . 'of a page. An "orphan" is the first line of a paragraph printed by ' + . 'itself at the bottom of a page. Set this option to "false" if you want ' + . 'to disable this automatic control.' + ), + null, + array('widowControl' => false, 'indentation' => array('left' => 240, 'right' => 120)) +); -$section->addText('Paragraph with keepNext = true (default: false). ' . - '"Keep with next" is used to prevent Word from inserting automatic page ' . - 'breaks between paragraphs. Set this option to "true" if you do not want ' . - 'your paragraph to be separated with the next paragraph.', - null, array('keepNext' => true, 'indentation' => array('firstLine' => 240))); +$section->addText( + htmlspecialchars( + 'Paragraph with keepNext = true (default: false). ' + . '"Keep with next" is used to prevent Word from inserting automatic page ' + . 'breaks between paragraphs. Set this option to "true" if you do not want ' + . 'your paragraph to be separated with the next paragraph.' + ), + null, + array('keepNext' => true, 'indentation' => array('firstLine' => 240)) +); -$section->addText('Paragraph with keepLines = true (default: false). ' . - '"Keep lines together" will prevent Word from inserting an automatic page ' . - 'break within a paragraph. Set this option to "true" if you do not want ' . - 'all lines of your paragraph to be in the same page.', - null, array('keepLines' => true, 'indentation' => array('left' => 240, 'hanging' => 240))); +$section->addText( + htmlspecialchars( + 'Paragraph with keepLines = true (default: false). ' + . '"Keep lines together" will prevent Word from inserting an automatic page ' + . 'break within a paragraph. Set this option to "true" if you do not want ' + . 'all lines of your paragraph to be in the same page.' + ), + null, + array('keepLines' => true, 'indentation' => array('left' => 240, 'hanging' => 240)) +); -$section->addText('Keep scrolling. More below.'); +$section->addText(htmlspecialchars('Keep scrolling. More below.')); -$section->addText('Paragraph with pageBreakBefore = true (default: false). ' . - 'Different with all other control above, "page break before" separates ' . - 'your paragraph into the next page. This option is most useful for ' . - 'heading styles.', - null, array('pageBreakBefore' => true)); +$section->addText( + htmlspecialchars( + 'Paragraph with pageBreakBefore = true (default: false). ' + . 'Different with all other control above, "page break before" separates ' + . 'your paragraph into the next page. This option is most useful for ' + . 'heading styles.' + ), + null, + array('pageBreakBefore' => true) +); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_09_Tables.php b/samples/Sample_09_Tables.php index 882653bc..5c305c83 100644 --- a/samples/Sample_09_Tables.php +++ b/samples/Sample_09_Tables.php @@ -2,7 +2,7 @@ include_once 'Sample_Header.php'; // New Word Document -echo date('H:i:s') , ' Create new PhpWord object' , EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); $header = array('size' => 16, 'bold' => true); @@ -11,20 +11,20 @@ $header = array('size' => 16, 'bold' => true); $rows = 10; $cols = 5; -$section->addText("Basic table", $header); +$section->addText(htmlspecialchars('Basic table'), $header); $table = $section->addTable(); -for($r = 1; $r <= 8; $r++) { +for ($r = 1; $r <= 8; $r++) { $table->addRow(); - for($c = 1; $c <= 5; $c++) { - $table->addCell(1750)->addText("Row $r, Cell $c"); + for ($c = 1; $c <= 5; $c++) { + $table->addCell(1750)->addText(htmlspecialchars("Row {$r}, Cell {$c}")); } } // 2. Advanced table $section->addTextBreak(1); -$section->addText("Fancy table", $header); +$section->addText(htmlspecialchars('Fancy table'), $header); $styleTable = array('borderSize' => 6, 'borderColor' => '006699', 'cellMargin' => 80); $styleFirstRow = array('borderBottomSize' => 18, 'borderBottomColor' => '0000FF', 'bgColor' => '66BBFF'); @@ -34,25 +34,25 @@ $fontStyle = array('bold' => true, 'align' => 'center'); $phpWord->addTableStyle('Fancy Table', $styleTable, $styleFirstRow); $table = $section->addTable('Fancy Table'); $table->addRow(900); -$table->addCell(2000, $styleCell)->addText('Row 1', $fontStyle); -$table->addCell(2000, $styleCell)->addText('Row 2', $fontStyle); -$table->addCell(2000, $styleCell)->addText('Row 3', $fontStyle); -$table->addCell(2000, $styleCell)->addText('Row 4', $fontStyle); -$table->addCell(500, $styleCellBTLR)->addText('Row 5', $fontStyle); -for($i = 1; $i <= 8; $i++) { +$table->addCell(2000, $styleCell)->addText(htmlspecialchars('Row 1'), $fontStyle); +$table->addCell(2000, $styleCell)->addText(htmlspecialchars('Row 2'), $fontStyle); +$table->addCell(2000, $styleCell)->addText(htmlspecialchars('Row 3'), $fontStyle); +$table->addCell(2000, $styleCell)->addText(htmlspecialchars('Row 4'), $fontStyle); +$table->addCell(500, $styleCellBTLR)->addText(htmlspecialchars('Row 5'), $fontStyle); +for ($i = 1; $i <= 8; $i++) { $table->addRow(); - $table->addCell(2000)->addText("Cell $i"); - $table->addCell(2000)->addText("Cell $i"); - $table->addCell(2000)->addText("Cell $i"); - $table->addCell(2000)->addText("Cell $i"); - $text = ($i % 2 == 0) ? 'X' : ''; - $table->addCell(500)->addText($text); + $table->addCell(2000)->addText(htmlspecialchars("Cell {$i}")); + $table->addCell(2000)->addText(htmlspecialchars("Cell {$i}")); + $table->addCell(2000)->addText(htmlspecialchars("Cell {$i}")); + $table->addCell(2000)->addText(htmlspecialchars("Cell {$i}")); + $text = (0== $i % 2) ? 'X' : ''; + $table->addCell(500)->addText(htmlspecialchars($text)); } // 3. colspan (gridSpan) and rowspan (vMerge) $section->addPageBreak(); -$section->addText("Table with colspan and rowspan", $header); +$section->addText(htmlspecialchars('Table with colspan and rowspan'), $header); $styleTable = array('borderSize' => 6, 'borderColor' => '999999'); $cellRowSpan = array('vMerge' => 'restart', 'valign' => 'center', 'bgColor' => 'FFFF00'); @@ -68,32 +68,32 @@ $table->addRow(); $cell1 = $table->addCell(2000, $cellRowSpan); $textrun1 = $cell1->addTextRun($cellHCentered); -$textrun1->addText('A'); -$textrun1->addFootnote()->addText('Row span'); +$textrun1->addText(htmlspecialchars('A')); +$textrun1->addFootnote()->addText(htmlspecialchars('Row span')); $cell2 = $table->addCell(4000, $cellColSpan); $textrun2 = $cell2->addTextRun($cellHCentered); -$textrun2->addText('B'); -$textrun2->addFootnote()->addText('Colspan span'); +$textrun2->addText(htmlspecialchars('B')); +$textrun2->addFootnote()->addText(htmlspecialchars('Colspan span')); -$table->addCell(2000, $cellRowSpan)->addText('E', null, $cellHCentered); +$table->addCell(2000, $cellRowSpan)->addText(htmlspecialchars('E'), null, $cellHCentered); $table->addRow(); $table->addCell(null, $cellRowContinue); -$table->addCell(2000, $cellVCentered)->addText('C', null, $cellHCentered); -$table->addCell(2000, $cellVCentered)->addText('D', null, $cellHCentered); +$table->addCell(2000, $cellVCentered)->addText(htmlspecialchars('C'), null, $cellHCentered); +$table->addCell(2000, $cellVCentered)->addText(htmlspecialchars('D'), null, $cellHCentered); $table->addCell(null, $cellRowContinue); // 4. Nested table $section->addTextBreak(2); -$section->addText('Nested table in a centered and 50% width table.', $header); +$section->addText(htmlspecialchars('Nested table in a centered and 50% width table.'), $header); $table = $section->addTable(array('width' => 50 * 50, 'unit' => 'pct', 'align' => 'center')); $cell = $table->addRow()->addCell(); -$cell->addText('This cell contains nested table.'); +$cell->addText(htmlspecialchars('This cell contains nested table.')); $innerCell = $cell->addTable(array('align' => 'center'))->addRow()->addCell(); -$innerCell->addText('Inside nested table'); +$innerCell->addText(htmlspecialchars('Inside nested table')); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_10_EastAsianFontStyle.php b/samples/Sample_10_EastAsianFontStyle.php index 44bca8a6..f3553bfe 100644 --- a/samples/Sample_10_EastAsianFontStyle.php +++ b/samples/Sample_10_EastAsianFontStyle.php @@ -2,12 +2,12 @@ include_once 'Sample_Header.php'; // New Word Document -echo date('H:i:s') , ' Create new PhpWord object' , EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); $header = array('size' => 16, 'bold' => true); //1.Use EastAisa FontStyle -$section->addText('中文楷体样式测试',array('name' => '楷体', 'size' => 16, 'color' => '1B2232')); +$section->addText(htmlspecialchars('中文楷体样式测试'), array('name' => '楷体', 'size' => 16, 'color' => '1B2232')); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_11_ReadWord97.php b/samples/Sample_11_ReadWord97.php new file mode 100644 index 00000000..68a30d36 --- /dev/null +++ b/samples/Sample_11_ReadWord97.php @@ -0,0 +1,19 @@ + 'docx', 'ODText' => 'odt', 'RTF' => 'rtf'); +foreach ($writers as $writer => $extension) { + echo date('H:i:s'), " Write to {$writer} format", EOL; + $xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $writer); + $xmlWriter->save("{$name}.{$extension}"); + rename("{$name}.{$extension}", "results/{$name}.{$extension}"); +} + +include_once 'Sample_Footer.php'; diff --git a/samples/Sample_12_HeaderFooter.php b/samples/Sample_12_HeaderFooter.php index 0fd56edc..dc4fc129 100644 --- a/samples/Sample_12_HeaderFooter.php +++ b/samples/Sample_12_HeaderFooter.php @@ -2,7 +2,7 @@ include_once 'Sample_Header.php'; // New Word document -echo date('H:i:s') , " Create new PhpWord object" , EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); // New portrait section @@ -15,8 +15,8 @@ $table = $header->addTable(); $table->addRow(); $cell = $table->addCell(4500); $textrun = $cell->addTextRun(); -$textrun->addText('This is the header with '); -$textrun->addLink('http://google.com', 'link to Google'); +$textrun->addText(htmlspecialchars('This is the header with ')); +$textrun->addLink('http://google.com', htmlspecialchars('link to Google')); $table->addCell(4500)->addImage( 'resources/PhpWord.png', array('width' => 80, 'height' => 80, 'align' => 'right') @@ -24,41 +24,41 @@ $table->addCell(4500)->addImage( // Add header for all other pages $subsequent = $section->addHeader(); -$subsequent->addText("Subsequent pages in Section 1 will Have this!"); +$subsequent->addText(htmlspecialchars('Subsequent pages in Section 1 will Have this!')); $subsequent->addImage('resources/_mars.jpg', array('width' => 80, 'height' => 80)); // Add footer $footer = $section->addFooter(); -$footer->addPreserveText('Page {PAGE} of {NUMPAGES}.', array('align' => 'center')); -$footer->addLink('http://google.com', 'Direct Google'); +$footer->addPreserveText(htmlspecialchars('Page {PAGE} of {NUMPAGES}.'), array('align' => 'center')); +$footer->addLink('http://google.com', htmlspecialchars('Direct Google')); // Write some text $section->addTextBreak(); -$section->addText('Some text...'); +$section->addText(htmlspecialchars('Some text...')); // Create a second page $section->addPageBreak(); // Write some text $section->addTextBreak(); -$section->addText('Some text...'); +$section->addText(htmlspecialchars('Some text...')); // Create a third page $section->addPageBreak(); // Write some text $section->addTextBreak(); -$section->addText('Some text...'); +$section->addText(htmlspecialchars('Some text...')); // New portrait section $section2 = $phpWord->addSection(); $sec2Header = $section2->addHeader(); -$sec2Header->addText("All pages in Section 2 will Have this!"); +$sec2Header->addText(htmlspecialchars('All pages in Section 2 will Have this!')); // Write some text $section2->addTextBreak(); -$section2->addText('Some text...'); +$section2->addText(htmlspecialchars('Some text...')); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_13_Images.php b/samples/Sample_13_Images.php index dd0c8801..d1391211 100644 --- a/samples/Sample_13_Images.php +++ b/samples/Sample_13_Images.php @@ -2,22 +2,22 @@ include_once 'Sample_Header.php'; // New Word document -echo date('H:i:s'), " Create new PhpWord object", EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); // Begin code $section = $phpWord->addSection(); -$section->addText('Local image without any styles:'); +$section->addText(htmlspecialchars('Local image without any styles:')); $section->addImage('resources/_mars.jpg'); $section->addTextBreak(2); -$section->addText('Local image with styles:'); +$section->addText(htmlspecialchars('Local image with styles:')); $section->addImage('resources/_earth.jpg', array('width' => 210, 'height' => 210, 'align' => 'center')); $section->addTextBreak(2); // Remote image $source = 'http://php.net/images/logos/php-med-trans-light.gif'; -$section->addText("Remote image from: {$source}"); +$section->addText(htmlspecialchars("Remote image from: {$source}")); $section->addImage($source); //Wrapping style @@ -25,43 +25,52 @@ $text = str_repeat('Hello World! ', 15); $wrappingStyles = array('inline', 'behind', 'infront', 'square', 'tight'); foreach ($wrappingStyles as $wrappingStyle) { $section->addTextBreak(5); - $section->addText('Wrapping style ' . $wrappingStyle); - $section->addImage('resources/_earth.jpg', array('positioning' => 'relative', 'marginTop' => -1, 'marginLeft' => 1, - 'width' => 80, 'height' => 80, 'wrappingStyle' => $wrappingStyle)); - $section->addText($text); + $section->addText(htmlspecialchars("Wrapping style {$wrappingStyle}")); + $section->addImage( + 'resources/_earth.jpg', + array( + 'positioning' => 'relative', + 'marginTop' => -1, + 'marginLeft' => 1, + 'width' => 80, + 'height' => 80, + 'wrappingStyle' => $wrappingStyle, + ) + ); + $section->addText(htmlspecialchars($text)); } //Absolute positioning $section->addTextBreak(3); -$section->addText('Absolute positioning: see top right corner of page'); +$section->addText(htmlspecialchars('Absolute positioning: see top right corner of page')); $section->addImage( 'resources/_mars.jpg', array( - 'width' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(3), - 'height' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(3), - 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_ABSOLUTE, - 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_RIGHT, + 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), + 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), + 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_ABSOLUTE, + 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_RIGHT, 'posHorizontalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_PAGE, - 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_PAGE, - 'marginLeft' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(15.5), - 'marginTop' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(1.55) + 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_PAGE, + 'marginLeft' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(15.5), + 'marginTop' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(1.55), ) ); //Relative positioning $section->addTextBreak(3); -$section->addText('Relative positioning: Horizontal position center relative to column,'); -$section->addText('Vertical position top relative to line'); +$section->addText(htmlspecialchars('Relative positioning: Horizontal position center relative to column,')); +$section->addText(htmlspecialchars('Vertical position top relative to line')); $section->addImage( 'resources/_mars.jpg', array( - 'width' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(3), - 'height' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(3), - 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE, - 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_CENTER, + 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), + 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), + 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE, + 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_CENTER, 'posHorizontalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_COLUMN, - 'posVertical' => \PhpOffice\PhpWord\Style\Image::POSITION_VERTICAL_TOP, - 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_LINE + 'posVertical' => \PhpOffice\PhpWord\Style\Image::POSITION_VERTICAL_TOP, + 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_LINE, ) ); diff --git a/samples/Sample_14_ListItem.php b/samples/Sample_14_ListItem.php index 3a3d34ab..3a29e3fd 100644 --- a/samples/Sample_14_ListItem.php +++ b/samples/Sample_14_ListItem.php @@ -2,7 +2,7 @@ include_once 'Sample_Header.php'; // New Word document -echo date('H:i:s'), " Create new PhpWord object", EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); // Begin code @@ -10,80 +10,83 @@ $section = $phpWord->addSection(); // Style definition -$phpWord->addFontStyle('myOwnStyle', array('color'=>'FF0000')); -$phpWord->addParagraphStyle('P-Style', array('spaceAfter'=>95)); +$phpWord->addFontStyle('myOwnStyle', array('color' => 'FF0000')); +$phpWord->addParagraphStyle('P-Style', array('spaceAfter' => 95)); $phpWord->addNumberingStyle( 'multilevel', - array('type' => 'multilevel', 'levels' => array( - array('format' => 'decimal', 'text' => '%1.', 'left' => 360, 'hanging' => 360, 'tabPos' => 360), - array('format' => 'upperLetter', 'text' => '%2.', 'left' => 720, 'hanging' => 360, 'tabPos' => 720), - ) + array( + 'type' => 'multilevel', + 'levels' => array( + array('format' => 'decimal', 'text' => '%1.', 'left' => 360, 'hanging' => 360, 'tabPos' => 360), + array('format' => 'upperLetter', 'text' => '%2.', 'left' => 720, 'hanging' => 360, 'tabPos' => 720), + ), ) ); $predefinedMultilevel = array('listType' => \PhpOffice\PhpWord\Style\ListItem::TYPE_NUMBER_NESTED); // Lists -$section->addText('Multilevel list.'); -$section->addListItem('List Item I', 0, null, 'multilevel'); -$section->addListItem('List Item I.a', 1, null, 'multilevel'); -$section->addListItem('List Item I.b', 1, null, 'multilevel'); -$section->addListItem('List Item II', 0, null, 'multilevel'); -$section->addListItem('List Item II.a', 1, null, 'multilevel'); -$section->addListItem('List Item III', 0, null, 'multilevel'); +$section->addText(htmlspecialchars('Multilevel list.')); +$section->addListItem(htmlspecialchars('List Item I'), 0, null, 'multilevel'); +$section->addListItem(htmlspecialchars('List Item I.a'), 1, null, 'multilevel'); +$section->addListItem(htmlspecialchars('List Item I.b'), 1, null, 'multilevel'); +$section->addListItem(htmlspecialchars('List Item II'), 0, null, 'multilevel'); +$section->addListItem(htmlspecialchars('List Item II.a'), 1, null, 'multilevel'); +$section->addListItem(htmlspecialchars('List Item III'), 0, null, 'multilevel'); $section->addTextBreak(2); -$section->addText('Basic simple bulleted list.'); -$section->addListItem('List Item 1'); -$section->addListItem('List Item 2'); -$section->addListItem('List Item 3'); +$section->addText(htmlspecialchars('Basic simple bulleted list.')); +$section->addListItem(htmlspecialchars('List Item 1')); +$section->addListItem(htmlspecialchars('List Item 2')); +$section->addListItem(htmlspecialchars('List Item 3')); $section->addTextBreak(2); -$section->addText('Continue from multilevel list above.'); -$section->addListItem('List Item IV', 0, null, 'multilevel'); -$section->addListItem('List Item IV.a', 1, null, 'multilevel'); +$section->addText(htmlspecialchars('Continue from multilevel list above.')); +$section->addListItem(htmlspecialchars('List Item IV'), 0, null, 'multilevel'); +$section->addListItem(htmlspecialchars('List Item IV.a'), 1, null, 'multilevel'); $section->addTextBreak(2); -$section->addText('Multilevel predefined list.'); -$section->addListItem('List Item 1', 0, 'myOwnStyle', $predefinedMultilevel, 'P-Style'); -$section->addListItem('List Item 2', 0, 'myOwnStyle', $predefinedMultilevel, 'P-Style'); -$section->addListItem('List Item 3', 1, 'myOwnStyle', $predefinedMultilevel, 'P-Style'); -$section->addListItem('List Item 4', 1, 'myOwnStyle', $predefinedMultilevel, 'P-Style'); -$section->addListItem('List Item 5', 2, 'myOwnStyle', $predefinedMultilevel, 'P-Style'); -$section->addListItem('List Item 6', 1, 'myOwnStyle', $predefinedMultilevel, 'P-Style'); -$section->addListItem('List Item 7', 0, 'myOwnStyle', $predefinedMultilevel, 'P-Style'); +$section->addText(htmlspecialchars('Multilevel predefined list.')); +$section->addListItem(htmlspecialchars('List Item 1'), 0, 'myOwnStyle', $predefinedMultilevel, 'P-Style'); +$section->addListItem(htmlspecialchars('List Item 2'), 0, 'myOwnStyle', $predefinedMultilevel, 'P-Style'); +$section->addListItem(htmlspecialchars('List Item 3'), 1, 'myOwnStyle', $predefinedMultilevel, 'P-Style'); +$section->addListItem(htmlspecialchars('List Item 4'), 1, 'myOwnStyle', $predefinedMultilevel, 'P-Style'); +$section->addListItem(htmlspecialchars('List Item 5'), 2, 'myOwnStyle', $predefinedMultilevel, 'P-Style'); +$section->addListItem(htmlspecialchars('List Item 6'), 1, 'myOwnStyle', $predefinedMultilevel, 'P-Style'); +$section->addListItem(htmlspecialchars('List Item 7'), 0, 'myOwnStyle', $predefinedMultilevel, 'P-Style'); $section->addTextBreak(2); -$section->addText('List with inline formatting.'); +$section->addText(htmlspecialchars('List with inline formatting.')); $listItemRun = $section->addListItemRun(); -$listItemRun->addText('List item 1'); -$listItemRun->addText(' in bold', array('bold'=>true)); +$listItemRun->addText(htmlspecialchars('List item 1')); +$listItemRun->addText(htmlspecialchars(' in bold'), array('bold' => true)); $listItemRun = $section->addListItemRun(); -$listItemRun->addText('List item 2'); -$listItemRun->addText(' in italic', array('italic'=>true)); +$listItemRun->addText(htmlspecialchars('List item 2')); +$listItemRun->addText(htmlspecialchars(' in italic'), array('italic' => true)); $listItemRun = $section->addListItemRun(); -$listItemRun->addText('List item 3'); -$listItemRun->addText(' underlined', array('underline'=>'dash')); +$listItemRun->addText(htmlspecialchars('List item 3')); +$listItemRun->addText(htmlspecialchars(' underlined'), array('underline' => 'dash')); $section->addTextBreak(2); // Numbered heading $phpWord->addNumberingStyle( 'headingNumbering', - array('type' => 'multilevel', 'levels' => array( - array('pStyle' => 'Heading1', 'format' => 'decimal', 'text' => '%1'), - array('pStyle' => 'Heading2', 'format' => 'decimal', 'text' => '%1.%2'), - array('pStyle' => 'Heading3', 'format' => 'decimal', 'text' => '%1.%2.%3'), - ) + array('type' => 'multilevel', + 'levels' => array( + array('pStyle' => 'Heading1', 'format' => 'decimal', 'text' => '%1'), + array('pStyle' => 'Heading2', 'format' => 'decimal', 'text' => '%1.%2'), + array('pStyle' => 'Heading3', 'format' => 'decimal', 'text' => '%1.%2.%3'), + ), ) ); $phpWord->addTitleStyle(1, array('size' => 16), array('numStyle' => 'headingNumbering', 'numLevel' => 0)); $phpWord->addTitleStyle(2, array('size' => 14), array('numStyle' => 'headingNumbering', 'numLevel' => 1)); $phpWord->addTitleStyle(3, array('size' => 12), array('numStyle' => 'headingNumbering', 'numLevel' => 2)); -$section->addTitle('Heading 1', 1); -$section->addTitle('Heading 2', 2); -$section->addTitle('Heading 3', 3); +$section->addTitle(htmlspecialchars('Heading 1'), 1); +$section->addTitle(htmlspecialchars('Heading 2'), 2); +$section->addTitle(htmlspecialchars('Heading 3'), 3); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_15_Link.php b/samples/Sample_15_Link.php index 1bd61e79..dd06670e 100644 --- a/samples/Sample_15_Link.php +++ b/samples/Sample_15_Link.php @@ -2,17 +2,21 @@ include_once 'Sample_Header.php'; // New Word document -echo date('H:i:s'), " Create new PhpWord object", EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); // Begin code $section = $phpWord->addSection(); // Add hyperlink elements -$section->addLink('http://www.google.com', 'Best search engine', array('color'=>'0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE)); +$section->addLink( + 'http://www.google.com', + htmlspecialchars('Best search engine'), + array('color' => '0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE) +); $section->addTextBreak(2); -$phpWord->addLinkStyle('myOwnLinkStyle', array('bold'=>true, 'color'=>'808000')); +$phpWord->addLinkStyle('myOwnLinkStyle', array('bold' => true, 'color' => '808000')); $section->addLink('http://www.bing.com', null, 'myOwnLinkStyle'); $section->addLink('http://www.yahoo.com', null, 'myOwnLinkStyle'); diff --git a/samples/Sample_16_Object.php b/samples/Sample_16_Object.php index af23a00f..2a216c23 100644 --- a/samples/Sample_16_Object.php +++ b/samples/Sample_16_Object.php @@ -2,12 +2,12 @@ include_once 'Sample_Header.php'; // New Word document -echo date('H:i:s'), " Create new PhpWord object", EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); // Begin code $section = $phpWord->addSection(); -$section->addText('You can open this OLE object by double clicking on the icon:'); +$section->addText(htmlspecialchars('You can open this OLE object by double clicking on the icon:')); $section->addTextBreak(2); $section->addObject('resources/_sheet.xls'); diff --git a/samples/Sample_17_TitleTOC.php b/samples/Sample_17_TitleTOC.php index b18b1bc9..8f8889b8 100644 --- a/samples/Sample_17_TitleTOC.php +++ b/samples/Sample_17_TitleTOC.php @@ -2,7 +2,7 @@ include_once 'Sample_Header.php'; // New Word document -echo date('H:i:s'), " Create new PhpWord object", EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); // Begin code @@ -19,7 +19,7 @@ $phpWord->addTitleStyle(3, array('size' => 14, 'italic' => true)); $phpWord->addTitleStyle(4, array('size' => 12)); // Add text elements -$section->addText('Table of contents 1'); +$section->addText(htmlspecialchars('Table of contents 1')); $section->addTextBreak(2); // Add TOC #1 @@ -27,11 +27,11 @@ $toc = $section->addTOC($fontStyle); $section->addTextBreak(2); // Filler -$section->addText('Text between TOC'); +$section->addText(htmlspecialchars('Text between TOC')); $section->addTextBreak(2); // Add TOC #1 -$section->addText('Table of contents 2'); +$section->addText(htmlspecialchars('Table of contents 2')); $section->addTextBreak(2); $toc2 = $section->addTOC($fontStyle2); $toc2->setMinDepth(2); @@ -40,33 +40,33 @@ $toc2->setMaxDepth(3); // Add Titles $section->addPageBreak(); -$section->addTitle('I am Title 1', 1); -$section->addText('Some text...'); +$section->addTitle(htmlspecialchars('Foo & Bar'), 1); +$section->addText(htmlspecialchars('Some text...')); $section->addTextBreak(2); -$section->addTitle('I am a Subtitle of Title 1', 2); +$section->addTitle(htmlspecialchars('I am a Subtitle of Title 1'), 2); $section->addTextBreak(2); -$section->addText('Some more text...'); +$section->addText(htmlspecialchars('Some more text...')); $section->addTextBreak(2); -$section->addTitle('Another Title (Title 2)', 1); -$section->addText('Some text...'); +$section->addTitle(htmlspecialchars('Another Title (Title 2)'), 1); +$section->addText(htmlspecialchars('Some text...')); $section->addPageBreak(); -$section->addTitle('I am Title 3', 1); -$section->addText('And more text...'); +$section->addTitle(htmlspecialchars('I am Title 3'), 1); +$section->addText(htmlspecialchars('And more text...')); $section->addTextBreak(2); -$section->addTitle('I am a Subtitle of Title 3', 2); -$section->addText('Again and again, more text...'); -$section->addTitle('Subtitle 3.1.1', 3); -$section->addText('Text'); -$section->addTitle('Subtitle 3.1.1.1', 4); -$section->addText('Text'); -$section->addTitle('Subtitle 3.1.1.2', 4); -$section->addText('Text'); -$section->addTitle('Subtitle 3.1.2', 3); -$section->addText('Text'); +$section->addTitle(htmlspecialchars('I am a Subtitle of Title 3'), 2); +$section->addText(htmlspecialchars('Again and again, more text...')); +$section->addTitle(htmlspecialchars('Subtitle 3.1.1'), 3); +$section->addText(htmlspecialchars('Text')); +$section->addTitle(htmlspecialchars('Subtitle 3.1.1.1'), 4); +$section->addText(htmlspecialchars('Text')); +$section->addTitle(htmlspecialchars('Subtitle 3.1.1.2'), 4); +$section->addText(htmlspecialchars('Text')); +$section->addTitle(htmlspecialchars('Subtitle 3.1.2'), 3); +$section->addText(htmlspecialchars('Text')); -echo date('H:i:s'), " Note: Please refresh TOC manually.", EOL; +echo date('H:i:s'), ' Note: Please refresh TOC manually.', EOL; // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_18_Watermark.php b/samples/Sample_18_Watermark.php index 313cfbed..f630bdf2 100644 --- a/samples/Sample_18_Watermark.php +++ b/samples/Sample_18_Watermark.php @@ -2,7 +2,7 @@ include_once 'Sample_Header.php'; // New Word document -echo date('H:i:s'), " Create new PhpWord object", EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); // Begin code @@ -10,7 +10,7 @@ $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); $header = $section->addHeader(); $header->addWatermark('resources/_earth.jpg', array('marginTop' => 200, 'marginLeft' => 55)); -$section->addText('The header reference to the current section includes a watermark image.'); +$section->addText(htmlspecialchars('The header reference to the current section includes a watermark image.')); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_19_TextBreak.php b/samples/Sample_19_TextBreak.php index a209ce39..fc0e5419 100644 --- a/samples/Sample_19_TextBreak.php +++ b/samples/Sample_19_TextBreak.php @@ -2,7 +2,7 @@ include_once 'Sample_Header.php'; // New Word document -echo date('H:i:s'), " Create new PhpWord object", EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); // Begin code @@ -13,17 +13,17 @@ $phpWord->addParagraphStyle('paragraphStyle', array('spacing' => 480)); $fontStyle = array('size' => 24); $section = $phpWord->addSection(); -$section->addText('Text break with no style:'); +$section->addText(htmlspecialchars('Text break with no style:')); $section->addTextBreak(); -$section->addText('Text break with defined font style:'); +$section->addText(htmlspecialchars('Text break with defined font style:')); $section->addTextBreak(1, 'fontStyle'); -$section->addText('Text break with defined paragraph style:'); +$section->addText(htmlspecialchars('Text break with defined paragraph style:')); $section->addTextBreak(1, null, 'paragraphStyle'); -$section->addText('Text break with inline font style:'); +$section->addText(htmlspecialchars('Text break with inline font style:')); $section->addTextBreak(1, $fontStyle); -$section->addText('Text break with inline paragraph style:'); +$section->addText(htmlspecialchars('Text break with inline paragraph style:')); $section->addTextBreak(1, null, $paragraphStyle); -$section->addText('Done.'); +$section->addText(htmlspecialchars('Done.')); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_20_BGColor.php b/samples/Sample_20_BGColor.php index 892cd8b2..ebee8544 100644 --- a/samples/Sample_20_BGColor.php +++ b/samples/Sample_20_BGColor.php @@ -2,13 +2,19 @@ include_once 'Sample_Header.php'; // New Word document -echo date('H:i:s'), " Create new PhpWord object", EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); -$section->addText("This is some text highlighted using fgColor (limited to 15 colors) ", array("fgColor" => \PhpOffice\PhpWord\Style\Font::FGCOLOR_YELLOW)); -$section->addText("This one uses bgColor and is using hex value (0xfbbb10)", array("bgColor" => "fbbb10")); -$section->addText("Compatible with font colors", array("color"=>"0000ff", "bgColor" => "fbbb10")); +$section->addText( + htmlspecialchars('This is some text highlighted using fgColor (limited to 15 colors) '), + array('fgColor' => \PhpOffice\PhpWord\Style\Font::FGCOLOR_YELLOW) +); +$section->addText( + htmlspecialchars('This one uses bgColor and is using hex value (0xfbbb10)'), + array('bgColor' => 'fbbb10') +); +$section->addText(htmlspecialchars('Compatible with font colors'), array('color' => '0000ff', 'bgColor' => 'fbbb10')); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_21_TableRowRules.php b/samples/Sample_21_TableRowRules.php index b600ec00..df3162c3 100644 --- a/samples/Sample_21_TableRowRules.php +++ b/samples/Sample_21_TableRowRules.php @@ -2,30 +2,50 @@ include_once 'Sample_Header.php'; // New Word document -echo date('H:i:s'), " Create new PhpWord object", EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); -$section->addText("By default, when you insert an image, it adds a textbreak after its content."); -$section->addText("If we want a simple border around an image, we wrap the image inside a table->row->cell"); -$section->addText("On the image with the red border, even if we set the row height to the height of the image, the textbreak is still there:"); +$section->addText(htmlspecialchars('By default, when you insert an image, it adds a textbreak after its content.')); +$section->addText( + htmlspecialchars('If we want a simple border around an image, we wrap the image inside a table->row->cell') +); +$section->addText( + htmlspecialchars( + 'On the image with the red border, even if we set the row height to the height of the image, ' + . 'the textbreak is still there:' + ) +); -$table1 = $section->addTable(array("cellMargin" => 0, "cellMarginRight" => 0, "cellMarginBottom" => 0, "cellMarginLeft" => 0)); +$table1 = $section->addTable(array('cellMargin' => 0, 'cellMarginRight' => 0, 'cellMarginBottom' => 0, 'cellMarginLeft' => 0)); $table1->addRow(3750); -$cell1 = $table1->addCell(null, array("valign" => "top", "borderSize" => 30, "borderColor" => "ff0000")); -$cell1->addImage("./resources/_earth.jpg", array("width" => 250, "height" => 250, "align" => "center")); +$cell1 = $table1->addCell(null, array('valign' => 'top', 'borderSize' => 30, 'borderColor' => 'ff0000')); +$cell1->addImage('./resources/_earth.jpg', array('width' => 250, 'height' => 250, 'align' => 'center')); $section->addTextBreak(); -$section->addText("But if we set the rowStyle 'exactHeight' to true, the real row height is used, removing the textbreak:"); +$section->addText( + htmlspecialchars( + "But if we set the rowStyle 'exactHeight' to true, the real row height is used, removing the textbreak:" + ) +); -$table2 = $section->addTable(array("cellMargin" => 0, "cellMarginRight" => 0, "cellMarginBottom" => 0, "cellMarginLeft" => 0)); -$table2->addRow(3750, array("exactHeight" => true)); -$cell2 = $table2->addCell(null, array("valign" => "top", "borderSize" => 30, "borderColor" => "00ff00")); -$cell2->addImage("./resources/_earth.jpg", array("width" => 250, "height" => 250, "align" => "center")); +$table2 = $section->addTable( + array( + 'cellMargin' => 0, + 'cellMarginRight' => 0, + 'cellMarginBottom' => 0, + 'cellMarginLeft' => 0, + ) +); +$table2->addRow(3750, array('exactHeight' => true)); +$cell2 = $table2->addCell(null, array('valign' => 'top', 'borderSize' => 30, 'borderColor' => '00ff00')); +$cell2->addImage('./resources/_earth.jpg', array('width' => 250, 'height' => 250, 'align' => 'center')); $section->addTextBreak(); -$section->addText("In this example, image is 250px height. Rows are calculated in twips, and 1px = 15twips."); -$section->addText("So: $"."table2->addRow(3750, array('exactHeight'=>true));"); +$section->addText( + htmlspecialchars('In this example, image is 250px height. Rows are calculated in twips, and 1px = 15twips.') +); +$section->addText(htmlspecialchars('So: $' . "table2->addRow(3750, array('exactHeight'=>true));")); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_22_CheckBox.php b/samples/Sample_22_CheckBox.php index e7aae5ba..b5d4a7a5 100644 --- a/samples/Sample_22_CheckBox.php +++ b/samples/Sample_22_CheckBox.php @@ -2,17 +2,17 @@ include_once 'Sample_Header.php'; // New Word document -echo date('H:i:s'), " Create new PhpWord object", EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); -$section->addText('Check box in section'); -$section->addCheckBox('chkBox1', 'Checkbox 1'); -$section->addText('Check box in table cell'); +$section->addText(htmlspecialchars('Check box in section')); +$section->addCheckBox('chkBox1', htmlspecialchars('Checkbox 1')); +$section->addText(htmlspecialchars('Check box in table cell')); $table = $section->addTable(); $table->addRow(); $cell = $table->addCell(); -$cell->addCheckBox('chkBox2', 'Checkbox 2'); +$cell->addCheckBox('chkBox2', htmlspecialchars('Checkbox 2')); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_23_TemplateBlock.php b/samples/Sample_23_TemplateBlock.php index 8ee8fc6d..2b7e9f68 100644 --- a/samples/Sample_23_TemplateBlock.php +++ b/samples/Sample_23_TemplateBlock.php @@ -1,22 +1,18 @@ loadTemplate('resources/Sample_23_TemplateBlock.docx'); +// Template processor instance creation +echo date('H:i:s') , ' Creating new TemplateProcessor instance...' , EOL; +$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('resources/Sample_23_TemplateBlock.docx'); // Will clone everything between ${tag} and ${/tag}, the number of times. By default, 1. -$document->cloneBlock('CLONEME', 3); +$templateProcessor->cloneBlock('CLONEME', 3); // Everything between ${tag} and ${/tag}, will be deleted/erased. -$document->deleteBlock('DELETEME'); +$templateProcessor->deleteBlock('DELETEME'); -$name = 'Sample_23_TemplateBlock.docx'; -echo date('H:i:s'), " Write to Word2007 format", EOL; -$document->saveAs($name); -rename($name, "results/{$name}"); +echo date('H:i:s'), ' Saving the result document...', EOL; +$templateProcessor->saveAs('results/Sample_23_TemplateBlock.docx'); echo getEndingNotes(array('Word2007' => 'docx')); if (!CLI) { diff --git a/samples/Sample_25_TextBox.php b/samples/Sample_25_TextBox.php index 0a659ddb..afeb863d 100644 --- a/samples/Sample_25_TextBox.php +++ b/samples/Sample_25_TextBox.php @@ -2,35 +2,43 @@ include_once 'Sample_Header.php'; // New Word Document -echo date('H:i:s') , ' Create new PhpWord object' , EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); // In section -$textbox = $section->addTextBox(array('align' => 'center', 'width' => 400, 'height' => 150, 'borderSize' => 1, 'borderColor' => '#FF0000')); -$textbox->addText('Text box content in section.'); -$textbox->addText('Another line.'); +$textbox = $section->addTextBox( + array( + 'align' => 'center', + 'width' => 400, + 'height' => 150, + 'borderSize' => 1, + 'borderColor' => '#FF0000', + ) +); +$textbox->addText(htmlspecialchars('Text box content in section.')); +$textbox->addText(htmlspecialchars('Another line.')); $cell = $textbox->addTable()->addRow()->addCell(); -$cell->addText('Table inside textbox'); +$cell->addText(htmlspecialchars('Table inside textbox')); // Inside table $section->addTextBreak(2); $cell = $section->addTable()->addRow()->addCell(300); $textbox = $cell->addTextBox(array('borderSize' => 1, 'borderColor' => '#0000FF', 'innerMargin' => 100)); -$textbox->addText('Textbox inside table'); +$textbox->addText(htmlspecialchars('Textbox inside table')); // Inside header with textrun $header = $section->addHeader(); $textbox = $header->addTextBox(array('width' => 600, 'borderSize' => 1, 'borderColor' => '#00FF00')); $textrun = $textbox->addTextRun(); -$textrun->addText('TextBox in header. TextBox can contain a TextRun '); -$textrun->addText('with bold text', array('bold' => true)); -$textrun->addText(', '); -$textrun->addLink('http://www.google.com', 'link'); -$textrun->addText(', and image '); +$textrun->addText(htmlspecialchars('TextBox in header. TextBox can contain a TextRun ')); +$textrun->addText(htmlspecialchars('with bold text'), array('bold' => true)); +$textrun->addText(htmlspecialchars(', ')); +$textrun->addLink('http://www.google.com', htmlspecialchars('link')); +$textrun->addText(htmlspecialchars(', and image ')); $textrun->addImage('resources/_earth.jpg', array('width' => 18, 'height' => 18)); -$textrun->addText('.'); +$textrun->addText(htmlspecialchars('.')); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index 92b3aa49..4235c946 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -20,4 +20,4 @@ $html .= '

  1. Item 1
  2. Item 2
'; echo write($phpWord, basename(__FILE__, '.php'), $writers); if (!CLI) { include_once 'Sample_Footer.php'; -} \ No newline at end of file +} diff --git a/samples/Sample_27_Field.php b/samples/Sample_27_Field.php index fd750372..9bdbef82 100644 --- a/samples/Sample_27_Field.php +++ b/samples/Sample_27_Field.php @@ -2,7 +2,7 @@ include_once 'Sample_Header.php'; // New Word document -echo date('H:i:s'), " Create new PhpWord object", EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); // Begin code @@ -10,19 +10,19 @@ $section = $phpWord->addSection(); // Add Field elements // See Element/Field.php for all options -$section->addText('Date field:'); -$section->addField('DATE', array('dateformat'=>'dddd d MMMM yyyy H:mm:ss'), array('PreserveFormat')); +$section->addText(htmlspecialchars('Date field:')); +$section->addField('DATE', array('dateformat' => 'dddd d MMMM yyyy H:mm:ss'), array('PreserveFormat')); -$section->addText('Page field:'); -$section->addField('PAGE', array('format'=>'ArabicDash')); +$section->addText(htmlspecialchars('Page field:')); +$section->addField('PAGE', array('format' => 'ArabicDash')); -$section->addText('Number of pages field:'); -$section->addField('NUMPAGES', array('format'=>'Arabic', 'numformat'=>'0,00'), array('PreserveFormat')); +$section->addText(htmlspecialchars('Number of pages field:')); +$section->addField('NUMPAGES', array('format' => 'Arabic', 'numformat' => '0,00'), array('PreserveFormat')); $textrun = $section->addTextRun(array('align' => 'center')); -$textrun->addText('This is the date of lunar calendar '); -$textrun->addField('DATE', array('dateformat'=>'d-M-yyyy H:mm:ss'), array('PreserveFormat', 'LunarCalendar')); -$textrun->addText(' written in a textrun.'); +$textrun->addText(htmlspecialchars('This is the date of lunar calendar ')); +$textrun->addField('DATE', array('dateformat' => 'd-M-yyyy H:mm:ss'), array('PreserveFormat', 'LunarCalendar')); +$textrun->addText(htmlspecialchars(' written in a textrun.')); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_29_Line.php b/samples/Sample_29_Line.php index 5a955702..8bb192cf 100644 --- a/samples/Sample_29_Line.php +++ b/samples/Sample_29_Line.php @@ -2,7 +2,7 @@ include_once 'Sample_Header.php'; // New Word document -echo date('H:i:s'), " Create new PhpWord object", EOL; +echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); // Begin code @@ -10,50 +10,50 @@ $section = $phpWord->addSection(); // Add Line elements // See Element/Line.php for all options -$section->addText('Horizontal Line (Inline style):'); +$section->addText(htmlspecialchars('Horizontal Line (Inline style):')); $section->addLine( array( - 'width' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(4), - 'height' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(0), - 'positioning' => 'absolute' + 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(4), + 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), + 'positioning' => 'absolute', ) ); -$section->addText('Vertical Line (Inline style):'); +$section->addText(htmlspecialchars('Vertical Line (Inline style):')); $section->addLine( array( - 'width' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(0), - 'height' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(1), - 'positioning' => 'absolute' + 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), + 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(1), + 'positioning' => 'absolute', ) ); // Two text break $section->addTextBreak(1); -$section->addText('Positioned Line (red):'); +$section->addText(htmlspecialchars('Positioned Line (red):')); $section->addLine( array( - 'width' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(4), - 'height' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(1), - 'positioning' => 'absolute', + 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(4), + 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(1), + 'positioning' => 'absolute', 'posHorizontalRel' => 'page', - 'posVerticalRel' => 'page', - 'marginLeft' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(10), - 'marginTop' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(8), - 'wrappingStyle' => \PhpOffice\PhpWord\Style\Image::WRAPPING_STYLE_SQUARE, - 'color' => 'red' + 'posVerticalRel' => 'page', + 'marginLeft' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(10), + 'marginTop' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(8), + 'wrappingStyle' => \PhpOffice\PhpWord\Style\Image::WRAPPING_STYLE_SQUARE, + 'color' => 'red', ) ); -$section->addText('Horizontal Formatted Line'); +$section->addText(htmlspecialchars('Horizontal Formatted Line')); $section->addLine( array( - 'width' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(15), - 'height' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(0), + 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(15), + 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), 'positioning' => 'absolute', - 'beginArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_BLOCK, - 'endArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_OVAL, - 'dash' => \PhpOffice\PhpWord\Style\Line::DASH_STYLE_LONG_DASH_DOT_DOT, - 'weight' => 10 + 'beginArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_BLOCK, + 'endArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_OVAL, + 'dash' => \PhpOffice\PhpWord\Style\Line::DASH_STYLE_LONG_DASH_DOT_DOT, + 'weight' => 10, ) ); diff --git a/samples/Sample_31_Shape.php b/samples/Sample_31_Shape.php new file mode 100644 index 00000000..3df71b4c --- /dev/null +++ b/samples/Sample_31_Shape.php @@ -0,0 +1,95 @@ +addTitleStyle(1, array('size' => 14, 'bold' => true)); + +$section = $phpWord->addSection(); + +// Arc +$section->addTitle(htmlspecialchars('Arc'), 1); +$section->addShape( + 'arc', + array( + 'points' => '-90 20', + 'frame' => array('width' => 120, 'height' => 120), + 'outline' => array('color' => '#333333', 'weight' => 2, 'startArrow' => 'oval', 'endArrow' => 'open'), + ) +); + +// Curve +$section->addTitle(htmlspecialchars('Curve'), 1); +$section->addShape( + 'curve', + array( + 'points' => '1,100 200,1 1,50 200,50', + 'connector' => 'elbow', + 'outline' => array( + 'color' => '#66cc00', + 'weight' => 2, + 'dash' => 'dash', + 'startArrow' => 'diamond', + 'endArrow' => 'block', + ), + ) +); + +// Line +$section->addTitle(htmlspecialchars('Line'), 1); +$section->addShape( + 'line', + array( + 'points' => '1,1 150,30', + 'outline' => array( + 'color' => '#cc00ff', + 'line' => 'thickThin', + 'weight' => 3, + 'startArrow' => 'oval', + 'endArrow' => 'classic', + ), + ) +); + +// Polyline +$section->addTitle(htmlspecialchars('Polyline'), 1); +$section->addShape( + 'polyline', + array( + 'points' => '1,30 20,10 55,20 75,10 100,40 115,50, 120,15 200,50', + 'outline' => array('color' => '#cc6666', 'weight' => 2, 'startArrow' => 'none', 'endArrow' => 'classic'), + ) +); + +// Rectangle +$section->addTitle(htmlspecialchars('Rectangle'), 1); +$section->addShape( + 'rect', + array( + 'roundness' => 0.2, + 'frame' => array('width' => 100, 'height' => 100, 'left' => 1, 'top' => 1), + 'fill' => array('color' => '#FFCC33'), + 'outline' => array('color' => '#990000', 'weight' => 1), + 'shadow' => array(), + ) +); + +// Oval +$section->addTitle(htmlspecialchars('Oval'), 1); +$section->addShape( + 'oval', + array( + 'frame' => array('width' => 100, 'height' => 70, 'left' => 1, 'top' => 1), + 'fill' => array('color' => '#33CC99'), + 'outline' => array('color' => '#333333', 'weight' => 2), + 'extrusion' => array(), + ) +); + +// Save file +echo write($phpWord, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/samples/Sample_32_Chart.php b/samples/Sample_32_Chart.php new file mode 100644 index 00000000..b61a646f --- /dev/null +++ b/samples/Sample_32_Chart.php @@ -0,0 +1,61 @@ +addTitleStyle(1, array('size' => 14, 'bold' => true), array('keepNext' => true, 'spaceBefore' => 240)); +$phpWord->addTitleStyle(2, array('size' => 14, 'bold' => true), array('keepNext' => true, 'spaceBefore' => 240)); + +// 2D charts +$section = $phpWord->addSection(); +$section->addTitle(htmlspecialchars('2D charts'), 1); +$section = $phpWord->addSection(array('colsNum' => 2, 'breakType' => 'continuous')); + +$chartTypes = array('pie', 'doughnut', 'bar', 'column', 'line', 'area', 'scatter', 'radar'); +$twoSeries = array('bar', 'column', 'line', 'area', 'scatter', 'radar'); +$threeSeries = array('bar', 'line'); +$categories = array('A', 'B', 'C', 'D', 'E'); +$series1 = array(1, 3, 2, 5, 4); +$series2 = array(3, 1, 7, 2, 6); +$series3 = array(8, 3, 2, 5, 4); + +foreach ($chartTypes as $chartType) { + $section->addTitle(ucfirst($chartType), 2); + $chart = $section->addChart($chartType, $categories, $series1); + $chart->getStyle()->setWidth(Converter::inchToEmu(2.5))->setHeight(Converter::inchToEmu(2)); + if (in_array($chartType, $twoSeries)) { + $chart->addSeries($categories, $series2); + } + if (in_array($chartType, $threeSeries)) { + $chart->addSeries($categories, $series3); + } + $section->addTextBreak(); +} + +// 3D charts +$section = $phpWord->addSection(array('breakType' => 'continuous')); +$section->addTitle(htmlspecialchars('3D charts'), 1); +$section = $phpWord->addSection(array('colsNum' => 2, 'breakType' => 'continuous')); + +$chartTypes = array('pie', 'bar', 'column', 'line', 'area'); +$multiSeries = array('bar', 'column', 'line', 'area'); +$style = array('width' => Converter::cmToEmu(5), 'height' => Converter::cmToEmu(4), '3d' => true); +foreach ($chartTypes as $chartType) { + $section->addTitle(ucfirst($chartType), 2); + $chart = $section->addChart($chartType, $categories, $series1, $style); + if (in_array($chartType, $multiSeries)) { + $chart->addSeries($categories, $series2); + $chart->addSeries($categories, $series3); + } + $section->addTextBreak(); +} + +// Save file +echo write($phpWord, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/samples/Sample_33_FormField.php b/samples/Sample_33_FormField.php new file mode 100644 index 00000000..9f356810 --- /dev/null +++ b/samples/Sample_33_FormField.php @@ -0,0 +1,27 @@ +getProtection()->setEditing('forms'); + +$section = $phpWord->addSection(); + +$textrun = $section->addTextRun(); +$textrun->addText(htmlspecialchars('Form fields can be added in a text run and can be in form of textinput ')); +$textrun->addFormField('textinput')->setName('MyTextBox'); +$textrun->addText(htmlspecialchars(', checkbox ')); +$textrun->addFormField('checkbox')->setDefault(true); +$textrun->addText(htmlspecialchars(', or dropdown ')); +$textrun->addFormField('dropdown')->setEntries(array('Choice 1', 'Choice 2', 'Choice 3')); +$textrun->addText(htmlspecialchars('. You have to set document protection to "forms" to enable dropdown.')); + +$section->addText(htmlspecialchars('They can also be added as a stand alone paragraph.')); +$section->addFormField('textinput')->setValue('Your name'); + +// Save file +echo write($phpWord, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/samples/Sample_34_SDT.php b/samples/Sample_34_SDT.php new file mode 100644 index 00000000..19ac42fe --- /dev/null +++ b/samples/Sample_34_SDT.php @@ -0,0 +1,26 @@ +addSection(); + +$textrun = $section->addTextRun(); +$textrun->addText(htmlspecialchars('Combobox: ')); +$textrun->addSDT('comboBox')->setListItems(array('1' => 'Choice 1', '2' => 'Choice 2')); + +$textrun = $section->addTextRun(); +$textrun->addText(htmlspecialchars('Date: ')); +$textrun->addSDT('date'); + +$textrun = $section->addTextRun(); +$textrun->addText(htmlspecialchars('Drop down list: ')); +$textrun->addSDT('dropDownList')->setListItems(array('1' => 'Choice 1', '2' => 'Choice 2')); + +// Save file +echo write($phpWord, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/samples/Sample_35_InternalLink.php b/samples/Sample_35_InternalLink.php new file mode 100644 index 00000000..1b907f87 --- /dev/null +++ b/samples/Sample_35_InternalLink.php @@ -0,0 +1,22 @@ +addSection(); +$section->addTitle(htmlspecialchars('This is page 1'), 1); +$linkIsInternal = true; +$section->addLink('MyBookmark', htmlspecialchars('Take me to page 3'), null, null, $linkIsInternal); +$section->addPageBreak(); +$section->addTitle(htmlspecialchars('This is page 2'), 1); +$section->addPageBreak(); +$section->addTitle(htmlspecialchars('This is page 3'), 1); +$section->addBookmark('MyBookmark'); + +// Save file +echo write($phpWord, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/samples/Sample_36_RTL.php b/samples/Sample_36_RTL.php new file mode 100644 index 00000000..ec326ae0 --- /dev/null +++ b/samples/Sample_36_RTL.php @@ -0,0 +1,19 @@ +addSection(); +$textrun = $section->addTextRun(); +$textrun->addText(htmlspecialchars('This is a Left to Right paragraph.')); + +$textrun = $section->addTextRun(array('align' => 'right')); +$textrun->addText(htmlspecialchars('سلام این یک پاراگراف راست به چپ است'), array('rtl' => true)); + +// Save file +echo write($phpWord, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/samples/Sample_Footer.php b/samples/Sample_Footer.php index f7e2305f..95ac693f 100644 --- a/samples/Sample_Footer.php +++ b/samples/Sample_Footer.php @@ -2,6 +2,9 @@ /** * Footer file */ +if (CLI) { + return; +} ?> diff --git a/samples/Sample_Header.php b/samples/Sample_Header.php index 7af23c94..22d27a4a 100644 --- a/samples/Sample_Header.php +++ b/samples/Sample_Header.php @@ -1,10 +1,13 @@ '); define('SCRIPT_FILENAME', basename($_SERVER['SCRIPT_FILENAME'], '.php')); define('IS_INDEX', SCRIPT_FILENAME == 'index'); -require_once __DIR__ . '/../src/PhpWord/Autoloader.php'; Autoloader::register(); Settings::loadConfig(); @@ -20,7 +22,7 @@ Settings::loadConfig(); $writers = array('Word2007' => 'docx', 'ODText' => 'odt', 'RTF' => 'rtf', 'HTML' => 'html', 'PDF' => 'pdf'); // Set PDF renderer -if (Settings::getPdfRendererPath() === null) { +if (null === Settings::getPdfRendererPath()) { $writers['PDF'] = null; } @@ -53,18 +55,19 @@ if ($handle = opendir('.')) { * @param \PhpOffice\PhpWord\PhpWord $phpWord * @param string $filename * @param array $writers + * + * @return string */ function write($phpWord, $filename, $writers) { $result = ''; // Write documents - foreach ($writers as $writer => $extension) { - $result .= date('H:i:s') . " Write to {$writer} format"; - if (!is_null($extension)) { - $xmlWriter = IOFactory::createWriter($phpWord, $writer); - $xmlWriter->save(__DIR__ . "/{$filename}.{$extension}"); - rename(__DIR__ . "/{$filename}.{$extension}", __DIR__ . "/results/{$filename}.{$extension}"); + foreach ($writers as $format => $extension) { + $result .= date('H:i:s') . " Write to {$format} format"; + if (null !== $extension) { + $targetFile = __DIR__ . "/results/{$filename}.{$extension}"; + $phpWord->save($targetFile, $format); } else { $result .= ' ... NOT DONE!'; } @@ -80,6 +83,8 @@ function write($phpWord, $filename, $writers) * Get ending notes * * @param array $writers + * + * @return string */ function getEndingNotes($writers) { @@ -144,7 +149,7 @@ function getEndingNotes($writers) diff --git a/samples/index.php b/samples/index.php index 420c5420..a65d8fd9 100644 --- a/samples/index.php +++ b/samples/index.php @@ -1,8 +1,12 @@ array('PHP 5.3.0', version_compare(phpversion(), '5.3.0', '>=')), + 'php' => array('PHP 5.3.3', version_compare(PHP_VERSION, '5.3.3', '>=')), 'xml' => array('PHP extension XML', extension_loaded('xml')), + 'temp' => array('Temp folder "' . Settings::getTempDir() . '" is writable', is_writable(Settings::getTempDir())), 'zip' => array('PHP extension ZipArchive (optional)', extension_loaded('zip')), 'gd' => array('PHP extension GD (optional)', extension_loaded('gd')), 'xmlw' => array('PHP extension XMLWriter (optional)', extension_loaded('xmlwriter')), @@ -15,7 +19,7 @@ if (!CLI) {

 

Fork us on Github! - Read the Docs + Read the Docs

$value) { list($label, $result) = $value; + $label = strip_tags($label); $status = $result ? '32m passed' : '31m failed'; echo "{$label} ... \033[{$status}\033[0m" . PHP_EOL; } diff --git a/samples/resources/Sample_11_ReadWord97.doc b/samples/resources/Sample_11_ReadWord97.doc new file mode 100644 index 00000000..a5ce295d Binary files /dev/null and b/samples/resources/Sample_11_ReadWord97.doc differ diff --git a/src/PhpWord/Autoloader.php b/src/PhpWord/Autoloader.php index c467f836..68da845d 100644 --- a/src/PhpWord/Autoloader.php +++ b/src/PhpWord/Autoloader.php @@ -28,17 +28,20 @@ class Autoloader /** * Register * + * @param bool $throw + * @param bool $prepend * @return void */ - public static function register() + public static function register($throw = true, $prepend = false) { - spl_autoload_register(array(new self, 'autoload')); + spl_autoload_register(array(new self, 'autoload'), $throw, $prepend); } /** * Autoload * * @param string $class + * @return void */ public static function autoload($class) { diff --git a/src/PhpWord/Collection/AbstractCollection.php b/src/PhpWord/Collection/AbstractCollection.php index ae1b6efb..41e40e2e 100644 --- a/src/PhpWord/Collection/AbstractCollection.php +++ b/src/PhpWord/Collection/AbstractCollection.php @@ -57,10 +57,11 @@ abstract class AbstractCollection } /** - * Set item + * Set item. * * @param int $index * @param mixed $item + * @return void */ public function setItem($index, $item) { diff --git a/src/PhpWord/Collection/Bookmarks.php b/src/PhpWord/Collection/Bookmarks.php new file mode 100644 index 00000000..cb9d74d5 --- /dev/null +++ b/src/PhpWord/Collection/Bookmarks.php @@ -0,0 +1,27 @@ + 1) { - $source = $args[1]; - } // Create element using reflection $reflection = new \ReflectionClass($elementClass); @@ -137,15 +144,10 @@ abstract class AbstractContainer extends AbstractElement /** @var \PhpOffice\PhpWord\Element\AbstractElement $element Type hint */ $element = $reflection->newInstanceArgs($elementArgs); - // Set nested level and relation Id - $this->setElementNestedLevel($element); - $this->setElementRelationId($element, $elementName, $source); - - // Set other properties and add element into collection - $element->setDocPart($this->getDocPart(), $this->getDocPartId()); + // Set parent container + $element->setParentContainer($this); $element->setElementIndex($this->countElements() + 1); $element->setElementId(); - $element->setPhpWord($this->phpWord); $this->elements[] = $element; @@ -172,54 +174,6 @@ abstract class AbstractContainer extends AbstractElement return count($this->elements); } - /** - * Set element nested level based on container; add one when it's inside a cell - */ - private function setElementNestedLevel(AbstractElement $element) - { - if ($this->container == 'Cell') { - $element->setNestedLevel($this->getNestedLevel() + 1); - } else { - $element->setNestedLevel($this->getNestedLevel()); - } - } - - /** - * Set relation Id - * - * @param string $elementName - * @param string $source - */ - private function setElementRelationId(AbstractElement $element, $elementName, $source) - { - $mediaContainer = $this->getMediaContainer(); - $hasMediaRelation = in_array($elementName, array('Link', 'Image', 'Object')); - $hasOtherRelation = in_array($elementName, array('Footnote', 'Endnote', 'Title')); - - // Set relation Id for media elements (link, image, object; legacy of OOXML) - // Only Image that needs to be passed to Media class - if ($hasMediaRelation) { - /** @var \PhpOffice\PhpWord\Element\Image $element Type hint */ - $image = ($elementName == 'Image') ? $element : null; - $rId = Media::addElement($mediaContainer, strtolower($elementName), $source, $image); - $element->setRelationId($rId); - } - - // Set relation Id for icon of object element - if ($elementName == 'Object') { - /** @var \PhpOffice\PhpWord\Element\Object $element Type hint */ - $rIdIcon = Media::addElement($mediaContainer, 'image', $element->getIcon(), new Image($element->getIcon())); - $element->setImageRelationId($rIdIcon); - } - - // Set relation Id for elements that will be registered in the Collection subnamespaces - if ($hasOtherRelation && $this->phpWord instanceof PhpWord) { - $addMethod = "add{$elementName}"; - $rId = $this->phpWord->$addMethod($element); - $element->setRelationId($rId); - } - } - /** * Check if a method is allowed for the current container * @@ -229,19 +183,22 @@ abstract class AbstractContainer extends AbstractElement */ private function checkValidity($method) { - // Valid containers for each element - $allContainers = array( - 'Section', 'Header', 'Footer', 'Footnote', 'Endnote', - 'Cell', 'TextRun', 'TextBox', 'ListItemRun', + $generalContainers = array( + 'Section', 'Header', 'Footer', 'Footnote', 'Endnote', 'Cell', 'TextRun', 'TextBox', 'ListItemRun', ); + $validContainers = array( - 'Text' => $allContainers, - 'Link' => $allContainers, - 'TextBreak' => $allContainers, - 'Image' => $allContainers, - 'Object' => $allContainers, - 'Field' => $allContainers, - 'Line' => $allContainers, + 'Text' => $generalContainers, + 'Bookmark' => $generalContainers, + 'Link' => $generalContainers, + 'TextBreak' => $generalContainers, + 'Image' => $generalContainers, + 'Object' => $generalContainers, + 'Field' => $generalContainers, + 'Line' => $generalContainers, + 'Shape' => $generalContainers, + 'FormField' => $generalContainers, + 'SDT' => $generalContainers, 'TextRun' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), 'ListItem' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), 'ListItemRun' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), @@ -251,7 +208,12 @@ abstract class AbstractContainer extends AbstractElement 'Footnote' => array('Section', 'TextRun', 'Cell'), 'Endnote' => array('Section', 'TextRun', 'Cell'), 'PreserveText' => array('Header', 'Footer', 'Cell'), + 'Title' => array('Section'), + 'TOC' => array('Section'), + 'PageBreak' => array('Section'), + 'Chart' => array('Section'), ); + // Special condition, e.g. preservetext can only exists in cell when // the cell is located in header or footer $validSubcontainers = array( @@ -261,19 +223,20 @@ abstract class AbstractContainer extends AbstractElement ); // Check if a method is valid for current container - if (array_key_exists($method, $validContainers)) { + if (isset($validContainers[$method])) { if (!in_array($this->container, $validContainers[$method])) { - throw new \BadMethodCallException("Cannot add $method in $this->container."); + throw new \BadMethodCallException("Cannot add {$method} in {$this->container}."); } } + // Check if a method is valid for current container, located in other container - if (array_key_exists($method, $validSubcontainers)) { + if (isset($validSubcontainers[$method])) { $rules = $validSubcontainers[$method]; $containers = $rules[0]; $allowedDocParts = $rules[1]; foreach ($containers as $container) { if ($this->container == $container && !in_array($this->getDocPart(), $allowedDocParts)) { - throw new \BadMethodCallException("Cannot add $method in $this->container."); + throw new \BadMethodCallException("Cannot add {$method} in {$this->container}."); } } } @@ -281,24 +244,6 @@ abstract class AbstractContainer extends AbstractElement return true; } - /** - * Return media element (image, object, link) container name - * - * @return string section|headerx|footerx|footnote|endnote - */ - private function getMediaContainer() - { - $partName = $this->container; - if (in_array($partName, array('Cell', 'TextRun', 'TextBox', 'ListItemRun'))) { - $partName = $this->getDocPart(); - } - if ($partName == 'Header' || $partName == 'Footer') { - $partName .= $this->getDocPartId(); - } - - return strtolower($partName); - } - /** * Add memory image element * diff --git a/src/PhpWord/Element/AbstractElement.php b/src/PhpWord/Element/AbstractElement.php index ca45ef23..99a7a1be 100644 --- a/src/PhpWord/Element/AbstractElement.php +++ b/src/PhpWord/Element/AbstractElement.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWord\Element; +use PhpOffice\PhpWord\Media; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Style; @@ -42,7 +43,7 @@ abstract class AbstractElement protected $sectionId; /** - * Document part type: section|header|footer + * Document part type: Section|Header|Footer|Footnote|Endnote * * Used by textrun and cell container to determine where the element is * located because it will affect the availability of other element, @@ -93,6 +94,27 @@ abstract class AbstractElement */ private $nestedLevel = 0; + /** + * Parent container type + * + * @var string + */ + private $parentContainer; + + /** + * Has media relation flag; true for Link, Image, and Object + * + * @var bool + */ + protected $mediaRelation = false; + + /** + * Is part of collection; true for Title, Footnote, Endnote, and Chart + * + * @var bool + */ + protected $collectionRelation = false; + /** * Get PhpWord * @@ -104,13 +126,14 @@ abstract class AbstractElement } /** - * Set PhpWord as reference + * Set PhpWord as reference. * - * @param \PhpOffice\PhpWord\PhpWord + * @param \PhpOffice\PhpWord\PhpWord $phpWord + * @return void */ - public function setPhpWord(PhpWord &$phpWord = null) + public function setPhpWord(PhpWord $phpWord = null) { - $this->phpWord = &$phpWord; + $this->phpWord = $phpWord; } /** @@ -124,10 +147,11 @@ abstract class AbstractElement } /** - * Set doc part + * Set doc part. * * @param string $docPart * @param int $docPartId + * @return void */ public function setDocPart($docPart, $docPartId = 1) { @@ -155,6 +179,21 @@ abstract class AbstractElement return $this->docPartId; } + /** + * Return media element (image, object, link) container name + * + * @return string section|headerx|footerx|footnote|endnote + */ + private function getMediaPart() + { + $mediaPart = $this->docPart; + if ($mediaPart == 'Header' || $mediaPart == 'Footer') { + $mediaPart .= $this->docPartId; + } + + return strtolower($mediaPart); + } + /** * Get element index * @@ -166,9 +205,10 @@ abstract class AbstractElement } /** - * Set element index + * Set element index. * * @param int $value + * @return void */ public function setElementIndex($value) { @@ -186,7 +226,9 @@ abstract class AbstractElement } /** - * Set element unique ID from 6 first digit of md5 + * Set element unique ID from 6 first digit of md5. + * + * @return void */ public function setElementId() { @@ -204,9 +246,10 @@ abstract class AbstractElement } /** - * Set relation Id + * Set relation Id. * * @param int $value + * @return void */ public function setRelationId($value) { @@ -224,13 +267,79 @@ abstract class AbstractElement } /** - * Set nested level + * Set parent container * - * @param int $value + * Passed parameter should be a container, except for Table (contain Row) and Row (contain Cell) + * + * @param \PhpOffice\PhpWord\Element\AbstractElement $container + * @return void */ - public function setNestedLevel($value) + public function setParentContainer(AbstractElement $container) { - $this->nestedLevel = $value; + $this->parentContainer = substr(get_class($container), strrpos(get_class($container), '\\') + 1); + + // Set nested level + $this->nestedLevel = $container->getNestedLevel(); + if ($this->parentContainer == 'Cell') { + $this->nestedLevel++; + } + + // Set phpword + $this->setPhpWord($container->getPhpWord()); + + // Set doc part + if (!$this instanceof Footnote) { + $this->setDocPart($container->getDocPart(), $container->getDocPartId()); + } + + $this->setMediaRelation(); + $this->setCollectionRelation(); + } + + /** + * Set relation Id for media elements (link, image, object; legacy of OOXML) + * + * - Image element needs to be passed to Media object + * - Icon needs to be set for Object element + * + * @return void + */ + private function setMediaRelation() + { + if (!$this instanceof Link && !$this instanceof Image && !$this instanceof Object) { + return; + } + + $elementName = substr(get_class($this), strrpos(get_class($this), '\\') + 1); + $mediaPart = $this->getMediaPart(); + $source = $this->getSource(); + $image = null; + if ($this instanceof Image) { + $image = $this; + } + $rId = Media::addElement($mediaPart, strtolower($elementName), $source, $image); + $this->setRelationId($rId); + + if ($this instanceof Object) { + $icon = $this->getIcon(); + $rId = Media::addElement($mediaPart, 'image', $icon, new Image($icon)); + $this->setImageRelationId($rId); + } + } + + /** + * Set relation Id for elements that will be registered in the Collection subnamespaces. + * + * @return void + */ + private function setCollectionRelation() + { + if ($this->collectionRelation === true && $this->phpWord instanceof PhpWord) { + $elementName = substr(get_class($this), strrpos(get_class($this), '\\') + 1); + $addMethod = "add{$elementName}"; + $rId = $this->phpWord->$addMethod($this); + $this->setRelationId($rId); + } } /** @@ -244,14 +353,14 @@ abstract class AbstractElement } /** - * Set style value + * Set new style value * * @param mixed $styleObject Style object * @param mixed $styleValue Style value * @param bool $returnObject Always return object * @return mixed */ - protected function setStyle($styleObject, $styleValue = null, $returnObject = false) + protected function setNewStyle($styleObject, $styleValue = null, $returnObject = false) { if (!is_null($styleValue) && is_array($styleValue)) { $styleObject->setStyleByArray($styleValue); @@ -262,4 +371,25 @@ abstract class AbstractElement return $style; } + + /** + * Set enum value + * + * @param mixed $value + * @param array $enum + * @param mixed $default + * @return mixed + * @throws \InvalidArgumentException + * @todo Merge with the same method in AbstractStyle + */ + protected function setEnumVal($value = null, $enum = array(), $default = null) + { + if ($value != null && trim($value) != '' && !empty($enum) && !in_array($value, $enum)) { + throw new \InvalidArgumentException("Invalid style value: {$value}"); + } elseif ($value === null || trim($value) == '') { + $value = $default; + } + + return $value; + } } diff --git a/src/PhpWord/Element/Bookmark.php b/src/PhpWord/Element/Bookmark.php new file mode 100644 index 00000000..d5b8ff6f --- /dev/null +++ b/src/PhpWord/Element/Bookmark.php @@ -0,0 +1,63 @@ +name = String::toUTF8($name); + return $this; + } + + /** + * Get Bookmark name + * + * @return string + */ + public function getName() + { + return $this->name; + } +} diff --git a/src/PhpWord/Element/Cell.php b/src/PhpWord/Element/Cell.php index ea49bc7b..cac37a78 100644 --- a/src/PhpWord/Element/Cell.php +++ b/src/PhpWord/Element/Cell.php @@ -52,7 +52,7 @@ class Cell extends AbstractContainer public function __construct($width = null, $style = null) { $this->width = $width; - $this->style = $this->setStyle(new CellStyle(), $style, true); + $this->style = $this->setNewStyle(new CellStyle(), $style, true); } /** diff --git a/src/PhpWord/Element/Chart.php b/src/PhpWord/Element/Chart.php new file mode 100644 index 00000000..66c59ff5 --- /dev/null +++ b/src/PhpWord/Element/Chart.php @@ -0,0 +1,125 @@ +setType($type); + $this->addSeries($categories, $values); + $this->style = $this->setNewStyle(new ChartStyle(), $style, true); + } + + /** + * Get type + * + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * Set type. + * + * @param string $value + * @return void + */ + public function setType($value) + { + $enum = array('pie', 'doughnut', 'line', 'bar', 'column', 'area', 'radar', 'scatter'); + $this->type = $this->setEnumVal($value, $enum, 'pie'); + } + + /** + * Add series + * + * @param array $categories + * @param array $values + * @return void + */ + public function addSeries($categories, $values) + { + $this->series[] = array('categories' => $categories, 'values' => $values); + } + + /** + * Get series + * + * @return array + */ + public function getSeries() + { + return $this->series; + } + + /** + * Get chart style + * + * @return \PhpOffice\PhpWord\Style\Chart + */ + public function getStyle() + { + return $this->style; + } +} diff --git a/src/PhpWord/Element/CheckBox.php b/src/PhpWord/Element/CheckBox.php index a5620580..d3b2a3c6 100644 --- a/src/PhpWord/Element/CheckBox.php +++ b/src/PhpWord/Element/CheckBox.php @@ -21,6 +21,8 @@ use PhpOffice\PhpWord\Shared\String; /** * Check box element + * + * @since 0.10.0 */ class CheckBox extends Text { diff --git a/src/PhpWord/Element/Endnote.php b/src/PhpWord/Element/Endnote.php index 20278898..10000555 100644 --- a/src/PhpWord/Element/Endnote.php +++ b/src/PhpWord/Element/Endnote.php @@ -38,6 +38,6 @@ class Endnote extends Footnote */ public function __construct($paragraphStyle = null) { - $this->paragraphStyle = $this->setStyle(new Paragraph(), $paragraphStyle); + $this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle); } } diff --git a/src/PhpWord/Element/Field.php b/src/PhpWord/Element/Field.php index 50f0522f..1eaa6f24 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -100,7 +100,7 @@ class Field extends AbstractElement public function setType($type = null) { if (isset($type)) { - if (array_key_exists($type, $this->fieldsArray)) { + if (isset($this->fieldsArray[$type])) { $this->type = $type; } else { throw new \InvalidArgumentException("Invalid type"); @@ -130,7 +130,7 @@ class Field extends AbstractElement { if (is_array($properties)) { foreach (array_keys($properties) as $propkey) { - if (!(array_key_exists($propkey, $this->fieldsArray[$this->type]['properties']))) { + if (!(isset($this->fieldsArray[$this->type]['properties'][$propkey]))) { throw new \InvalidArgumentException("Invalid property"); } } @@ -160,7 +160,7 @@ class Field extends AbstractElement { if (is_array($options)) { foreach (array_keys($options) as $optionkey) { - if (!(array_key_exists($optionkey, $this->fieldsArray[$this->type]['options']))) { + if (!(isset($this->fieldsArray[$this->type]['options'][$optionkey]))) { throw new \InvalidArgumentException("Invalid option"); } } diff --git a/src/PhpWord/Element/Footer.php b/src/PhpWord/Element/Footer.php index 142ccfda..8e19eaf7 100644 --- a/src/PhpWord/Element/Footer.php +++ b/src/PhpWord/Element/Footer.php @@ -59,10 +59,12 @@ class Footer extends AbstractContainer } /** - * Set type + * Set type. + * + * @since 0.10.0 * * @param string $value - * @since 0.10.0 + * @return void */ public function setType($value = self::AUTO) { diff --git a/src/PhpWord/Element/Footnote.php b/src/PhpWord/Element/Footnote.php index 76311c6b..162a703e 100644 --- a/src/PhpWord/Element/Footnote.php +++ b/src/PhpWord/Element/Footnote.php @@ -36,6 +36,13 @@ class Footnote extends AbstractContainer */ protected $paragraphStyle; + /** + * Is part of collection + * + * @var bool + */ + protected $collectionRelation = true; + /** * Create new instance * @@ -43,7 +50,8 @@ class Footnote extends AbstractContainer */ public function __construct($paragraphStyle = null) { - $this->paragraphStyle = $this->setStyle(new Paragraph(), $paragraphStyle); + $this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle); + $this->setDocPart($this->container); } /** diff --git a/src/PhpWord/Element/FormField.php b/src/PhpWord/Element/FormField.php new file mode 100644 index 00000000..7bd61be1 --- /dev/null +++ b/src/PhpWord/Element/FormField.php @@ -0,0 +1,195 @@ +setType($type); + } + + /** + * Get type + * + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * Set type + * + * @param string $value + * @return self + */ + public function setType($value) + { + $enum = array('textinput', 'checkbox', 'dropdown'); + $this->type = $this->setEnumVal($value, $enum, $this->type); + + return $this; + } + + /** + * Get name + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Set name + * + * @param string|bool|int $value + * @return self + */ + public function setName($value) + { + $this->name = $value; + + return $this; + } + + /** + * Get default + * + * @return string|bool|int + */ + public function getDefault() + { + return $this->default; + } + + /** + * Set default + * + * @param string|bool|int $value + * @return self + */ + public function setDefault($value) + { + $this->default = $value; + + return $this; + } + + /** + * Get value + * + * @return string|bool|int + */ + public function getValue() + { + return $this->value; + } + + /** + * Set value + * + * @param string|bool|int $value + * @return self + */ + public function setValue($value) + { + $this->value = $value; + + return $this; + } + + /** + * Get entries + * + * @return array + */ + public function getEntries() + { + return $this->entries; + } + + /** + * Set entries + * + * @param array $value + * @return self + */ + public function setEntries($value) + { + $this->entries = $value; + + return $this; + } +} diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php index a1cb8250..cab2527a 100644 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -17,8 +17,10 @@ namespace PhpOffice\PhpWord\Element; +use PhpOffice\PhpWord\Exception\CreateTemporaryFileException; use PhpOffice\PhpWord\Exception\InvalidImageException; use PhpOffice\PhpWord\Exception\UnsupportedImageTypeException; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Shared\ZipArchive; use PhpOffice\PhpWord\Style\Image as ImageStyle; @@ -111,6 +113,13 @@ class Image extends AbstractElement */ private $mediaIndex; + /** + * Has media relation flag; true for Link, Image, and Object + * + * @var bool + */ + protected $mediaRelation = true; + /** * Create new image element * @@ -124,7 +133,7 @@ class Image extends AbstractElement { $this->source = $source; $this->setIsWatermark($watermark); - $this->style = $this->setStyle(new ImageStyle(), $style, true); + $this->style = $this->setNewStyle(new ImageStyle(), $style, true); $this->checkImage($source); } @@ -250,9 +259,10 @@ class Image extends AbstractElement } /** - * Set target file name + * Set target file name. * * @param string $value + * @return void */ public function setTarget($value) { @@ -270,9 +280,10 @@ class Image extends AbstractElement } /** - * Set media index + * Set media index. * * @param integer $value + * @return void */ public function setMediaIndex($value) { @@ -304,8 +315,8 @@ class Image extends AbstractElement if ($zip->open($zipFilename) !== false) { if ($zip->locateName($imageFilename)) { $isTemp = true; - $zip->extractTo(sys_get_temp_dir(), $imageFilename); - $actualSource = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $imageFilename; + $zip->extractTo(Settings::getTempDir(), $imageFilename); + $actualSource = Settings::getTempDir() . DIRECTORY_SEPARATOR . $imageFilename; } } $zip->close(); @@ -351,9 +362,10 @@ class Image extends AbstractElement } /** - * Check memory image, supported type, image functions, and proportional width/height + * Check memory image, supported type, image functions, and proportional width/height. * * @param string $source + * @return void * @throws \PhpOffice\PhpWord\Exception\InvalidImageException * @throws \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException */ @@ -388,9 +400,10 @@ class Image extends AbstractElement } /** - * Set source type + * Set source type. * * @param string $source + * @return void */ private function setSourceType($source) { @@ -409,15 +422,22 @@ class Image extends AbstractElement /** * Get image size from archive * + * @since 0.12.0 Throws CreateTemporaryFileException. + * * @param string $source * @return array|null + * @throws \PhpOffice\PhpWord\Exception\CreateTemporaryFileException */ private function getArchiveImageSize($source) { $imageData = null; $source = substr($source, 6); list($zipFilename, $imageFilename) = explode('#', $source); - $tempFilename = tempnam(sys_get_temp_dir(), 'PHPWordImage'); + + $tempFilename = tempnam(Settings::getTempDir(), 'PHPWordImage'); + if (false === $tempFilename) { + throw new CreateTemporaryFileException(); + } $zip = new ZipArchive(); if ($zip->open($zipFilename) !== false) { @@ -425,7 +445,7 @@ class Image extends AbstractElement $imageContent = $zip->getFromName($imageFilename); if ($imageContent !== false) { file_put_contents($tempFilename, $imageContent); - $imageData = @getimagesize($tempFilename); + $imageData = getimagesize($tempFilename); unlink($tempFilename); } } @@ -436,7 +456,9 @@ class Image extends AbstractElement } /** - * Set image functions and extensions + * Set image functions and extensions. + * + * @return void */ private function setFunctions() { @@ -469,10 +491,11 @@ class Image extends AbstractElement } /** - * Set proportional width/height if one dimension not available + * Set proportional width/height if one dimension not available. * * @param integer $actualWidth * @param integer $actualHeight + * @return void */ private function setProportionalSize($actualWidth, $actualHeight) { diff --git a/src/PhpWord/Element/Line.php b/src/PhpWord/Element/Line.php index 4acca8ed..b76ac4fb 100644 --- a/src/PhpWord/Element/Line.php +++ b/src/PhpWord/Element/Line.php @@ -38,7 +38,7 @@ class Line extends AbstractElement */ public function __construct($style = null) { - $this->style = $this->setStyle(new LineStyle(), $style); + $this->style = $this->setNewStyle(new LineStyle(), $style); } /** diff --git a/src/PhpWord/Element/Link.php b/src/PhpWord/Element/Link.php index 3ffe58d4..9d0eb766 100644 --- a/src/PhpWord/Element/Link.php +++ b/src/PhpWord/Element/Link.php @@ -27,11 +27,11 @@ use PhpOffice\PhpWord\Style\Paragraph; class Link extends AbstractElement { /** - * Link target + * Link source * * @var string */ - private $target; + private $source; /** * Link text @@ -54,33 +54,46 @@ class Link extends AbstractElement */ private $paragraphStyle; + /** + * Has media relation flag; true for Link, Image, and Object + * + * @var bool + */ + protected $mediaRelation = true; + + /** + * Has internal flag - anchor to internal bookmark + * + * @var bool + */ + protected $internal = false; /** * Create a new Link Element * - * @param string $target + * @param string $source * @param string $text * @param mixed $fontStyle * @param mixed $paragraphStyle */ - public function __construct($target, $text = null, $fontStyle = null, $paragraphStyle = null) + public function __construct($source, $text = null, $fontStyle = null, $paragraphStyle = null, $internal = false) { - $this->target = String::toUTF8($target); - $this->text = is_null($text) ? $this->target : String::toUTF8($text); - $this->fontStyle = $this->setStyle(new Font('text'), $fontStyle); - $this->paragraphStyle = $this->setStyle(new Paragraph(), $paragraphStyle); - + $this->source = String::toUTF8($source); + $this->text = is_null($text) ? $this->source : String::toUTF8($text); + $this->fontStyle = $this->setNewStyle(new Font('text'), $fontStyle); + $this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle); + $this->internal = $internal; return $this; } /** - * Get link target + * Get link source * * @return string */ - public function getTarget() + public function getSource() { - return $this->target; + return $this->source; } /** @@ -113,6 +126,18 @@ class Link extends AbstractElement return $this->paragraphStyle; } + /** + * Get link target + * + * @return string + * @deprecated 0.12.0 + * @codeCoverageIgnore + */ + public function getTarget() + { + return $this->source; + } + /** * Get Link source * @@ -122,7 +147,7 @@ class Link extends AbstractElement */ public function getLinkSrc() { - return $this->getTarget(); + return $this->getSource(); } /** @@ -136,4 +161,14 @@ class Link extends AbstractElement { return $this->getText(); } + + /** + * is internal + * + * @return bool + */ + public function isInternal() + { + return $this->internal; + } } diff --git a/src/PhpWord/Element/ListItem.php b/src/PhpWord/Element/ListItem.php index 59bd8391..4cb8d339 100644 --- a/src/PhpWord/Element/ListItem.php +++ b/src/PhpWord/Element/ListItem.php @@ -64,7 +64,7 @@ class ListItem extends AbstractElement if (!is_null($listStyle) && is_string($listStyle)) { $this->style = new ListItemStyle($listStyle); } else { - $this->style = $this->setStyle(new ListItemStyle(), $listStyle, true); + $this->style = $this->setNewStyle(new ListItemStyle(), $listStyle, true); } } diff --git a/src/PhpWord/Element/ListItemRun.php b/src/PhpWord/Element/ListItemRun.php index fb219f91..1b77830d 100644 --- a/src/PhpWord/Element/ListItemRun.php +++ b/src/PhpWord/Element/ListItemRun.php @@ -59,13 +59,15 @@ class ListItemRun extends TextRun if (!is_null($listStyle) && is_string($listStyle)) { $this->style = new ListItemStyle($listStyle); } else { - $this->style = $this->setStyle(new ListItemStyle(), $listStyle, true); + $this->style = $this->setNewStyle(new ListItemStyle(), $listStyle, true); } - $this->paragraphStyle = $this->setStyle(new Paragraph(), $paragraphStyle); + $this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle); } /** - * Get ListItem style + * Get ListItem style. + * + * @return \PhpOffice\PhpWord\Style\ListItem */ public function getStyle() { @@ -73,7 +75,9 @@ class ListItemRun extends TextRun } /** - * Get ListItem depth + * Get ListItem depth. + * + * @return int */ public function getDepth() { diff --git a/src/PhpWord/Element/Object.php b/src/PhpWord/Element/Object.php index a63c1869..31943ba6 100644 --- a/src/PhpWord/Element/Object.php +++ b/src/PhpWord/Element/Object.php @@ -53,6 +53,13 @@ class Object extends AbstractElement */ private $imageRelationId; + /** + * Has media relation flag; true for Link, Image, and Object + * + * @var bool + */ + protected $mediaRelation = true; + /** * Create a new Ole-Object Element * @@ -72,7 +79,7 @@ class Object extends AbstractElement } $this->source = $source; - $this->style = $this->setStyle(new ImageStyle(), $style, true); + $this->style = $this->setNewStyle(new ImageStyle(), $style, true); $this->icon = realpath(__DIR__ . "/../resources/{$ext}.png"); return $this; @@ -122,9 +129,10 @@ class Object extends AbstractElement } /** - * Set Image Relation ID + * Set Image Relation ID. * * @param int $rId + * @return void */ public function setImageRelationId($rId) { diff --git a/src/PhpWord/Element/PreserveText.php b/src/PhpWord/Element/PreserveText.php index 100385c9..44aef3b4 100644 --- a/src/PhpWord/Element/PreserveText.php +++ b/src/PhpWord/Element/PreserveText.php @@ -58,8 +58,8 @@ class PreserveText extends AbstractElement */ public function __construct($text = null, $fontStyle = null, $paragraphStyle = null) { - $this->fontStyle = $this->setStyle(new Font('text'), $fontStyle); - $this->paragraphStyle = $this->setStyle(new Paragraph(), $paragraphStyle); + $this->fontStyle = $this->setNewStyle(new Font('text'), $fontStyle); + $this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle); $this->text = String::toUTF8($text); $matches = preg_split('/({.*?})/', $this->text, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); diff --git a/src/PhpWord/Element/Row.php b/src/PhpWord/Element/Row.php index d7dcea34..e2df6325 100644 --- a/src/PhpWord/Element/Row.php +++ b/src/PhpWord/Element/Row.php @@ -56,7 +56,7 @@ class Row extends AbstractElement public function __construct($height = null, $style = null) { $this->height = $height; - $this->style = $this->setStyle(new RowStyle(), $style, true); + $this->style = $this->setNewStyle(new RowStyle(), $style, true); } /** @@ -69,9 +69,7 @@ class Row extends AbstractElement public function addCell($width = null, $style = null) { $cell = new Cell($width, $style); - $cell->setDocPart($this->getDocPart(), $this->getDocPartId()); - $cell->setPhpWord($this->phpWord); - $cell->setNestedLevel($this->getNestedLevel()); + $cell->setParentContainer($this); $this->cells[] = $cell; return $cell; diff --git a/src/PhpWord/Element/SDT.php b/src/PhpWord/Element/SDT.php new file mode 100644 index 00000000..c69ed427 --- /dev/null +++ b/src/PhpWord/Element/SDT.php @@ -0,0 +1,130 @@ +setType($type); + } + + /** + * Get type + * + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * Set type + * + * @param string $value + * @return self + */ + public function setType($value) + { + $enum = array('comboBox', 'dropDownList', 'date'); + $this->type = $this->setEnumVal($value, $enum, 'comboBox'); + + return $this; + } + + /** + * Get value + * + * @return string|bool|int + */ + public function getValue() + { + return $this->value; + } + + /** + * Set value + * + * @param string|bool|int $value + * @return self + */ + public function setValue($value) + { + $this->value = $value; + + return $this; + } + + /** + * Get listItems + * + * @return array + */ + public function getListItems() + { + return $this->listItems; + } + + /** + * Set listItems + * + * @param array $value + * @return self + */ + public function setListItems($value) + { + $this->listItems = $value; + + return $this; + } +} diff --git a/src/PhpWord/Element/Section.php b/src/PhpWord/Element/Section.php index b7cee6a2..d746f69b 100644 --- a/src/PhpWord/Element/Section.php +++ b/src/PhpWord/Element/Section.php @@ -18,7 +18,7 @@ namespace PhpOffice\PhpWord\Element; use PhpOffice\PhpWord\Exception\Exception; -use PhpOffice\PhpWord\Style\Section as SectionSettings; +use PhpOffice\PhpWord\Style\Section as SectionStyle; /** * Section @@ -31,11 +31,11 @@ class Section extends AbstractContainer protected $container = 'Section'; /** - * Section settings + * Section style * * @var \PhpOffice\PhpWord\Style\Section */ - private $settings; + private $style; /** * Section headers, indexed from 1, not zero @@ -55,75 +55,37 @@ class Section extends AbstractContainer * Create new instance * * @param int $sectionCount - * @param array $settings + * @param array $style */ - public function __construct($sectionCount, $settings = null) + public function __construct($sectionCount, $style = null) { $this->sectionId = $sectionCount; $this->setDocPart($this->container, $this->sectionId); - $this->settings = new SectionSettings(); - $this->setSettings($settings); + $this->style = new SectionStyle(); + $this->setStyle($style); } /** - * Set section settings + * Set section style. * - * @param array $settings + * @param array $style + * @return void */ - public function setSettings($settings = null) + public function setStyle($style = null) { - if (!is_null($settings) && is_array($settings)) { - foreach ($settings as $key => $value) { - if (is_null($value)) { - continue; - } - $this->settings->setSettingValue($key, $value); - } + if (!is_null($style) && is_array($style)) { + $this->style->setStyleByArray($style); } } /** - * Get Section Settings + * Get section style * * @return \PhpOffice\PhpWord\Style\Section */ - public function getSettings() + public function getStyle() { - return $this->settings; - } - - /** - * Add a Title Element - * - * @param string $text - * @param int $depth - * @return \PhpOffice\PhpWord\Element\Title - */ - public function addTitle($text, $depth = 1) - { - return $this->addElement('Title', $text, $depth); - } - - /** - * Add a PageBreak Element - */ - public function addPageBreak() - { - return $this->addElement('PageBreak'); - } - - /** - * Add a Table-of-Contents Element - * - * @param mixed $fontStyle - * @param mixed $tocStyle - * @param integer $minDepth - * @param integer $maxDepth - * @return \PhpOffice\PhpWord\Element\TOC - */ - public function addTOC($fontStyle = null, $tocStyle = null, $minDepth = 1, $maxDepth = 9) - { - return $this->addElement('TOC', $fontStyle, $tocStyle, $minDepth, $maxDepth); + return $this->style; } /** @@ -218,6 +180,30 @@ class Section extends AbstractContainer } + /** + * Set section style + * + * @param array $settings + * @deprecated 0.12.0 + * @codeCoverageIgnore + */ + public function setSettings($settings = null) + { + $this->setStyle($settings); + } + + /** + * Get section style + * + * @return \PhpOffice\PhpWord\Style\Section + * @deprecated 0.12.0 + * @codeCoverageIgnore + */ + public function getSettings() + { + return $this->getStyle(); + } + /** * Create header * diff --git a/src/PhpWord/Element/Shape.php b/src/PhpWord/Element/Shape.php new file mode 100644 index 00000000..a7a96d18 --- /dev/null +++ b/src/PhpWord/Element/Shape.php @@ -0,0 +1,88 @@ +setType($type); + $this->style = $this->setNewStyle(new ShapeStyle(), $style); + } + + /** + * Get type + * + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * Set pattern + * + * @param string $value + * @return self + */ + public function setType($value = null) + { + $enum = array('arc', 'curve', 'line', 'polyline', 'rect', 'oval'); + $this->type = $this->setEnumVal($value, $enum, null); + + return $this; + } + + /** + * Get shape style + * + * @return \PhpOffice\PhpWord\Style\Shape + */ + public function getStyle() + { + return $this->style; + } +} diff --git a/src/PhpWord/Element/TOC.php b/src/PhpWord/Element/TOC.php index 9ac74554..a56d9ffe 100644 --- a/src/PhpWord/Element/TOC.php +++ b/src/PhpWord/Element/TOC.php @@ -129,9 +129,10 @@ class TOC extends AbstractElement } /** - * Set max depth + * Set max depth. * * @param int $value + * @return void */ public function setMaxDepth($value) { @@ -149,9 +150,10 @@ class TOC extends AbstractElement } /** - * Set min depth + * Set min depth. * * @param int $value + * @return void */ public function setMinDepth($value) { diff --git a/src/PhpWord/Element/Table.php b/src/PhpWord/Element/Table.php index ace63460..5f0b8f79 100644 --- a/src/PhpWord/Element/Table.php +++ b/src/PhpWord/Element/Table.php @@ -52,7 +52,7 @@ class Table extends AbstractElement */ public function __construct($style = null) { - $this->style = $this->setStyle(new TableStyle(), $style); + $this->style = $this->setNewStyle(new TableStyle(), $style); } /** @@ -65,9 +65,7 @@ class Table extends AbstractElement public function addRow($height = null, $style = null) { $row = new Row($height, $style); - $row->setDocPart($this->getDocPart(), $this->getDocPartId()); - $row->setPhpWord($this->phpWord); - $row->setNestedLevel($this->getNestedLevel()); + $row->setParentContainer($this); $this->rows[] = $row; return $row; @@ -120,9 +118,10 @@ class Table extends AbstractElement } /** - * Set table width + * Set table width. * * @param int $width + * @return void */ public function setWidth($width) { diff --git a/src/PhpWord/Element/TextBox.php b/src/PhpWord/Element/TextBox.php index 06c95181..d929bf35 100644 --- a/src/PhpWord/Element/TextBox.php +++ b/src/PhpWord/Element/TextBox.php @@ -45,7 +45,7 @@ class TextBox extends AbstractContainer */ public function __construct($style = null) { - $this->style = $this->setStyle(new TextBoxStyle(), $style); + $this->style = $this->setNewStyle(new TextBoxStyle(), $style); } /** diff --git a/src/PhpWord/Element/TextRun.php b/src/PhpWord/Element/TextRun.php index 75837104..c356cfa8 100644 --- a/src/PhpWord/Element/TextRun.php +++ b/src/PhpWord/Element/TextRun.php @@ -43,7 +43,7 @@ class TextRun extends AbstractContainer */ public function __construct($paragraphStyle = null) { - $this->paragraphStyle = $this->setStyle(new Paragraph(), $paragraphStyle); + $this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle); } /** diff --git a/src/PhpWord/Element/Title.php b/src/PhpWord/Element/Title.php index d5206879..cf1d49c8 100644 --- a/src/PhpWord/Element/Title.php +++ b/src/PhpWord/Element/Title.php @@ -46,6 +46,13 @@ class Title extends AbstractElement */ private $style; + /** + * Is part of collection + * + * @var bool + */ + protected $collectionRelation = true; + /** * Create a new Title Element * @@ -54,11 +61,10 @@ class Title extends AbstractElement */ public function __construct($text, $depth = 1) { - $this->text = String::toUTF8($text); $this->depth = $depth; - if (array_key_exists('Heading_' . $this->depth, Style::getStyles())) { - $this->style = 'Heading' . $this->depth; + if (array_key_exists("Heading_{$this->depth}", Style::getStyles())) { + $this->style = "Heading{$this->depth}"; } return $this; diff --git a/src/PhpWord/Exception/CopyFileException.php b/src/PhpWord/Exception/CopyFileException.php new file mode 100644 index 00000000..97a900e3 --- /dev/null +++ b/src/PhpWord/Exception/CopyFileException.php @@ -0,0 +1,39 @@ +load($filename); } - /** * Check if it's a concrete class (not abstract nor interface) * @@ -82,7 +86,6 @@ abstract class IOFactory private static function isConcreteClass($class) { $reflection = new \ReflectionClass($class); - return !$reflection->isAbstract() && !$reflection->isInterface(); } } diff --git a/src/PhpWord/Media.php b/src/PhpWord/Media.php index 7f35841c..59735cea 100644 --- a/src/PhpWord/Media.php +++ b/src/PhpWord/Media.php @@ -44,16 +44,16 @@ class Media * @since 0.9.2 * @since 0.10.0 */ - public static function addElement($container, $mediaType, $source, Image &$image = null) + public static function addElement($container, $mediaType, $source, Image $image = null) { // Assign unique media Id and initiate media container if none exists $mediaId = md5($container . $source); - if (!array_key_exists($container, self::$elements)) { + if (!isset(self::$elements[$container])) { self::$elements[$container] = array(); } // Add media if not exists or point to existing media - if (!array_key_exists($mediaId, self::$elements[$container])) { + if (!isset(self::$elements[$container][$mediaId])) { $mediaCount = self::countElements($container); $mediaTypeCount = self::countElements($container, $mediaType); $mediaTypeCount++; @@ -120,7 +120,7 @@ class Media { $mediaCount = 0; - if (array_key_exists($container, self::$elements)) { + if (isset(self::$elements[$container])) { foreach (self::$elements[$container] as $mediaData) { if (!is_null($mediaType)) { if ($mediaType == $mediaData['type']) { @@ -156,7 +156,7 @@ class Media } return $elements; } else { - if (!array_key_exists($container, self::$elements)) { + if (!isset(self::$elements[$container])) { return $elements; } return self::getElementsByType($container, $type); diff --git a/src/PhpWord/Metadata/Compatibility.php b/src/PhpWord/Metadata/Compatibility.php new file mode 100644 index 00000000..d78b97f1 --- /dev/null +++ b/src/PhpWord/Metadata/Compatibility.php @@ -0,0 +1,62 @@ +ooxmlVersion; + } + + /** + * Set OOXML version + * + * @param int $value + * @return self + */ + public function setOoxmlVersion($value) + { + $this->ooxmlVersion = $value; + + return $this; + } +} diff --git a/src/PhpWord/DocumentProperties.php b/src/PhpWord/Metadata/DocInfo.php similarity index 99% rename from src/PhpWord/DocumentProperties.php rename to src/PhpWord/Metadata/DocInfo.php index 5644c3d9..9643685f 100644 --- a/src/PhpWord/DocumentProperties.php +++ b/src/PhpWord/Metadata/DocInfo.php @@ -15,12 +15,12 @@ * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ -namespace PhpOffice\PhpWord; +namespace PhpOffice\PhpWord\Metadata; /** - * Document properties + * Document information */ -class DocumentProperties +class DocInfo { /** @const string Property type constants */ const PROPERTY_TYPE_BOOLEAN = 'b'; @@ -115,7 +115,7 @@ class DocumentProperties private $customProperties = array(); /** - * Create new DocumentProperties + * Create new instance */ public function __construct() { diff --git a/src/PhpWord/Metadata/Protection.php b/src/PhpWord/Metadata/Protection.php new file mode 100644 index 00000000..3556ce8c --- /dev/null +++ b/src/PhpWord/Metadata/Protection.php @@ -0,0 +1,69 @@ +setEditing($editing); + } + + /** + * Get editing protection + * + * @return string + */ + public function getEditing() + { + return $this->editing; + } + + /** + * Set editing protection + * + * @param string $editing + * @return self + */ + public function setEditing($editing = null) + { + $this->editing = $editing; + + return $this; + } +} diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index c54faa36..99c95c79 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -17,14 +17,28 @@ namespace PhpOffice\PhpWord; -use PhpOffice\PhpWord\Collection\Endnotes; -use PhpOffice\PhpWord\Collection\Footnotes; -use PhpOffice\PhpWord\Collection\Titles; use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\Exception\Exception; /** * PHPWord main class + * + * @method Collection\Titles getTitles() + * @method Collection\Footnotes getFootnotes() + * @method Collection\Endnotes getEndnotes() + * @method Collection\Charts getCharts() + * @method int addBookmark(Element\Bookmark $bookmark) + * @method int addTitle(Element\Title $title) + * @method int addFootnote(Element\Footnote $footnote) + * @method int addEndnote(Element\Endnote $endnote) + * @method int addChart(Element\Chart $chart) + * + * @method Style\Paragraph addParagraphStyle(string $styleName, array $styles) + * @method Style\Font addFontStyle(string $styleName, mixed $fontStyle, mixed $paragraphStyle = null) + * @method Style\Font addLinkStyle(string $styleName, mixed $styles) + * @method Style\Font addTitleStyle(int $depth, mixed $fontStyle, mixed $paragraphStyle = null) + * @method Style\Table addTableStyle(string $styleName, mixed $styleTable, mixed $styleFirstRow = null) + * @method Style\Numbering addNumberingStyle(string $styleName, mixed $styles) */ class PhpWord { @@ -39,13 +53,6 @@ class PhpWord const DEFAULT_FONT_COLOR = Settings::DEFAULT_FONT_COLOR; const DEFAULT_FONT_CONTENT_TYPE = Settings::DEFAULT_FONT_CONTENT_TYPE; - /** - * Document properties object - * - * @var DocumentProperties - */ - private $documentProperties; - /** * Collection of sections * @@ -54,58 +61,126 @@ class PhpWord private $sections = array(); /** - * Collection of titles + * Collections * - * @var \PhpOffice\PhpWord\Collection\Titles + * @var array */ - private $titles; + private $collections = array(); /** - * Collection of footnotes + * Metadata * - * @var \PhpOffice\PhpWord\Collection\Footnotes + * @var array + * @since 0.12.0 */ - private $footnotes; + private $metadata = array(); /** - * Collection of endnotes + * Create new instance * - * @var \PhpOffice\PhpWord\Collection\Endnotes - */ - private $endnotes; - - /** - * Create new + * Collections are created dynamically */ public function __construct() { - $this->documentProperties = new DocumentProperties(); - $this->titles = new Titles(); - $this->footnotes = new Footnotes(); - $this->endnotes = new Endnotes(); + // Collection + $collections = array('Bookmarks', 'Titles', 'Footnotes', 'Endnotes', 'Charts'); + foreach ($collections as $collection) { + $class = 'PhpOffice\\PhpWord\\Collection\\' . $collection; + $this->collections[$collection] = new $class(); + } + + // Metadata + $metadata = array('DocInfo', 'Protection', 'Compatibility'); + foreach ($metadata as $meta) { + $class = 'PhpOffice\\PhpWord\\Metadata\\' . $meta; + $this->metadata[$meta] = new $class(); + } + } + + /** + * Dynamic function call to reduce static dependency + * + * @param mixed $function + * @param mixed $args + * @throws \BadMethodCallException + * @return mixed + * @since 0.12.0 + */ + public function __call($function, $args) + { + $function = strtolower($function); + + $getCollection = array(); + $addCollection = array(); + $addStyle = array(); + + $collections = array('Bookmark', 'Title', 'Footnote', 'Endnote', 'Chart'); + foreach ($collections as $collection) { + $getCollection[] = strtolower("get{$collection}s"); + $addCollection[] = strtolower("add{$collection}"); + } + + $styles = array('Paragraph', 'Font', 'Table', 'Numbering', 'Link', 'Title'); + foreach ($styles as $style) { + $addStyle[] = strtolower("add{$style}Style"); + } + + // Run get collection method + if (in_array($function, $getCollection)) { + $key = ucfirst(str_replace('get', '', $function)); + + return $this->collections[$key]; + } + + // Run add collection item method + if (in_array($function, $addCollection)) { + $key = ucfirst(str_replace('add', '', $function) . 's'); + + /** @var \PhpOffice\PhpWord\Collection\AbstractCollection $collectionObject */ + $collectionObject = $this->collections[$key]; + + return $collectionObject->addItem(isset($args[0]) ? $args[0] : null); + } + + // Run add style method + if (in_array($function, $addStyle)) { + return forward_static_call_array(array('PhpOffice\\PhpWord\\Style', $function), $args); + } + + // Exception + throw new \BadMethodCallException("Method $function is not defined."); } /** * Get document properties object * - * @return DocumentProperties + * @return \PhpOffice\PhpWord\Metadata\DocInfo */ - public function getDocumentProperties() + public function getDocInfo() { - return $this->documentProperties; + return $this->metadata['DocInfo']; } /** - * Set document properties object + * Get protection * - * @param DocumentProperties $documentProperties - * @return self + * @return \PhpOffice\PhpWord\Metadata\Protection + * @since 0.12.0 */ - public function setDocumentProperties(DocumentProperties $documentProperties) + public function getProtection() { - $this->documentProperties = $documentProperties; + return $this->metadata['Protection']; + } - return $this; + /** + * Get compatibility + * + * @return \PhpOffice\PhpWord\Metadata\Compatibility + * @since 0.12.0 + */ + public function getCompatibility() + { + return $this->metadata['Compatibility']; } /** @@ -121,81 +196,18 @@ class PhpWord /** * Create new section * - * @param array $settings + * @param array $style * @return \PhpOffice\PhpWord\Element\Section */ - public function addSection($settings = null) + public function addSection($style = null) { - $section = new Section(count($this->sections) + 1, $settings); + $section = new Section(count($this->sections) + 1, $style); $section->setPhpWord($this); $this->sections[] = $section; return $section; } - /** - * Get titles - * - * @return \PhpOffice\PhpWord\Collection\Titles - */ - public function getTitles() - { - return $this->titles; - } - - /** - * Add new title - * - * @param \PhpOffice\PhpWord\Element\Title $title - * @return int - */ - public function addTitle($title) - { - return $this->titles->addItem($title); - } - - /** - * Get footnotes - * - * @return \PhpOffice\PhpWord\Collection\Footnotes - */ - public function getFootnotes() - { - return $this->footnotes; - } - - /** - * Add new footnote - * - * @param \PhpOffice\PhpWord\Element\Footnote $footnote - * @return int - */ - public function addFootnote($footnote) - { - return $this->footnotes->addItem($footnote); - } - - /** - * Get endnotes - * - * @return \PhpOffice\PhpWord\Collection\Endnotes - */ - public function getEndnotes() - { - return $this->endnotes; - } - - /** - * Add new endnote - * - * @param \PhpOffice\PhpWord\Element\Endnote $endnote - * @return int - */ - public function addEndnote($endnote) - { - return $this->endnotes->addItem($endnote); - } - /** * Get default font name * @@ -207,9 +219,10 @@ class PhpWord } /** - * Set default font name + * Set default font name. * * @param string $fontName + * @return void */ public function setDefaultFontName($fontName) { @@ -227,9 +240,10 @@ class PhpWord } /** - * Set default font size + * Set default font size. * * @param int $fontSize + * @return void */ public function setDefaultFontSize($fontSize) { @@ -247,97 +261,61 @@ class PhpWord return Style::setDefaultParagraphStyle($styles); } - /** - * Adds a paragraph style definition to styles.xml - * - * @param string $styleName - * @param array $styles - * @return \PhpOffice\PhpWord\Style\Paragraph - */ - public function addParagraphStyle($styleName, $styles) - { - return Style::addParagraphStyle($styleName, $styles); - } - - /** - * Adds a font style definition to styles.xml - * - * @param string $styleName - * @param mixed $fontStyle - * @param mixed $paragraphStyle - * @return \PhpOffice\PhpWord\Style\Font - */ - public function addFontStyle($styleName, $fontStyle, $paragraphStyle = null) - { - return Style::addFontStyle($styleName, $fontStyle, $paragraphStyle); - } - - /** - * Adds a table style definition to styles.xml - * - * @param string $styleName - * @param mixed $styleTable - * @param mixed $styleFirstRow - * @return \PhpOffice\PhpWord\Style\Table - */ - public function addTableStyle($styleName, $styleTable, $styleFirstRow = null) - { - return Style::addTableStyle($styleName, $styleTable, $styleFirstRow); - } - - /** - * Adds a numbering style - * - * @param string $styleName - * @param mixed $styles - * @return \PhpOffice\PhpWord\Style\Numbering - */ - public function addNumberingStyle($styleName, $styles) - { - return Style::addNumberingStyle($styleName, $styles); - } - - /** - * Adds a hyperlink style to styles.xml - * - * @param string $styleName - * @param mixed $styles - * @return \PhpOffice\PhpWord\Style\Font - */ - public function addLinkStyle($styleName, $styles) - { - return Style::addLinkStyle($styleName, $styles); - } - - /** - * Adds a heading style definition to styles.xml - * - * @param int $depth - * @param mixed $fontStyle - * @param mixed $paragraphStyle - * @return \PhpOffice\PhpWord\Style\Font - */ - public function addTitleStyle($depth, $fontStyle, $paragraphStyle = null) - { - return Style::addTitleStyle($depth, $fontStyle, $paragraphStyle); - } - /** * Load template by filename * + * @deprecated 0.12.0 Use `new TemplateProcessor($documentTemplate)` instead. + * * @param string $filename Fully qualified filename. - * @return Template + * @return TemplateProcessor * @throws \PhpOffice\PhpWord\Exception\Exception */ public function loadTemplate($filename) { if (file_exists($filename)) { - return new Template($filename); + return new TemplateProcessor($filename); } else { throw new Exception("Template file {$filename} not found."); } } + /** + * Save to file or download + * + * All exceptions should already been handled by the writers + * + * @param string $filename + * @param string $format + * @param bool $download + * @return bool + */ + public function save($filename, $format = 'Word2007', $download = false) + { + $mime = array( + 'Word2007' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'ODText' => 'application/vnd.oasis.opendocument.text', + 'RTF' => 'application/rtf', + 'HTML' => 'text/html', + 'PDF' => 'application/pdf', + ); + + $writer = IOFactory::createWriter($this, $format); + + if ($download === true) { + header("Content-Description: File Transfer"); + header('Content-Disposition: attachment; filename="' . $filename . '"'); + header('Content-Type: ' . $mime[$format]); + header('Content-Transfer-Encoding: binary'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header('Expires: 0'); + $filename = 'php://output'; // Change filename to force download + } + + $writer->save($filename); + + return true; + } + /** * Create new section * @@ -350,4 +328,31 @@ class PhpWord { return $this->addSection($settings); } + + /** + * Get document properties object + * + * @return \PhpOffice\PhpWord\Metadata\DocInfo + * @deprecated 0.12.0 + * @codeCoverageIgnore + */ + public function getDocumentProperties() + { + return $this->getDocInfo(); + } + + /** + * Set document properties object + * + * @param \PhpOffice\PhpWord\Metadata\DocInfo $documentProperties + * @return self + * @deprecated 0.12.0 + * @codeCoverageIgnore + */ + public function setDocumentProperties($documentProperties) + { + $this->metadata['Document'] = $documentProperties; + + return $this; + } } diff --git a/src/PhpWord/Reader/MsDoc.php b/src/PhpWord/Reader/MsDoc.php new file mode 100644 index 00000000..c63d8d9e --- /dev/null +++ b/src/PhpWord/Reader/MsDoc.php @@ -0,0 +1,2341 @@ +phpWord = new PhpWord(); + + $this->loadOLE($filename); + + $this->readFib($this->dataWorkDocument); + $this->readFibContent(); + + return $this->phpWord; + } + + /** + * Load an OLE Document + * @param string $filename + */ + private function loadOLE($filename) + { + // OLE reader + $ole = new OLERead(); + $ole->read($filename); + + // Get WorkDocument stream + $this->dataWorkDocument = $ole->getStream($ole->wrkdocument); + // Get 1Table stream + $this->data1Table = $ole->getStream($ole->wrk1Table); + // Get Data stream + $this->dataData = $ole->getStream($ole->wrkData); + // Get Data stream + $this->dataObjectPool = $ole->getStream($ole->wrkObjectPool); + // Get Summary Information data + $this->_SummaryInformation = $ole->getStream($ole->summaryInformation); + // Get Document Summary Information data + $this->_DocumentSummaryInformation = $ole->getStream($ole->documentSummaryInformation); + } + + private function getNumInLcb($lcb, $iSize) + { + return ($lcb - 4) / (4 + $iSize); + } + + private function getArrayCP($data, $posMem, $iNum) + { + $arrayCP = array(); + for ($inc = 0; $inc < $iNum; $inc++) { + $arrayCP[$inc] = self::getInt4d($data, $posMem); + $posMem += 4; + } + return $arrayCP; + } + + /** + * + * @link http://msdn.microsoft.com/en-us/library/dd949344%28v=office.12%29.aspx + * @link https://igor.io/2012/09/24/binary-parsing.html + */ + private function readFib($data) + { + $pos = 0; + //----- FibBase + // wIdent + $pos += 2; + // nFib + $pos += 2; + // unused + $pos += 2; + // lid : Language Identifier + $pos += 2; + // pnNext + $pos += 2; + + // $mem = self::getInt2d($data, $pos); + // $fDot = ($mem >> 15) & 1; + // $fGlsy = ($mem >> 14) & 1; + // $fComplex = ($mem >> 13) & 1; + // $fHasPic = ($mem >> 12) & 1; + // $cQuickSaves = ($mem >> 8) & bindec('1111'); + // $fEncrypted = ($mem >> 7) & 1; + // $fWhichTblStm = ($mem >> 6) & 1; + // $fReadOnlyRecommended = ($mem >> 5) & 1; + // $fWriteReservation = ($mem >> 4) & 1; + // $fExtChar = ($mem >> 3) & 1; + // $fLoadOverride = ($mem >> 2) & 1; + // $fFarEast = ($mem >> 1) & 1; + // $fObfuscated = ($mem >> 0) & 1; + $pos += 2; + // nFibBack + $pos += 2; + // lKey + $pos += 4; + // envr + $pos += 1; + + // $mem = self::getInt1d($data, $pos); + // $fMac = ($mem >> 7) & 1; + // $fEmptySpecial = ($mem >> 6) & 1; + // $fLoadOverridePage = ($mem >> 5) & 1; + // $reserved1 = ($mem >> 4) & 1; + // $reserved2 = ($mem >> 3) & 1; + // $fSpare0 = ($mem >> 0) & bindec('111'); + $pos += 1; + + // reserved3 + $pos += 2; + // reserved4 + $pos += 2; + // reserved5 + $pos += 4; + // reserved6 + $pos += 4; + + //----- csw + $pos += 2; + + //----- fibRgW + // reserved1 + $pos += 2; + // reserved2 + $pos += 2; + // reserved3 + $pos += 2; + // reserved4 + $pos += 2; + // reserved5 + $pos += 2; + // reserved6 + $pos += 2; + // reserved7 + $pos += 2; + // reserved8 + $pos += 2; + // reserved9 + $pos += 2; + // reserved10 + $pos += 2; + // reserved11 + $pos += 2; + // reserved12 + $pos += 2; + // reserved13 + $pos += 2; + // lidFE + $pos += 2; + + //----- cslw + $pos += 2; + + //----- fibRgLw + // cbMac + $pos += 4; + // reserved1 + $pos += 4; + // reserved2 + $pos += 4; + $this->arrayFib['ccpText'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['ccpFtn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['ccpHdd'] = self::getInt4d($data, $pos); + $pos += 4; + // reserved3 + $pos += 4; + // ccpAtn + $pos += 4; + // ccpEdn + $pos += 4; + // ccpTxbx + $pos += 4; + // ccpHdrTxbx + $pos += 4; + // reserved4 + $pos += 4; + // reserved5 + $pos += 4; + // reserved6 + $pos += 4; + // reserved7 + $pos += 4; + // reserved8 + $pos += 4; + // reserved9 + $pos += 4; + // reserved10 + $pos += 4; + // reserved11 + $pos += 4; + // reserved12 + $pos += 4; + // reserved13 + $pos += 4; + // reserved14 + $pos += 4; + + //----- cbRgFcLcb + $cbRgFcLcb = self::getInt2d($data, $pos); + $pos += 2; + //----- fibRgFcLcbBlob + switch ($cbRgFcLcb) { + case 0x005D: + $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_97); + break; + case 0x006C: + $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_97); + $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2000); + break; + case 0x0088: + $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_97); + $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2000); + $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2002); + break; + case 0x00A4: + $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_97); + $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2000); + $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2002); + $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2003); + break; + case 0x00B7: + $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_97); + $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2000); + $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2002); + $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2003); + $pos = $this->readBlockFibRgFcLcb($data, $pos, self::VERSION_2007); + break; + } + //----- cswNew + $this->arrayFib['cswNew'] = self::getInt2d($data, $pos); + $pos += 2; + + if ($this->arrayFib['cswNew'] != 0) { + //@todo : fibRgCswNew + } + + return $pos; + } + + private function readBlockFibRgFcLcb($data, $pos, $version) + { + if ($version == self::VERSION_97) { + $this->arrayFib['fcStshfOrig'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbStshfOrig'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcStshf'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbStshf'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcffndRef'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcffndRef'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcffndTxt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcffndTxt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfandRef'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfandRef'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfandTxt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfandTxt '] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfSed'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfSed'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcPad'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcPad'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfPhe'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfPhe'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfGlsy'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfGlsy'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfGlsy'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfGlsy'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfHdd'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfHdd'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBteChpx'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBteChpx'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBtePapx'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBtePapx'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfSea'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfSea'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfFfn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfFfn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfFldMom'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfFldMom'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfFldHdr'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfFldHdr'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfFldFtn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfFldFtn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfFldAtn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfFldAtn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfFldMcr'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfFldMcr'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfBkmk'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfBkmk'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBkf'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBkf'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBkl'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBkl'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcCmds'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbCmds'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcUnused1'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbUnused1'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfMcr'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfMcr'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPrDrvr'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPrDrvr'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPrEnvPort'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPrEnvPort'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPrEnvLand'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPrEnvLand'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcWss'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbWss'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcDop'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbDop'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfAssoc'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfAssoc'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcClx'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbClx'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfPgdFtn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfPgdFtn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcAutosaveSource'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbAutosaveSource'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcGrpXstAtnOwners'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbGrpXstAtnOwners'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfAtnBkmk'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfAtnBkmk'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcUnused2'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbUnused2'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcUnused3'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbUnused3'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcSpaMom'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcSpaMom'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcSpaHdr'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcSpaHdr'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfAtnBkf'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfAtnBkf'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfAtnBkl'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfAtnBkl'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPms'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPms'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcFormFldSttbs'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbFormFldSttbs'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfendRef'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfendRef'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfendTxt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfendTxt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfFldEdn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfFldEdn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcUnused4'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbUnused4'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcDggInfo'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbDggInfo'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfRMark'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfRMark'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfCaption'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfCaption'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfAutoCaption'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfAutoCaption'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfWkb'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfWkb'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfSpl'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfSpl'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcftxbxTxt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcftxbxTxt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfFldTxbx'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfFldTxbx'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfHdrtxbxTxt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfHdrtxbxTxt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcffldHdrTxbx'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcffldHdrTxbx'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcStwUser'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbStwUser'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbTtmbd'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbTtmbd'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcCookieData'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbCookieData'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPgdMotherOldOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPgdMotherOldOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcBkdMotherOldOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbBkdMotherOldOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPgdFtnOldOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPgdFtnOldOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcBkdFtnOldOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbBkdFtnOldOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPgdEdnOldOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPgdEdnOldOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcBkdEdnOldOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbBkdEdnOldOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfIntlFld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfIntlFld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcRouteSlip'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbRouteSlip'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbSavedBy'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbSavedBy'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbFnm'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbFnm'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlfLst'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlfLst'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlfLfo'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlfLfo'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfTxbxBkd'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfTxbxBkd'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfTxbxHdrBkd'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfTxbxHdrBkd'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcDocUndoWord9'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbDocUndoWord9'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcRgbUse'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbRgbUse'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcUsp'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbUsp'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcUskf'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbUskf'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcupcRgbUse'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcupcRgbUse'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcupcUsp'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcupcUsp'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbGlsyStyle'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbGlsyStyle'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlgosl'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlgosl'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcocx'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcocx'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBteLvc'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBteLvc'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['dwLowDateTime'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['dwHighDateTime'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfLvcPre10'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfLvcPre10'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfAsumy'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfAsumy'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfGram'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfGram'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbListNames'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbListNames'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfUssr'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfUssr'] = self::getInt4d($data, $pos); + $pos += 4; + } + if ($version == self::VERSION_2000) { + $this->arrayFib['fcPlcfTch'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfTch'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcRmdThreading'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbRmdThreading'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcMid'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbMid'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbRgtplc'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbRgtplc'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcMsoEnvelope'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbMsoEnvelope'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfLad'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfLad'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcRgDofr'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbRgDofr'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcosl'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcosl'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfCookieOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfCookieOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPgdMotherOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPgdMotherOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcBkdMotherOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbBkdMotherOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPgdFtnOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPgdFtnOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcBkdFtnOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbBkdFtnOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPgdEdnOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPgdEdnOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcBkdEdnOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbBkdEdnOld'] = self::getInt4d($data, $pos); + $pos += 4; + } + if ($version == self::VERSION_2002) { + $this->arrayFib['fcUnused1'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbUnused1'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfPgp'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfPgp'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfuim'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfuim'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlfguidUim'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlfguidUim'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcAtrdExtra'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbAtrdExtra'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlrsid'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlrsid'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfBkmkFactoid'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfBkmkFactoid'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBkfFactoid'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBkfFactoid'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfcookie'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfcookie'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBklFactoid'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBklFactoid'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcFactoidData'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbFactoidData'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcDocUndo'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbDocUndo'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfBkmkFcc'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfBkmkFcc'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBkfFcc'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBkfFcc'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBklFcc'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBklFcc'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfbkmkBPRepairs'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfbkmkBPRepairs'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfbkfBPRepairs'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfbkfBPRepairs'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfbklBPRepairs'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfbklBPRepairs'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPmsNew'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPmsNew'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcODSO'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbODSO'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfpmiOldXP'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfpmiOldXP'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfpmiNewXP'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfpmiNewXP'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfpmiMixedXP'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfpmiMixedXP'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcUnused2'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbUnused2'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcffactoid'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcffactoid'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcflvcOldXP'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcflvcOldXP'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcflvcNewXP'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcflvcNewXP'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcflvcMixedXP'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcflvcMixedXP'] = self::getInt4d($data, $pos); + $pos += 4; + } + if ($version == self::VERSION_2003) { + $this->arrayFib['fcHplxsdr'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbHplxsdr'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfBkmkSdt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfBkmkSdt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBkfSdt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBkfSdt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBklSdt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBklSdt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcCustomXForm'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbCustomXForm'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfBkmkProt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfBkmkProt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBkfProt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBkfProt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBklProt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBklProt'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbProtUser'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbProtUser'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcUnused'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbUnused'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfpmiOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfpmiOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfpmiOldInline'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfpmiOldInline'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfpmiNew'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfpmiNew'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfpmiNewInline'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfpmiNewInline'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcflvcOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcflvcOld'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcflvcOldInline'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcflvcOldInline'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcflvcNew'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcflvcNew'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcflvcNewInline'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcflvcNewInline'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPgdMother'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPgdMother'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcBkdMother'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbBkdMother'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcAfdMother'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbAfdMother'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPgdFtn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPgdFtn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcBkdFtn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbBkdFtn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcAfdFtn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbAfdFtn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPgdEdn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPgdEdn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcBkdEdn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbBkdEdn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcAfdEdn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbAfdEdn'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcAfd'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbAfd'] = self::getInt4d($data, $pos); + $pos += 4; + } + if ($version == self::VERSION_2007) { + $this->arrayFib['fcPlcfmthd'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfmthd'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfBkmkMoveFrom'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfBkmkMoveFrom'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBkfMoveFrom'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBkfMoveFrom'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBklMoveFrom'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBklMoveFrom'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfBkmkMoveTo'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfBkmkMoveTo'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBkfMoveTo'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBkfMoveTo'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBklMoveTo'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBklMoveTo'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcUnused1'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbUnused1'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcUnused2'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbUnused2'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcUnused3'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbUnused3'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcSttbfBkmkArto'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbSttbfBkmkArto'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBkfArto'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBkfArto'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcPlcfBklArto'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbPlcfBklArto'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcArtoData'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbArtoData'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcUnused4'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbUnused4'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcUnused5'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbUnused5'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcUnused6'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbUnused6'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcOssTheme'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbOssTheme'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['fcColorSchemeMapping'] = self::getInt4d($data, $pos); + $pos += 4; + $this->arrayFib['lcbColorSchemeMapping'] = self::getInt4d($data, $pos); + $pos += 4; + } + return $pos; + } + + private function readFibContent() + { + // Informations about Font + $this->readRecordSttbfFfn(); + + // Informations about page + $this->readRecordPlcfSed(); + + // reading paragraphs + //@link https://github.com/notmasteryet/CompoundFile/blob/ec118f354efebdee9102e41b5b7084fce81125b0/WordFileReader/WordDocument.cs#L86 + $this->readRecordPlcfBtePapx(); + + // reading character formattings + //@link https://github.com/notmasteryet/CompoundFile/blob/ec118f354efebdee9102e41b5b7084fce81125b0/WordFileReader/WordDocument.cs#L94 + $this->readRecordPlcfBteChpx(); + + $this->generatePhpWord(); + } + + /** + * Section and information about them + * @link : http://msdn.microsoft.com/en-us/library/dd924458%28v=office.12%29.aspx + */ + private function readRecordPlcfSed() + { + $posMem = $this->arrayFib['fcPlcfSed']; + // PlcfSed + // PlcfSed : aCP + $aCP = array(); + $aCP[0] = self::getInt4d($this->data1Table, $posMem); + $posMem += 4; + $aCP[1] = self::getInt4d($this->data1Table, $posMem); + $posMem += 4; + + // PlcfSed : aSed + //@link : http://msdn.microsoft.com/en-us/library/dd950194%28v=office.12%29.aspx + $numSed = $this->getNumInLcb($this->arrayFib['lcbPlcfSed'], 12); + + $aSed = array(); + for ($iInc = 0; $iInc < $numSed; ++$iInc) { + // Sed : http://msdn.microsoft.com/en-us/library/dd950982%28v=office.12%29.aspx + // fn + $posMem += 2; + // fnMpr + $aSed[$iInc] = self::getInt4d($this->data1Table, $posMem); + $posMem += 4; + // fnMpr + $posMem += 2; + // fcMpr + $posMem += 4; + } + + foreach ($aSed as $offsetSed) { + // Sepx : http://msdn.microsoft.com/en-us/library/dd921348%28v=office.12%29.aspx + $cb = self::getInt2d($this->dataWorkDocument, $offsetSed); + $offsetSed += 2; + + $oStylePrl = $this->readPrl($this->dataWorkDocument, $offsetSed, $cb); + $offsetSed += $oStylePrl->length; + + $this->arraySections[] = $oStylePrl; + } + } + + /** + * Specifies the fonts that are used in the document + * @link : http://msdn.microsoft.com/en-us/library/dd943880%28v=office.12%29.aspx + */ + private function readRecordSttbfFfn() + { + $posMem = $this->arrayFib['fcSttbfFfn']; + + $cData = self::getInt2d($this->data1Table, $posMem); + $posMem += 2; + $cbExtra = self::getInt2d($this->data1Table, $posMem); + $posMem += 2; + + if ($cData < 0x7FF0 && $cbExtra == 0) { + for ($inc = 0; $inc < $cData; $inc++) { + // len + $posMem += 1; + // ffid + $posMem += 1; + // wWeight (400 : Normal - 700 bold) + $posMem += 2; + // chs + $posMem += 1; + // ixchSzAlt + $ixchSzAlt = self::getInt1d($this->data1Table, $posMem); + $posMem += 1; + // panose + $posMem += 10; + // fs + $posMem += 24; + // xszFfn + $xszFfn = ''; + do { + $char = self::getInt2d($this->data1Table, $posMem); + $posMem += 2; + if ($char > 0) { + $xszFfn .= chr($char); + } + } while ($char != 0); + // xszAlt + $xszAlt = ''; + if ($ixchSzAlt > 0) { + do { + $char = self::getInt2d($this->data1Table, $posMem); + $posMem += 2; + if ($char == 0) { + break; + } + $xszAlt .= chr($char); + } while ($char != 0); + } + $this->arrayFonts[] = array( + 'main' => $xszFfn, + 'alt' => $xszAlt, + ); + } + } + } + + /** + * Paragraph and information about them + * @link http://msdn.microsoft.com/en-us/library/dd908569%28v=office.12%29.aspx + */ + private function readRecordPlcfBtePapx() + { + $posMem = $this->arrayFib['fcPlcfBtePapx']; + $num = $this->getNumInLcb($this->arrayFib['lcbPlcfBtePapx'], 4); + $posMem += 4 * ($num + 1); + $arrAPnBtePapx = $this->getArrayCP($this->data1Table, $posMem, $num); + $posMem += 4 * $num; + + foreach ($arrAPnBtePapx as $aPnBtePapx) { + $offsetBase = $aPnBtePapx * 512; + $offset = $offsetBase; + + $string = ''; + + $numRun = self::getInt1d($this->dataWorkDocument, $offset + 511); + $arrayRGFC = array(); + for ($inc = 0; $inc <= $numRun; $inc++) { + $arrayRGFC[$inc] = self::getInt4d($this->dataWorkDocument, $offset); + $offset += 4; + } + $arrayRGB = array(); + for ($inc = 1; $inc <= $numRun; $inc++) { + // @link http://msdn.microsoft.com/en-us/library/dd925804(v=office.12).aspx + $arrayRGB[$inc] = self::getInt1d($this->dataWorkDocument, $offset); + $offset += 1; + // reserved + $offset += 12; + } + + foreach (array_keys($arrayRGFC) as $key) { + if (!isset($arrayRGFC[$key + 1])) { + break; + } + $strLen = $arrayRGFC[$key + 1] - $arrayRGFC[$key] - 1; + for ($inc = 0; $inc < $strLen; $inc++) { + $byte = self::getInt1d($this->dataWorkDocument, $arrayRGFC[$key] + $inc); + if ($byte > 0) { + $string .= chr($byte); + } + } + } + $this->arrayParagraphs[] = $string; + + //@todo readPrl for paragraphs + /*// use $this->readPrl() + foreach ($arrayRGB as $key => $rgb) { + $offset = $offsetBase + ($rgb * 2); + + $cb = self::getInt1d($this->dataWorkDocument, $offset); + $offset += 1; + print_r('$cb : '.$cb.PHP_EOL); + if ($cb == 0) { + $cb = self::getInt1d($this->dataWorkDocument, $offset); + $cb = $cb * 2; + $offset += 1; + print_r('$cb0 : '.$cb.PHP_EOL); + } else { + $cb = $cb * 2 - 1; + print_r('$cbD : '.$cb.PHP_EOL); + } + $istd = self::getInt2d($this->dataWorkDocument, $offset); + $offset += 2; + $cb -= 2; + print_r('$istd : '.$istd.($istd == 0 ? ' (Normal)' : '').PHP_EOL); + if ($cb > 0) { + do{ + $sprm = self::getInt2d($this->dataWorkDocument, $offset); + $offset += 2; + $cb -= 2; + $sprm_IsPmd = $sprm & 0x01FF; + $sprm_F = ($sprm/512) & 0x0001; + $sprm_Sgc = ($sprm/1024) & 0x0007; + $sprm_Spra = ($sprm/8192); + + print_r('$sprm : 0x'.dechex($sprm).PHP_EOL); + print_r('$sprm.ispmd : 0x'.dechex($sprm_IsPmd).PHP_EOL); + print_r('$sprm.f : 0x'.dechex($sprm_F).PHP_EOL); + print_r('$sprm.sgc : 0x'.dechex($sprm_Sgc)); + switch(dechex($sprm_Sgc)) { + case 0x01: + print_r(' (Paragraph property)'); + break; + case 0x02: + print_r(' (Character property)'); + break; + case 0x03: + print_r(' (Picture property)'); + break; + case 0x04: + print_r(' (Section property)'); + break; + case 0x05: + print_r(' (Table property)'); + break; + } + print_r(PHP_EOL); + print_r('$sprm.spra : 0x'.dechex($sprm_Spra).PHP_EOL); + switch(dechex($sprm_Spra)) { + case 0x0: + $operand = self::getInt1d($this->dataWorkDocument, $offset); + $offset += 1; + $cb -= 1; + switch(dechex($operand)) { + case 0x00: + $operand = 'OFF'; + break; + case 0x01: + $operand = 'ON'; + break; + case 0x80: + $operand = 'CURRENT VALUE'; + print_r(''.PHP_EOL.PHP_EOL); + break; + case 0x81: + $operand = 'OPPOSITE OF THE CURRENT VALUE'; + break; + } + break; + case 0x1: + $operand = self::getInt1d($this->dataWorkDocument, $offset); + $offset += 1; + $cb -= 1; + print_r('$operand : 0x'.dechex($operand).PHP_EOL); + break; + case 0x2: + case 0x4: + case 0x5: + $operand = self::getInt2d($this->dataWorkDocument, $offset); + $offset += 2; + $cb -= 2; + print_r('$operand : 0x'.dechex($operand).PHP_EOL); + break; + case 0x3: + if ($sprm_IsPmd != 0x70) { + $operand = self::getInt4d($this->dataWorkDocument, $offset); + $offset += 4; + $cb -= 4; + print_r('$operand : 0x'.dechex($operand).PHP_EOL); + } + break; + case 0x7: + $operand = self::getInt3d($this->dataWorkDocument, $offset); + $offset += 3; + $cb -= 3; + print_r('$operand : 0x'.dechex($operand).PHP_EOL); + break; + default: + print_r('YO YO YO : '.PHP_EOL); + } + + // + switch(dechex($sprm_Sgc)) { + case 0x01: // Sprm is modifying a paragraph property. + switch($sprm_IsPmd) { + case 0x0A: // sprmPIlvl + print_r('sprmPIlvl : '.$operand.PHP_EOL.PHP_EOL); + break; + case 0x0B: // sprmPIlfo + print_r('sprmPIlfo : '.$operand.PHP_EOL.PHP_EOL); + break; + default: + print_r('$sprm_IsPmd(1) : '.$sprm_IsPmd.PHP_EOL.PHP_EOL); + break; + } + break; + case 0x02: // Sprm is modifying a character property. + switch($sprm_IsPmd) { + default: + print_r('$sprm_IsPmd(2) : '.$sprm_IsPmd.PHP_EOL.PHP_EOL); + break; + } + break; + case 0x03: // Sprm is modifying a picture property. + switch($sprm_IsPmd) { + default: + print_r('$sprm_IsPmd(3) : '.$sprm_IsPmd.PHP_EOL.PHP_EOL); + break; + } + break; + case 0x04: // Sprm is modifying a section property. + switch($sprm_IsPmd) { + default: + print_r('$sprm_IsPmd(4) : '.$sprm_IsPmd.PHP_EOL.PHP_EOL); + break; + } + break; + case 0x05: // Sprm is modifying a table property. + switch($sprm_IsPmd) { + default: + print_r('$sprm_IsPmd(4) : '.$sprm_IsPmd.PHP_EOL.PHP_EOL); + break; + } + break; + default: + print_r('$sprm_Sgc : '.dechex($sprm_Sgc).PHP_EOL.PHP_EOL); + break; + } + } while ($cb > 0); + } else { + if ($istd > 0) { + // @todo : Determining Properties of a Paragraph Style + # @link http://msdn.microsoft.com/en-us/library/dd948631%28v=office.12%29.aspx + } + } + }*/ + } + } + + /** + * Character formatting properties to text in a document + * @link http://msdn.microsoft.com/en-us/library/dd907108%28v=office.12%29.aspx + */ + private function readRecordPlcfBteChpx() + { + $posMem = $this->arrayFib['fcPlcfBteChpx']; + $num = $this->getNumInLcb($this->arrayFib['lcbPlcfBteChpx'], 4); + $aPnBteChpx = array(); + for ($inc = 0; $inc <= $num; $inc++) { + $aPnBteChpx[$inc] = self::getInt4d($this->data1Table, $posMem); + $posMem += 4; + } + $pnFkpChpx = self::getInt4d($this->data1Table, $posMem); + $posMem += 4; + + $offsetBase = $pnFkpChpx * 512; + $offset = $offsetBase; + + // ChpxFkp + // @link : http://msdn.microsoft.com/en-us/library/dd910989%28v=office.12%29.aspx + $numRGFC = self::getInt1d($this->dataWorkDocument, $offset + 511); + $arrayRGFC = array(); + for ($inc = 0; $inc <= $numRGFC; $inc++) { + $arrayRGFC[$inc] = self::getInt4d($this->dataWorkDocument, $offset); + $offset += 4; + } + + $arrayRGB = array(); + for ($inc = 1; $inc <= $numRGFC; $inc++) { + $arrayRGB[$inc] = self::getInt1d($this->dataWorkDocument, $offset); + $offset += 1; + } + + $start = 0; + foreach ($arrayRGB as $keyRGB => $rgb) { + $oStyle = new \stdClass(); + $oStyle->pos_start = $start; + $oStyle->pos_len = (int)ceil((($arrayRGFC[$keyRGB] -1) - $arrayRGFC[$keyRGB -1]) / 2); + $start += $oStyle->pos_len; + + if ($rgb > 0) { + // Chp Structure + // @link : http://msdn.microsoft.com/en-us/library/dd772849%28v=office.12%29.aspx + $posRGB = $offsetBase + $rgb * 2; + + $cb = self::getInt1d($this->dataWorkDocument, $posRGB); + $posRGB += 1; + + $oStyle->style = $this->readPrl($this->dataWorkDocument, $posRGB, $cb); + $posRGB += $oStyle->style->length; + } + $this->arrayCharacters[] = $oStyle; + } + } + + /** + * @param $sprm + * @return \stdClass + */ + private function readSprm($sprm) + { + $oSprm = new \stdClass(); + $oSprm->isPmd = $sprm & 0x01FF; + $oSprm->f = ($sprm / 512) & 0x0001; + $oSprm->sgc = ($sprm / 1024) & 0x0007; + $oSprm->spra = ($sprm / 8192); + return $oSprm; + } + + /** + * @param string $data + * @param integer $pos + * @param \stdClass $oSprm + * @return array + */ + private function readSprmSpra($data, $pos, $oSprm) + { + $length = 0; + $operand = null; + + switch(dechex($oSprm->spra)) { + case 0x0: + $operand = self::getInt1d($data, $pos); + $length = 1; + switch(dechex($operand)) { + case 0x00: + $operand = false; + break; + case 0x01: + $operand = true; + break; + case 0x80: + $operand = self::SPRA_VALUE; + break; + case 0x81: + $operand = self::SPRA_VALUE_OPPOSITE; + break; + } + break; + case 0x1: + $operand = self::getInt1d($data, $pos); + $length = 1; + break; + case 0x2: + case 0x4: + case 0x5: + $operand = self::getInt2d($data, $pos); + $length = 2; + break; + case 0x3: + if ($oSprm->isPmd != 0x70) { + $operand = self::getInt4d($data, $pos); + $length = 4; + } + break; + case 0x7: + $operand = self::getInt3d($data, $pos); + $length = 3; + break; + default: + // print_r('YO YO YO : '.PHP_EOL); + } + + return array( + 'length' => $length, + 'operand' => $operand, + ); + } + + /** + * @param $data integer + * @param $pos integer + * @return \stdClass + * @link http://msdn.microsoft.com/en-us/library/dd772849%28v=office.12%29.aspx + */ + private function readPrl($data, $pos, $cbNum) + { + $posStart = $pos; + $oStylePrl = new \stdClass(); + + // Variables + $sprmCPicLocation = null; + $sprmCFData = null; + $sprmCFSpec = null; + + do { + // Variables + $operand = null; + + $sprm = self::getInt2d($data, $pos); + $oSprm = $this->readSprm($sprm); + $pos += 2; + $cbNum -= 2; + + $arrayReturn = $this->readSprmSpra($data, $pos, $oSprm); + $pos += $arrayReturn['length']; + $cbNum -= $arrayReturn['length']; + $operand = $arrayReturn['operand']; + + switch(dechex($oSprm->sgc)) { + // Paragraph property + case 0x01: + break; + // Character property + case 0x02: + if (!isset($oStylePrl->styleFont)) { + $oStylePrl->styleFont = array(); + } + switch($oSprm->isPmd) { + // sprmCFRMarkIns + case 0x01: + break; + // sprmCFFldVanish + case 0x02: + break; + // sprmCPicLocation + case 0x03: + $sprmCPicLocation = $operand; + break; + // sprmCFData + case 0x06: + $sprmCFData = dechex($operand) == 0x00 ? false : true; + break; + // sprmCFItalic + case 0x36: + // By default, text is not italicized. + switch($operand) { + case false: + case true: + $oStylePrl->styleFont['italic'] = $operand; + break; + case self::SPRA_VALUE: + $oStylePrl->styleFont['italic'] = false; + break; + case self::SPRA_VALUE_OPPOSITE: + $oStylePrl->styleFont['italic'] = true; + break; + } + break; + // sprmCIstd + case 0x30: + //print_r('sprmCIstd : '.dechex($operand).PHP_EOL.PHP_EOL); + break; + // sprmCFBold + case 0x35: + // By default, text is not bold. + switch($operand) { + case false: + case true: + $oStylePrl->styleFont['bold'] = $operand; + break; + case self::SPRA_VALUE: + $oStylePrl->styleFont['bold'] = false; + break; + case self::SPRA_VALUE_OPPOSITE: + $oStylePrl->styleFont['bold'] = true; + break; + } + break; + // sprmCFStrike + case 0x37: + // By default, text is not struck through. + switch($operand) { + case false: + case true: + $oStylePrl->styleFont['strikethrough'] = $operand; + break; + case self::SPRA_VALUE: + $oStylePrl->styleFont['strikethrough'] = false; + break; + case self::SPRA_VALUE_OPPOSITE: + $oStylePrl->styleFont['strikethrough'] = true; + break; + } + break; + // sprmCKul + case 0x3E: + switch(dechex($operand)) { + case 0x00: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_NONE; + break; + case 0x01: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_SINGLE; + break; + case 0x02: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_WORDS; + break; + case 0x03: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOUBLE; + break; + case 0x04: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTTED; + break; + case 0x06: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_HEAVY; + break; + case 0x07: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DASH; + break; + case 0x09: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTHASH; + break; + case 0x0A: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTDOTDASH; + break; + case 0x0B: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_WAVY; + break; + case 0x14: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTTEDHEAVY; + break; + case 0x17: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DASHHEAVY; + break; + case 0x19: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTHASHHEAVY; + break; + case 0x1A: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTDOTDASHHEAVY; + break; + case 0x1B: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_WAVYHEAVY; + break; + case 0x27: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DASHLONG; + break; + case 0x2B: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_WAVYDOUBLE; + break; + case 0x37: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DASHLONGHEAVY; + break; + default: + $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_NONE; + break; + } + break; + // sprmCIco + //@link http://msdn.microsoft.com/en-us/library/dd773060%28v=office.12%29.aspx + case 0x42: + switch(dechex($operand)) { + case 0x00: + case 0x01: + $oStylePrl->styleFont['color'] = '000000'; + break; + case 0x02: + $oStylePrl->styleFont['color'] = '0000FF'; + break; + case 0x03: + $oStylePrl->styleFont['color'] = '00FFFF'; + break; + case 0x04: + $oStylePrl->styleFont['color'] = '00FF00'; + break; + case 0x05: + $oStylePrl->styleFont['color'] = 'FF00FF'; + break; + case 0x06: + $oStylePrl->styleFont['color'] = 'FF0000'; + break; + case 0x07: + $oStylePrl->styleFont['color'] = 'FFFF00'; + break; + case 0x08: + $oStylePrl->styleFont['color'] = 'FFFFFF'; + break; + case 0x09: + $oStylePrl->styleFont['color'] = '000080'; + break; + case 0x0A: + $oStylePrl->styleFont['color'] = '008080'; + break; + case 0x0B: + $oStylePrl->styleFont['color'] = '008000'; + break; + case 0x0C: + $oStylePrl->styleFont['color'] = '800080'; + break; + case 0x0D: + $oStylePrl->styleFont['color'] = '800080'; + break; + case 0x0E: + $oStylePrl->styleFont['color'] = '808000'; + break; + case 0x0F: + $oStylePrl->styleFont['color'] = '808080'; + break; + case 0x10: + $oStylePrl->styleFont['color'] = 'C0C0C0'; + } + break; + // sprmCHps + case 0x43: + $oStylePrl->styleFont['size'] = dechex($operand/2); + break; + // sprmCIss + case 0x48: + if (!isset($oStylePrl->styleFont['superScript'])) { + $oStylePrl->styleFont['superScript'] = false; + } + if (!isset($oStylePrl->styleFont['subScript'])) { + $oStylePrl->styleFont['subScript'] = false; + } + switch (dechex($operand)) { + case 0x00: + // Normal text + break; + case 0x01: + $oStylePrl->styleFont['superScript'] = true; + break; + case 0x02: + $oStylePrl->styleFont['subScript'] = true; + break; + } + break; + // sprmCRgFtc0 + case 0x4F: + $oStylePrl->styleFont['name'] = ''; + if (isset($this->arrayFonts[$operand])) { + $oStylePrl->styleFont['name'] = $this->arrayFonts[$operand]['main']; + } + break; + // sprmCRgFtc1 + case 0x50: + // if the language for the text is an East Asian language + break; + // sprmCRgFtc2 + case 0x51: + // if the character falls outside the Unicode character range + break; + // sprmCFSpec + case 0x55: + $sprmCFSpec = $operand; + break; + // sprmCFtcBi + case 0x5E: + break; + // sprmCFItalicBi + case 0x5D: + break; + // sprmCHpsBi + case 0x61: + break; + // sprmCShd80 + //@link http://msdn.microsoft.com/en-us/library/dd923447%28v=office.12%29.aspx + case 0x66: + // $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 + //@link : 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 += 1; + $green = str_pad(dechex(self::getInt1d($this->dataWorkDocument, $pos)), 2, '0', STR_PAD_LEFT); + $pos += 1; + $blue = str_pad(dechex(self::getInt1d($this->dataWorkDocument, $pos)), 2, '0', STR_PAD_LEFT); + $pos += 1; + $pos += 1; + $oStylePrl->styleFont['color'] = $red.$green.$blue; + $cbNum -= 4; + break; + default: + // print_r('@todo Character : 0x'.dechex($oSprm->isPmd)); + // print_r(PHP_EOL); + } + break; + // Picture property + case 0x03: + break; + // Section property + case 0x04: + if (!isset($oStylePrl->styleSection)) { + $oStylePrl->styleSection = array(); + } + switch($oSprm->isPmd) { + // sprmSNfcPgn + case 0x0E: + // numbering format used for page numbers + break; + // sprmSXaPage + case 0x1F: + $oStylePrl->styleSection['pageSizeW'] = $operand; + break; + // sprmSYaPage + case 0x20: + $oStylePrl->styleSection['pageSizeH'] = $operand; + break; + // sprmSDxaLeft + case 0x21: + $oStylePrl->styleSection['marginLeft'] = $operand; + break; + // sprmSDxaRight + case 0x22: + $oStylePrl->styleSection['marginRight'] = $operand; + break; + // sprmSDyaTop + case 0x23: + $oStylePrl->styleSection['marginTop'] = $operand; + break; + // sprmSDyaBottom + case 0x24: + $oStylePrl->styleSection['marginBottom'] = $operand; + break; + // sprmSFBiDi + case 0x28: + // RTL layout + break; + // sprmSDxtCharSpace + case 0x30: + // characpter pitch + break; + // sprmSDyaLinePitch + case 0x31: + // line height + break; + // sprmSClm + case 0x32: + // document grid mode + break; + // sprmSTextFlow + case 0x33: + // text flow + break; + default: + // print_r('@todo Section : 0x'.dechex($oSprm->isPmd)); + // print_r(PHP_EOL); + + } + break; + // Table property + case 0x05: + break; + } + } while ($cbNum > 0); + + if (!is_null($sprmCPicLocation)) { + if (!is_null($sprmCFData) && $sprmCFData == 0x01) { + // NilPICFAndBinData + //@todo Read Hyperlink structure + /*$lcb = self::getInt4d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 4; + $cbHeader = self::getInt2d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 2; + // ignored + $sprmCPicLocation += 62; + // depending of the element + // Hyperlink => HFD + // HFD > bits + $sprmCPicLocation += 1; + // HFD > clsid + $sprmCPicLocation += 16; + // HFD > hyperlink + //@link : 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); + $sprmCPicLocation += 4; + $hlstmfAbsFromGetdataRel = ($data >> 9) & bindec('1'); + $hlstmfMonikerSavedAsStr = ($data >> 8) & bindec('1'); + $hlstmfHasFrameName = ($data >> 7) & bindec('1'); + $hlstmfHasCreationTime = ($data >> 6) & bindec('1'); + $hlstmfHasGUID = ($data >> 5) & bindec('1'); + $hlstmfHasDisplayName = ($data >> 4) & bindec('1'); + $hlstmfHasLocationStr = ($data >> 3) & bindec('1'); + $hlstmfSiteGaveDisplayName = ($data >> 2) & bindec('1'); + $hlstmfIsAbsolute = ($data >> 1) & bindec('1'); + $hlstmfHasMoniker = ($data >> 0) & bindec('1'); + for ($inc = 0; $inc <= 32; $inc++) { + echo ($data >> $inc) & bindec('1'); + } + + print_r('$hlstmfHasMoniker > '.$hlstmfHasMoniker.PHP_EOL); + print_r('$hlstmfIsAbsolute > '.$hlstmfIsAbsolute.PHP_EOL); + print_r('$hlstmfSiteGaveDisplayName > '.$hlstmfSiteGaveDisplayName.PHP_EOL); + print_r('$hlstmfHasLocationStr > '.$hlstmfHasLocationStr.PHP_EOL); + print_r('$hlstmfHasDisplayName > '.$hlstmfHasDisplayName.PHP_EOL); + print_r('$hlstmfHasGUID > '.$hlstmfHasGUID.PHP_EOL); + print_r('$hlstmfHasCreationTime > '.$hlstmfHasCreationTime.PHP_EOL); + print_r('$hlstmfHasFrameName > '.$hlstmfHasFrameName.PHP_EOL); + print_r('$hlstmfMonikerSavedAsStr > '.$hlstmfMonikerSavedAsStr.PHP_EOL); + print_r('$hlstmfAbsFromGetdataRel > '.$hlstmfAbsFromGetdataRel.PHP_EOL); + if ($streamVersion == 2) { + $AAA = self::getInt4d($this->dataData, $sprmCPicLocation); + echo 'AAAA : '.$AAA.PHP_EOL; + if ($hlstmfHasDisplayName == 1) { + echo 'displayName'.PHP_EOL; + } + if ($hlstmfHasFrameName == 1) { + echo 'targetFrameName'.PHP_EOL; + } + if ($hlstmfHasMoniker == 1 || $hlstmfMonikerSavedAsStr == 1) { + $sprmCPicLocation += 16; + $length = self::getInt4d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 4; + for ($inc = 0; $inc < ($length / 2); $inc++) { + $chr = self::getInt2d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 2; + print_r(chr($chr)); + } + echo PHP_EOL; + echo 'moniker : '.$length.PHP_EOL; + } + if ($hlstmfHasMoniker == 1 || $hlstmfMonikerSavedAsStr == 1) { + echo 'oleMoniker'.PHP_EOL; + } + if ($hlstmfHasLocationStr == 1) { + echo 'location'.PHP_EOL; + } + if ($hlstmfHasGUID == 1) { + echo 'guid'.PHP_EOL; + $sprmCPicLocation += 16; + } + if ($hlstmfHasCreationTime == 1) { + echo 'fileTime'.PHP_EOL; + $sprmCPicLocation += 4; + } + echo 'HYPERLINK'.PHP_EOL; + }*/ + } else { + // Pictures + //@link : http://msdn.microsoft.com/en-us/library/dd925458%28v=office.12%29.aspx + //@link : http://msdn.microsoft.com/en-us/library/dd926136%28v=office.12%29.aspx + // PICF : lcb + $sprmCPicLocation += 4; + // PICF : cbHeader + $sprmCPicLocation += 2; + // PICF : mfpf : mm + $mfpfMm = self::getInt2d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 2; + // PICF : mfpf : xExt + $sprmCPicLocation += 2; + // PICF : mfpf : yExt + $sprmCPicLocation += 2; + // PICF : mfpf : swHMF + $sprmCPicLocation += 2; + // PICF : innerHeader : grf + $sprmCPicLocation += 4; + // PICF : innerHeader : padding1 + $sprmCPicLocation += 4; + // PICF : innerHeader : mmPM + $sprmCPicLocation += 2; + // PICF : innerHeader : padding2 + $sprmCPicLocation += 4; + // PICF : picmid : dxaGoal + $picmidDxaGoal = self::getInt2d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 2; + // PICF : picmid : dyaGoal + $picmidDyaGoal = self::getInt2d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 2; + // PICF : picmid : mx + $picmidMx = self::getInt2d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 2; + // PICF : picmid : my + $picmidMy = self::getInt2d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 2; + // PICF : picmid : dxaReserved1 + $picmidDxaCropLeft = self::getInt2d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 2; + // PICF : picmid : dyaReserved1 + $picmidDxaCropTop = self::getInt2d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 2; + // PICF : picmid : dxaReserved2 + $picmidDxaCropRight = self::getInt2d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 2; + // PICF : picmid : dyaReserved2 + $picmidDxaCropBottom = self::getInt2d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 2; + // PICF : picmid : fReserved + $sprmCPicLocation += 1; + // PICF : picmid : bpp + $sprmCPicLocation += 1; + // PICF : picmid : brcTop80 + $sprmCPicLocation += 4; + // PICF : picmid : brcLeft80 + $sprmCPicLocation += 4; + // PICF : picmid : brcBottom80 + $sprmCPicLocation += 4; + // PICF : picmid : brcRight80 + $sprmCPicLocation += 4; + // PICF : picmid : dxaReserved3 + $sprmCPicLocation += 2; + // PICF : picmid : dyaReserved3 + $sprmCPicLocation += 2; + // PICF : cProps + $sprmCPicLocation += 2; + + if ($mfpfMm == 0x0066) { + // cchPicName + $cchPicName = self::getInt1d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 1; + + // stPicName + $stPicName = ''; + for ($inc = 0; $inc <= $cchPicName; $inc++) { + $chr = self::getInt1d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 1; + $stPicName .= chr($chr); + } + } + + // picture (OfficeArtInlineSpContainer) + // picture : shape + $shapeRH = $this->loadRecordHeader($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 8; + if ($shapeRH['recVer'] == 0xF && $shapeRH['recInstance'] == 0x000 && $shapeRH['recType'] == 0xF004) { + $sprmCPicLocation += $shapeRH['recLen']; + } + // picture : rgfb + //@link : 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 + //@link : http://msdn.microsoft.com/en-us/library/dd944923%28v=office.12%29.aspx + case 0xF007: + // btWin32 + $sprmCPicLocation += 1; + // btMacOS + $sprmCPicLocation += 1; + // rgbUid + $sprmCPicLocation += 16; + // tag + $sprmCPicLocation += 2; + // size + $sprmCPicLocation += 4; + // cRef + $sprmCPicLocation += 4; + // foDelay + $sprmCPicLocation += 4; + // unused1 + $sprmCPicLocation += 1; + // cbName + $cbName = self::getInt1d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 1; + // unused2 + $sprmCPicLocation += 1; + // unused3 + $sprmCPicLocation += 1; + // nameData + if ($cbName > 0) { + $nameData = ''; + for ($inc = 0; $inc <= ($cbName / 2); $inc++) { + $chr = self::getInt2d($this->dataData, $sprmCPicLocation); + $sprmCPicLocation += 2; + $nameData .= chr($chr); + } + } + // embeddedBlip + //@link : 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: + case self::OFFICEARTBLIPJPEG: + if (!isset($oStylePrl->image)) { + $oStylePrl->image = array(); + } + $sprmCPicLocation += 8; + // embeddedBlip : rgbUid1 + $sprmCPicLocation += 16; + if ($embeddedBlipRH['recInstance'] == 0x6E1) { + // rgbUid2 + $sprmCPicLocation += 16; + } + // embeddedBlip : tag + $sprmCPicLocation += 1; + // embeddedBlip : BLIPFileData + $oStylePrl->image['data'] = substr($this->dataData, $sprmCPicLocation, $embeddedBlipRH['recLen']); + $oStylePrl->image['format'] = 'jpg'; + // Image Size + $iCropWidth = $picmidDxaGoal - ($picmidDxaCropLeft + $picmidDxaCropRight); + $iCropHeight = $picmidDyaGoal - ($picmidDxaCropTop + $picmidDxaCropBottom); + if (!$iCropWidth) { + $iCropWidth = 1; + } + if (!$iCropHeight) { + $iCropHeight = 1; + } + $oStylePrl->image['width'] = Drawing::twipsToPixels($iCropWidth * $picmidMx / 1000); + $oStylePrl->image['height'] = Drawing::twipsToPixels($iCropHeight * $picmidMy / 1000); + + $sprmCPicLocation += $embeddedBlipRH['recLen']; + break; + default: + // print_r(dechex($embeddedBlipRH['recType'])); + } + break; + } + $fileBlockRH = $this->loadRecordHeader($this->dataData, $sprmCPicLocation); + } + } + } + + $oStylePrl->length = $pos - $posStart; + return $oStylePrl; + } + + /** + * Read a record header + * @param string $stream + * @param integer $pos + * @return array + */ + private function loadRecordHeader($stream, $pos) + { + $rec = self::getInt2d($stream, $pos); + $recType = self::getInt2d($stream, $pos + 2); + $recLen = self::getInt4d($stream, $pos + 4); + return array( + 'recVer' => ($rec >> 0) & bindec('1111'), + 'recInstance' => ($rec >> 4) & bindec('111111111111'), + 'recType' => $recType, + 'recLen' => $recLen, + ); + } + + private function generatePhpWord() + { + foreach ($this->arraySections as $itmSection) { + $oSection = $this->phpWord->addSection(); + $oSection->setSettings($itmSection->styleSection); + + $sHYPERLINK = ''; + foreach ($this->arrayParagraphs as $itmParagraph) { + $textPara = $itmParagraph; + foreach ($this->arrayCharacters as $oCharacters) { + $subText = substr($textPara, $oCharacters->pos_start, $oCharacters->pos_len); + $subText = str_replace(chr(13), PHP_EOL, $subText); + $arrayText = explode(PHP_EOL, $subText); + if (end($arrayText) == '') { + array_pop($arrayText); + } + if (reset($arrayText) == '') { + array_shift($arrayText); + } + + // Style Character + $styleFont = array(); + if (isset($oCharacters->style)) { + if (isset($oCharacters->style->styleFont)) { + $styleFont = $oCharacters->style->styleFont; + } + } + + foreach ($arrayText as $sText) { + // HyperLink + if (empty($sText) && !empty($sHYPERLINK)) { + $arrHYPERLINK = explode('"', $sHYPERLINK); + $oSection->addLink($arrHYPERLINK[1], null); + // print_r('>addHyperLink<'.$sHYPERLINK.'>'.ord($sHYPERLINK[0]).EOL); + $sHYPERLINK = ''; + } + + // TextBreak + if (empty($sText)) { + $oSection->addTextBreak(); + $sHYPERLINK = ''; + // print_r('>addTextBreak<' . EOL); + } + + if (!empty($sText)) { + if (!empty($sHYPERLINK) && ord($sText[0]) > 20) { + $sHYPERLINK .= $sText; + } + if (empty($sHYPERLINK)) { + if (ord($sText[0]) > 20) { + if (strpos(trim($sText), 'HYPERLINK "') === 0) { + $sHYPERLINK = $sText; + } else { + $oSection->addText($sText, $styleFont); + // print_r('>addText<'.$sText.'>'.ord($sText[0]).EOL); + } + } + if (ord($sText[0]) == 1) { + if (isset($oCharacters->style->image)) { + $fileImage = tempnam(sys_get_temp_dir(), 'PHPWord_MsDoc').'.'.$oCharacters->style->image['format']; + file_put_contents($fileImage, $oCharacters->style->image['data']); + $oSection->addImage($fileImage, array('width' => $oCharacters->style->image['width'], 'height' => $oCharacters->style->image['height'])); + // print_r('>addImage<'.$fileImage.'>'.EOL); + } + } + } + } + } + } + } + + } + } + + /** + * Read 8-bit unsigned integer + * + * @param string $data + * @param int $pos + * @return int + */ + public static function getInt1d($data, $pos) + { + return ord($data[$pos]); + } + + /** + * Read 16-bit unsigned integer + * + * @param string $data + * @param int $pos + * @return int + */ + public static function getInt2d($data, $pos) + { + return ord($data[$pos]) | (ord($data[$pos+1]) << 8); + } + + /** + * Read 24-bit signed integer + * + * @param string $data + * @param int $pos + * @return int + */ + public static function getInt3d($data, $pos) + { + return ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16); + } + + /** + * Read 32-bit signed integer + * + * @param string $data + * @param int $pos + * @return int + */ + public static function getInt4d($data, $pos) + { + // FIX: represent numbers correctly on 64-bit system + // http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334 + // Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems + $or24 = ord($data[$pos + 3]); + if ($or24 >= 128) { + // negative number + $ord24 = -abs((256 - $or24) << 24); + } else { + $ord24 = ($or24 & 127) << 24; + } + return ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | $ord24; + } +} diff --git a/src/PhpWord/Reader/ODText.php b/src/PhpWord/Reader/ODText.php index 19efdc51..d992f7fd 100644 --- a/src/PhpWord/Reader/ODText.php +++ b/src/PhpWord/Reader/ODText.php @@ -51,15 +51,16 @@ class ODText extends AbstractReader implements ReaderInterface } /** - * Read document part + * Read document part. * * @param \PhpOffice\PhpWord\PhpWord $phpWord * @param array $relationships * @param string $partName * @param string $docFile * @param string $xmlFile + * @return void */ - private function readPart(PhpWord &$phpWord, $relationships, $partName, $docFile, $xmlFile) + private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile, $xmlFile) { $partClass = "PhpOffice\\PhpWord\\Reader\\ODText\\{$partName}"; if (class_exists($partClass)) { @@ -68,7 +69,6 @@ class ODText extends AbstractReader implements ReaderInterface $part->setRels($relationships); $part->read($phpWord); } - } /** diff --git a/src/PhpWord/Reader/ODText/Content.php b/src/PhpWord/Reader/ODText/Content.php index 12b39f74..cf2fd653 100644 --- a/src/PhpWord/Reader/ODText/Content.php +++ b/src/PhpWord/Reader/ODText/Content.php @@ -28,11 +28,12 @@ use PhpOffice\PhpWord\Shared\XMLReader; class Content extends AbstractPart { /** - * Read content.xml + * Read content.xml. * * @param \PhpOffice\PhpWord\PhpWord $phpWord + * @return void */ - public function read(PhpWord &$phpWord) + public function read(PhpWord $phpWord) { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); @@ -57,7 +58,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); + $section->addListItem($listItem->nodeValue, 0); } break; } diff --git a/src/PhpWord/Reader/ODText/Meta.php b/src/PhpWord/Reader/ODText/Meta.php index f7f4542d..d08ce3a6 100644 --- a/src/PhpWord/Reader/ODText/Meta.php +++ b/src/PhpWord/Reader/ODText/Meta.php @@ -28,16 +28,17 @@ use PhpOffice\PhpWord\Shared\XMLReader; class Meta extends AbstractPart { /** - * Read meta.xml + * Read meta.xml. * * @param \PhpOffice\PhpWord\PhpWord $phpWord + * @return void * @todo Process property type */ - public function read(PhpWord &$phpWord) + public function read(PhpWord $phpWord) { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); - $docProps = $phpWord->getDocumentProperties(); + $docProps = $phpWord->getDocInfo(); $metaNode = $xmlReader->getElement('office:meta'); diff --git a/src/PhpWord/Reader/RTF/Document.php b/src/PhpWord/Reader/RTF/Document.php index cb082fdc..3f63e339 100644 --- a/src/PhpWord/Reader/RTF/Document.php +++ b/src/PhpWord/Reader/RTF/Document.php @@ -130,9 +130,10 @@ class Document * - Pushes every other character into the text queue * * @param \PhpOffice\PhpWord\PhpWord $phpWord + * @return void * @todo Use `fread` stream for scalability */ - public function read(PhpWord &$phpWord) + public function read(PhpWord $phpWord) { $markers = array( 123 => 'markOpening', // { @@ -154,7 +155,7 @@ class Document $char = $this->rtf[$this->offset]; $ascii = ord($char); - if (array_key_exists($ascii, $markers)) { // Marker found: {, }, \, LF, or CR + if (isset($markers[$ascii])) { // Marker found: {, }, \, LF, or CR $markerFunction = $markers[$ascii]; $this->$markerFunction(); } else { @@ -181,7 +182,9 @@ class Document } /** - * Mark opening braket `{` character + * Mark opening braket `{` character. + * + * @return void */ private function markOpening() { @@ -190,7 +193,9 @@ class Document } /** - * Mark closing braket `}` character + * Mark closing braket `}` character. + * + * @return void */ private function markClosing() { @@ -199,7 +204,9 @@ class Document } /** - * Mark backslash `\` character + * Mark backslash `\` character. + * + * @return void */ private function markBackslash() { @@ -214,7 +221,9 @@ class Document } /** - * Mark newline character: Flush control word because it's not possible to span multiline + * Mark newline character: Flush control word because it's not possible to span multiline. + * + * @return void */ private function markNewline() { @@ -224,9 +233,10 @@ class Document } /** - * Flush control word or text + * Flush control word or text. * * @param bool $isControl + * @return void */ private function flush($isControl = false) { @@ -238,9 +248,10 @@ class Document } /** - * Flush control word + * Flush control word. * * @param bool $isControl + * @return void */ private function flushControl($isControl = false) { @@ -255,7 +266,9 @@ class Document } /** - * Flush text in queue + * Flush text in queue. + * + * @return void */ private function flushText() { @@ -279,9 +292,10 @@ class Document } /** - * Reset control word and first char state + * Reset control word and first char state. * * @param bool $value + * @return void */ private function setControl($value) { @@ -290,9 +304,10 @@ class Document } /** - * Push text into queue + * Push text into queue. * * @param string $char + * @return void */ private function pushText($char) { @@ -306,10 +321,11 @@ class Document } /** - * Parse control + * Parse control. * * @param string $control * @param string $parameter + * @return void */ private function parseControl($control, $parameter) { @@ -335,7 +351,7 @@ class Document 'fldinst' => array(self::SKIP, 'link', null), ); - if (array_key_exists($control, $controls)) { + if (isset($controls[$control])) { list($function) = $controls[$control]; if (method_exists($this, $function)) { $directives = $controls[$control]; @@ -346,9 +362,10 @@ class Document } /** - * Read paragraph + * Read paragraph. * * @param array $directives + * @return void */ private function readParagraph($directives) { @@ -358,9 +375,10 @@ class Document } /** - * Read style + * Read style. * * @param array $directives + * @return void */ private function readStyle($directives) { @@ -369,9 +387,10 @@ class Document } /** - * Read skip + * Read skip. * * @param array $directives + * @return void */ private function readSkip($directives) { @@ -381,7 +400,9 @@ class Document } /** - * Read text + * Read text. + * + * @return void */ private function readText() { diff --git a/src/PhpWord/Reader/Word2007.php b/src/PhpWord/Reader/Word2007.php index 70d5f60b..ebe6c4f7 100644 --- a/src/PhpWord/Reader/Word2007.php +++ b/src/PhpWord/Reader/Word2007.php @@ -63,7 +63,7 @@ class Word2007 extends AbstractReader implements ReaderInterface $stepItems = $step['stepItems']; foreach ($relationships[$stepPart] as $relItem) { $relType = $relItem['type']; - if (array_key_exists($relType, $stepItems)) { + if (isset($stepItems[$relType])) { $partName = $stepItems[$relType]; $xmlFile = $relItem['target']; $this->readPart($phpWord, $relationships, $partName, $docFile, $xmlFile); @@ -75,15 +75,16 @@ class Word2007 extends AbstractReader implements ReaderInterface } /** - * Read document part + * Read document part. * * @param \PhpOffice\PhpWord\PhpWord $phpWord * @param array $relationships * @param string $partName * @param string $docFile * @param string $xmlFile + * @return void */ - private function readPart(PhpWord &$phpWord, $relationships, $partName, $docFile, $xmlFile) + private function readPart(PhpWord $phpWord, $relationships, $partName, $docFile, $xmlFile) { $partClass = "PhpOffice\\PhpWord\\Reader\\Word2007\\{$partName}"; if (class_exists($partClass)) { diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index a7261d6d..021bdba1 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -62,9 +62,9 @@ abstract class AbstractPart protected $rels = array(); /** - * Read part + * Read part. */ - abstract public function read(PhpWord &$phpWord); + abstract public function read(PhpWord $phpWord); /** * Create new instance @@ -79,9 +79,10 @@ abstract class AbstractPart } /** - * Set relationships + * Set relationships. * * @param array $value + * @return void */ public function setRels($value) { @@ -89,23 +90,24 @@ abstract class AbstractPart } /** - * Read w:p + * Read w:p. * * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader * @param \DOMElement $domNode * @param mixed $parent * @param string $docPart + * @return void * * @todo Get font style for preserve text */ - protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart = 'document') + protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $parent, $docPart = 'document') { // Paragraph style $paragraphStyle = null; $headingMatches = array(); if ($xmlReader->elementExists('w:pPr', $domNode)) { $paragraphStyle = $this->readParagraphStyle($xmlReader, $domNode); - if (is_array($paragraphStyle) && array_key_exists('styleName', $paragraphStyle)) { + if (is_array($paragraphStyle) && isset($paragraphStyle['styleName'])) { preg_match('/Heading(\d)/', $paragraphStyle['styleName'], $headingMatches); } } @@ -164,32 +166,33 @@ abstract class AbstractPart if ($runLinkCount == 0) { $parent->addTextBreak(null, $paragraphStyle); } else { - if ($runLinkCount > 1) { - $textrun = $parent->addTextRun($paragraphStyle); - $textParent = &$textrun; - } else { - $textParent = &$parent; - } $nodes = $xmlReader->getElements('*', $domNode); foreach ($nodes as $node) { - $this->readRun($xmlReader, $node, $textParent, $docPart, $paragraphStyle); + $this->readRun( + $xmlReader, + $node, + ($runLinkCount > 1) ? $parent->addTextRun($paragraphStyle) : $parent, + $docPart, + $paragraphStyle + ); } } } } /** - * Read w:r + * Read w:r. * * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader * @param \DOMElement $domNode * @param mixed $parent * @param string $docPart * @param mixed $paragraphStyle + * @return void * * @todo Footnote paragraph style */ - protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart, $paragraphStyle = null) + protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, $parent, $docPart, $paragraphStyle = null) { if (!in_array($domNode->nodeName, array('w:r', 'w:hyperlink'))) { return; @@ -241,14 +244,15 @@ abstract class AbstractPart } /** - * Read w:tbl + * Read w:tbl. * * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader * @param \DOMElement $domNode * @param mixed $parent * @param string $docPart + * @return void */ - protected function readTable(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart = 'document') + protected function readTable(XMLReader $xmlReader, \DOMElement $domNode, $parent, $docPart = 'document') { // Table style $tblStyle = null; @@ -301,7 +305,7 @@ abstract class AbstractPart } /** - * Read w:pPr + * Read w:pPr. * * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader * @param \DOMElement $domNode @@ -337,7 +341,7 @@ abstract class AbstractPart * * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader * @param \DOMElement $domNode - * @return array + * @return array|null */ protected function readFontStyle(XMLReader $xmlReader, \DOMElement $domNode) { @@ -369,6 +373,7 @@ abstract class AbstractPart 'superScript' => array(self::READ_EQUAL, 'w:vertAlign', 'w:val', 'superscript'), 'subScript' => array(self::READ_EQUAL, 'w:vertAlign', 'w:val', 'subscript'), 'fgColor' => array(self::READ_VALUE, 'w:highlight'), + 'rtl' => array(self::READ_TRUE, 'w:rtl'), ); return $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); @@ -483,8 +488,8 @@ abstract class AbstractPart $style = true; } elseif ($method == self::READ_FALSE) { $style = false; - } elseif ($method == self::READ_EQUAL && $attributeValue == $expected) { - $style = true; + } elseif ($method == self::READ_EQUAL) { + $style = $attributeValue == $expected; } return $style; @@ -500,10 +505,9 @@ abstract class AbstractPart private function getMediaTarget($docPart, $rId) { $target = null; - if (array_key_exists($docPart, $this->rels)) { - if (array_key_exists($rId, $this->rels[$docPart])) { - $target = $this->rels[$docPart][$rId]['target']; - } + + if (isset($this->rels[$docPart]) && isset($this->rels[$docPart][$rId])) { + $target = $this->rels[$docPart][$rId]['target']; } return $target; diff --git a/src/PhpWord/Reader/Word2007/DocPropsCore.php b/src/PhpWord/Reader/Word2007/DocPropsCore.php index 0b92b64d..54537525 100644 --- a/src/PhpWord/Reader/Word2007/DocPropsCore.php +++ b/src/PhpWord/Reader/Word2007/DocPropsCore.php @@ -52,26 +52,27 @@ class DocPropsCore extends AbstractPart protected $callbacks = array('dcterms:created' => 'strtotime', 'dcterms:modified' => 'strtotime'); /** - * Read core/extended document properties + * Read core/extended document properties. * * @param \PhpOffice\PhpWord\PhpWord $phpWord + * @return void */ - public function read(PhpWord &$phpWord) + public function read(PhpWord $phpWord) { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); - $docProps = $phpWord->getDocumentProperties(); + $docProps = $phpWord->getDocInfo(); $nodes = $xmlReader->getElements('*'); if ($nodes->length > 0) { foreach ($nodes as $node) { - if (!array_key_exists($node->nodeName, $this->mapping)) { + if (!isset($this->mapping[$node->nodeName])) { continue; } $method = $this->mapping[$node->nodeName]; $value = $node->nodeValue == '' ? null : $node->nodeValue; - if (array_key_exists($node->nodeName, $this->callbacks)) { + if (isset($this->callbacks[$node->nodeName])) { $value = $this->callbacks[$node->nodeName]($value); } if (method_exists($docProps, $method)) { diff --git a/src/PhpWord/Reader/Word2007/DocPropsCustom.php b/src/PhpWord/Reader/Word2007/DocPropsCustom.php index efbbfaa5..eb725b2e 100644 --- a/src/PhpWord/Reader/Word2007/DocPropsCustom.php +++ b/src/PhpWord/Reader/Word2007/DocPropsCustom.php @@ -17,7 +17,7 @@ namespace PhpOffice\PhpWord\Reader\Word2007; -use PhpOffice\PhpWord\DocumentProperties; +use PhpOffice\PhpWord\Metadata\DocInfo; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Shared\XMLReader; @@ -29,15 +29,16 @@ use PhpOffice\PhpWord\Shared\XMLReader; class DocPropsCustom extends AbstractPart { /** - * Read custom document properties + * Read custom document properties. * * @param \PhpOffice\PhpWord\PhpWord $phpWord + * @return void */ - public function read(PhpWord &$phpWord) + public function read(PhpWord $phpWord) { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); - $docProps = $phpWord->getDocumentProperties(); + $docProps = $phpWord->getDocInfo(); $nodes = $xmlReader->getElements('*'); if ($nodes->length > 0) { @@ -46,8 +47,8 @@ class DocPropsCustom extends AbstractPart $attributeNode = $xmlReader->getElement('*', $node); $attributeType = $attributeNode->nodeName; $attributeValue = $attributeNode->nodeValue; - $attributeValue = DocumentProperties::convertProperty($attributeValue, $attributeType); - $attributeType = DocumentProperties::convertPropertyType($attributeType); + $attributeValue = DocInfo::convertProperty($attributeValue, $attributeType); + $attributeType = DocInfo::convertPropertyType($attributeType); $docProps->setCustomProperty($propertyName, $attributeValue, $attributeType); } } diff --git a/src/PhpWord/Reader/Word2007/Document.php b/src/PhpWord/Reader/Word2007/Document.php index be804531..e1beed06 100644 --- a/src/PhpWord/Reader/Word2007/Document.php +++ b/src/PhpWord/Reader/Word2007/Document.php @@ -17,9 +17,9 @@ namespace PhpOffice\PhpWord\Reader\Word2007; +use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Shared\XMLReader; -use PhpOffice\PhpWord\Element\Section; /** * Document reader @@ -37,11 +37,12 @@ class Document extends AbstractPart private $phpWord; /** - * Read document.xml + * Read document.xml. * * @param \PhpOffice\PhpWord\PhpWord $phpWord + * @return void */ - public function read(PhpWord &$phpWord) + public function read(PhpWord $phpWord) { $this->phpWord = $phpWord; $xmlReader = new XMLReader(); @@ -52,7 +53,7 @@ class Document extends AbstractPart if ($nodes->length > 0) { $section = $this->phpWord->addSection(); foreach ($nodes as $node) { - if (array_key_exists($node->nodeName, $readMethods)) { + if (isset($readMethods[$node->nodeName])) { $readMethod = $readMethods[$node->nodeName]; $this->$readMethod($xmlReader, $node, $section); } @@ -61,18 +62,19 @@ class Document extends AbstractPart } /** - * Read header footer + * Read header footer. * * @param array $settings - * @param \PhpOffice\PhpWord\Element\Section $section + * @param \PhpOffice\PhpWord\Element\Section &$section + * @return void */ private function readHeaderFooter($settings, Section &$section) { $readMethods = array('w:p' => 'readParagraph', 'w:tbl' => 'readTable'); - if (is_array($settings) && array_key_exists('hf', $settings)) { + if (is_array($settings) && isset($settings['hf'])) { foreach ($settings['hf'] as $rId => $hfSetting) { - if (array_key_exists($rId, $this->rels['document'])) { + if (isset($this->rels['document'][$rId])) { list($hfType, $xmlFile, $docPart) = array_values($this->rels['document'][$rId]); $addMethod = "add{$hfType}"; $hfObject = $section->$addMethod($hfSetting['type']); @@ -83,7 +85,7 @@ class Document extends AbstractPart $nodes = $xmlReader->getElements('*'); if ($nodes->length > 0) { foreach ($nodes as $node) { - if (array_key_exists($node->nodeName, $readMethods)) { + if (isset($readMethods[$node->nodeName])) { $readMethod = $readMethods[$node->nodeName]; $this->$readMethod($xmlReader, $node, $hfObject, $docPart); } @@ -138,11 +140,12 @@ class Document extends AbstractPart } /** - * Read w:p node + * Read w:p node. * * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader * @param \DOMElement $node - * @param \PhpOffice\PhpWord\Element\Section $section + * @param \PhpOffice\PhpWord\Element\Section &$section + * @return void * * @todo */ @@ -167,16 +170,17 @@ class Document extends AbstractPart } /** - * Read w:sectPr node + * Read w:sectPr node. * * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader * @param \DOMElement $node - * @param \PhpOffice\PhpWord\Element\Section $section + * @param \PhpOffice\PhpWord\Element\Section &$section + * @return void */ private function readWSectPrNode(XMLReader $xmlReader, \DOMElement $node, Section &$section) { - $settings = $this->readSectionStyle($xmlReader, $node); - $section->setSettings($settings); - $this->readHeaderFooter($settings, $section); + $style = $this->readSectionStyle($xmlReader, $node); + $section->setStyle($style); + $this->readHeaderFooter($style, $section); } } diff --git a/src/PhpWord/Reader/Word2007/Footnotes.php b/src/PhpWord/Reader/Word2007/Footnotes.php index 47713cfb..6f6adc87 100644 --- a/src/PhpWord/Reader/Word2007/Footnotes.php +++ b/src/PhpWord/Reader/Word2007/Footnotes.php @@ -42,11 +42,12 @@ class Footnotes extends AbstractPart protected $element = 'footnote'; /** - * Read (footnotes|endnotes).xml + * Read (footnotes|endnotes).xml. * * @param \PhpOffice\PhpWord\PhpWord $phpWord + * @return void */ - public function read(PhpWord &$phpWord) + public function read(PhpWord $phpWord) { $getMethod = "get{$this->collection}"; $collection = $phpWord->$getMethod()->getItems(); @@ -61,7 +62,7 @@ class Footnotes extends AbstractPart // Avoid w:type "separator" and "continuationSeparator" // Only look for or without w:type attribute - if (is_null($type) && array_key_exists($id, $collection)) { + if (is_null($type) && isset($collection[$id])) { $element = $collection[$id]; $pNodes = $xmlReader->getElements('w:p/*', $node); foreach ($pNodes as $pNode) { diff --git a/src/PhpWord/Reader/Word2007/Numbering.php b/src/PhpWord/Reader/Word2007/Numbering.php index 2dd3f521..872d4503 100644 --- a/src/PhpWord/Reader/Word2007/Numbering.php +++ b/src/PhpWord/Reader/Word2007/Numbering.php @@ -28,11 +28,12 @@ use PhpOffice\PhpWord\Shared\XMLReader; class Numbering extends AbstractPart { /** - * Read numbering.xml + * Read numbering.xml. * * @param \PhpOffice\PhpWord\PhpWord $phpWord + * @return void */ - public function read(PhpWord &$phpWord) + public function read(PhpWord $phpWord) { $abstracts = array(); $numberings = array(); diff --git a/src/PhpWord/Reader/Word2007/Styles.php b/src/PhpWord/Reader/Word2007/Styles.php index 7dc4b6ea..299fe1df 100644 --- a/src/PhpWord/Reader/Word2007/Styles.php +++ b/src/PhpWord/Reader/Word2007/Styles.php @@ -28,11 +28,12 @@ use PhpOffice\PhpWord\Shared\XMLReader; class Styles extends AbstractPart { /** - * Read styles.xml + * Read styles.xml. * * @param \PhpOffice\PhpWord\PhpWord $phpWord + * @return void */ - public function read(PhpWord &$phpWord) + public function read(PhpWord $phpWord) { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); diff --git a/src/PhpWord/Settings.php b/src/PhpWord/Settings.php index cb74389a..67b1dbed 100644 --- a/src/PhpWord/Settings.php +++ b/src/PhpWord/Settings.php @@ -119,6 +119,13 @@ class Settings */ private static $defaultFontSize = self::DEFAULT_FONT_SIZE; + /** + * The user defined temporary directory. + * + * @var string + */ + private static $tempDir = ''; + /** * Return the compatibility option used by the XMLWriter * @@ -188,7 +195,9 @@ class Settings } /** - * Return the PDF Rendering Library + * Return the PDF Rendering Library. + * + * @return string */ public static function getPdfRendererName() { @@ -214,7 +223,9 @@ class Settings /** - * Return the directory path to the PDF Rendering Library + * Return the directory path to the PDF Rendering Library. + * + * @return string */ public static function getPdfRendererPath() { @@ -229,7 +240,7 @@ class Settings */ public static function setPdfRendererPath($libraryBaseDir) { - if ((file_exists($libraryBaseDir) === false) || (is_readable($libraryBaseDir) === false)) { + if (false === file_exists($libraryBaseDir) || false === is_readable($libraryBaseDir)) { return false; } self::$pdfRendererPath = $libraryBaseDir; @@ -265,6 +276,37 @@ class Settings return true; } + /** + * Sets the user defined path to temporary directory. + * + * @since 0.12.0 + * + * @param string $tempDir The user defined path to temporary directory. + * @return void + */ + public static function setTempDir($tempDir) + { + self::$tempDir = $tempDir; + } + + /** + * Returns path to temporary directory. + * + * @since 0.12.0 + * + * @return string + */ + public static function getTempDir() + { + $tempDir = sys_get_temp_dir(); + + if (!empty(self::$tempDir)) { + $tempDir = self::$tempDir; + } + + return $tempDir; + } + /** * Get default font name * diff --git a/src/PhpWord/Shared/Converter.php b/src/PhpWord/Shared/Converter.php new file mode 100644 index 00000000..c6727edd --- /dev/null +++ b/src/PhpWord/Shared/Converter.php @@ -0,0 +1,278 @@ +' . $html . ''; } @@ -83,12 +89,13 @@ class Html } /** - * Parse a node and add a corresponding element to the parent element + * Parse a node and add a corresponding element to the parent element. * * @param \DOMNode $node node to parse * @param \PhpOffice\PhpWord\Element\AbstractContainer $element object to add an element corresponding with the node * @param array $styles Array with all styles * @param array $data Array to transport data to a next level in the DOM tree, for example level of listitems + * @return void */ protected static function parseNode($node, $element, $styles = array(), $data = array()) { @@ -126,8 +133,7 @@ class Html $newElement = null; $keys = array('node', 'element', 'styles', 'data', 'argument1', 'argument2'); - if (array_key_exists($node->nodeName, $nodes)) { - + if (isset($nodes[$node->nodeName])) { // Execute method based on node mapping table and return $newElement or null // Arguments are passed by reference $arguments = array(); @@ -157,12 +163,13 @@ class Html } /** - * Parse child nodes + * Parse child nodes. * * @param \DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element * @param array $styles * @param array $data + * @return void */ private static function parseChildNodes($node, $element, $styles, $data) { @@ -183,7 +190,7 @@ class Html * * @param \DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element - * @param array $styles + * @param array &$styles * @return \PhpOffice\PhpWord\Element\TextRun */ private static function parseParagraph($node, $element, &$styles) @@ -198,7 +205,7 @@ class Html * Parse heading node * * @param \PhpOffice\PhpWord\Element\AbstractContainer $element - * @param array $styles + * @param array &$styles * @param string $argument1 Name of heading style * @return \PhpOffice\PhpWord\Element\TextRun * @@ -218,7 +225,7 @@ class Html * * @param \DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element - * @param array $styles + * @param array &$styles * @return null */ private static function parseText($node, $element, &$styles) @@ -237,7 +244,7 @@ class Html /** * Parse property node * - * @param array $styles + * @param array &$styles * @param string $argument1 Style name * @param string $argument2 Style value * @return null @@ -254,7 +261,7 @@ class Html * * @param \DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element - * @param array $styles + * @param array &$styles * @param string $argument1 Method name * @return \PhpOffice\PhpWord\Element\AbstractContainer $element * @@ -284,8 +291,8 @@ class Html /** * Parse list node * - * @param array $styles - * @param array $data + * @param array &$styles + * @param array &$data * @param string $argument1 List type * @return null */ @@ -306,7 +313,7 @@ class Html * * @param \DOMNode $node * @param \PhpOffice\PhpWord\Element\AbstractContainer $element - * @param array $styles + * @param array &$styles * @param array $data * @return null * diff --git a/src/PhpWord/Shared/OLERead.php b/src/PhpWord/Shared/OLERead.php new file mode 100644 index 00000000..82815afc --- /dev/null +++ b/src/PhpWord/Shared/OLERead.php @@ -0,0 +1,313 @@ +data = file_get_contents($sFileName, false, null, 0, 8); + + // Check OLE identifier + if ($this->data != self::IDENTIFIER_OLE) { + throw new Exception('The filename ' . $sFileName . ' is not recognised as an OLE file'); + } + + // Get the file data + $this->data = file_get_contents($sFileName); + + // Total number of sectors used for the SAT + $this->numBigBlockDepotBlocks = self::getInt4d($this->data, self::NUM_BIG_BLOCK_DEPOT_BLOCKS_POS); + + // SecID of the first sector of the directory stream + $this->rootStartBlock = self::getInt4d($this->data, self::ROOT_START_BLOCK_POS); + + // SecID of the first sector of the SSAT (or -2 if not extant) + $this->sbdStartBlock = self::getInt4d($this->data, self::SMALL_BLOCK_DEPOT_BLOCK_POS); + + // SecID of the first sector of the MSAT (or -2 if no additional sectors are used) + $this->extensionBlock = self::getInt4d($this->data, self::EXTENSION_BLOCK_POS); + + // Total number of sectors used by MSAT + $this->numExtensionBlocks = self::getInt4d($this->data, self::NUM_EXTENSION_BLOCK_POS); + + $bigBlockDepotBlocks = array(); + $pos = self::BIG_BLOCK_DEPOT_BLOCKS_POS; + + $bbdBlocks = $this->numBigBlockDepotBlocks; + + if ($this->numExtensionBlocks != 0) { + $bbdBlocks = (self::BIG_BLOCK_SIZE - self::BIG_BLOCK_DEPOT_BLOCKS_POS)/4; + } + + for ($i = 0; $i < $bbdBlocks; ++$i) { + $bigBlockDepotBlocks[$i] = self::getInt4d($this->data, $pos); + $pos += 4; + } + + for ($j = 0; $j < $this->numExtensionBlocks; ++$j) { + $pos = ($this->extensionBlock + 1) * self::BIG_BLOCK_SIZE; + $blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, self::BIG_BLOCK_SIZE / 4 - 1); + + for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; ++$i) { + $bigBlockDepotBlocks[$i] = self::getInt4d($this->data, $pos); + $pos += 4; + } + + $bbdBlocks += $blocksToRead; + if ($bbdBlocks < $this->numBigBlockDepotBlocks) { + $this->extensionBlock = self::getInt4d($this->data, $pos); + } + } + + $pos = 0; + $this->bigBlockChain = ''; + $bbs = self::BIG_BLOCK_SIZE / 4; + for ($i = 0; $i < $this->numBigBlockDepotBlocks; ++$i) { + $pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE; + + $this->bigBlockChain .= substr($this->data, $pos, 4*$bbs); + $pos += 4*$bbs; + } + + $pos = 0; + $sbdBlock = $this->sbdStartBlock; + $this->smallBlockChain = ''; + while ($sbdBlock != -2) { + $pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE; + + $this->smallBlockChain .= substr($this->data, $pos, 4*$bbs); + $pos += 4*$bbs; + + $sbdBlock = self::getInt4d($this->bigBlockChain, $sbdBlock*4); + } + + // read the directory stream + $block = $this->rootStartBlock; + $this->entry = $this->readData($block); + + $this->readPropertySets(); + } + + /** + * Extract binary stream data + * + * @return string + */ + public function getStream($stream) + { + if ($stream === null) { + return null; + } + + $streamData = ''; + + if ($this->props[$stream]['size'] < self::SMALL_BLOCK_THRESHOLD) { + $rootdata = $this->readData($this->props[$this->rootentry]['startBlock']); + + $block = $this->props[$stream]['startBlock']; + + while ($block != -2) { + $pos = $block * self::SMALL_BLOCK_SIZE; + $streamData .= substr($rootdata, $pos, self::SMALL_BLOCK_SIZE); + + $block = self::getInt4d($this->smallBlockChain, $block*4); + } + + return $streamData; + } else { + $numBlocks = $this->props[$stream]['size'] / self::BIG_BLOCK_SIZE; + if ($this->props[$stream]['size'] % self::BIG_BLOCK_SIZE != 0) { + ++$numBlocks; + } + + if ($numBlocks == 0) { + return ''; + } + + $block = $this->props[$stream]['startBlock']; + + while ($block != -2) { + $pos = ($block + 1) * self::BIG_BLOCK_SIZE; + $streamData .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); + $block = self::getInt4d($this->bigBlockChain, $block*4); + } + + return $streamData; + } + } + + /** + * Read a standard stream (by joining sectors using information from SAT) + * + * @param int $blSectorId Sector ID where the stream starts + * @return string Data for standard stream + */ + private function readData($blSectorId) + { + $block = $blSectorId; + $data = ''; + + while ($block != -2) { + $pos = ($block + 1) * self::BIG_BLOCK_SIZE; + $data .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); + $block = self::getInt4d($this->bigBlockChain, $block*4); + } + return $data; + } + + /** + * Read entries in the directory stream. + */ + private function readPropertySets() + { + $offset = 0; + + // loop through entires, each entry is 128 bytes + $entryLen = strlen($this->entry); + while ($offset < $entryLen) { + // entry data (128 bytes) + $data = substr($this->entry, $offset, self::PROPERTY_STORAGE_BLOCK_SIZE); + + // size in bytes of name + $nameSize = ord($data[self::SIZE_OF_NAME_POS]) | (ord($data[self::SIZE_OF_NAME_POS+1]) << 8); + + // type of entry + $type = ord($data[self::TYPE_POS]); + + // sectorID of first sector or short sector, if this entry refers to a stream (the case with workbook) + // sectorID of first sector of the short-stream container stream, if this entry is root entry + $startBlock = self::getInt4d($data, self::START_BLOCK_POS); + + $size = self::getInt4d($data, self::SIZE_POS); + + $name = str_replace("\x00", "", substr($data, 0, $nameSize)); + + + $this->props[] = array ( + 'name' => $name, + 'type' => $type, + 'startBlock' => $startBlock, + 'size' => $size); + + // tmp helper to simplify checks + $upName = strtoupper($name); + + // Workbook directory entry (BIFF5 uses Book, BIFF8 uses Workbook) + // print_r($upName.PHP_EOL); + if (($upName === 'WORDDOCUMENT')) { + $this->wrkdocument = count($this->props) - 1; + } elseif ($upName === '1TABLE') { + $this->wrk1Table = count($this->props) - 1; + } elseif ($upName === 'DATA') { + $this->wrkData = count($this->props) - 1; + } elseif ($upName === 'OBJECTPOOL') { + $this->wrkObjectPoolelseif = count($this->props) - 1; + } elseif ($upName === 'ROOT ENTRY' || $upName === 'R') { + $this->rootentry = count($this->props) - 1; + } + + // Summary information + if ($name == chr(5) . 'SummaryInformation') { + $this->summaryInformation = count($this->props) - 1; + } + + // Additional Document Summary information + if ($name == chr(5) . 'DocumentSummaryInformation') { + $this->docSummaryInfos = count($this->props) - 1; + } + + $offset += self::PROPERTY_STORAGE_BLOCK_SIZE; + } + + } + + /** + * Read 4 bytes of data at specified position + * + * @param string $data + * @param int $pos + * @return int + */ + private static function getInt4d($data, $pos) + { + // FIX: represent numbers correctly on 64-bit system + // http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334 + // Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems + $or24 = ord($data[$pos + 3]); + if ($or24 >= 128) { + // negative number + $ord24 = -abs((256 - $or24) << 24); + } else { + $ord24 = ($or24 & 127) << 24; + } + return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) | (ord($data[$pos + 2]) << 16) | $ord24; + } +} diff --git a/src/PhpWord/Shared/String.php b/src/PhpWord/Shared/String.php index 1e4504cc..be04fd0e 100644 --- a/src/PhpWord/Shared/String.php +++ b/src/PhpWord/Shared/String.php @@ -178,7 +178,9 @@ class String } /** - * Build control characters array + * Build control characters array. + * + * @return void */ private static function buildControlCharacters() { diff --git a/src/PhpWord/Shared/XMLReader.php b/src/PhpWord/Shared/XMLReader.php index 153152ee..ca6869eb 100644 --- a/src/PhpWord/Shared/XMLReader.php +++ b/src/PhpWord/Shared/XMLReader.php @@ -96,7 +96,11 @@ class XMLReader $this->xpath = new \DOMXpath($this->dom); } - return $this->xpath->query($path, $contextNode); + if (is_null($contextNode)) { + return $this->xpath->query($path); + } else { + return $this->xpath->query($path, $contextNode); + } } /** diff --git a/src/PhpWord/Shared/XMLWriter.php b/src/PhpWord/Shared/XMLWriter.php index cb00c70b..2134f62a 100644 --- a/src/PhpWord/Shared/XMLWriter.php +++ b/src/PhpWord/Shared/XMLWriter.php @@ -66,12 +66,12 @@ class XMLWriter $this->xmlWriter->openMemory(); } else { // Create temporary filename - $this->tempFile = @tempnam($tempFolder, 'xml'); + $this->tempFile = tempnam($tempFolder, 'xml'); // Fallback to memory when temporary file cannot be used // @codeCoverageIgnoreStart // Can't find any test case. Uncomment when found. - if ($this->xmlWriter->openUri($this->tempFile) === false) { + if (false === $this->tempFile || false === $this->xmlWriter->openUri($this->tempFile)) { $this->xmlWriter->openMemory(); } // @codeCoverageIgnoreEnd @@ -139,6 +139,30 @@ class XMLWriter } } + /** + * Write simple element and attribute(s) block + * + * There are two options: + * 1. If the `$attributes` is an array, then it's an associative array of attributes + * 2. If not, then it's a simple attribute-value pair + * + * @param string $element + * @param string|array $attributes + * @param string $value + * @return void + */ + public function writeElementBlock($element, $attributes, $value = null) + { + $this->xmlWriter->startElement($element); + if (!is_array($attributes)) { + $attributes = array($attributes => $value); + } + foreach ($attributes as $attribute => $value) { + $this->xmlWriter->writeAttribute($attribute, $value); + } + $this->xmlWriter->endElement(); + } + /** * Write element if ... * @@ -146,6 +170,7 @@ class XMLWriter * @param string $element * @param string $attribute * @param mixed $value + * @return void */ public function writeElementIf($condition, $element, $attribute = null, $value = null) { @@ -166,6 +191,7 @@ class XMLWriter * @param bool $condition * @param string $attribute * @param mixed $value + * @return void */ public function writeAttributeIf($condition, $attribute, $value) { diff --git a/src/PhpWord/Shared/ZipArchive.php b/src/PhpWord/Shared/ZipArchive.php index cbfcb071..157959e8 100644 --- a/src/PhpWord/Shared/ZipArchive.php +++ b/src/PhpWord/Shared/ZipArchive.php @@ -83,7 +83,7 @@ class ZipArchive $this->usePclzip = (Settings::getZipClass() != 'ZipArchive'); if ($this->usePclzip) { if (!defined('PCLZIP_TEMPORARY_DIR')) { - define('PCLZIP_TEMPORARY_DIR', sys_get_temp_dir() . '/'); + define('PCLZIP_TEMPORARY_DIR', Settings::getTempDir() . '/'); } require_once 'PCLZip/pclzip.lib.php'; } @@ -139,7 +139,7 @@ class ZipArchive $this->numFiles = $zip->numFiles; } else { $zip = new \PclZip($this->filename); - $this->tempDir = sys_get_temp_dir(); + $this->tempDir = Settings::getTempDir(); $this->numFiles = count($zip->listContent()); } $this->zip = $zip; @@ -158,7 +158,7 @@ class ZipArchive { if (!$this->usePclzip) { if ($this->zip->close() === false) { - throw new Exception("Could not close zip file $this->filename."); + throw new Exception("Could not close zip file {$this->filename}."); } } @@ -218,14 +218,22 @@ class ZipArchive { /** @var \PclZip $zip Type hint */ $zip = $this->zip; - $filename = realpath($filename); + + // Bugfix GH-261 https://github.com/PHPOffice/PHPWord/pull/261 + $realpathFilename = realpath($filename); + if ($realpathFilename !== false) { + $filename = $realpathFilename; + } + $filenameParts = pathinfo($filename); $localnameParts = pathinfo($localname); // To Rename the file while adding it to the zip we // need to create a temp file with the correct name + $tempFile = false; if ($filenameParts['basename'] != $localnameParts['basename']) { - $temppath = $this->tempDir . '/' . $localnameParts['basename']; + $tempFile = true; // temp file created + $temppath = $this->tempDir . DIRECTORY_SEPARATOR . $localnameParts['basename']; copy($filename, $temppath); $filename = $temppath; $filenameParts = pathinfo($temppath); @@ -236,6 +244,11 @@ class ZipArchive $res = $zip->add($filename, PCLZIP_OPT_REMOVE_PATH, $pathRemoved, PCLZIP_OPT_ADD_PATH, $pathAdded); + if ($tempFile) { + // Remove temp file, if created + unlink($this->tempDir . DIRECTORY_SEPARATOR . $localnameParts['basename']); + } + return ($res == 0) ? false : true; } @@ -253,19 +266,19 @@ class ZipArchive $filenameParts = pathinfo($localname); // Write $contents to a temp file - $handle = fopen($this->tempDir . '/' . $filenameParts["basename"], "wb"); + $handle = fopen($this->tempDir . DIRECTORY_SEPARATOR . $filenameParts['basename'], 'wb'); fwrite($handle, $contents); fclose($handle); // Add temp file to zip - $filename = $this->tempDir . '/' . $filenameParts["basename"]; + $filename = $this->tempDir . DIRECTORY_SEPARATOR . $filenameParts['basename']; $pathRemoved = $this->tempDir; $pathAdded = $filenameParts['dirname']; $res = $zip->add($filename, PCLZIP_OPT_REMOVE_PATH, $pathRemoved, PCLZIP_OPT_ADD_PATH, $pathAdded); // Remove temp file - @unlink($this->tempDir . '/' . $filenameParts["basename"]); + @unlink($this->tempDir . DIRECTORY_SEPARATOR . $filenameParts['basename']); return ($res == 0) ? false : true; } @@ -325,7 +338,7 @@ class ZipArchive $extracted = $zip->extractByIndex($listIndex, PCLZIP_OPT_EXTRACT_AS_STRING); } if ((is_array($extracted)) && ($extracted != 0)) { - $contents = $extracted[0]["content"]; + $contents = $extracted[0]['content']; } return $contents; @@ -364,8 +377,8 @@ class ZipArchive $listCount = count($list); $listIndex = -1; for ($i = 0; $i < $listCount; ++$i) { - if (strtolower($list[$i]["filename"]) == strtolower($filename) || - strtolower($list[$i]["stored_filename"]) == strtolower($filename)) { + if (strtolower($list[$i]['filename']) == strtolower($filename) || + strtolower($list[$i]['stored_filename']) == strtolower($filename)) { $listIndex = $i; break; } diff --git a/src/PhpWord/Style.php b/src/PhpWord/Style.php index d56c73fe..ab03106f 100644 --- a/src/PhpWord/Style.php +++ b/src/PhpWord/Style.php @@ -123,8 +123,11 @@ class Style } /** - * Reset styles + * Reset styles. + * * @since 0.10.0 + * + * @return void */ public static function resetStyles() { @@ -160,7 +163,7 @@ class Style */ public static function getStyle($styleName) { - if (array_key_exists($styleName, self::$styles)) { + if (isset(self::$styles[$styleName])) { return self::$styles[$styleName]; } else { return null; @@ -179,7 +182,7 @@ class Style */ private static function setStyleValues($name, $style, $value = null) { - if (!array_key_exists($name, self::$styles)) { + if (!isset(self::$styles[$name])) { if ($value !== null) { if (is_array($value)) { $style->setStyleByArray($value); diff --git a/src/PhpWord/Style/AbstractStyle.php b/src/PhpWord/Style/AbstractStyle.php index 13ef8f9b..ab1a1ee7 100644 --- a/src/PhpWord/Style/AbstractStyle.php +++ b/src/PhpWord/Style/AbstractStyle.php @@ -126,6 +126,24 @@ abstract class AbstractStyle return $this; } + /** + * Return style value of child style object, e.g. `left` from `Indentation` child style of `Paragraph` + * + * @param \PhpOffice\PhpWord\Style\AbstractStyle $substyleObject + * @param string $substyleProperty + * @return mixed + * @since 0.12.0 + */ + public function getChildStyleValue($substyleObject, $substyleProperty) + { + if ($substyleObject !== null) { + $method = "get{$substyleProperty}"; + return $substyleObject->$method(); + } else { + return null; + } + } + /** * Set style value template method * @@ -226,8 +244,10 @@ abstract class AbstractStyle if (is_string($value) && (preg_match('/[^\d]/', $value) == 0)) { $value = intval($value); } - if (!is_int($value)) { + if (!is_numeric($value)) { $value = $default; + } else { + $value = intval($value); } return $value; @@ -264,7 +284,7 @@ abstract class AbstractStyle protected function setEnumVal($value = null, $enum = array(), $default = null) { if ($value != null && trim($value) != '' && !empty($enum) && !in_array($value, $enum)) { - throw new \InvalidArgumentException('Invalid style value.'); + throw new \InvalidArgumentException("Invalid style value: {$value} Options:".join(',', $enum)); } elseif ($value === null || trim($value) == '') { $value = $default; } @@ -277,7 +297,7 @@ abstract class AbstractStyle * * @param mixed $value * @param string $styleName - * @param mixed $style + * @param mixed &$style * @return mixed */ protected function setObjectVal($value, $styleName, &$style) @@ -296,6 +316,24 @@ abstract class AbstractStyle return $style; } + /** + * Set $property value and set $pairProperty = false when $value = true + * + * @param bool &$property + * @param bool &$pairProperty + * @param bool $value + * @return self + */ + protected function setPairedVal(&$property, &$pairProperty, $value) + { + $property = $this->setBoolVal($value, $property); + if ($value == true) { + $pairProperty = false; + } + + return $this; + } + /** * Set style using associative array * diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index 2d1b88d0..11290c87 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -94,7 +94,9 @@ class Cell extends Border private $shading; /** - * Get vertical align + * Get vertical align. + * + * @return string */ public function getVAlign() { @@ -116,7 +118,9 @@ class Cell extends Border } /** - * Get text direction + * Get text direction. + * + * @return string */ public function getTextDirection() { @@ -163,7 +167,9 @@ class Cell extends Border } /** - * Get grid span (colspan) + * Get grid span (colspan). + * + * @return integer */ public function getGridSpan() { @@ -184,7 +190,9 @@ class Cell extends Border } /** - * Get vertical merge (rowspan) + * Get vertical merge (rowspan). + * + * @return string */ public function getVMerge() { diff --git a/src/PhpWord/Style/Chart.php b/src/PhpWord/Style/Chart.php new file mode 100644 index 00000000..13b72a33 --- /dev/null +++ b/src/PhpWord/Style/Chart.php @@ -0,0 +1,127 @@ +setStyleByArray($style); + } + + /** + * Get width + * + * @return int + */ + public function getWidth() + { + return $this->width; + } + + /** + * Set width + * + * @param int $value + * @return self + */ + public function setWidth($value = null) + { + $this->width = $this->setIntVal($value, $this->width); + + return $this; + } + + /** + * Get height + * + * @return int + */ + public function getHeight() + { + return $this->height; + } + + /** + * Set height + * + * @param int $value + * @return self + */ + public function setHeight($value = null) + { + $this->height = $this->setIntVal($value, $this->height); + + return $this; + } + + /** + * Is 3D + * + * @return bool + */ + public function is3d() + { + return $this->is3d; + } + + /** + * Set 3D + * + * @param bool $value + * @return self + */ + public function set3d($value = true) + { + $this->is3d = $this->setBoolVal($value, $this->is3d); + + return $this; + } +} diff --git a/src/PhpWord/Style/Extrusion.php b/src/PhpWord/Style/Extrusion.php new file mode 100644 index 00000000..ccbb2650 --- /dev/null +++ b/src/PhpWord/Style/Extrusion.php @@ -0,0 +1,106 @@ +setStyleByArray($style); + } + + /** + * Get type + * + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * Set pattern + * + * @param string $value + * @return self + */ + public function setType($value = null) + { + $enum = array(self::EXTRUSION_PARALLEL, self::EXTRUSION_PERSPECTIVE); + $this->type = $this->setEnumVal($value, $enum, null); + + return $this; + } + + /** + * Get color + * + * @return string + */ + public function getColor() + { + return $this->color; + } + + /** + * Set color + * + * @param string $value + * @return self + */ + public function setColor($value = null) + { + $this->color = $value; + + return $this; + } +} diff --git a/src/PhpWord/Style/Fill.php b/src/PhpWord/Style/Fill.php new file mode 100644 index 00000000..08c7a857 --- /dev/null +++ b/src/PhpWord/Style/Fill.php @@ -0,0 +1,69 @@ +setStyleByArray($style); + } + + /** + * Get color + * + * @return string + */ + public function getColor() + { + return $this->color; + } + + /** + * Set color + * + * @param string $value + * @return self + */ + public function setColor($value = null) + { + $this->color = $value; + + return $this; + } +} diff --git a/src/PhpWord/Style/Font.php b/src/PhpWord/Style/Font.php index 0775b8b3..8980258b 100644 --- a/src/PhpWord/Style/Font.php +++ b/src/PhpWord/Style/Font.php @@ -182,10 +182,31 @@ class Font extends AbstractStyle private $fgColor; /** - * Text line height + * Expanded/compressed text: 0-600 (percent) * * @var int + * @since 0.12.0 + * @link http://www.schemacentral.com/sc/ooxml/e-w_w-1.html */ + private $scale; + + /** + * Character spacing adjustment: twip + * + * @var int|float + * @since 0.12.0 + * @link http://www.schemacentral.com/sc/ooxml/e-w_spacing-2.html + */ + private $spacing; + + /** + * Font kerning: halfpoint + * + * @var int|float + * @since 0.12.0 + * @link http://www.schemacentral.com/sc/ooxml/e-w_kern-1.html + */ + private $kerning; /** * Paragraph style @@ -201,6 +222,12 @@ class Font extends AbstractStyle */ private $shading; + /** + * Right to left languages + * @var boolean + */ + private $rtl = false; + /** * Create new font style * @@ -213,6 +240,47 @@ class Font extends AbstractStyle $this->setParagraph($paragraph); } + /** + * Get style values + * + * @return array + * @since 0.12.0 + */ + public function getStyleValues() + { + $styles = array( + 'name' => $this->getStyleName(), + 'basic' => array( + 'name' => $this->getName(), + 'size' => $this->getSize(), + 'color' => $this->getColor(), + 'hint' => $this->getHint(), + ), + 'style' => array( + 'bold' => $this->isBold(), + 'italic' => $this->isItalic(), + 'underline' => $this->getUnderline(), + 'strike' => $this->isStrikethrough(), + 'dStrike' => $this->isDoubleStrikethrough(), + 'super' => $this->isSuperScript(), + 'sub' => $this->isSubScript(), + 'smallCaps' => $this->isSmallCaps(), + 'allCaps' => $this->isAllCaps(), + 'fgColor' => $this->getFgColor(), + ), + 'spacing' => array( + 'scale' => $this->getScale(), + 'spacing' => $this->getSpacing(), + 'kerning' => $this->getKerning(), + ), + 'paragraph' => $this->getParagraph(), + 'rtl' => $this->isRTL(), + 'shading' => $this->getShading(), + ); + + return $styles; + } + /** * Get style type * @@ -236,7 +304,7 @@ class Font extends AbstractStyle /** * Set font name * - * @param string $value + * @param string $value * @return self */ public function setName($value = null) @@ -259,7 +327,7 @@ class Font extends AbstractStyle /** * Set Font Content Type * - * @param string $value + * @param string $value * @return self */ public function setHint($value = null) @@ -272,7 +340,7 @@ class Font extends AbstractStyle /** * Get font size * - * @return int|float + * @return int|float */ public function getSize() { @@ -282,7 +350,7 @@ class Font extends AbstractStyle /** * Set font size * - * @param int|float $value + * @param int|float $value * @return self */ public function setSize($value = null) @@ -305,7 +373,7 @@ class Font extends AbstractStyle /** * Set font color * - * @param string $value + * @param string $value * @return self */ public function setColor($value = null) @@ -328,7 +396,7 @@ class Font extends AbstractStyle /** * Set bold * - * @param bool $value + * @param bool $value * @return self */ public function setBold($value = true) @@ -351,7 +419,7 @@ class Font extends AbstractStyle /** * Set italic * - * @param bool $value + * @param bool $value * @return self */ public function setItalic($value = true) @@ -374,7 +442,7 @@ class Font extends AbstractStyle /** * Set underline * - * @param string $value + * @param string $value * @return self */ public function setUnderline($value = self::UNDERLINE_NONE) @@ -397,12 +465,12 @@ class Font extends AbstractStyle /** * Set superscript * - * @param bool $value + * @param bool $value * @return self */ public function setSuperScript($value = true) { - return $this->setPairedProperty($this->superScript, $this->subScript, $value); + return $this->setPairedVal($this->superScript, $this->subScript, $value); } /** @@ -418,12 +486,12 @@ class Font extends AbstractStyle /** * Set subscript * - * @param bool $value + * @param bool $value * @return self */ public function setSubScript($value = true) { - return $this->setPairedProperty($this->subScript, $this->superScript, $value); + return $this->setPairedVal($this->subScript, $this->superScript, $value); } /** @@ -439,12 +507,12 @@ class Font extends AbstractStyle /** * Set strikethrough * - * @param bool $value + * @param bool $value * @return self */ public function setStrikethrough($value = true) { - return $this->setPairedProperty($this->strikethrough, $this->doubleStrikethrough, $value); + return $this->setPairedVal($this->strikethrough, $this->doubleStrikethrough, $value); } /** @@ -460,12 +528,12 @@ class Font extends AbstractStyle /** * Set double strikethrough * - * @param bool $value + * @param bool $value * @return self */ public function setDoubleStrikethrough($value = true) { - return $this->setPairedProperty($this->doubleStrikethrough, $this->strikethrough, $value); + return $this->setPairedVal($this->doubleStrikethrough, $this->strikethrough, $value); } /** @@ -481,12 +549,12 @@ class Font extends AbstractStyle /** * Set small caps * - * @param bool $value + * @param bool $value * @return self */ public function setSmallCaps($value = true) { - return $this->setPairedProperty($this->smallCaps, $this->allCaps, $value); + return $this->setPairedVal($this->smallCaps, $this->allCaps, $value); } /** @@ -502,12 +570,12 @@ class Font extends AbstractStyle /** * Set all caps * - * @param bool $value + * @param bool $value * @return self */ public function setAllCaps($value = true) { - return $this->setPairedProperty($this->allCaps, $this->smallCaps, $value); + return $this->setPairedVal($this->allCaps, $this->smallCaps, $value); } /** @@ -523,7 +591,7 @@ class Font extends AbstractStyle /** * Set foreground/highlight color * - * @param string $value + * @param string $value * @return self */ public function setFgColor($value = null) @@ -540,11 +608,7 @@ class Font extends AbstractStyle */ public function getBgColor() { - if ($this->shading !== null) { - return $this->shading->getFill(); - } else { - return null; - } + return $this->getChildStyleValue($this->shading, 'fill'); } /** @@ -558,6 +622,75 @@ class Font extends AbstractStyle $this->setShading(array('fill' => $value)); } + /** + * Get scale + * + * @return int + */ + public function getScale() + { + return $this->scale; + } + + /** + * Set scale + * + * @param int $value + * @return self + */ + public function setScale($value = null) + { + $this->scale = $this->setIntVal($value, null); + + return $this; + } + + /** + * Get font spacing + * + * @return int|float + */ + public function getSpacing() + { + return $this->spacing; + } + + /** + * Set font spacing + * + * @param int|float $value + * @return self + */ + public function setSpacing($value = null) + { + $this->spacing = $this->setNumericVal($value, null); + + return $this; + } + + /** + * Get font kerning + * + * @return int|float + */ + public function getKerning() + { + return $this->kerning; + } + + /** + * Set font kerning + * + * @param int|float $value + * @return self + */ + public function setKerning($value = null) + { + $this->kerning = $this->setNumericVal($value, null); + + return $this; + } + /** * Get line height * @@ -571,7 +704,7 @@ class Font extends AbstractStyle /** * Set lineheight * - * @param int|float|string $value + * @param int|float|string $value * @return self */ public function setLineHeight($value) @@ -604,6 +737,29 @@ class Font extends AbstractStyle return $this; } + /** + * Get rtl + * + * @return bool + */ + public function isRTL() + { + return $this->rtl; + } + + /** + * Set rtl + * + * @param bool $value + * @return self + */ + public function setRTL($value = true) + { + $this->rtl = $this->setBoolVal($value, $this->rtl); + + return $this; + } + /** * Get shading * @@ -627,24 +783,6 @@ class Font extends AbstractStyle return $this; } - /** - * Set $property value and set $pairProperty = false when $value = true - * - * @param bool $property - * @param bool $pairProperty - * @param bool $value - * @return self - */ - private function setPairedProperty(&$property, &$pairProperty, $value) - { - $property = $this->setBoolVal($value, $property); - if ($value == true) { - $pairProperty = false; - } - - return $this; - } - /** * Get bold * diff --git a/src/PhpWord/Style/Frame.php b/src/PhpWord/Style/Frame.php new file mode 100644 index 00000000..5fef5f01 --- /dev/null +++ b/src/PhpWord/Style/Frame.php @@ -0,0 +1,513 @@ +alignment = new Alignment(); + $this->setStyleByArray($style); + } + + /** + * Get alignment + * + * @return string + */ + public function getAlign() + { + return $this->alignment->getValue(); + } + + /** + * Set alignment + * + * @param string $value + * @return self + */ + public function setAlign($value = null) + { + $this->alignment->setValue($value); + + return $this; + } + + /** + * Get unit + * + * @return string + */ + public function getUnit() + { + return $this->unit; + } + + /** + * Set unit + * + * @param string $value + * @return self + */ + public function setUnit($value) + { + $this->unit = $value; + + return $this; + } + + /** + * Get width + * + * @return int|float + */ + public function getWidth() + { + return $this->width; + } + + /** + * Set width + * + * @param int|float $value + * @return self + */ + public function setWidth($value = null) + { + $this->width = $this->setNumericVal($value, null); + + return $this; + } + + /** + * Get height + * + * @return int|float + */ + public function getHeight() + { + return $this->height; + } + + /** + * Set height + * + * @param int|float $value + * @return self + */ + public function setHeight($value = null) + { + $this->height = $this->setNumericVal($value, null); + + return $this; + } + + /** + * Get left + * + * @return int|float + */ + public function getLeft() + { + return $this->left; + } + + /** + * Set left + * + * @param int|float $value + * @return self + */ + public function setLeft($value = 0) + { + $this->left = $this->setNumericVal($value, 0); + + return $this; + } + + /** + * Get topmost position + * + * @return int|float + */ + public function getTop() + { + return $this->top; + } + + /** + * Set topmost position + * + * @param int|float $value + * @return self + */ + public function setTop($value = 0) + { + $this->top = $this->setNumericVal($value, 0); + + return $this; + } + + /** + * Get position type + * + * @return string + */ + public function getPos() + { + return $this->pos; + } + + /** + * Set position type + * + * @param string $value + * @return self + */ + public function setPos($value) + { + $enum = array( + self::POS_ABSOLUTE, + self::POS_RELATIVE, + ); + $this->pos = $this->setEnumVal($value, $enum, $this->pos); + + return $this; + } + + /** + * Get horizontal position + * + * @return string + */ + public function getHPos() + { + return $this->hPos; + } + + /** + * Set horizontal position + * + * @since 0.12.0 "absolute" option is available. + * + * @param string $value + * @return self + */ + public function setHPos($value) + { + $enum = array( + self::POS_ABSOLUTE, + self::POS_LEFT, + self::POS_CENTER, + self::POS_RIGHT, + self::POS_INSIDE, + self::POS_OUTSIDE, + ); + $this->hPos = $this->setEnumVal($value, $enum, $this->hPos); + + return $this; + } + + /** + * Get vertical position + * + * @return string + */ + public function getVPos() + { + return $this->vPos; + } + + /** + * Set vertical position + * + * @since 0.12.0 "absolute" option is available. + * + * @param string $value + * @return self + */ + public function setVPos($value) + { + $enum = array( + self::POS_ABSOLUTE, + self::POS_TOP, + self::POS_CENTER, + self::POS_BOTTOM, + self::POS_INSIDE, + self::POS_OUTSIDE, + ); + $this->vPos = $this->setEnumVal($value, $enum, $this->vPos); + + return $this; + } + + /** + * Get horizontal position relative to + * + * @return string + */ + public function getHPosRelTo() + { + return $this->hPosRelTo; + } + + /** + * Set horizontal position relative to + * + * @param string $value + * @return self + */ + public function setHPosRelTo($value) + { + $enum = array( + self::POS_RELTO_MARGIN, + self::POS_RELTO_PAGE, + self::POS_RELTO_COLUMN, + self::POS_RELTO_CHAR, + self::POS_RELTO_LMARGIN, + self::POS_RELTO_RMARGIN, + self::POS_RELTO_IMARGIN, + self::POS_RELTO_OMARGIN, + ); + $this->hPosRelTo = $this->setEnumVal($value, $enum, $this->hPosRelTo); + + return $this; + } + + /** + * Get vertical position relative to + * + * @return string + */ + public function getVPosRelTo() + { + return $this->vPosRelTo; + } + + /** + * Set vertical position relative to + * + * @param string $value + * @return self + */ + public function setVPosRelTo($value) + { + $enum = array( + self::POS_RELTO_MARGIN, + self::POS_RELTO_PAGE, + self::POS_RELTO_TEXT, + self::POS_RELTO_LINE, + self::POS_RELTO_TMARGIN, + self::POS_RELTO_BMARGIN, + self::POS_RELTO_IMARGIN, + self::POS_RELTO_OMARGIN, + ); + $this->vPosRelTo = $this->setEnumVal($value, $enum, $this->vPosRelTo); + + return $this; + } + + /** + * Get wrap type + * + * @return string + */ + public function getWrap() + { + return $this->wrap; + } + + /** + * Set wrap type + * + * @param string $value + * @return self + */ + public function setWrap($value) + { + $enum = array( + self::WRAP_INLINE, + self::WRAP_SQUARE, + self::WRAP_TIGHT, + self::WRAP_THROUGH, + self::WRAP_TOPBOTTOM, + self::WRAP_BEHIND, + self::WRAP_INFRONT, + ); + $this->wrap = $this->setEnumVal($value, $enum, $this->wrap); + + return $this; + } +} diff --git a/src/PhpWord/Style/Image.php b/src/PhpWord/Style/Image.php index 3798c1a2..babfa679 100644 --- a/src/PhpWord/Style/Image.php +++ b/src/PhpWord/Style/Image.php @@ -19,217 +19,56 @@ namespace PhpOffice\PhpWord\Style; /** * Image and memory image style */ -class Image extends AbstractStyle +class Image extends Frame { /** - * Wrapping styles + * Backward compatibility constants * * @const string */ - const WRAPPING_STYLE_INLINE = 'inline'; - const WRAPPING_STYLE_SQUARE = 'square'; - const WRAPPING_STYLE_TIGHT = 'tight'; - const WRAPPING_STYLE_BEHIND = 'behind'; - const WRAPPING_STYLE_INFRONT = 'infront'; - - /** - * Horizontal alignment - * - * @const string - */ - const POSITION_HORIZONTAL_LEFT = 'left'; - const POSITION_HORIZONTAL_CENTER = 'center'; - const POSITION_HORIZONTAL_RIGHT = 'right'; - - /** - * Vertical alignment - * - * @const string - */ - const POSITION_VERTICAL_TOP = 'top'; - const POSITION_VERTICAL_CENTER = 'center'; - const POSITION_VERTICAL_BOTTOM = 'bottom'; - const POSITION_VERTICAL_INSIDE = 'inside'; - const POSITION_VERTICAL_OUTSIDE = 'outside'; - - /** - * Position relative to - * - * @const string - */ - const POSITION_RELATIVE_TO_MARGIN = 'margin'; - const POSITION_RELATIVE_TO_PAGE = 'page'; - const POSITION_RELATIVE_TO_COLUMN = 'column'; // horizontal only - const POSITION_RELATIVE_TO_CHAR = 'char'; // horizontal only - const POSITION_RELATIVE_TO_TEXT = 'text'; // vertical only - const POSITION_RELATIVE_TO_LINE = 'line'; // vertical only - const POSITION_RELATIVE_TO_LMARGIN = 'left-margin-area'; // horizontal only - const POSITION_RELATIVE_TO_RMARGIN = 'right-margin-area'; // horizontal only - const POSITION_RELATIVE_TO_TMARGIN = 'top-margin-area'; // vertical only - const POSITION_RELATIVE_TO_BMARGIN = 'bottom-margin-area'; // vertical only - const POSITION_RELATIVE_TO_IMARGIN = 'inner-margin-area'; - const POSITION_RELATIVE_TO_OMARGIN = 'outer-margin-area'; - - /** - * Position type, relative/absolute - * - * @const string - */ - const POSITION_ABSOLUTE = 'absolute'; - const POSITION_RELATIVE = 'relative'; - - /** - * Image width - * - * @var int - */ - private $width; - - /** - * Image width - * - * @var int - */ - private $height; - - /** - * Alignment - * - * @var \PhpOffice\PhpWord\Style\Alignment - */ - private $alignment; - - /** - * Margin Top - * - * @var int|float - */ - private $marginTop = 0; - - /** - * Margin Left - * - * @var int|float - */ - private $marginLeft = 0; - - /** - * Wrapping style - * - * @var string - */ - private $wrappingStyle = self::WRAPPING_STYLE_INLINE; - - /** - * Positioning type (relative or absolute) - * - * @var string - */ - private $positioning; - - /** - * Horizontal alignment - * - * @var string - */ - private $posHorizontal = self::POSITION_HORIZONTAL_LEFT; - - /** - * Horizontal Relation - * - * @var string - */ - private $posHorizontalRel = self::POSITION_RELATIVE_TO_CHAR; - - /** - * Vertical alignment - * - * @var string - */ - private $posVertical = self::POSITION_VERTICAL_TOP; - - /** - * Vertical Relation - * - * @var string - */ - private $posVerticalRel = self::POSITION_RELATIVE_TO_LINE; + const WRAPPING_STYLE_INLINE = self::WRAP_INLINE; + const WRAPPING_STYLE_SQUARE = self::WRAP_SQUARE; + const WRAPPING_STYLE_TIGHT = self::WRAP_TIGHT; + const WRAPPING_STYLE_BEHIND = self::WRAP_BEHIND; + const WRAPPING_STYLE_INFRONT = self::WRAP_INFRONT; + const POSITION_HORIZONTAL_LEFT = self::POS_LEFT; + const POSITION_HORIZONTAL_CENTER = self::POS_CENTER; + const POSITION_HORIZONTAL_RIGHT = self::POS_RIGHT; + const POSITION_VERTICAL_TOP = self::POS_TOP; + const POSITION_VERTICAL_CENTER = self::POS_CENTER; + const POSITION_VERTICAL_BOTTOM = self::POS_BOTTOM; + const POSITION_VERTICAL_INSIDE = self::POS_INSIDE; + const POSITION_VERTICAL_OUTSIDE = self::POS_OUTSIDE; + const POSITION_RELATIVE_TO_MARGIN = self::POS_RELTO_MARGIN; + const POSITION_RELATIVE_TO_PAGE = self::POS_RELTO_PAGE; + const POSITION_RELATIVE_TO_COLUMN = self::POS_RELTO_COLUMN; + const POSITION_RELATIVE_TO_CHAR = self::POS_RELTO_CHAR; + const POSITION_RELATIVE_TO_TEXT = self::POS_RELTO_TEXT; + const POSITION_RELATIVE_TO_LINE = self::POS_RELTO_LINE; + const POSITION_RELATIVE_TO_LMARGIN = self::POS_RELTO_LMARGIN; + const POSITION_RELATIVE_TO_RMARGIN = self::POS_RELTO_RMARGIN; + const POSITION_RELATIVE_TO_TMARGIN = self::POS_RELTO_TMARGIN; + const POSITION_RELATIVE_TO_BMARGIN = self::POS_RELTO_BMARGIN; + const POSITION_RELATIVE_TO_IMARGIN = self::POS_RELTO_IMARGIN; + const POSITION_RELATIVE_TO_OMARGIN = self::POS_RELTO_OMARGIN; + const POSITION_ABSOLUTE = self::POS_ABSOLUTE; + const POSITION_RELATIVE = self::POS_RELATIVE; /** * Create new instance */ public function __construct() { - $this->alignment = new Alignment(); - } + parent::__construct(); + $this->setUnit('px'); - /** - * Get width - * - * @return int - */ - public function getWidth() - { - return $this->width; - } - - /** - * Set width - * - * @param int $value - * @return self - */ - public function setWidth($value = null) - { - $this->width = $value; - - return $this; - } - - /** - * Get height - * - * @return int - */ - public function getHeight() - { - return $this->height; - } - - /** - * Set height - * - * @param int $value - * @return self - */ - public function setHeight($value = null) - { - $this->height = $value; - - return $this; - } - - /** - * Get alignment - * - * @return string - */ - public function getAlign() - { - return $this->alignment->getValue(); - } - - /** - * Set alignment - * - * @param string $value - * @return self - */ - public function setAlign($value = null) - { - $this->alignment->setValue($value); - - return $this; + // Backward compatilibity setting + // @todo Remove on 1.0.0 + $this->setWrap(self::WRAPPING_STYLE_INLINE); + $this->setHPos(self::POSITION_HORIZONTAL_LEFT); + $this->setHPosRelTo(self::POSITION_RELATIVE_TO_CHAR); + $this->setVPos(self::POSITION_VERTICAL_TOP); + $this->setVPosRelTo(self::POSITION_RELATIVE_TO_LINE); } /** @@ -239,7 +78,7 @@ class Image extends AbstractStyle */ public function getMarginTop() { - return $this->marginTop; + return $this->getTop(); } /** @@ -251,7 +90,7 @@ class Image extends AbstractStyle */ public function setMarginTop($value = 0) { - $this->marginTop = $this->setNumericVal($value, 0); + $this->setTop($value); return $this; } @@ -263,7 +102,7 @@ class Image extends AbstractStyle */ public function getMarginLeft() { - return $this->marginLeft; + return $this->getLeft(); } /** @@ -275,7 +114,7 @@ class Image extends AbstractStyle */ public function setMarginLeft($value = 0) { - $this->marginLeft = $this->setNumericVal($value, 0); + $this->setLeft($value); return $this; } @@ -287,7 +126,7 @@ class Image extends AbstractStyle */ public function getWrappingStyle() { - return $this->wrappingStyle; + return $this->getWrap(); } /** @@ -299,12 +138,7 @@ class Image extends AbstractStyle */ public function setWrappingStyle($wrappingStyle) { - $enum = array( - self::WRAPPING_STYLE_INLINE, - self::WRAPPING_STYLE_INFRONT, self::WRAPPING_STYLE_BEHIND, - self::WRAPPING_STYLE_SQUARE, self::WRAPPING_STYLE_TIGHT, - ); - $this->wrappingStyle = $this->setEnumVal($wrappingStyle, $enum, $this->wrappingStyle); + $this->setWrap($wrappingStyle); return $this; } @@ -316,7 +150,7 @@ class Image extends AbstractStyle */ public function getPositioning() { - return $this->positioning; + return $this->getPos(); } /** @@ -328,8 +162,7 @@ class Image extends AbstractStyle */ public function setPositioning($positioning) { - $enum = array(self::POSITION_RELATIVE, self::POSITION_ABSOLUTE); - $this->positioning = $this->setEnumVal($positioning, $enum, $this->positioning); + $this->setPos($positioning); return $this; } @@ -341,7 +174,7 @@ class Image extends AbstractStyle */ public function getPosHorizontal() { - return $this->posHorizontal; + return $this->getHPos(); } /** @@ -353,11 +186,7 @@ class Image extends AbstractStyle */ public function setPosHorizontal($alignment) { - $enum = array( - self::POSITION_HORIZONTAL_LEFT, self::POSITION_HORIZONTAL_CENTER, - self::POSITION_HORIZONTAL_RIGHT, self::POSITION_ABSOLUTE - ); - $this->posHorizontal = $this->setEnumVal($alignment, $enum, $this->posHorizontal); + $this->setHPos($alignment); return $this; } @@ -369,7 +198,7 @@ class Image extends AbstractStyle */ public function getPosVertical() { - return $this->posVertical; + return $this->getVPos(); } /** @@ -381,12 +210,7 @@ class Image extends AbstractStyle */ public function setPosVertical($alignment) { - $enum = array( - self::POSITION_VERTICAL_TOP, self::POSITION_VERTICAL_CENTER, - self::POSITION_VERTICAL_BOTTOM, self::POSITION_VERTICAL_INSIDE, - self::POSITION_VERTICAL_OUTSIDE, self::POSITION_ABSOLUTE - ); - $this->posVertical = $this->setEnumVal($alignment, $enum, $this->posVertical); + $this->setVPos($alignment); return $this; } @@ -398,7 +222,7 @@ class Image extends AbstractStyle */ public function getPosHorizontalRel() { - return $this->posHorizontalRel; + return $this->getHPosRelTo(); } /** @@ -410,13 +234,7 @@ class Image extends AbstractStyle */ public function setPosHorizontalRel($relto) { - $enum = array( - self::POSITION_RELATIVE_TO_MARGIN, self::POSITION_RELATIVE_TO_PAGE, - self::POSITION_RELATIVE_TO_COLUMN, self::POSITION_RELATIVE_TO_CHAR, - self::POSITION_RELATIVE_TO_LMARGIN, self::POSITION_RELATIVE_TO_RMARGIN, - self::POSITION_RELATIVE_TO_IMARGIN, self::POSITION_RELATIVE_TO_OMARGIN, - ); - $this->posHorizontalRel = $this->setEnumVal($relto, $enum, $this->posHorizontalRel); + $this->setHPosRelTo($relto); return $this; } @@ -428,7 +246,7 @@ class Image extends AbstractStyle */ public function getPosVerticalRel() { - return $this->posVerticalRel; + return $this->getVPosRelTo(); } /** @@ -440,13 +258,7 @@ class Image extends AbstractStyle */ public function setPosVerticalRel($relto) { - $enum = array( - self::POSITION_RELATIVE_TO_MARGIN, self::POSITION_RELATIVE_TO_PAGE, - self::POSITION_RELATIVE_TO_TEXT, self::POSITION_RELATIVE_TO_LINE, - self::POSITION_RELATIVE_TO_TMARGIN, self::POSITION_RELATIVE_TO_BMARGIN, - self::POSITION_RELATIVE_TO_IMARGIN, self::POSITION_RELATIVE_TO_OMARGIN, - ); - $this->posVerticalRel = $this->setEnumVal($relto, $enum, $this->posVerticalRel); + $this->setVPosRelTo($relto); return $this; } diff --git a/src/PhpWord/Style/Outline.php b/src/PhpWord/Style/Outline.php new file mode 100644 index 00000000..bfd14a14 --- /dev/null +++ b/src/PhpWord/Style/Outline.php @@ -0,0 +1,308 @@ +setStyleByArray($style); + } + + /** + * Get unit + * + * @return string + */ + public function getUnit() + { + return $this->unit; + } + + /** + * Get weight + * + * @return int|float + */ + public function getWeight() + { + return $this->weight; + } + + /** + * Set weight + * + * @param int|float $value + * @return self + */ + public function setWeight($value = null) + { + $this->weight = $this->setNumericVal($value, null); + + return $this; + } + + /** + * Get color + * + * @return string + */ + public function getColor() + { + return $this->color; + } + + /** + * Set color + * + * @param string $value + * @return self + */ + public function setColor($value = null) + { + $this->color = $value; + + return $this; + } + + /** + * Get dash type + * + * @return string + */ + public function getDash() + { + return $this->dash; + } + + /** + * Set dash type + * + * @param string $value + * @return self + */ + public function setDash($value = null) + { + $this->dash = $value; + + return $this; + } + + /** + * Get line style + * + * @return string + */ + public function getLine() + { + return $this->line; + } + + /** + * Set line style + * + * @param string $value + * @return self + */ + public function setLine($value = null) + { + $enum = array(self::LINE_SINGLE, self::LINE_THIN_THIN, self::LINE_THIN_THICK, + self::LINE_THICK_THIN, self::LINE_THICK_BETWEEN_THIN); + $this->line = $this->setEnumVal($value, $enum, null); + + return $this; + } + + /** + * Get endCap style + * + * @return string + */ + public function getEndCap() + { + return $this->endCap; + } + + /** + * Set endCap style + * + * @param string $value + * @return self + */ + public function setEndCap($value = null) + { + $enum = array(self::ENDCAP_FLAT, self::ENDCAP_SQUARE, self::ENDCAP_ROUND); + $this->endCap = $this->setEnumVal($value, $enum, null); + + return $this; + } + + /** + * Get startArrow + * + * @return string + */ + public function getStartArrow() + { + return $this->startArrow; + } + + /** + * Set pattern + * + * @param string $value + * @return self + */ + public function setStartArrow($value = null) + { + $enum = array(self::ARROW_NONE, self::ARROW_BLOCK, self::ARROW_CLASSIC, + self::ARROW_OVAL, self::ARROW_DIAMOND, self::ARROW_OPEN); + $this->startArrow = $this->setEnumVal($value, $enum, null); + + return $this; + } + + /** + * Get endArrow + * + * @return string + */ + public function getEndArrow() + { + return $this->endArrow; + } + + /** + * Set pattern + * + * @param string $value + * @return self + */ + public function setEndArrow($value = null) + { + $enum = array(self::ARROW_NONE, self::ARROW_BLOCK, self::ARROW_CLASSIC, + self::ARROW_OVAL, self::ARROW_DIAMOND, self::ARROW_OPEN); + $this->endArrow = $this->setEnumVal($value, $enum, null); + + return $this; + } +} diff --git a/src/PhpWord/Style/Paper.php b/src/PhpWord/Style/Paper.php new file mode 100644 index 00000000..642666b5 --- /dev/null +++ b/src/PhpWord/Style/Paper.php @@ -0,0 +1,188 @@ + array(297, 420, 'mm'), + 'A4' => array(210, 297, 'mm'), + 'A5' => array(148, 210, 'mm'), + 'Folio' => array(8.5, 13, 'in'), + 'Legal' => array(8.5, 14, 'in'), + 'Letter' => array(8.5, 11, 'in'), + ); + + /** + * Paper size + * + * @var string + */ + private $size = 'A4'; + + /** + * Width + * + * @var int (twip) + */ + private $width; + + /** + * Height + * + * @var int (twip) + */ + private $height; + + /** + * Create a new instance + * + * @param string $size + */ + public function __construct($size = 'A4') + { + $this->setSize($size); + } + + /** + * Get size + * + * @return string + */ + public function getSize() + { + return $this->size; + } + + /** + * Set size + * + * @param string $size + * @return self + */ + public function setSize($size) + { + $this->size = $this->setEnumVal($size, array_keys($this->sizes), $this->size); + + list($width, $height, $unit) = $this->sizes[$this->size]; + $multipliers = array('mm' => 56.5217, 'in' => 1440); + $multiplier = $multipliers[$unit]; + + $this->width = (int)round($width * $multiplier); + $this->height = (int)round($height * $multiplier); + + return $this; + } + + /** + * Get width + * + * @return int + */ + public function getWidth() + { + return $this->width; + } + + /** + * Get height + * + * @return int + */ + public function getHeight() + { + return $this->height; + } +} diff --git a/src/PhpWord/Style/Paragraph.php b/src/PhpWord/Style/Paragraph.php index 81673586..964a4ec9 100644 --- a/src/PhpWord/Style/Paragraph.php +++ b/src/PhpWord/Style/Paragraph.php @@ -47,7 +47,7 @@ use PhpOffice\PhpWord\Shared\String; * * @link http://www.schemacentral.com/sc/ooxml/t-w_CT_PPr.html */ -class Paragraph extends AbstractStyle +class Paragraph extends Border { /** * @const int One line height equals 240 twip @@ -152,6 +152,13 @@ class Paragraph extends AbstractStyle */ private $tabs = array(); + /** + * Shading + * + * @var \PhpOffice\PhpWord\Style\Shading + */ + private $shading; + /** * Create new instance */ @@ -209,6 +216,7 @@ class Paragraph extends AbstractStyle 'level' => $this->getNumLevel(), ), 'tabs' => $this->getTabs(), + 'shading' => $this->getShading(), ); return $styles; @@ -313,11 +321,7 @@ class Paragraph extends AbstractStyle */ public function getIndent() { - if ($this->indentation !== null) { - return $this->indentation->getLeft(); - } else { - return null; - } + return $this->getChildStyleValue($this->indentation, 'left'); } /** @@ -338,11 +342,7 @@ class Paragraph extends AbstractStyle */ public function getHanging() { - if ($this->indentation !== null) { - return $this->indentation->getHanging(); - } else { - return null; - } + return $this->getChildStyleValue($this->indentation, 'hanging'); } /** @@ -388,11 +388,7 @@ class Paragraph extends AbstractStyle */ public function getSpaceBefore() { - if ($this->spacing !== null) { - return $this->spacing->getBefore(); - } else { - return null; - } + return $this->getChildStyleValue($this->spacing, 'before'); } /** @@ -413,11 +409,7 @@ class Paragraph extends AbstractStyle */ public function getSpaceAfter() { - if ($this->spacing !== null) { - return $this->spacing->getAfter(); - } else { - return null; - } + return $this->getChildStyleValue($this->spacing, 'after'); } /** @@ -438,11 +430,7 @@ class Paragraph extends AbstractStyle */ public function getSpacing() { - if ($this->spacing !== null) { - return $this->spacing->getLine(); - } else { - return null; - } + return $this->getChildStyleValue($this->spacing, 'line'); } /** @@ -694,4 +682,27 @@ class Paragraph extends AbstractStyle { return $this->hasPageBreakBefore(); } + + /** + * Get shading + * + * @return \PhpOffice\PhpWord\Style\Shading + */ + public function getShading() + { + return $this->shading; + } + + /** + * Set shading + * + * @param mixed $value + * @return self + */ + public function setShading($value = null) + { + $this->setObjectVal($value, 'Shading', $this->shading); + + return $this; + } } diff --git a/src/PhpWord/Style/Section.php b/src/PhpWord/Style/Section.php index fd59f1b4..128e8e6b 100644 --- a/src/PhpWord/Style/Section.php +++ b/src/PhpWord/Style/Section.php @@ -35,8 +35,8 @@ class Section extends Border * * @const int|float */ - const DEFAULT_WIDTH = 11906; // In twip - const DEFAULT_HEIGHT = 16838; // In twip + const DEFAULT_WIDTH = 11870; // In twip + const DEFAULT_HEIGHT = 16787; // In twip const DEFAULT_MARGIN = 1440; // In twip const DEFAULT_GUTTER = 0; // In twip const DEFAULT_HEADER_HEIGHT = 720; // In twip @@ -52,6 +52,13 @@ class Section extends Border */ private $orientation = self::ORIENTATION_PORTRAIT; + /** + * Paper size + * + * @var \PhpOffice\PhpWord\Style\Paper + */ + private $paper; + /** * Page Size Width * @@ -159,6 +166,42 @@ class Section extends Border */ private $lineNumbering; + /** + * Create new instance + */ + public function __construct() + { + $this->setPaperSize(); + } + + /** + * Get paper size + * + * @return string + */ + public function getPaperSize() + { + return $this->paper->getSize(); + } + + /** + * Set paper size + * + * @param string $value + * @return self + */ + public function setPaperSize($value = 'A4') + { + if ($this->paper === null) { + $this->paper = new Paper(); + } + $this->paper->setSize($value); + $this->pageSizeW = $this->paper->getWidth(); + $this->pageSizeH = $this->paper->getHeight(); + + return $this; + } + /** * Set Setting Value * @@ -232,23 +275,55 @@ class Section extends Border /** * Get Page Size Width * - * @return int|float + * @return int|float|null + * + * @since 0.12.0 */ public function getPageSizeW() { return $this->pageSizeW; } + /** + * @param int|float|null $value + * + * @return \PhpOffice\PhpWord\Style\Section + * + * @since 0.12.0 + */ + public function setPageSizeW($value = null) + { + $this->pageSizeW = $this->setNumericVal($value, self::DEFAULT_WIDTH); + + return $this; + } + /** * Get Page Size Height * - * @return int|float + * @return int|float|null + * + * @since 0.12.0 */ public function getPageSizeH() { return $this->pageSizeH; } + /** + * @param int|float|null $value + * + * @return \PhpOffice\PhpWord\Style\Section + * + * @since 0.12.0 + */ + public function setPageSizeH($value = null) + { + $this->pageSizeH = $this->setNumericVal($value, self::DEFAULT_HEIGHT); + + return $this; + } + /** * Get Margin Top * diff --git a/src/PhpWord/Style/Shadow.php b/src/PhpWord/Style/Shadow.php new file mode 100644 index 00000000..deafbff0 --- /dev/null +++ b/src/PhpWord/Style/Shadow.php @@ -0,0 +1,97 @@ +setStyleByArray($style); + } + + /** + * Get color + * + * @return string + */ + public function getColor() + { + return $this->color; + } + + /** + * Set color + * + * @param string $value + * @return self + */ + public function setColor($value = null) + { + $this->color = $value; + + return $this; + } + + /** + * Get offset + * + * @return string + */ + public function getOffset() + { + return $this->offset; + } + + /** + * Set offset + * + * @param string $value + * @return self + */ + public function setOffset($value = null) + { + $this->offset = $value; + + return $this; + } +} diff --git a/src/PhpWord/Style/Shape.php b/src/PhpWord/Style/Shape.php new file mode 100644 index 00000000..c9809920 --- /dev/null +++ b/src/PhpWord/Style/Shape.php @@ -0,0 +1,255 @@ +setStyleByArray($style); + } + + /** + * Get points + * + * @return string + */ + public function getPoints() + { + return $this->points; + } + + /** + * Set points + * + * @param string $value + * @return self + */ + public function setPoints($value = null) + { + $this->points = $value; + + return $this; + } + + /** + * Get roundness + * + * @return int|float + */ + public function getRoundness() + { + return $this->roundness; + } + + /** + * Set roundness + * + * @param int|float $value + * @return self + */ + public function setRoundness($value = null) + { + $this->roundness = $this->setNumericVal($value, null); + + return $this; + } + + /** + * Get frame + * + * @return \PhpOffice\PhpWord\Style\Frame + */ + public function getFrame() + { + return $this->frame; + } + + /** + * Set frame + * + * @param mixed $value + * @return self + */ + public function setFrame($value = null) + { + $this->setObjectVal($value, 'Frame', $this->frame); + + return $this; + } + + /** + * Get fill + * + * @return \PhpOffice\PhpWord\Style\Fill + */ + public function getFill() + { + return $this->fill; + } + + /** + * Set fill + * + * @param mixed $value + * @return self + */ + public function setFill($value = null) + { + $this->setObjectVal($value, 'Fill', $this->fill); + + return $this; + } + + /** + * Get outline + * + * @return \PhpOffice\PhpWord\Style\Outline + */ + public function getOutline() + { + return $this->outline; + } + + /** + * Set outline + * + * @param mixed $value + * @return self + */ + public function setOutline($value = null) + { + $this->setObjectVal($value, 'Outline', $this->outline); + + return $this; + } + + /** + * Get shadow + * + * @return \PhpOffice\PhpWord\Style\Shadow + */ + public function getShadow() + { + return $this->shadow; + } + + /** + * Set shadow + * + * @param mixed $value + * @return self + */ + public function setShadow($value = null) + { + $this->setObjectVal($value, 'Shadow', $this->shadow); + + return $this; + } + + /** + * Get 3D extrusion + * + * @return \PhpOffice\PhpWord\Style\Extrusion + */ + public function getExtrusion() + { + return $this->extrusion; + } + + /** + * Set 3D extrusion + * + * @param mixed $value + * @return self + */ + public function setExtrusion($value = null) + { + $this->setObjectVal($value, 'Extrusion', $this->extrusion); + + return $this; + } +} diff --git a/src/PhpWord/Style/TextBox.php b/src/PhpWord/Style/TextBox.php index 9f0a1dde..6220b740 100644 --- a/src/PhpWord/Style/TextBox.php +++ b/src/PhpWord/Style/TextBox.php @@ -67,9 +67,10 @@ class TextBox extends Image private $borderColor; /** - * Set margin top + * Set margin top. * * @param int $value + * @return void */ public function setInnerMarginTop($value = null) { @@ -87,9 +88,10 @@ class TextBox extends Image } /** - * Set margin left + * Set margin left. * * @param int $value + * @return void */ public function setInnerMarginLeft($value = null) { @@ -107,9 +109,10 @@ class TextBox extends Image } /** - * Set margin right + * Set margin right. * * @param int $value + * @return void */ public function setInnerMarginRight($value = null) { @@ -127,9 +130,10 @@ class TextBox extends Image } /** - * Set margin bottom + * Set margin bottom. * * @param int $value + * @return void */ public function setInnerMarginBottom($value = null) { @@ -147,9 +151,10 @@ class TextBox extends Image } /** - * Set TLRB cell margin + * Set TLRB cell margin. * * @param int $value Margin in twips + * @return void */ public function setInnerMargin($value = null) { @@ -188,9 +193,10 @@ class TextBox extends Image } /** - * Set border size + * Set border size. * * @param int $value Size in points + * @return void */ public function setBorderSize($value = null) { @@ -208,9 +214,10 @@ class TextBox extends Image } /** - * Set border color + * Set border color. * * @param string $value + * @return void */ public function setBorderColor($value = null) { diff --git a/src/PhpWord/Template.php b/src/PhpWord/Template.php index 21e8b988..f6ad790e 100644 --- a/src/PhpWord/Template.php +++ b/src/PhpWord/Template.php @@ -17,433 +17,9 @@ namespace PhpOffice\PhpWord; -use PhpOffice\PhpWord\Exception\Exception; -use PhpOffice\PhpWord\Shared\String; -use PhpOffice\PhpWord\Shared\ZipArchive; - /** - * Template + * @deprecated 0.12.0 Use \PhpOffice\PhpWord\TemplateProcessor instead. */ -class Template +class Template extends TemplateProcessor { - /** - * ZipArchive object - * - * @var mixed - */ - private $zipClass; - - /** - * Temporary file name - * - * @var string - */ - private $tempFileName; - - /** - * Document XML - * - * @var string - */ - private $documentXML; - - /** - * Document header XML - * - * @var string[] - */ - private $headerXMLs = array(); - - /** - * Document footer XML - * - * @var string[] - */ - private $footerXMLs = array(); - - /** - * Create a new Template Object - * - * @param string $strFilename - * @throws \PhpOffice\PhpWord\Exception\Exception - */ - public function __construct($strFilename) - { - $this->tempFileName = tempnam(sys_get_temp_dir(), ''); - if ($this->tempFileName === false) { - throw new Exception('Could not create temporary file with unique name in the default temporary directory.'); - } - - // Copy the source File to the temp File - if (!copy($strFilename, $this->tempFileName)) { - throw new Exception("Could not copy the template from {$strFilename} to {$this->tempFileName}."); - } - - $this->zipClass = new ZipArchive(); - $this->zipClass->open($this->tempFileName); - - // Find and load headers and footers - $index = 1; - while ($this->zipClass->locateName($this->getHeaderName($index)) !== false) { - $this->headerXMLs[$index] = $this->zipClass->getFromName($this->getHeaderName($index)); - $index++; - } - - $index = 1; - while ($this->zipClass->locateName($this->getFooterName($index)) !== false) { - $this->footerXMLs[$index] = $this->zipClass->getFromName($this->getFooterName($index)); - $index++; - } - - $this->documentXML = $this->zipClass->getFromName('word/document.xml'); - } - - /** - * Applies XSL style sheet to template's parts - * - * @param \DOMDocument $xslDOMDocument - * @param array $xslOptions - * @param string $xslOptionsURI - * @throws \PhpOffice\PhpWord\Exception\Exception - */ - public function applyXslStyleSheet(&$xslDOMDocument, $xslOptions = array(), $xslOptionsURI = '') - { - $processor = new \XSLTProcessor(); - - $processor->importStylesheet($xslDOMDocument); - - if ($processor->setParameter($xslOptionsURI, $xslOptions) === false) { - throw new Exception('Could not set values for the given XSL style sheet parameters.'); - } - - $xmlDOMDocument = new \DOMDocument(); - if ($xmlDOMDocument->loadXML($this->documentXML) === false) { - throw new Exception('Could not load XML from the given template.'); - } - - $xmlTransformed = $processor->transformToXml($xmlDOMDocument); - if ($xmlTransformed === false) { - throw new Exception('Could not transform the given XML document.'); - } - - $this->documentXML = $xmlTransformed; - } - - /** - * Set a Template value - * - * @param mixed $search - * @param mixed $replace - * @param integer $limit - */ - public function setValue($search, $replace, $limit = -1) - { - foreach ($this->headerXMLs as $index => $headerXML) { - $this->headerXMLs[$index] = $this->setValueForPart($this->headerXMLs[$index], $search, $replace, $limit); - } - - $this->documentXML = $this->setValueForPart($this->documentXML, $search, $replace, $limit); - - foreach ($this->footerXMLs as $index => $headerXML) { - $this->footerXMLs[$index] = $this->setValueForPart($this->footerXMLs[$index], $search, $replace, $limit); - } - } - - /** - * Returns array of all variables in template - * @return string[] - */ - public function getVariables() - { - $variables = $this->getVariablesForPart($this->documentXML); - - foreach ($this->headerXMLs as $headerXML) { - $variables = array_merge($variables, $this->getVariablesForPart($headerXML)); - } - - foreach ($this->footerXMLs as $footerXML) { - $variables = array_merge($variables, $this->getVariablesForPart($footerXML)); - } - - return array_unique($variables); - } - - /** - * Clone a table row in a template document - * - * @param string $search - * @param integer $numberOfClones - * @throws \PhpOffice\PhpWord\Exception\Exception - */ - public function cloneRow($search, $numberOfClones) - { - if (substr($search, 0, 2) !== '${' && substr($search, -1) !== '}') { - $search = '${' . $search . '}'; - } - - $tagPos = strpos($this->documentXML, $search); - if (!$tagPos) { - throw new Exception("Can not clone row, template variable not found or variable contains markup."); - } - - $rowStart = $this->findRowStart($tagPos); - $rowEnd = $this->findRowEnd($tagPos); - $xmlRow = $this->getSlice($rowStart, $rowEnd); - - // Check if there's a cell spanning multiple rows. - if (preg_match('##', $xmlRow)) { - // $extraRowStart = $rowEnd; - $extraRowEnd = $rowEnd; - while (true) { - $extraRowStart = $this->findRowStart($extraRowEnd + 1); - $extraRowEnd = $this->findRowEnd($extraRowEnd + 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('##', $tmpXmlRow) && - !preg_match('##', $tmpXmlRow)) { - break; - } - // This row was a spanned row, update $rowEnd and search for the next row. - $rowEnd = $extraRowEnd; - } - $xmlRow = $this->getSlice($rowStart, $rowEnd); - } - - $result = $this->getSlice(0, $rowStart); - for ($i = 1; $i <= $numberOfClones; $i++) { - $result .= preg_replace('/\$\{(.*?)\}/', '\${\\1#' . $i . '}', $xmlRow); - } - $result .= $this->getSlice($rowEnd); - - $this->documentXML = $result; - } - - /** - * Clone a block - * - * @param string $blockname - * @param integer $clones - * @param boolean $replace - * @return string|null - */ - public function cloneBlock($blockname, $clones = 1, $replace = true) - { - $xmlBlock = null; - preg_match( - '/(<\?xml.*)(\${' . $blockname . '}<\/w:.*?p>)(.*)()/is', - $this->documentXML, - $matches - ); - - if (isset($matches[3])) { - $xmlBlock = $matches[3]; - $cloned = array(); - for ($i = 1; $i <= $clones; $i++) { - $cloned[] = $xmlBlock; - } - - if ($replace) { - $this->documentXML = str_replace( - $matches[2] . $matches[3] . $matches[4], - implode('', $cloned), - $this->documentXML - ); - } - } - - return $xmlBlock; - } - - /** - * Replace a block - * - * @param string $blockname - * @param string $replacement - */ - public function replaceBlock($blockname, $replacement) - { - preg_match( - '/(<\?xml.*)(\${' . $blockname . '}<\/w:.*?p>)(.*)()/is', - $this->documentXML, - $matches - ); - - if (isset($matches[3])) { - $this->documentXML = str_replace( - $matches[2] . $matches[3] . $matches[4], - $replacement, - $this->documentXML - ); - } - } - - /** - * Delete a block of text - * - * @param string $blockname - */ - public function deleteBlock($blockname) - { - $this->replaceBlock($blockname, ''); - } - - /** - * Save XML to temporary file - * - * @return string - * @throws \PhpOffice\PhpWord\Exception\Exception - */ - public function save() - { - foreach ($this->headerXMLs as $index => $headerXML) { - $this->zipClass->addFromString($this->getHeaderName($index), $this->headerXMLs[$index]); - } - - $this->zipClass->addFromString('word/document.xml', $this->documentXML); - - foreach ($this->footerXMLs as $index => $headerXML) { - $this->zipClass->addFromString($this->getFooterName($index), $this->footerXMLs[$index]); - } - - // Close zip file - if ($this->zipClass->close() === false) { - throw new Exception('Could not close zip file.'); - } - - return $this->tempFileName; - } - - /** - * Save XML to defined name - * - * @param string $strFilename - * @since 0.8.0 - */ - public function saveAs($strFilename) - { - $tempFilename = $this->save(); - - if (file_exists($strFilename)) { - unlink($strFilename); - } - - rename($tempFilename, $strFilename); - } - - /** - * Find and replace placeholders in the given XML section. - * - * @param string $documentPartXML - * @param string $search - * @param string $replace - * @param integer $limit - * @return string - */ - protected function setValueForPart($documentPartXML, $search, $replace, $limit) - { - $pattern = '|\$\{([^\}]+)\}|U'; - preg_match_all($pattern, $documentPartXML, $matches); - foreach ($matches[0] as $value) { - $valueCleaned = preg_replace('/<[^>]+>/', '', $value); - $valueCleaned = preg_replace('/<\/[^>]+>/', '', $valueCleaned); - $documentPartXML = str_replace($value, $valueCleaned, $documentPartXML); - } - - if (substr($search, 0, 2) !== '${' && substr($search, -1) !== '}') { - $search = '${' . $search . '}'; - } - - if (!String::isUTF8($replace)) { - $replace = utf8_encode($replace); - } - $replace = htmlspecialchars($replace); - - $regExpDelim = '/'; - $escapedSearch = preg_quote($search, $regExpDelim); - return preg_replace("{$regExpDelim}{$escapedSearch}{$regExpDelim}u", $replace, $documentPartXML, $limit); - } - - /** - * Find all variables in $documentPartXML - * @param string $documentPartXML - * @return string[] - */ - protected function getVariablesForPart($documentPartXML) - { - preg_match_all('/\$\{(.*?)}/i', $documentPartXML, $matches); - - return $matches[1]; - } - - /** - * Get the name of the footer file for $index - * @param integer $index - * @return string - */ - private function getFooterName($index) - { - return sprintf('word/footer%d.xml', $index); - } - - /** - * Get the name of the header file for $index - * @param integer $index - * @return string - */ - private function getHeaderName($index) - { - return sprintf('word/header%d.xml', $index); - } - - /** - * Find the start position of the nearest table row before $offset - * - * @param integer $offset - * @return integer - * @throws \PhpOffice\PhpWord\Exception\Exception - */ - private function findRowStart($offset) - { - $rowStart = strrpos($this->documentXML, "documentXML) - $offset) * -1)); - if (!$rowStart) { - $rowStart = strrpos($this->documentXML, "", ((strlen($this->documentXML) - $offset) * -1)); - } - if (!$rowStart) { - throw new Exception("Can not find the start position of the row to clone."); - } - return $rowStart; - } - - /** - * Find the end position of the nearest table row after $offset - * - * @param integer $offset - * @return integer - */ - private function findRowEnd($offset) - { - $rowEnd = strpos($this->documentXML, "", $offset) + 7; - return $rowEnd; - } - - /** - * Get a slice of a string - * - * @param integer $startPosition - * @param integer $endPosition - * @return string - */ - private function getSlice($startPosition, $endPosition = 0) - { - if (!$endPosition) { - $endPosition = strlen($this->documentXML); - } - return substr($this->documentXML, $startPosition, ($endPosition - $startPosition)); - } } diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php new file mode 100644 index 00000000..cbed9730 --- /dev/null +++ b/src/PhpWord/TemplateProcessor.php @@ -0,0 +1,455 @@ +temporaryDocumentFilename = tempnam(Settings::getTempDir(), 'PhpWord'); + if (false === $this->temporaryDocumentFilename) { + throw new CreateTemporaryFileException(); + } + + // Template file cloning + if (false === copy($documentTemplate, $this->temporaryDocumentFilename)) { + throw new CopyFileException($documentTemplate, $this->temporaryDocumentFilename); + } + + // Temporary document content extraction + $this->zipClass = new ZipArchive(); + $this->zipClass->open($this->temporaryDocumentFilename); + $index = 1; + while ($this->zipClass->locateName($this->getHeaderName($index)) !== false) { + $this->temporaryDocumentHeaders[$index] = $this->zipClass->getFromName($this->getHeaderName($index)); + $index++; + } + $index = 1; + while ($this->zipClass->locateName($this->getFooterName($index)) !== false) { + $this->temporaryDocumentFooters[$index] = $this->zipClass->getFromName($this->getFooterName($index)); + $index++; + } + $this->temporaryDocumentMainPart = $this->zipClass->getFromName('word/document.xml'); + } + + /** + * Applies XSL style sheet to template's parts. + * + * @param \DOMDocument $xslDOMDocument + * @param array $xslOptions + * @param string $xslOptionsURI + * @return void + * @throws \PhpOffice\PhpWord\Exception\Exception + */ + public function applyXslStyleSheet($xslDOMDocument, $xslOptions = array(), $xslOptionsURI = '') + { + $xsltProcessor = new \XSLTProcessor(); + + $xsltProcessor->importStylesheet($xslDOMDocument); + + if (false === $xsltProcessor->setParameter($xslOptionsURI, $xslOptions)) { + throw new Exception('Could not set values for the given XSL style sheet parameters.'); + } + + $xmlDOMDocument = new \DOMDocument(); + if (false === $xmlDOMDocument->loadXML($this->temporaryDocumentMainPart)) { + throw new Exception('Could not load XML from the given template.'); + } + + $xmlTransformed = $xsltProcessor->transformToXml($xmlDOMDocument); + if (false === $xmlTransformed) { + throw new Exception('Could not transform the given XML document.'); + } + + $this->temporaryDocumentMainPart = $xmlTransformed; + } + + /** + * @param mixed $search + * @param mixed $replace + * @param integer $limit + * @return void + */ + public function setValue($search, $replace, $limit = -1) + { + foreach ($this->temporaryDocumentHeaders as $index => $headerXML) { + $this->temporaryDocumentHeaders[$index] = $this->setValueForPart($this->temporaryDocumentHeaders[$index], $search, $replace, $limit); + } + + $this->temporaryDocumentMainPart = $this->setValueForPart($this->temporaryDocumentMainPart, $search, $replace, $limit); + + foreach ($this->temporaryDocumentFooters as $index => $headerXML) { + $this->temporaryDocumentFooters[$index] = $this->setValueForPart($this->temporaryDocumentFooters[$index], $search, $replace, $limit); + } + } + + /** + * Returns array of all variables in template. + * + * @return string[] + */ + public function getVariables() + { + $variables = $this->getVariablesForPart($this->temporaryDocumentMainPart); + + foreach ($this->temporaryDocumentHeaders as $headerXML) { + $variables = array_merge($variables, $this->getVariablesForPart($headerXML)); + } + + foreach ($this->temporaryDocumentFooters as $footerXML) { + $variables = array_merge($variables, $this->getVariablesForPart($footerXML)); + } + + return array_unique($variables); + } + + /** + * Clone a table row in a template document. + * + * @param string $search + * @param integer $numberOfClones + * @return void + * @throws \PhpOffice\PhpWord\Exception\Exception + */ + public function cloneRow($search, $numberOfClones) + { + if (substr($search, 0, 2) !== '${' && substr($search, -1) !== '}') { + $search = '${' . $search . '}'; + } + + $tagPos = strpos($this->temporaryDocumentMainPart, $search); + if (!$tagPos) { + throw new Exception("Can not clone row, template variable not found or variable contains markup."); + } + + $rowStart = $this->findRowStart($tagPos); + $rowEnd = $this->findRowEnd($tagPos); + $xmlRow = $this->getSlice($rowStart, $rowEnd); + + // Check if there's a cell spanning multiple rows. + if (preg_match('##', $xmlRow)) { + // $extraRowStart = $rowEnd; + $extraRowEnd = $rowEnd; + while (true) { + $extraRowStart = $this->findRowStart($extraRowEnd + 1); + $extraRowEnd = $this->findRowEnd($extraRowEnd + 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('##', $tmpXmlRow) && + !preg_match('##', $tmpXmlRow)) { + break; + } + // This row was a spanned row, update $rowEnd and search for the next row. + $rowEnd = $extraRowEnd; + } + $xmlRow = $this->getSlice($rowStart, $rowEnd); + } + + $result = $this->getSlice(0, $rowStart); + for ($i = 1; $i <= $numberOfClones; $i++) { + $result .= preg_replace('/\$\{(.*?)\}/', '\${\\1#' . $i . '}', $xmlRow); + } + $result .= $this->getSlice($rowEnd); + + $this->temporaryDocumentMainPart = $result; + } + + /** + * Clone a block. + * + * @param string $blockname + * @param integer $clones + * @param boolean $replace + * @return string|null + */ + public function cloneBlock($blockname, $clones = 1, $replace = true) + { + $xmlBlock = null; + preg_match( + '/(<\?xml.*)(\${' . $blockname . '}<\/w:.*?p>)(.*)()/is', + $this->temporaryDocumentMainPart, + $matches + ); + + if (isset($matches[3])) { + $xmlBlock = $matches[3]; + $cloned = array(); + for ($i = 1; $i <= $clones; $i++) { + $cloned[] = $xmlBlock; + } + + if ($replace) { + $this->temporaryDocumentMainPart = str_replace( + $matches[2] . $matches[3] . $matches[4], + implode('', $cloned), + $this->temporaryDocumentMainPart + ); + } + } + + return $xmlBlock; + } + + /** + * Replace a block. + * + * @param string $blockname + * @param string $replacement + * @return void + */ + public function replaceBlock($blockname, $replacement) + { + preg_match( + '/(<\?xml.*)(\${' . $blockname . '}<\/w:.*?p>)(.*)()/is', + $this->temporaryDocumentMainPart, + $matches + ); + + if (isset($matches[3])) { + $this->temporaryDocumentMainPart = str_replace( + $matches[2] . $matches[3] . $matches[4], + $replacement, + $this->temporaryDocumentMainPart + ); + } + } + + /** + * Delete a block of text. + * + * @param string $blockname + * @return void + */ + public function deleteBlock($blockname) + { + $this->replaceBlock($blockname, ''); + } + + /** + * Saves the result document. + * + * @return string + * @throws \PhpOffice\PhpWord\Exception\Exception + */ + public function save() + { + foreach ($this->temporaryDocumentHeaders as $index => $headerXML) { + $this->zipClass->addFromString($this->getHeaderName($index), $this->temporaryDocumentHeaders[$index]); + } + + $this->zipClass->addFromString('word/document.xml', $this->temporaryDocumentMainPart); + + foreach ($this->temporaryDocumentFooters as $index => $headerXML) { + $this->zipClass->addFromString($this->getFooterName($index), $this->temporaryDocumentFooters[$index]); + } + + // Close zip file + if (false === $this->zipClass->close()) { + throw new Exception('Could not close zip file.'); + } + + return $this->temporaryDocumentFilename; + } + + /** + * Saves the result document to the user defined file. + * + * @since 0.8.0 + * + * @param string $fileName + * @return void + */ + public function saveAs($fileName) + { + $tempFileName = $this->save(); + + if (file_exists($fileName)) { + unlink($fileName); + } + + rename($tempFileName, $fileName); + } + + /** + * Find and replace placeholders in the given XML section. + * + * @param string $documentPartXML + * @param string $search + * @param string $replace + * @param integer $limit + * @return string + */ + protected function setValueForPart($documentPartXML, $search, $replace, $limit) + { + $pattern = '|\$\{([^\}]+)\}|U'; + preg_match_all($pattern, $documentPartXML, $matches); + foreach ($matches[0] as $value) { + $valueCleaned = preg_replace('/<[^>]+>/', '', $value); + $valueCleaned = preg_replace('/<\/[^>]+>/', '', $valueCleaned); + $documentPartXML = str_replace($value, $valueCleaned, $documentPartXML); + } + + if (substr($search, 0, 2) !== '${' && substr($search, -1) !== '}') { + $search = '${' . $search . '}'; + } + + if (!String::isUTF8($replace)) { + $replace = utf8_encode($replace); + } + + $regExpDelim = '/'; + $escapedSearch = preg_quote($search, $regExpDelim); + return preg_replace("{$regExpDelim}{$escapedSearch}{$regExpDelim}u", $replace, $documentPartXML, $limit); + } + + /** + * Find all variables in $documentPartXML. + * + * @param string $documentPartXML + * @return string[] + */ + protected function getVariablesForPart($documentPartXML) + { + preg_match_all('/\$\{(.*?)}/i', $documentPartXML, $matches); + + return $matches[1]; + } + + /** + * Get the name of the footer file for $index. + * + * @param integer $index + * @return string + */ + private function getFooterName($index) + { + return sprintf('word/footer%d.xml', $index); + } + + /** + * Get the name of the header file for $index. + * + * @param integer $index + * @return string + */ + private function getHeaderName($index) + { + return sprintf('word/header%d.xml', $index); + } + + /** + * Find the start position of the nearest table row before $offset. + * + * @param integer $offset + * @return integer + * @throws \PhpOffice\PhpWord\Exception\Exception + */ + private function findRowStart($offset) + { + $rowStart = strrpos($this->temporaryDocumentMainPart, 'temporaryDocumentMainPart) - $offset) * -1)); + + if (!$rowStart) { + $rowStart = strrpos($this->temporaryDocumentMainPart, '', ((strlen($this->temporaryDocumentMainPart) - $offset) * -1)); + } + if (!$rowStart) { + throw new Exception('Can not find the start position of the row to clone.'); + } + + return $rowStart; + } + + /** + * Find the end position of the nearest table row after $offset. + * + * @param integer $offset + * @return integer + */ + private function findRowEnd($offset) + { + return strpos($this->temporaryDocumentMainPart, '', $offset) + 7; + } + + /** + * Get a slice of a string. + * + * @param integer $startPosition + * @param integer $endPosition + * @return string + */ + private function getSlice($startPosition, $endPosition = 0) + { + if (!$endPosition) { + $endPosition = strlen($this->temporaryDocumentMainPart); + } + + return substr($this->temporaryDocumentMainPart, $startPosition, ($endPosition - $startPosition)); + } +} diff --git a/src/PhpWord/Writer/AbstractWriter.php b/src/PhpWord/Writer/AbstractWriter.php index 346e9b66..599d8a6f 100644 --- a/src/PhpWord/Writer/AbstractWriter.php +++ b/src/PhpWord/Writer/AbstractWriter.php @@ -17,8 +17,10 @@ namespace PhpOffice\PhpWord\Writer; +use PhpOffice\PhpWord\Exception\CopyFileException; use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Shared\ZipArchive; /** @@ -213,18 +215,15 @@ abstract class AbstractWriter implements WriterInterface protected function getTempFile($filename) { // Temporary directory - $this->setTempDir(sys_get_temp_dir() . '/PHPWordWriter/'); + $this->setTempDir(Settings::getTempDir() . '/PHPWordWriter/'); // Temporary file $this->originalFilename = $filename; if (strtolower($filename) == 'php://output' || strtolower($filename) == 'php://stdout') { - $filename = @tempnam(sys_get_temp_dir(), 'phpword_'); - // @codeCoverageIgnoreStart - // Can't find any test case. Uncomment when found. - if ($filename == '') { + $filename = tempnam(Settings::getTempDir(), 'PhpWord'); + if (false === $filename) { $filename = $this->originalFilename; } - // @codeCoverageIgnoreEnd } $this->tempFilename = $filename; @@ -232,15 +231,18 @@ abstract class AbstractWriter implements WriterInterface } /** - * Cleanup temporary file + * Cleanup temporary file. + * + * @return void + * @throws \PhpOffice\PhpWord\Exception\CopyFileException */ protected function cleanupTempFile() { if ($this->originalFilename != $this->tempFilename) { // @codeCoverageIgnoreStart // Can't find any test case. Uncomment when found. - if (copy($this->tempFilename, $this->originalFilename) === false) { - throw new Exception("Could not copy temporary zip file."); + if (false === copy($this->tempFilename, $this->originalFilename)) { + throw new CopyFileException($this->tempFilename, $this->originalFilename); } // @codeCoverageIgnoreEnd @unlink($this->tempFilename); @@ -250,7 +252,9 @@ abstract class AbstractWriter implements WriterInterface } /** - * Clear temporary directory + * Clear temporary directory. + * + * @return void */ protected function clearTempDir() { @@ -311,13 +315,15 @@ abstract class AbstractWriter implements WriterInterface } /** - * Write content to file + * Write content to file. + * + * @since 0.11.0 * * @param resource $fileHandle * @param string $content - * @since 0.11.0 + * @return void */ - protected function writeFile(&$fileHandle, $content) + protected function writeFile($fileHandle, $content) { fwrite($fileHandle, $content); fclose($fileHandle); @@ -325,10 +331,11 @@ abstract class AbstractWriter implements WriterInterface } /** - * Add files to package + * Add files to package. * * @param \PhpOffice\PhpWord\Shared\ZipArchive $zip * @param mixed $elements + * @return void */ protected function addFilesToPackage(ZipArchive $zip, $elements) { @@ -336,7 +343,7 @@ abstract class AbstractWriter implements WriterInterface $type = $element['type']; // image|object|link // Skip nonregistered types and set target - if (!array_key_exists($type, $this->mediaPaths)) { + if (!isset($this->mediaPaths[$type])) { continue; } $target = $this->mediaPaths[$type] . $element['target']; @@ -357,13 +364,14 @@ abstract class AbstractWriter implements WriterInterface } /** - * Add file to package + * Add file to package. * - * Get the actual source from an archive image + * Get the actual source from an archive image. * * @param \PhpOffice\PhpWord\Shared\ZipArchive $zipPackage * @param string $source * @param string $target + * @return void */ protected function addFileToPackage($zipPackage, $source, $target) { @@ -391,9 +399,10 @@ abstract class AbstractWriter implements WriterInterface } /** - * Delete directory + * Delete directory. * * @param string $dir + * @return void */ private function deleteDir($dir) { diff --git a/src/PhpWord/Writer/HTML.php b/src/PhpWord/Writer/HTML.php index 29173ff2..5c58acfc 100644 --- a/src/PhpWord/Writer/HTML.php +++ b/src/PhpWord/Writer/HTML.php @@ -61,15 +61,15 @@ class HTML extends AbstractWriter implements WriterInterface } /** - * Save PhpWord to file + * Save PhpWord to file. * * @param string $filename + * @return void * @throws \PhpOffice\PhpWord\Exception\Exception */ public function save($filename = null) { - $fileHandle = $this->openFile($filename); - $this->writeFile($fileHandle, $this->getContent()); + $this->writeFile($this->openFile($filename), $this->getContent()); } /** @@ -113,10 +113,11 @@ class HTML extends AbstractWriter implements WriterInterface } /** - * Add note + * Add note. * * @param int $noteId * @param string $noteMark + * @return void */ public function addNote($noteId, $noteMark) { diff --git a/src/PhpWord/Writer/HTML/Element/AbstractElement.php b/src/PhpWord/Writer/HTML/Element/AbstractElement.php index 53b994df..73f88d3d 100644 --- a/src/PhpWord/Writer/HTML/Element/AbstractElement.php +++ b/src/PhpWord/Writer/HTML/Element/AbstractElement.php @@ -68,9 +68,10 @@ abstract class AbstractElement } /** - * Set without paragraph + * Set without paragraph. * * @param bool $value + * @return void */ public function setWithoutP($value) { diff --git a/src/PhpWord/Writer/HTML/Element/Link.php b/src/PhpWord/Writer/HTML/Element/Link.php index d1256eb0..4e99810c 100644 --- a/src/PhpWord/Writer/HTML/Element/Link.php +++ b/src/PhpWord/Writer/HTML/Element/Link.php @@ -37,7 +37,7 @@ class Link extends Text $content = ''; $content .= $this->writeOpening(); - $content .= "element->getTarget()}\">{$this->element->getText()}"; + $content .= "element->getSource()}\">{$this->element->getText()}"; $content .= $this->writeClosing(); return $content; diff --git a/src/PhpWord/Writer/HTML/Element/ListItem.php b/src/PhpWord/Writer/HTML/Element/ListItem.php index 79a3b393..ef8eb34d 100644 --- a/src/PhpWord/Writer/HTML/Element/ListItem.php +++ b/src/PhpWord/Writer/HTML/Element/ListItem.php @@ -35,7 +35,7 @@ class ListItem extends AbstractElement return ''; } - $text = htmlspecialchars($this->element->getTextObject()->getText()); + $text = $this->element->getTextObject()->getText(); $content = '

' . $text . '

' . PHP_EOL; return $content; diff --git a/src/PhpWord/Writer/HTML/Element/PageBreak.php b/src/PhpWord/Writer/HTML/Element/PageBreak.php index a3fb1f3b..774ed9d2 100644 --- a/src/PhpWord/Writer/HTML/Element/PageBreak.php +++ b/src/PhpWord/Writer/HTML/Element/PageBreak.php @@ -24,4 +24,21 @@ namespace PhpOffice\PhpWord\Writer\HTML\Element; */ class PageBreak extends TextBreak { + /** + * Write page break + * + * @since 0.12.0 + * + * @return string + */ + public function write() + { + /** @var \PhpOffice\PhpWord\Writer\HTML $parentWriter Type hint */ + $parentWriter = $this->parentWriter; + if ($parentWriter->isPdf()) { + return ''; + } + + return ""; + } } diff --git a/src/PhpWord/Writer/HTML/Element/Table.php b/src/PhpWord/Writer/HTML/Element/Table.php index c8813a67..9027603b 100644 --- a/src/PhpWord/Writer/HTML/Element/Table.php +++ b/src/PhpWord/Writer/HTML/Element/Table.php @@ -51,7 +51,7 @@ class Table extends AbstractElement $cellTag = $tblHeader ? 'th' : 'td'; $content .= "<{$cellTag}>" . PHP_EOL; $content .= $writer->write(); - $content .= '' . PHP_EOL; + $content .= "" . PHP_EOL; } $content .= '' . PHP_EOL; } diff --git a/src/PhpWord/Writer/HTML/Element/Text.php b/src/PhpWord/Writer/HTML/Element/Text.php index 52e7a6b5..0c31df36 100644 --- a/src/PhpWord/Writer/HTML/Element/Text.php +++ b/src/PhpWord/Writer/HTML/Element/Text.php @@ -72,7 +72,7 @@ class Text extends AbstractElement $content .= $this->writeOpening(); $content .= $this->openingText; $content .= $this->openingTags; - $content .= htmlspecialchars($element->getText()); + $content .= $element->getText(); $content .= $this->closingTags; $content .= $this->closingText; $content .= $this->writeClosing(); @@ -81,9 +81,10 @@ class Text extends AbstractElement } /** - * Set opening text + * Set opening text. * * @param string $value + * @return void */ public function setOpeningText($value) { @@ -91,9 +92,10 @@ class Text extends AbstractElement } /** - * Set closing text + * Set closing text. * * @param string $value + * @return void */ public function setClosingText($value) { @@ -164,7 +166,9 @@ class Text extends AbstractElement } /** - * Get font style + * Get font style. + * + * @return void */ private function getFontStyle() { diff --git a/src/PhpWord/Writer/HTML/Element/Title.php b/src/PhpWord/Writer/HTML/Element/Title.php index 20747bf9..c054ccf9 100644 --- a/src/PhpWord/Writer/HTML/Element/Title.php +++ b/src/PhpWord/Writer/HTML/Element/Title.php @@ -36,7 +36,7 @@ class Title extends AbstractElement } $tag = 'h' . $this->element->getDepth(); - $text = htmlspecialchars($this->element->getText()); + $text = $this->element->getText(); $content = "<{$tag}>{$text}" . PHP_EOL; return $content; diff --git a/src/PhpWord/Writer/HTML/Part/AbstractPart.php b/src/PhpWord/Writer/HTML/Part/AbstractPart.php index 319aa20f..124cc15a 100644 --- a/src/PhpWord/Writer/HTML/Part/AbstractPart.php +++ b/src/PhpWord/Writer/HTML/Part/AbstractPart.php @@ -42,9 +42,10 @@ abstract class AbstractPart abstract public function write(); /** - * Set parent writer + * Set parent writer. * * @param \PhpOffice\PhpWord\Writer\AbstractWriter $writer + * @return void */ public function setParentWriter(AbstractWriter $writer = null) { diff --git a/src/PhpWord/Writer/HTML/Part/Body.php b/src/PhpWord/Writer/HTML/Part/Body.php index 4fd61a83..b91ca3ad 100644 --- a/src/PhpWord/Writer/HTML/Part/Body.php +++ b/src/PhpWord/Writer/HTML/Part/Body.php @@ -72,7 +72,7 @@ class Body extends AbstractPart $method = 'get' . ($noteType == 'endnote' ? 'Endnotes' : 'Footnotes'); $collection = $phpWord->$method()->getItems(); - if (array_key_exists($noteTypeId, $collection)) { + if (isset($collection[$noteTypeId])) { $element = $collection[$noteTypeId]; $noteAnchor = ""; $noteAnchor .= "{$noteId}"; diff --git a/src/PhpWord/Writer/HTML/Part/Head.php b/src/PhpWord/Writer/HTML/Part/Head.php index edbc8dcf..503f75b8 100644 --- a/src/PhpWord/Writer/HTML/Part/Head.php +++ b/src/PhpWord/Writer/HTML/Part/Head.php @@ -39,7 +39,7 @@ class Head extends AbstractPart */ public function write() { - $docProps = $this->getParentWriter()->getPhpWord()->getDocumentProperties(); + $docProps = $this->getParentWriter()->getPhpWord()->getDocInfo(); $propertiesMapping = array( 'creator' => 'author', 'title' => '', @@ -57,13 +57,13 @@ class Head extends AbstractPart $content .= '' . PHP_EOL; $content .= '' . PHP_EOL; - $content .= '' . htmlspecialchars($title) . '' . PHP_EOL; + $content .= '' . $title . '' . PHP_EOL; foreach ($propertiesMapping as $key => $value) { $value = ($value == '') ? $key : $value; $method = "get" . $key; if ($docProps->$method() != '') { $content .= '' . PHP_EOL; + $docProps->$method() . '" />' . PHP_EOL; } } $content .= $this->writeStyles(); @@ -71,6 +71,7 @@ class Head extends AbstractPart return $content; } + /** * Get styles * @@ -96,6 +97,14 @@ class Head extends AbstractPart 'border' => '0', 'border-top' => '1px solid #CCC', ), + 'table' => array( + 'border' => '1px solid black', + 'border-spacing' => '0px', + 'width' => '100%', + ), + 'td' => array( + 'border' => '1px solid black', + ), ); foreach ($defaultStyles as $selector => $style) { $styleWriter = new GenericStyleWriter($style); diff --git a/src/PhpWord/Writer/HTML/Style/AbstractStyle.php b/src/PhpWord/Writer/HTML/Style/AbstractStyle.php index cd37174a..07ef1618 100644 --- a/src/PhpWord/Writer/HTML/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/HTML/Style/AbstractStyle.php @@ -26,6 +26,13 @@ use PhpOffice\PhpWord\Style\AbstractStyle as Style; */ abstract class AbstractStyle { + /** + * Parent writer + * + * @var \PhpOffice\PhpWord\Writer\AbstractWriter + */ + private $parentWriter; + /** * Style * @@ -48,6 +55,27 @@ abstract class AbstractStyle $this->style = $style; } + /** + * Set parent writer. + * + * @param \PhpOffice\PhpWord\Writer\AbstractWriter $writer + * @return void + */ + public function setParentWriter($writer) + { + $this->parentWriter = $writer; + } + + /** + * Get parent writer + * + * @return \PhpOffice\PhpWord\Writer\AbstractWriter + */ + public function getParentWriter() + { + return $this->parentWriter; + } + /** * Get style * diff --git a/src/PhpWord/Writer/HTML/Style/Font.php b/src/PhpWord/Writer/HTML/Style/Font.php index 18f28287..8645a1f4 100644 --- a/src/PhpWord/Writer/HTML/Style/Font.php +++ b/src/PhpWord/Writer/HTML/Style/Font.php @@ -17,7 +17,6 @@ namespace PhpOffice\PhpWord\Writer\HTML\Style; -use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Style\Font as FontStyle; /** diff --git a/src/PhpWord/Writer/ODText.php b/src/PhpWord/Writer/ODText.php index f9c8d5d4..8fa364be 100644 --- a/src/PhpWord/Writer/ODText.php +++ b/src/PhpWord/Writer/ODText.php @@ -60,9 +60,10 @@ class ODText extends AbstractWriter implements WriterInterface } /** - * Save PhpWord to file + * Save PhpWord to file. * - * @param string $filename + * @param string $filename + * @return void */ public function save($filename = null) { diff --git a/src/PhpWord/Writer/ODText/Element/Image.php b/src/PhpWord/Writer/ODText/Element/Image.php index 3229b59c..3cbb3854 100644 --- a/src/PhpWord/Writer/ODText/Element/Image.php +++ b/src/PhpWord/Writer/ODText/Element/Image.php @@ -17,7 +17,7 @@ namespace PhpOffice\PhpWord\Writer\ODText\Element; -use PhpOffice\PhpWord\Shared\Drawing; +use PhpOffice\PhpWord\Shared\Converter; /** * Image element writer @@ -40,8 +40,8 @@ class Image extends AbstractElement $mediaIndex = $element->getMediaIndex(); $target = 'Pictures/' . $element->getTarget(); $style = $element->getStyle(); - $width = Drawing::pixelsToCentimeters($style->getWidth()); - $height = Drawing::pixelsToCentimeters($style->getHeight()); + $width = Converter::pixelToCm($style->getWidth()); + $height = Converter::pixelToCm($style->getHeight()); $xmlWriter->startElement('text:p'); $xmlWriter->writeAttribute('text:style-name', 'Standard'); diff --git a/src/PhpWord/Writer/ODText/Element/Link.php b/src/PhpWord/Writer/ODText/Element/Link.php index 79d3aa24..adb64f85 100644 --- a/src/PhpWord/Writer/ODText/Element/Link.php +++ b/src/PhpWord/Writer/ODText/Element/Link.php @@ -41,7 +41,7 @@ class Link extends AbstractElement $xmlWriter->startElement('text:a'); $xmlWriter->writeAttribute('xlink:type', 'simple'); - $xmlWriter->writeAttribute('xlink:href', $element->getTarget()); + $xmlWriter->writeAttribute('xlink:href', $element->getSource()); $xmlWriter->writeRaw($element->getText()); $xmlWriter->endElement(); // text:a diff --git a/src/PhpWord/Writer/ODText/Part/AbstractPart.php b/src/PhpWord/Writer/ODText/Part/AbstractPart.php index 31118ef9..edc8d07f 100644 --- a/src/PhpWord/Writer/ODText/Part/AbstractPart.php +++ b/src/PhpWord/Writer/ODText/Part/AbstractPart.php @@ -34,7 +34,10 @@ abstract class AbstractPart extends Word2007AbstractPart protected $dateFormat = 'Y-m-d\TH:i:s.000'; /** - * Write common root attributes + * Write common root attributes. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @return void */ protected function writeCommonRootAttributes(XMLWriter $xmlWriter) { @@ -68,7 +71,10 @@ abstract class AbstractPart extends Word2007AbstractPart } /** - * Write font faces declaration + * Write font faces declaration. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @return void */ protected function writeFontFaces(XMLWriter $xmlWriter) { diff --git a/src/PhpWord/Writer/ODText/Part/Content.php b/src/PhpWord/Writer/ODText/Part/Content.php index f16937a0..4bde66ee 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -106,9 +106,12 @@ class Content extends AbstractPart } /** - * Write automatic styles other than fonts and paragraphs + * Write automatic styles other than fonts and paragraphs. * * @since 0.11.0 + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @return void */ private function writeAutoStyles(XMLWriter $xmlWriter) { @@ -129,7 +132,10 @@ class Content extends AbstractPart } /** - * Write automatic styles + * Write automatic styles. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @return void */ private function writeTextStyles(XMLWriter $xmlWriter) { @@ -160,7 +166,10 @@ class Content extends AbstractPart } /** - * Get automatic styles + * Get automatic styles. + * + * @param \PhpOffice\PhpWord\PhpWord $phpWord + * @return void */ private function getAutoStyles(PhpWord $phpWord) { @@ -168,7 +177,7 @@ class Content extends AbstractPart $paragraphStyleCount = 0; $fontStyleCount = 0; foreach ($sections as $section) { - $style = $section->getSettings(); + $style = $section->getStyle(); $style->setStyleName("Section{$section->getSectionId()}"); $this->autoStyles['Section'][] = $style; $this->getContainerStyle($section, $paragraphStyleCount, $fontStyleCount); @@ -181,8 +190,9 @@ class Content extends AbstractPart * Table style can be null or string of the style name * * @param \PhpOffice\PhpWord\Element\AbstractContainer $container - * @param int $paragraphStyleCount - * @param int $fontStyleCount + * @param int &$paragraphStyleCount + * @param int &$fontStyleCount + * @return void * @todo Simplify the logic */ private function getContainerStyle($container, &$paragraphStyleCount, &$fontStyleCount) @@ -213,9 +223,10 @@ class Content extends AbstractPart /** * Get style of individual element * - * @param \PhpOffice\PhpWord\Element\Text $element - * @param int $paragraphStyleCount - * @param int $fontStyleCount + * @param \PhpOffice\PhpWord\Element\Text &$element + * @param int &$paragraphStyleCount + * @param int &$fontStyleCount + * @return void */ private function getElementStyle(&$element, &$paragraphStyleCount, &$fontStyleCount) { diff --git a/src/PhpWord/Writer/ODText/Part/Meta.php b/src/PhpWord/Writer/ODText/Part/Meta.php index c9e729ad..15c81a4e 100644 --- a/src/PhpWord/Writer/ODText/Part/Meta.php +++ b/src/PhpWord/Writer/ODText/Part/Meta.php @@ -34,7 +34,7 @@ class Meta extends AbstractPart public function write() { $phpWord = $this->getParentWriter()->getPhpWord(); - $docProps = $phpWord->getDocumentProperties(); + $docProps = $phpWord->getDocInfo(); $xmlWriter = $this->getXmlWriter(); $xmlWriter->startDocument('1.0', 'UTF-8'); @@ -89,6 +89,7 @@ class Meta extends AbstractPart * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param string $property * @param string $value + * @return void * * @todo Handle other `$type`: double|date|dateTime|duration|boolean (4th arguments) */ diff --git a/src/PhpWord/Writer/ODText/Part/Styles.php b/src/PhpWord/Writer/ODText/Part/Styles.php index b7864fe3..7522872d 100644 --- a/src/PhpWord/Writer/ODText/Part/Styles.php +++ b/src/PhpWord/Writer/ODText/Part/Styles.php @@ -61,7 +61,10 @@ class Styles extends AbstractPart } /** - * Write default styles + * Write default styles. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @return void */ private function writeDefault(XMLWriter $xmlWriter) { @@ -103,7 +106,10 @@ class Styles extends AbstractPart } /** - * Write named styles + * Write named styles. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @return void */ private function writeNamed(XMLWriter $xmlWriter) { @@ -122,7 +128,10 @@ class Styles extends AbstractPart } } /** - * Write page layout styles + * Write page layout styles. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @return void */ private function writePageLayout(XMLWriter $xmlWriter) { @@ -170,8 +179,12 @@ class Styles extends AbstractPart $xmlWriter->endElement(); // style:page-layout } + /** - * Write master style + * Write master style. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @return void */ private function writeMaster(XMLWriter $xmlWriter) { diff --git a/src/PhpWord/Writer/ODText/Style/Font.php b/src/PhpWord/Writer/ODText/Style/Font.php index acab0ee5..45184505 100644 --- a/src/PhpWord/Writer/ODText/Style/Font.php +++ b/src/PhpWord/Writer/ODText/Style/Font.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\ODText\Style; class Font extends AbstractStyle { /** - * Write style + * Write style. + * + * @return void */ public function write() { diff --git a/src/PhpWord/Writer/ODText/Style/Image.php b/src/PhpWord/Writer/ODText/Style/Image.php index de97f474..21b9c4ee 100644 --- a/src/PhpWord/Writer/ODText/Style/Image.php +++ b/src/PhpWord/Writer/ODText/Style/Image.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\ODText\Style; class Image extends AbstractStyle { /** - * Write style + * Write style. + * + * @return void */ public function write() { diff --git a/src/PhpWord/Writer/ODText/Style/Paragraph.php b/src/PhpWord/Writer/ODText/Style/Paragraph.php index 133b8cdf..03e605a1 100644 --- a/src/PhpWord/Writer/ODText/Style/Paragraph.php +++ b/src/PhpWord/Writer/ODText/Style/Paragraph.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\ODText\Style; class Paragraph extends AbstractStyle { /** - * Write style + * Write style. + * + * @return void */ public function write() { diff --git a/src/PhpWord/Writer/ODText/Style/Section.php b/src/PhpWord/Writer/ODText/Style/Section.php index 3d910157..fa432856 100644 --- a/src/PhpWord/Writer/ODText/Style/Section.php +++ b/src/PhpWord/Writer/ODText/Style/Section.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\ODText\Style; class Section extends AbstractStyle { /** - * Write style + * Write style. + * + * @return void */ public function write() { diff --git a/src/PhpWord/Writer/ODText/Style/Table.php b/src/PhpWord/Writer/ODText/Style/Table.php index b32349af..dbfb94ed 100644 --- a/src/PhpWord/Writer/ODText/Style/Table.php +++ b/src/PhpWord/Writer/ODText/Style/Table.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\ODText\Style; class Table extends AbstractStyle { /** - * Write style + * Write style. + * + * @return void */ public function write() { diff --git a/src/PhpWord/Writer/PDF/AbstractRenderer.php b/src/PhpWord/Writer/PDF/AbstractRenderer.php index d4288c8a..572e4b1d 100644 --- a/src/PhpWord/Writer/PDF/AbstractRenderer.php +++ b/src/PhpWord/Writer/PDF/AbstractRenderer.php @@ -190,6 +190,7 @@ abstract class AbstractRenderer extends HTML * Save PhpWord to PDF file, post-save * * @param resource $fileHandle + * @return void * @throws Exception */ protected function restoreStateAfterSave($fileHandle) diff --git a/src/PhpWord/Writer/PDF/DomPDF.php b/src/PhpWord/Writer/PDF/DomPDF.php index a40e2cea..47054c4a 100644 --- a/src/PhpWord/Writer/PDF/DomPDF.php +++ b/src/PhpWord/Writer/PDF/DomPDF.php @@ -35,9 +35,10 @@ class DomPDF extends AbstractRenderer implements WriterInterface protected $includeFile = 'dompdf_config.inc.php'; /** - * Save PhpWord to file + * Save PhpWord to file. * * @param string $filename Name of the file to save as + * @return void */ public function save($filename = null) { diff --git a/src/PhpWord/Writer/PDF/MPDF.php b/src/PhpWord/Writer/PDF/MPDF.php index 9d4e050c..46d456d4 100644 --- a/src/PhpWord/Writer/PDF/MPDF.php +++ b/src/PhpWord/Writer/PDF/MPDF.php @@ -35,9 +35,10 @@ class MPDF extends AbstractRenderer implements WriterInterface protected $includeFile = 'mpdf.php'; /** - * Save PhpWord to file + * Save PhpWord to file. * * @param string $filename Name of the file to save as + * @return void */ public function save($filename = null) { @@ -54,7 +55,7 @@ class MPDF extends AbstractRenderer implements WriterInterface // Write document properties $phpWord = $this->getPhpWord(); - $docProps = $phpWord->getDocumentProperties(); + $docProps = $phpWord->getDocInfo(); $pdf->setTitle($docProps->getTitle()); $pdf->setAuthor($docProps->getCreator()); $pdf->setSubject($docProps->getSubject()); diff --git a/src/PhpWord/Writer/PDF/TCPDF.php b/src/PhpWord/Writer/PDF/TCPDF.php index 669a2cdd..36849e24 100644 --- a/src/PhpWord/Writer/PDF/TCPDF.php +++ b/src/PhpWord/Writer/PDF/TCPDF.php @@ -35,9 +35,10 @@ class TCPDF extends AbstractRenderer implements WriterInterface protected $includeFile = 'tcpdf.php'; /** - * Save PhpWord to file + * Save PhpWord to file. * * @param string $filename Name of the file to save as + * @return vois */ public function save($filename = null) { @@ -58,7 +59,7 @@ class TCPDF extends AbstractRenderer implements WriterInterface // Write document properties $phpWord = $this->getPhpWord(); - $docProps = $phpWord->getDocumentProperties(); + $docProps = $phpWord->getDocInfo(); $pdf->setTitle($docProps->getTitle()); $pdf->setAuthor($docProps->getCreator()); $pdf->setSubject($docProps->getSubject()); diff --git a/src/PhpWord/Writer/RTF.php b/src/PhpWord/Writer/RTF.php index d7fed942..58210c99 100644 --- a/src/PhpWord/Writer/RTF.php +++ b/src/PhpWord/Writer/RTF.php @@ -55,15 +55,15 @@ class RTF extends AbstractWriter implements WriterInterface } /** - * Save content to file + * Save content to file. * * @param string $filename + * @return void * @throws \PhpOffice\PhpWord\Exception\Exception */ public function save($filename = null) { - $fileHandle = $this->openFile($filename); - $this->writeFile($fileHandle, $this->getContent()); + $this->writeFile($this->openFile($filename), $this->getContent()); } /** @@ -86,7 +86,9 @@ class RTF extends AbstractWriter implements WriterInterface } /** - * Get font table + * Get font table. + * + * @return array */ public function getFontTable() { @@ -94,7 +96,9 @@ class RTF extends AbstractWriter implements WriterInterface } /** - * Get color table + * Get color table. + * + * @return array */ public function getColorTable() { @@ -102,7 +106,9 @@ class RTF extends AbstractWriter implements WriterInterface } /** - * Get last paragraph style + * Get last paragraph style. + * + * @return mixed */ public function getLastParagraphStyle() { @@ -110,9 +116,10 @@ class RTF extends AbstractWriter implements WriterInterface } /** - * Set last paragraph style + * Set last paragraph style. * * @param mixed $value + * @return void */ public function setLastParagraphStyle($value = '') { diff --git a/src/PhpWord/Writer/RTF/Element/AbstractElement.php b/src/PhpWord/Writer/RTF/Element/AbstractElement.php index 79e13947..73da5cbd 100644 --- a/src/PhpWord/Writer/RTF/Element/AbstractElement.php +++ b/src/PhpWord/Writer/RTF/Element/AbstractElement.php @@ -47,7 +47,9 @@ abstract class AbstractElement extends HTMLAbstractElement private $paragraphStyle; /** - * Get font and paragraph styles + * Get font and paragraph styles. + * + * @return void */ protected function getStyles() { diff --git a/src/PhpWord/Writer/RTF/Element/Image.php b/src/PhpWord/Writer/RTF/Element/Image.php index 1daae2a0..52e705e9 100644 --- a/src/PhpWord/Writer/RTF/Element/Image.php +++ b/src/PhpWord/Writer/RTF/Element/Image.php @@ -18,7 +18,7 @@ namespace PhpOffice\PhpWord\Writer\RTF\Element; use PhpOffice\PhpWord\Element\Image as ImageElement; -use PhpOffice\PhpWord\Shared\Font; +use PhpOffice\PhpWord\Shared\Converter; /** * Image element RTF writer @@ -45,8 +45,8 @@ class Image extends AbstractElement $content .= $this->writeOpening(); $content .= '{\*\shppict {\pict'; $content .= '\pngblip\picscalex100\picscaley100'; - $content .= '\picwgoal' . round(Font::pixelSizeToTwips($style->getWidth())); - $content .= '\pichgoal' . round(Font::pixelSizeToTwips($style->getHeight())); + $content .= '\picwgoal' . round(Converter::pixelToTwip($style->getWidth())); + $content .= '\pichgoal' . round(Converter::pixelToTwip($style->getHeight())); $content .= PHP_EOL; $content .= $this->element->getImageStringData(); $content .= '}}'; diff --git a/src/PhpWord/Writer/RTF/Element/Link.php b/src/PhpWord/Writer/RTF/Element/Link.php index 22b08588..adbc7976 100644 --- a/src/PhpWord/Writer/RTF/Element/Link.php +++ b/src/PhpWord/Writer/RTF/Element/Link.php @@ -39,7 +39,7 @@ class Link extends AbstractElement $content = ''; $content .= $this->writeOpening(); - $content .= '{\field {\*\fldinst {HYPERLINK "' . $this->element->getTarget() . '"}}{\\fldrslt {'; + $content .= '{\field {\*\fldinst {HYPERLINK "' . $this->element->getSource() . '"}}{\\fldrslt {'; $content .= $this->writeFontStyle(); $content .= $this->writeText($this->element->getText()); $content .= '}}}'; diff --git a/src/PhpWord/Writer/RTF/Element/Table.php b/src/PhpWord/Writer/RTF/Element/Table.php index b48e084f..7c4329f7 100644 --- a/src/PhpWord/Writer/RTF/Element/Table.php +++ b/src/PhpWord/Writer/RTF/Element/Table.php @@ -66,6 +66,7 @@ class Table extends AbstractElement /** * Write column * + * @param \PhpOffice\PhpWord\Element\Row $row * @return string */ private function writeRowDef(RowElement $row) @@ -89,6 +90,7 @@ class Table extends AbstractElement /** * Write row * + * @param \PhpOffice\PhpWord\Element\Row $row * @return string */ private function writeRow(RowElement $row) @@ -106,6 +108,7 @@ class Table extends AbstractElement /** * Write cell * + * @param \PhpOffice\PhpWord\Element\Cell $cell * @return string */ private function writeCell(CellElement $cell) diff --git a/src/PhpWord/Writer/RTF/Part/Document.php b/src/PhpWord/Writer/RTF/Part/Document.php index 71565044..edcdbd84 100644 --- a/src/PhpWord/Writer/RTF/Part/Document.php +++ b/src/PhpWord/Writer/RTF/Part/Document.php @@ -19,11 +19,13 @@ namespace PhpOffice\PhpWord\Writer\RTF\Part; use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Writer\RTF\Element\Container; +use PhpOffice\PhpWord\Writer\RTF\Style\Section as SectionStyleWriter; /** * RTF document part writer * * @since 0.11.0 + * @link http://www.biblioscape.com/rtf15_spec.htm#Heading24 */ class Document extends AbstractPart { @@ -50,7 +52,7 @@ class Document extends AbstractPart */ private function writeInfo() { - $docProps = $this->getParentWriter()->getPhpWord()->getDocumentProperties(); + $docProps = $this->getParentWriter()->getPhpWord()->getDocInfo(); $properties = array('title', 'subject', 'category', 'keywords', 'comment', 'author', 'operator', 'creatim', 'revtim', 'company', 'manager'); $mapping = array('comment' => 'description', 'author' => 'creator', 'operator' => 'lastModifiedBy', @@ -62,7 +64,7 @@ class Document extends AbstractPart $content .= '{'; $content .= '\info'; foreach ($properties as $property) { - $method = 'get' . (array_key_exists($property, $mapping) ? $mapping[$property] : $property); + $method = 'get' . (isset($mapping[$property]) ? $mapping[$property] : $property); $value = $docProps->$method(); $value = in_array($property, $dateFields) ? $this->getDateValue($value) : $value; $content .= "{\\{$property} {$value}}"; @@ -103,12 +105,19 @@ class Document extends AbstractPart */ private function writeSections() { + $content = ''; $sections = $this->getParentWriter()->getPhpWord()->getSections(); foreach ($sections as $section) { - $writer = new Container($this->getParentWriter(), $section); - $content .= $writer->write(); + $styleWriter = new SectionStyleWriter($section->getStyle()); + $styleWriter->setParentWriter($this->getParentWriter()); + $content .= $styleWriter->write(); + + $elementWriter = new Container($this->getParentWriter(), $section); + $content .= $elementWriter->write(); + + $content .= '\sect' . PHP_EOL; } return $content; diff --git a/src/PhpWord/Writer/RTF/Part/Header.php b/src/PhpWord/Writer/RTF/Part/Header.php index 15a0c303..31fbb7f4 100644 --- a/src/PhpWord/Writer/RTF/Part/Header.php +++ b/src/PhpWord/Writer/RTF/Part/Header.php @@ -18,14 +18,22 @@ namespace PhpOffice\PhpWord\Writer\RTF\Part; use PhpOffice\PhpWord\Settings; -use PhpOffice\PhpWord\Shared\Drawing; +use PhpOffice\PhpWord\Shared\Converter; use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Style\Font; /** * RTF header part writer * + * - Character set + * - Font table + * - File table (not supported yet) + * - Color table + * - Style sheet (not supported yet) + * - List table (not supported yet) + * * @since 0.11.0 + * @link http://www.biblioscape.com/rtf15_spec.htm#Heading6 */ class Header extends AbstractPart { @@ -44,7 +52,9 @@ class Header extends AbstractPart private $colorTable = array(); /** - * Get font table + * Get font table. + * + * @return array */ public function getFontTable() { @@ -52,7 +62,9 @@ class Header extends AbstractPart } /** - * Get color table + * Get color table. + * + * @return array */ public function getColorTable() { @@ -141,10 +153,10 @@ class Header extends AbstractPart $content = ''; $content .= '{'; - $content .= '\colortbl'; + $content .= '\colortbl;'; foreach ($this->colorTable as $color) { - list($red, $green, $blue) = Drawing::htmlToRGB($color); - $content .= ";\\red{$red}\\green{$green}\\blue{$blue}"; + list($red, $green, $blue) = Converter::htmlToRgb($color); + $content .= "\\red{$red}\\green{$green}\\blue{$blue};"; } $content .= '}'; $content .= PHP_EOL; @@ -168,7 +180,9 @@ class Header extends AbstractPart } /** - * Register all fonts and colors in both named and inline styles to appropriate header table + * Register all fonts and colors in both named and inline styles to appropriate header table. + * + * @return void */ private function registerFont() { @@ -185,6 +199,7 @@ class Header extends AbstractPart $sections = $phpWord->getSections(); foreach ($sections as $section) { $elements = $section->getElements(); + $this->registerBorderColor($section->getStyle()); foreach ($elements as $element) { if (method_exists($element, 'getFontStyle')) { $style = $element->getFontStyle(); @@ -195,9 +210,26 @@ class Header extends AbstractPart } /** - * Register fonts and colors + * Register border colors. + * + * @param \PhpOffice\PhpWord\Style\Border $style + * @return void + */ + private function registerBorderColor($style) + { + $colors = $style->getBorderColor(); + foreach ($colors as $color) { + if ($color !== null) { + $this->registerTableItem($this->colorTable, $color); + } + } + } + + /** + * Register fonts and colors. * * @param \PhpOffice\PhpWord\Style\AbstractStyle $style + * @return void */ private function registerFontItems($style) { @@ -205,20 +237,21 @@ class Header extends AbstractPart $defaultColor = Settings::DEFAULT_FONT_COLOR; if ($style instanceof Font) { - $this->registerFontItem($this->fontTable, $style->getName(), $defaultFont); - $this->registerFontItem($this->colorTable, $style->getColor(), $defaultColor); - $this->registerFontItem($this->colorTable, $style->getFgColor(), $defaultColor); + $this->registerTableItem($this->fontTable, $style->getName(), $defaultFont); + $this->registerTableItem($this->colorTable, $style->getColor(), $defaultColor); + $this->registerTableItem($this->colorTable, $style->getFgColor(), $defaultColor); } } /** - * Register individual font and color + * Register individual font and color. * - * @param array $table + * @param array &$table * @param string $value * @param string $default + * @return void */ - private function registerFontItem(&$table, $value, $default) + private function registerTableItem(&$table, $value, $default = null) { if (in_array($value, $table) === false && $value !== null && $value != $default) { $table[] = $value; diff --git a/src/PhpWord/Writer/RTF/Style/Border.php b/src/PhpWord/Writer/RTF/Style/Border.php new file mode 100644 index 00000000..88c517ad --- /dev/null +++ b/src/PhpWord/Writer/RTF/Style/Border.php @@ -0,0 +1,124 @@ +sizes) - 1; + + // Page border measure + // 8 = from text, infront off; 32 = from edge, infront on; 40 = from edge, infront off + $content .= '\pgbrdropt32'; + + for ($i = 0; $i < $sizeCount; $i++) { + if ($this->sizes[$i] !== null) { + $color = null; + if (isset($this->colors[$i])) { + $color = $this->colors[$i]; + } + $content .= $this->writeSide($sides[$i], $this->sizes[$i], $color); + } + } + + return $content; + } + + /** + * Write side + * + * @param string $side + * @param int $width + * @param string $color + * @return string + */ + private function writeSide($side, $width, $color = '') + { + /** @var \PhpOffice\PhpWord\Writer\RTF $rtfWriter */ + $rtfWriter = $this->getParentWriter(); + $colorIndex = 0; + if ($rtfWriter !== null) { + $colorTable = $rtfWriter->getColorTable(); + $index = array_search($color, $colorTable); + if ($index !== false && $colorIndex !== null) { + $colorIndex = $index + 1; + } + } + + $content = ''; + + $content .= '\pgbrdr' . substr($side, 0, 1); + $content .= '\brdrs'; // Single-thickness border; @todo Get other type of border + $content .= '\brdrw' . $width; // Width + $content .= '\brdrcf' . $colorIndex; // Color + $content .= '\brsp480'; // Space in twips between borders and the paragraph (24pt, following OOXML) + $content .= ' '; + + return $content; + } + + /** + * Set sizes. + * + * @param integer[] $value + * @return void + */ + public function setSizes($value) + { + $this->sizes = $value; + } + + /** + * Set colors. + * + * @param string[] $value + * @return void + */ + public function setColors($value) + { + $this->colors = $value; + } +} diff --git a/src/PhpWord/Writer/RTF/Style/Font.php b/src/PhpWord/Writer/RTF/Style/Font.php index 9634b566..20c47aee 100644 --- a/src/PhpWord/Writer/RTF/Style/Font.php +++ b/src/PhpWord/Writer/RTF/Style/Font.php @@ -66,9 +66,11 @@ class Font extends AbstractStyle } /** - * Set font name index + * Set font name index. + * * * @param int $value + * @return void */ public function setNameIndex($value = 0) { @@ -76,9 +78,10 @@ class Font extends AbstractStyle } /** - * Set font color index + * Set font color index. * * @param int $value + * @return void */ public function setColorIndex($value = 0) { diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index b166cc27..1a7de0a3 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -73,9 +73,10 @@ class Paragraph extends AbstractStyle } /** - * Set nested level + * Set nested level. * * @param int $value + * @return void */ public function setNestedLevel($value) { diff --git a/src/PhpWord/Writer/RTF/Style/Section.php b/src/PhpWord/Writer/RTF/Style/Section.php new file mode 100644 index 00000000..4169b630 --- /dev/null +++ b/src/PhpWord/Writer/RTF/Style/Section.php @@ -0,0 +1,69 @@ +getStyle(); + if (!$style instanceof SectionStyle) { + return ''; + } + + $content = ''; + + $content .= '\sectd '; + + // Size & margin + $content .= $this->getValueIf($style->getPageSizeW() !== null, '\pgwsxn' . $style->getPageSizeW()); + $content .= $this->getValueIf($style->getPageSizeH() !== null, '\pghsxn' . $style->getPageSizeH()); + $content .= ' '; + $content .= $this->getValueIf($style->getMarginTop() !== null, '\margtsxn' . $style->getMarginTop()); + $content .= $this->getValueIf($style->getMarginRight() !== null, '\margrsxn' . $style->getMarginRight()); + $content .= $this->getValueIf($style->getMarginBottom() !== null, '\margbsxn' . $style->getMarginBottom()); + $content .= $this->getValueIf($style->getMarginLeft() !== null, '\marglsxn' . $style->getMarginLeft()); + $content .= $this->getValueIf($style->getHeaderHeight() !== null, '\headery' . $style->getHeaderHeight()); + $content .= $this->getValueIf($style->getFooterHeight() !== null, '\footery' . $style->getFooterHeight()); + $content .= $this->getValueIf($style->getGutter() !== null, '\guttersxn' . $style->getGutter()); + $content .= ' '; + + // Borders + if ($style->hasBorder()) { + $styleWriter = new Border($style); + $styleWriter->setParentWriter($this->getParentWriter()); + $styleWriter->setSizes($style->getBorderSize()); + $styleWriter->setColors($style->getBorderColor()); + $content .= $styleWriter->write(); + } + + return $content . PHP_EOL; + } +} diff --git a/src/PhpWord/Writer/Word2007.php b/src/PhpWord/Writer/Word2007.php index 751b58b6..09d09509 100644 --- a/src/PhpWord/Writer/Word2007.php +++ b/src/PhpWord/Writer/Word2007.php @@ -71,6 +71,7 @@ class Word2007 extends AbstractWriter implements WriterInterface 'Footer' => '', 'Footnotes' => '', 'Endnotes' => '', + 'Chart' => '', ); foreach (array_keys($this->parts) as $partName) { $partClass = get_class($this) . '\\Part\\' . $partName; @@ -87,9 +88,10 @@ class Word2007 extends AbstractWriter implements WriterInterface } /** - * Save document by name + * Save document by name. * * @param string $filename + * @return void */ public function save($filename = null) { @@ -127,6 +129,7 @@ class Word2007 extends AbstractWriter implements WriterInterface $this->addNotes($zip, $rId, 'footnote'); $this->addNotes($zip, $rId, 'endnote'); + $this->addChart($zip, $rId); // Write parts foreach ($this->parts as $partName => $fileName) { @@ -161,10 +164,11 @@ class Word2007 extends AbstractWriter implements WriterInterface } /** - * Add header/footer media files, e.g. footer1.xml.rels + * Add header/footer media files, e.g. footer1.xml.rels. * * @param \PhpOffice\PhpWord\Shared\ZipArchive $zip * @param string $docPart + * @return void */ private function addHeaderFooterMedia(ZipArchive $zip, $docPart) { @@ -186,12 +190,13 @@ class Word2007 extends AbstractWriter implements WriterInterface } /** - * Add header/footer content + * Add header/footer content. * - * @param \PhpOffice\PhpWord\Element\Section $section + * @param \PhpOffice\PhpWord\Element\Section &$section * @param \PhpOffice\PhpWord\Shared\ZipArchive $zip * @param string $elmType header|footer - * @param integer $rId + * @param integer &$rId + * @return void */ private function addHeaderFooterContent(Section &$section, ZipArchive $zip, $elmType, &$rId) { @@ -216,8 +221,9 @@ class Word2007 extends AbstractWriter implements WriterInterface * Add footnotes/endnotes * * @param \PhpOffice\PhpWord\Shared\ZipArchive $zip - * @param integer $rId + * @param integer &$rId * @param string $noteType + * @return void */ private function addNotes(ZipArchive $zip, &$rId, $noteType = 'footnote') { @@ -250,9 +256,45 @@ class Word2007 extends AbstractWriter implements WriterInterface } /** - * Register content types for each media + * Add chart. + * + * @param \PhpOffice\PhpWord\Shared\ZipArchive $zip + * @param integer &$rId + * @return void + */ + private function addChart(ZipArchive $zip, &$rId) + { + $phpWord = $this->getPhpWord(); + + $collection = $phpWord->getCharts(); + $index = 0; + if ($collection->countItems() > 0) { + foreach ($collection->getItems() as $chart) { + $index++; + $rId++; + $filename = "charts/chart{$index}.xml"; + + // ContentTypes.xml + $this->contentTypes['override']["/word/{$filename}"] = 'chart'; + + // word/_rels/document.xml.rel + $this->relationships[] = array('target' => $filename, 'type' => 'chart', 'rID' => $rId); + + // word/charts/chartN.xml + /** @var \PhpOffice\PhpWord\Element\Chart $chart */ + $chart->setRelationId($rId); + $writerPart = $this->getWriterPart('Chart'); + $writerPart->setElement($chart); + $zip->addFromString("word/{$filename}", $writerPart->write()); + } + } + } + + /** + * Register content types for each media. * * @param array $media + * @return void */ private function registerContentTypes($media) { @@ -260,11 +302,11 @@ class Word2007 extends AbstractWriter implements WriterInterface $mediumType = $medium['type']; if ($mediumType == 'image') { $extension = $medium['imageExtension']; - if (!array_key_exists($extension, $this->contentTypes['default'])) { + if (!isset($this->contentTypes['default'][$extension])) { $this->contentTypes['default'][$extension] = $medium['imageType']; } } elseif ($mediumType == 'object') { - if (!array_key_exists('bin', $this->contentTypes['default'])) { + if (!isset($this->contentTypes['default']['bin'])) { $this->contentTypes['default']['bin'] = 'application/vnd.openxmlformats-officedocument.oleObject'; } } diff --git a/src/PhpWord/Writer/Word2007/Element/AbstractElement.php b/src/PhpWord/Writer/Word2007/Element/AbstractElement.php index 52b4c62e..3b6432ed 100644 --- a/src/PhpWord/Writer/Word2007/Element/AbstractElement.php +++ b/src/PhpWord/Writer/Word2007/Element/AbstractElement.php @@ -49,13 +49,6 @@ abstract class AbstractElement */ protected $withoutP = false; - /** - * Has page break before - * - * @var bool - */ - private $pageBreakBefore = false; - /** * Write element */ @@ -96,23 +89,74 @@ abstract class AbstractElement } /** - * Has page break before + * Start w:p DOM element. * - * @return bool + * @uses \PhpOffice\PhpWord\Writer\Word2007\Element\PageBreak::write() + * @return void */ - public function hasPageBreakBefore() + protected function startElementP() { - return $this->pageBreakBefore; + if (!$this->withoutP) { + $this->xmlWriter->startElement('w:p'); + // Paragraph style + if (method_exists($this->element, 'getParagraphStyle')) { + $this->writeParagraphStyle(); + } + } } /** - * Set page break before + * End w:p DOM element. * - * @param bool $value + * @return void */ - public function setPageBreakBefore($value = true) + protected function endElementP() { - $this->pageBreakBefore = (bool)$value; + if (!$this->withoutP) { + $this->xmlWriter->endElement(); // w:p + } + } + + /** + * Write ending. + * + * @return void + */ + protected function writeParagraphStyle() + { + $this->writeTextStyle('Paragraph'); + } + + /** + * Write ending. + * + * @return void + */ + protected function writeFontStyle() + { + $this->writeTextStyle('Font'); + } + + + /** + * Write text style. + * + * @param string $styleType Font|Paragraph + * @return void + */ + private function writeTextStyle($styleType) + { + $method = "get{$styleType}Style"; + $class = "PhpOffice\\PhpWord\\Writer\\Word2007\\Style\\{$styleType}"; + $styleObject = $this->element->$method(); + + $styleWriter = new $class($this->xmlWriter, $styleObject); + if (method_exists($styleWriter, 'setIsInline')) { + $styleWriter->setIsInline(true); + } + + /** @var \PhpOffice\PhpWord\Writer\Word2007\Style\AbstractStyle $styleWriter */ + $styleWriter->write(); } /** @@ -123,6 +167,6 @@ abstract class AbstractElement */ protected function getText($text) { - return String::controlCharacterPHP2OOXML(htmlspecialchars($text)); + return String::controlCharacterPHP2OOXML($text); } } diff --git a/src/PhpWord/Writer/Word2007/Element/Bookmark.php b/src/PhpWord/Writer/Word2007/Element/Bookmark.php new file mode 100644 index 00000000..df5a104a --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/Bookmark.php @@ -0,0 +1,49 @@ +getXmlWriter(); + $element = $this->getElement(); + if (!$element instanceof \PhpOffice\PhpWord\Element\Bookmark) { + return; + } + + $rId = $element->getRelationId(); + + $xmlWriter->startElement('w:bookmarkStart'); + $xmlWriter->writeAttribute('w:id', $rId); + $xmlWriter->writeAttribute('w:name', $element->getName()); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:bookmarkEnd'); + $xmlWriter->writeAttribute('w:id', $rId); + $xmlWriter->endElement(); + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/Chart.php b/src/PhpWord/Writer/Word2007/Element/Chart.php new file mode 100644 index 00000000..ccd8cd77 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/Chart.php @@ -0,0 +1,77 @@ +getXmlWriter(); + $element = $this->getElement(); + if (!$element instanceof ChartElement) { + return; + } + + $rId = $element->getRelationId(); + $style = $element->getStyle(); + + if (!$this->withoutP) { + $xmlWriter->startElement('w:p'); + } + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:drawing'); + $xmlWriter->startElement('wp:inline'); + + // EMU + $xmlWriter->writeElementBlock('wp:extent', array('cx' => $style->getWidth(), 'cy' => $style->getHeight())); + $xmlWriter->writeElementBlock('wp:docPr', array('id' => $rId, 'name' => "Chart{$rId}")); + + $xmlWriter->startElement('a:graphic'); + $xmlWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); + $xmlWriter->startElement('a:graphicData'); + $xmlWriter->writeAttribute('uri', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); + + $xmlWriter->startElement('c:chart'); + $xmlWriter->writeAttribute('r:id', "rId{$rId}"); + $xmlWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); + $xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + $xmlWriter->endElement(); // c:chart + + $xmlWriter->endElement(); // a:graphicData + $xmlWriter->endElement(); // a:graphic + + $xmlWriter->endElement(); // wp:inline + $xmlWriter->endElement(); // w:drawing + $xmlWriter->endElement(); // w:r + + $this->endElementP(); // w:p + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/CheckBox.php b/src/PhpWord/Writer/Word2007/Element/CheckBox.php index ea13b8f9..deafbd1d 100644 --- a/src/PhpWord/Writer/Word2007/Element/CheckBox.php +++ b/src/PhpWord/Writer/Word2007/Element/CheckBox.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; class CheckBox extends Text { /** - * Write element + * Write element. + * + * @return void */ public function write() { @@ -35,7 +37,7 @@ class CheckBox extends Text return; } - $this->writeOpeningWP(); + $this->startElementP(); $xmlWriter->startElement('w:r'); $xmlWriter->startElement('w:fldChar'); @@ -66,7 +68,7 @@ class CheckBox extends Text $xmlWriter->endElement(); // w:r $xmlWriter->startElement('w:r'); $xmlWriter->startElement('w:fldChar'); - $xmlWriter->writeAttribute('w:fldCharType', 'seperate'); + $xmlWriter->writeAttribute('w:fldCharType', 'separate'); $xmlWriter->endElement();// w:fldChar $xmlWriter->endElement(); // w:r $xmlWriter->startElement('w:r'); @@ -85,6 +87,6 @@ class CheckBox extends Text $xmlWriter->endElement(); // w:t $xmlWriter->endElement(); // w:r - $this->writeClosingWP(); + $this->endElementP(); // w:p } } diff --git a/src/PhpWord/Writer/Word2007/Element/Container.php b/src/PhpWord/Writer/Word2007/Element/Container.php index 3dad824d..771fe5c3 100644 --- a/src/PhpWord/Writer/Word2007/Element/Container.php +++ b/src/PhpWord/Writer/Word2007/Element/Container.php @@ -17,8 +17,8 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; -use PhpOffice\PhpWord\Element\AbstractElement as Element; use PhpOffice\PhpWord\Element\AbstractContainer as ContainerElement; +use PhpOffice\PhpWord\Element\AbstractElement as Element; use PhpOffice\PhpWord\Element\TextBreak as TextBreakElement; use PhpOffice\PhpWord\Shared\XMLWriter; @@ -37,7 +37,9 @@ class Container extends AbstractElement protected $namespace = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element'; /** - * Write element + * Write element. + * + * @return void */ public function write() { @@ -81,21 +83,9 @@ class Container extends AbstractElement $elementClass = substr(get_class($element), strrpos(get_class($element), '\\') + 1); $writerClass = $this->namespace . '\\' . $elementClass; - // Check it's a page break. No need to write it, instead, flag containers' - // pageBreakBefore to be assigned to the next element - if ($elementClass == 'PageBreak') { - $this->setPageBreakBefore(true); - return $elementClass; - } - if (class_exists($writerClass)) { - // Get container's page break before and reset it - $pageBreakBefore = $this->hasPageBreakBefore(); - $this->setPageBreakBefore(false); - /** @var \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement $writer Type hint */ $writer = new $writerClass($xmlWriter, $element, $withoutP); - $writer->setPageBreakBefore($pageBreakBefore); $writer->write(); } diff --git a/src/PhpWord/Writer/Word2007/Element/Field.php b/src/PhpWord/Writer/Word2007/Element/Field.php index 68c4c40c..b9c3c34b 100644 --- a/src/PhpWord/Writer/Word2007/Element/Field.php +++ b/src/PhpWord/Writer/Word2007/Element/Field.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; class Field extends Text { /** - * Write field element + * Write field element. + * + * @return void */ public function write() { @@ -67,7 +69,8 @@ class Field extends Text } } - $this->writeOpeningWP(); + $this->startElementP(); + $xmlWriter->startElement('w:fldSimple'); $xmlWriter->writeAttribute('w:instr', $instruction); $xmlWriter->startElement('w:r'); @@ -82,6 +85,6 @@ class Field extends Text $xmlWriter->endElement(); // w:r $xmlWriter->endElement(); // w:fldSimple - $this->writeClosingWP(); + $this->endElementP(); // w:p } } diff --git a/src/PhpWord/Writer/Word2007/Element/Footnote.php b/src/PhpWord/Writer/Word2007/Element/Footnote.php index 240a8a00..5640a90d 100644 --- a/src/PhpWord/Writer/Word2007/Element/Footnote.php +++ b/src/PhpWord/Writer/Word2007/Element/Footnote.php @@ -32,7 +32,9 @@ class Footnote extends Text protected $referenceType = 'footnoteReference'; /** - * Write element + * Write element. + * + * @return void */ public function write() { @@ -42,7 +44,7 @@ class Footnote extends Text return; } - $this->writeOpeningWP(); + $this->startElementP(); $xmlWriter->startElement('w:r'); $xmlWriter->startElement('w:rPr'); @@ -55,6 +57,6 @@ class Footnote extends Text $xmlWriter->endElement(); // w:$referenceType $xmlWriter->endElement(); // w:r - $this->writeClosingWP(); + $this->endElementP(); // w:p } } diff --git a/src/PhpWord/Writer/Word2007/Element/FormField.php b/src/PhpWord/Writer/Word2007/Element/FormField.php new file mode 100644 index 00000000..432dc9c2 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/FormField.php @@ -0,0 +1,172 @@ +getXmlWriter(); + $element = $this->getElement(); + if (!$element instanceof FormFieldElement) { + return; + } + + $type = $element->getType(); + $instructions = array('textinput' => 'FORMTEXT', 'checkbox' => 'FORMCHECKBOX', 'dropdown' => 'FORMDROPDOWN'); + $instruction = $instructions[$type]; + $writeFormField = "write{$type}"; + $name = $element->getName(); + if ($name === null) { + $name = $type . $element->getElementId(); + } + $value = $element->getValue(); + if ($value === null) { + $value = str_repeat(' ', self::FILLER_LENGTH); + } + + $this->startElementP(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'begin'); + $xmlWriter->startElement('w:ffData'); + $xmlWriter->writeElementBlock('w:enabled', 'w:val', 1); + $xmlWriter->writeElementBlock('w:name', 'w:val', $name); + $xmlWriter->writeElementBlock('w:calcOnExit', 'w:val', 0); + $this->$writeFormField($xmlWriter, $element); + $xmlWriter->endElement(); // w:ffData + $xmlWriter->endElement(); // w:fldChar + $xmlWriter->endElement(); // w:r + + $xmlWriter->startElement('w:r'); + $this->writeFontStyle(); + $xmlWriter->startElement('w:instrText'); + $xmlWriter->writeAttribute('xml:space', 'preserve'); + $xmlWriter->writeRaw("{$instruction}"); + $xmlWriter->endElement();// w:instrText + $xmlWriter->endElement(); // w:r + + $xmlWriter->startElement('w:r'); + $this->writeFontStyle(); + $xmlWriter->writeElementBlock('w:fldChar', 'w:fldCharType', 'separate'); + $xmlWriter->endElement(); // w:r + + $xmlWriter->startElement('w:r'); + $this->writeFontStyle(); + $xmlWriter->startElement('w:t'); + $xmlWriter->writeAttribute('xml:space', 'preserve'); + $xmlWriter->writeRaw($value); + $xmlWriter->endElement(); // w:t + $xmlWriter->endElement(); // w:r + + $xmlWriter->startElement('w:r'); + $this->writeFontStyle(); + $xmlWriter->writeElementBlock('w:fldChar', 'w:fldCharType', 'end'); + $xmlWriter->endElement(); // w:r + + $this->endElementP(); // w:p + } + + /** + * Write textinput. + * + * @link http://www.datypic.com/sc/ooxml/t-w_CT_FFTextInput.html + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Element\FormField $element + * @return void + */ + private function writeTextInput(XMLWriter $xmlWriter, FormFieldElement $element) + { + $default = $element->getDefault(); + + $xmlWriter->startElement('w:textInput'); + $xmlWriter->writeElementBlock('w:default', 'w:val', $default); + $xmlWriter->endElement(); + } + + /** + * Write checkbox. + * + * @link http://www.datypic.com/sc/ooxml/t-w_CT_FFCheckBox.html + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Element\FormField $element + * @return void + */ + private function writeCheckBox(XMLWriter $xmlWriter, FormFieldElement $element) + { + $default = $element->getDefault() ? 1 : 0; + $value = $element->getValue(); + if ($value == null) { + $value = $default; + } + $value = $value ? 1 : 0; + + $xmlWriter->startElement('w:checkBox'); + $xmlWriter->writeElementBlock('w:sizeAuto', 'w:val', ''); + $xmlWriter->writeElementBlock('w:default', 'w:val', $default); + $xmlWriter->writeElementBlock('w:checked', 'w:val', $value); + $xmlWriter->endElement(); + } + + /** + * Write dropdown. + * + * @link http://www.datypic.com/sc/ooxml/t-w_CT_FFDDList.html + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Element\FormField $element + * @return void + */ + private function writeDropDown(XMLWriter $xmlWriter, FormFieldElement $element) + { + $default = $element->getDefault(); + $value = $element->getValue(); + if ($value == null) { + $value = $default; + } + $entries = $element->getEntries(); + + $xmlWriter->startElement('w:ddList'); + $xmlWriter->writeElementBlock('w:result', 'w:val', $value); + $xmlWriter->writeElementBlock('w:default', 'w:val', $default); + foreach ($entries as $entry) { + $xmlWriter->writeElementBlock('w:listEntry', 'w:val', $entry); + } + $xmlWriter->endElement(); + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/Image.php b/src/PhpWord/Writer/Word2007/Element/Image.php index a882040e..73988423 100644 --- a/src/PhpWord/Writer/Word2007/Element/Image.php +++ b/src/PhpWord/Writer/Word2007/Element/Image.php @@ -29,7 +29,9 @@ use PhpOffice\PhpWord\Writer\Word2007\Style\Image as ImageStyleWriter; class Image extends AbstractElement { /** - * Write element + * Write element. + * + * @return void */ public function write() { @@ -47,7 +49,9 @@ class Image extends AbstractElement } /** - * Write image element + * Write image element. + * + * @return void */ private function writeImage(XMLWriter $xmlWriter, ImageElement $element) { @@ -59,26 +63,30 @@ class Image extends AbstractElement $xmlWriter->startElement('w:p'); $styleWriter->writeAlignment(); } + $xmlWriter->startElement('w:r'); $xmlWriter->startElement('w:pict'); $xmlWriter->startElement('v:shape'); $xmlWriter->writeAttribute('type', '#_x0000_t75'); + $styleWriter->write(); + $xmlWriter->startElement('v:imagedata'); $xmlWriter->writeAttribute('r:id', 'rId' . $rId); $xmlWriter->writeAttribute('o:title', ''); $xmlWriter->endElement(); // v:imagedata - $styleWriter->writeW10Wrap(); + $xmlWriter->endElement(); // v:shape $xmlWriter->endElement(); // w:pict $xmlWriter->endElement(); // w:r - if (!$this->withoutP) { - $xmlWriter->endElement(); // w:p - } + $this->endElementP(); } + /** - * Write watermark element + * Write watermark element. + * + * @return void */ private function writeWatermark(XMLWriter $xmlWriter, ImageElement $element) { @@ -92,7 +100,9 @@ class Image extends AbstractElement $xmlWriter->startElement('w:pict'); $xmlWriter->startElement('v:shape'); $xmlWriter->writeAttribute('type', '#_x0000_t75'); + $styleWriter->write(); + $xmlWriter->startElement('v:imagedata'); $xmlWriter->writeAttribute('r:id', 'rId' . $rId); $xmlWriter->writeAttribute('o:title', ''); diff --git a/src/PhpWord/Writer/Word2007/Element/Line.php b/src/PhpWord/Writer/Word2007/Element/Line.php index 1ae10694..a6c7c240 100644 --- a/src/PhpWord/Writer/Word2007/Element/Line.php +++ b/src/PhpWord/Writer/Word2007/Element/Line.php @@ -27,7 +27,9 @@ use PhpOffice\PhpWord\Writer\Word2007\Style\Line as LineStyleWriter; class Line extends AbstractElement { /** - * Write element + * Write element. + * + * @return void */ public function write() { @@ -37,16 +39,19 @@ class Line extends AbstractElement return; } - $style = $element->getStyle(); + $style = $element->getStyle(); $styleWriter = new LineStyleWriter($xmlWriter, $style); $elementId = $element->getElementIndex(); + if (!$this->withoutP) { $xmlWriter->startElement('w:p'); $styleWriter->writeAlignment(); } + $xmlWriter->startElement('w:r'); $xmlWriter->startElement('w:pict'); + // Shapetype could be defined for each line separately, but then a unique id would be necessary if ($elementId == 1) { $xmlWriter->startElement('v:shapetype'); @@ -67,18 +72,19 @@ class Line extends AbstractElement $xmlWriter->endElement(); // o:lock $xmlWriter->endElement(); // v:shapetype } + $xmlWriter->startElement('v:shape'); $xmlWriter->writeAttribute('id', sprintf('_x0000_s1%1$03d', $elementId)); $xmlWriter->writeAttribute('type', '#_x0000_t32'); //type should correspond to shapetype id + $styleWriter->write(); $styleWriter->writeStroke(); - $styleWriter->writeW10Wrap(); + $xmlWriter->endElement(); // v:shape + $xmlWriter->endElement(); // w:pict $xmlWriter->endElement(); // w:r - if (!$this->withoutP) { - $xmlWriter->endElement(); // w:p - } + $this->endElementP(); // w:p } } diff --git a/src/PhpWord/Writer/Word2007/Element/Link.php b/src/PhpWord/Writer/Word2007/Element/Link.php index ec531bac..2cb8407f 100644 --- a/src/PhpWord/Writer/Word2007/Element/Link.php +++ b/src/PhpWord/Writer/Word2007/Element/Link.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; class Link extends Text { /** - * Write link element + * Write link element. + * + * @return void */ public function write() { @@ -37,10 +39,14 @@ class Link extends Text $rId = $element->getRelationId() + ($element->isInSection() ? 6 : 0); - $this->writeOpeningWP(); + $this->startElementP(); $xmlWriter->startElement('w:hyperlink'); - $xmlWriter->writeAttribute('r:id', 'rId' . $rId); + if ($element->isInternal()) { + $xmlWriter->writeAttribute('w:anchor', $element->getSource()); + } else { + $xmlWriter->writeAttribute('r:id', 'rId' . $rId); + } $xmlWriter->writeAttribute('w:history', '1'); $xmlWriter->startElement('w:r'); @@ -53,6 +59,6 @@ class Link extends Text $xmlWriter->endElement(); // w:r $xmlWriter->endElement(); // w:hyperlink - $this->writeClosingWP(); + $this->endElementP(); // w:p } } diff --git a/src/PhpWord/Writer/Word2007/Element/ListItem.php b/src/PhpWord/Writer/Word2007/Element/ListItem.php index 7b86efae..0f559a4e 100644 --- a/src/PhpWord/Writer/Word2007/Element/ListItem.php +++ b/src/PhpWord/Writer/Word2007/Element/ListItem.php @@ -27,7 +27,9 @@ use PhpOffice\PhpWord\Writer\Word2007\Style\Paragraph as ParagraphStyleWriter; class ListItem extends AbstractElement { /** - * Write list item element + * Write list item element. + * + * @return void */ public function write() { diff --git a/src/PhpWord/Writer/Word2007/Element/ListItemRun.php b/src/PhpWord/Writer/Word2007/Element/ListItemRun.php index 747c2625..289cb054 100644 --- a/src/PhpWord/Writer/Word2007/Element/ListItemRun.php +++ b/src/PhpWord/Writer/Word2007/Element/ListItemRun.php @@ -27,7 +27,9 @@ use PhpOffice\PhpWord\Writer\Word2007\Style\Paragraph as ParagraphStyleWriter; class ListItemRun extends AbstractElement { /** - * Write list item element + * Write list item element. + * + * @return void */ public function write() { diff --git a/src/PhpWord/Writer/Word2007/Element/Object.php b/src/PhpWord/Writer/Word2007/Element/Object.php index ae03f04f..a9cc449a 100644 --- a/src/PhpWord/Writer/Word2007/Element/Object.php +++ b/src/PhpWord/Writer/Word2007/Element/Object.php @@ -27,7 +27,9 @@ use PhpOffice\PhpWord\Writer\Word2007\Style\Image as ImageStyleWriter; class Object extends AbstractElement { /** - * Write object element + * Write object element. + * + * @return void */ public function write() { @@ -41,6 +43,7 @@ class Object extends AbstractElement $rIdImage = $element->getImageRelationId() + ($element->isInSection() ? 6 : 0); $shapeId = md5($rIdObject . '_' . $rIdImage); $objectId = $element->getRelationId() + 1325353440; + $style = $element->getStyle(); $styleWriter = new ImageStyleWriter($xmlWriter, $style); @@ -48,20 +51,27 @@ class Object extends AbstractElement $xmlWriter->startElement('w:p'); $styleWriter->writeAlignment(); } + $xmlWriter->startElement('w:r'); $xmlWriter->startElement('w:object'); $xmlWriter->writeAttribute('w:dxaOrig', '249'); $xmlWriter->writeAttribute('w:dyaOrig', '160'); + + // Icon $xmlWriter->startElement('v:shape'); $xmlWriter->writeAttribute('id', $shapeId); $xmlWriter->writeAttribute('type', '#_x0000_t75'); $xmlWriter->writeAttribute('style', 'width:104px;height:67px'); $xmlWriter->writeAttribute('o:ole', ''); + $xmlWriter->startElement('v:imagedata'); $xmlWriter->writeAttribute('r:id', 'rId' . $rIdImage); $xmlWriter->writeAttribute('o:title', ''); $xmlWriter->endElement(); // v:imagedata + $xmlWriter->endElement(); // v:shape + + // Object $xmlWriter->startElement('o:OLEObject'); $xmlWriter->writeAttribute('Type', 'Embed'); $xmlWriter->writeAttribute('ProgID', 'Package'); @@ -70,10 +80,10 @@ class Object extends AbstractElement $xmlWriter->writeAttribute('ObjectID', '_' . $objectId); $xmlWriter->writeAttribute('r:id', 'rId' . $rIdObject); $xmlWriter->endElement(); // o:OLEObject + $xmlWriter->endElement(); // w:object $xmlWriter->endElement(); // w:r - if (!$this->withoutP) { - $xmlWriter->endElement(); // w:p - } + + $this->endElementP(); // w:p } } diff --git a/src/PhpWord/Writer/Word2007/Element/PageBreak.php b/src/PhpWord/Writer/Word2007/Element/PageBreak.php index 6974777a..fb831ca7 100644 --- a/src/PhpWord/Writer/Word2007/Element/PageBreak.php +++ b/src/PhpWord/Writer/Word2007/Element/PageBreak.php @@ -20,27 +20,26 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; /** * PageBreak element writer * - * Originally, page break is rendered as a `w:p`, but this turns out to produce bug #150. - * As of 0.11.0, page break is rendered as a `w:r` with `w:br` type "page" and `w:lastRenderedPageBreak` - * * @since 0.10.0 */ class PageBreak extends AbstractElement { /** - * Write element + * Write element. * - * @usedby \PhpOffice\PhpWord\Writer\Word2007\Element\Text::writeOpeningWP() + * @usedby \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement::startElementP() + * @return void */ public function write() { $xmlWriter = $this->getXmlWriter(); + $xmlWriter->startElement('w:p'); $xmlWriter->startElement('w:r'); $xmlWriter->startElement('w:br'); $xmlWriter->writeAttribute('w:type', 'page'); $xmlWriter->endElement(); // w:br - $xmlWriter->writeElement('w:lastRenderedPageBreak'); $xmlWriter->endElement(); // w:r + $xmlWriter->endElement(); // w:p } } diff --git a/src/PhpWord/Writer/Word2007/Element/PreserveText.php b/src/PhpWord/Writer/Word2007/Element/PreserveText.php index dd5d9008..894b3050 100644 --- a/src/PhpWord/Writer/Word2007/Element/PreserveText.php +++ b/src/PhpWord/Writer/Word2007/Element/PreserveText.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; class PreserveText extends Text { /** - * Write preserve text element + * Write preserve text element. + * + * @return void */ public function write() { @@ -40,7 +42,7 @@ class PreserveText extends Text $texts = array($texts); } - $this->writeOpeningWP(); + $this->startElementP(); foreach ($texts as $text) { if (substr($text, 0, 1) == '{') { @@ -86,6 +88,6 @@ class PreserveText extends Text } } - $this->writeClosingWP(); + $this->endElementP(); // w:p } } diff --git a/src/PhpWord/Writer/Word2007/Element/SDT.php b/src/PhpWord/Writer/Word2007/Element/SDT.php new file mode 100644 index 00000000..79d7004d --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/SDT.php @@ -0,0 +1,124 @@ +getXmlWriter(); + $element = $this->getElement(); + if (!$element instanceof SDTElement) { + return; + } + $type = $element->getType(); + $writeFormField = "write{$type}"; + + $this->startElementP(); + + $xmlWriter->startElement('w:sdt'); + + // Properties + $xmlWriter->startElement('w:sdtPr'); + $xmlWriter->writeElementBlock('w:id', 'w:val', rand(100000000, 999999999)); + $xmlWriter->writeElementBlock('w:lock', 'w:val', 'sdtLocked'); + $this->$writeFormField($xmlWriter, $element); + $xmlWriter->endElement(); // w:sdtPr + + // Content + $xmlWriter->startElement('w:sdtContent'); + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:t'); + $xmlWriter->writeRaw('Pick value'); + $xmlWriter->endElement(); // w:t + $xmlWriter->endElement(); // w:r + $xmlWriter->endElement(); // w:sdtContent + + $xmlWriter->endElement(); // w:sdt + + $this->endElementP(); // w:p + } + + /** + * Write combo box. + * + * @link http://www.datypic.com/sc/ooxml/t-w_CT_SdtComboBox.html + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Element\SDT $element + * @return void + */ + private function writeComboBox(XMLWriter $xmlWriter, SDTElement $element) + { + $type = $element->getType(); + $listItems = $element->getListItems(); + + $xmlWriter->startElement("w:{$type}"); + foreach ($listItems as $key => $val) { + $xmlWriter->writeElementBlock('w:listItem', array('w:value' => $key, 'w:displayText' => $val)); + } + $xmlWriter->endElement(); // w:{$type} + } + + /** + * Write drop down list. + * + * @link http://www.datypic.com/sc/ooxml/t-w_CT_SdtDropDownList.html + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Element\SDT $element + * @return void + */ + private function writeDropDownList(XMLWriter $xmlWriter, SDTElement $element) + { + $this->writecomboBox($xmlWriter, $element); + } + + /** + * Write date. + * + * @link http://www.datypic.com/sc/ooxml/t-w_CT_SdtDate.html + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Element\SDT $element + * @return void + */ + private function writeDate(XMLWriter $xmlWriter, SDTElement $element) + { + $type = $element->getType(); + + $xmlWriter->startElement("w:{$type}"); + $xmlWriter->writeElementBlock('w:dateFormat', 'w:val', 'd/M/yyyy'); + $xmlWriter->writeElementBlock('w:lid', 'w:val', 'en-US'); + $xmlWriter->writeElementBlock('w:storeMappedDataAs', 'w:val', 'dateTime'); + $xmlWriter->writeElementBlock('w:calendar', 'w:val', 'gregorian'); + $xmlWriter->endElement(); // w:date + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/Shape.php b/src/PhpWord/Writer/Word2007/Element/Shape.php new file mode 100644 index 00000000..bd9320a2 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/Shape.php @@ -0,0 +1,175 @@ +getXmlWriter(); + $element = $this->getElement(); + if (!$element instanceof ShapeElement) { + return; + } + + $style = $element->getStyle(); + $styleWriter = new ShapeStyleWriter($xmlWriter, $style); + + $type = $element->getType(); + if ($type == 'rect' && $style->getRoundness() !== null) { + $type = 'roundrect'; + } + $method = "write{$type}"; + + if (!$this->withoutP) { + $xmlWriter->startElement('w:p'); + } + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:pict'); + $xmlWriter->startElement("v:{$type}"); + + // Element style + if (method_exists($this, $method)) { + $this->$method($xmlWriter, $style); + } + + // Child style + $styleWriter->write(); + + $xmlWriter->endElement(); // v:$type + $xmlWriter->endElement(); // w:pict + $xmlWriter->endElement(); // w:r + + $this->endElementP(); // w:p + } + + /** + * Write arc. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Style\Shape $style + * @return void + */ + private function writeArc(XMLWriter $xmlWriter, ShapeStyle $style) + { + $points = $this->getPoints('arc', $style->getPoints()); + + $xmlWriter->writeAttributeIf($points['start'] !== null, 'startAngle', $points['start']); + $xmlWriter->writeAttributeIf($points['end'] !== null, 'endAngle', $points['end']); + } + + /** + * Write curve. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Style\Shape $style + * @return void + */ + private function writeCurve(XMLWriter $xmlWriter, ShapeStyle $style) + { + $points = $this->getPoints('curve', $style->getPoints()); + + $this->writeLine($xmlWriter, $style); + $xmlWriter->writeAttributeIf($points['point1'] !== null, 'control1', $points['point1']); + $xmlWriter->writeAttributeIf($points['point2'] !== null, 'control2', $points['point2']); + } + + /** + * Write line. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Style\Shape $style + * @return void + */ + private function writeLine(XMLWriter $xmlWriter, ShapeStyle $style) + { + $points = $this->getPoints('line', $style->getPoints()); + + $xmlWriter->writeAttributeIf($points['start'] !== null, 'from', $points['start']); + $xmlWriter->writeAttributeIf($points['end'] !== null, 'to', $points['end']); + } + + /** + * Write polyline. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Style\Shape $style + * @return void + */ + private function writePolyline(XMLWriter $xmlWriter, ShapeStyle $style) + { + $xmlWriter->writeAttributeIf($style->getPoints() !== null, 'points', $style->getPoints()); + } + + /** + * Write rectangle. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Style\Shape $style + * @return void + */ + private function writeRoundRect(XMLWriter $xmlWriter, ShapeStyle $style) + { + $xmlWriter->writeAttribute('arcsize', $style->getRoundness()); + } + + /** + * Set points + * + * @param string $type + * @param string $value + * @return array + */ + private function getPoints($type, $value) + { + $points = array(); + + switch ($type) { + case 'arc': + case 'line': + $points = explode(' ', $value); + @list($start, $end) = $points; + $points = array('start' => $start, 'end' => $end); + break; + case 'curve': + $points = explode(' ', $value); + @list($start, $end, $point1, $point2) = $points; + $points = array('start' => $start, 'end' => $end, 'point1' => $point1, 'point2' => $point2); + break; + } + + return $points; + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/TOC.php b/src/PhpWord/Writer/Word2007/Element/TOC.php index 1db2efdd..db2a65d0 100644 --- a/src/PhpWord/Writer/Word2007/Element/TOC.php +++ b/src/PhpWord/Writer/Word2007/Element/TOC.php @@ -32,7 +32,9 @@ use PhpOffice\PhpWord\Writer\Word2007\Style\Tab as TabStyleWriter; class TOC extends AbstractElement { /** - * Write element + * Write element. + * + * @return void */ public function write() { @@ -68,6 +70,7 @@ class TOC extends AbstractElement * @param \PhpOffice\PhpWord\Element\TOC $element * @param \PhpOffice\PhpWord\Element\Title $title * @param bool $writeFieldMark + * @return void */ private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, $title, $writeFieldMark) { @@ -135,6 +138,7 @@ class TOC extends AbstractElement * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param \PhpOffice\PhpWord\Element\TOC $element * @param int $indent + * @return void */ private function writeStyle(XMLWriter $xmlWriter, TOCElement $element, $indent) { @@ -176,7 +180,11 @@ class TOC extends AbstractElement } /** - * Write TOC Field + * Write TOC Field. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Element\TOC $element + * @return void */ private function writeFieldMark(XMLWriter $xmlWriter, TOCElement $element) { diff --git a/src/PhpWord/Writer/Word2007/Element/Table.php b/src/PhpWord/Writer/Word2007/Element/Table.php index 8cadfc38..f090d05c 100644 --- a/src/PhpWord/Writer/Word2007/Element/Table.php +++ b/src/PhpWord/Writer/Word2007/Element/Table.php @@ -35,7 +35,9 @@ use PhpOffice\PhpWord\Writer\Word2007\Style\Table as TableStyleWriter; class Table extends AbstractElement { /** - * Write element + * Write element. + * + * @return void */ public function write() { @@ -69,7 +71,11 @@ class Table extends AbstractElement } /** - * Write column + * Write column. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Element\Table $element + * @return void */ private function writeColumns(XMLWriter $xmlWriter, TableElement $element) { @@ -102,7 +108,11 @@ class Table extends AbstractElement } /** - * Write row + * Write row. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Element\Row $row + * @return void */ private function writeRow(XMLWriter $xmlWriter, RowElement $row) { @@ -125,7 +135,11 @@ class Table extends AbstractElement } /** - * Write cell + * Write cell. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Element\Cell $cell + * @return void */ private function writeCell(XMLWriter $xmlWriter, CellElement $cell) { diff --git a/src/PhpWord/Writer/Word2007/Element/Text.php b/src/PhpWord/Writer/Word2007/Element/Text.php index 64c4b766..cfb991c2 100644 --- a/src/PhpWord/Writer/Word2007/Element/Text.php +++ b/src/PhpWord/Writer/Word2007/Element/Text.php @@ -17,10 +17,6 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; -use PhpOffice\PhpWord\Element\PageBreak as PageBreakElement; -use PhpOffice\PhpWord\Writer\Word2007\Style\Font as FontStyleWriter; -use PhpOffice\PhpWord\Writer\Word2007\Style\Paragraph as ParagraphStyleWriter; - /** * Text element writer * @@ -29,7 +25,9 @@ use PhpOffice\PhpWord\Writer\Word2007\Style\Paragraph as ParagraphStyleWriter; class Text extends AbstractElement { /** - * Write text element + * Write text element. + * + * @return void */ public function write() { @@ -39,7 +37,7 @@ class Text extends AbstractElement return; } - $this->writeOpeningWP(); + $this->startElementP(); $xmlWriter->startElement('w:r'); @@ -51,72 +49,6 @@ class Text extends AbstractElement $xmlWriter->endElement(); $xmlWriter->endElement(); // w:r - $this->writeClosingWP(); - } - - /** - * Write opening - * - * @uses \PhpOffice\PhpWord\Writer\Word2007\Element\PageBreak::write() - */ - protected function writeOpeningWP() - { - $xmlWriter = $this->getXmlWriter(); - $element = $this->getElement(); - - if (!$this->withoutP) { - $xmlWriter->startElement('w:p'); - // Paragraph style - if (method_exists($element, 'getParagraphStyle')) { - $this->writeParagraphStyle(); - } - // PageBreak - if ($this->hasPageBreakBefore()) { - $elementWriter = new PageBreak($xmlWriter, new PageBreakElement()); - $elementWriter->write(); - } - } - } - - /** - * Write ending - */ - protected function writeClosingWP() - { - $xmlWriter = $this->getXmlWriter(); - - if (!$this->withoutP) { - $xmlWriter->endElement(); // w:p - } - } - - /** - * Write ending - */ - protected function writeParagraphStyle() - { - $xmlWriter = $this->getXmlWriter(); - - /** @var \PhpOffice\PhpWord\Element\Text $element Type hint */ - $element = $this->getElement(); - $paragraphStyle = $element->getParagraphStyle(); - $styleWriter = new ParagraphStyleWriter($xmlWriter, $paragraphStyle); - $styleWriter->setIsInline(true); - $styleWriter->write(); - } - - /** - * Write ending - */ - protected function writeFontStyle() - { - $xmlWriter = $this->getXmlWriter(); - - /** @var \PhpOffice\PhpWord\Element\Text $element Type hint */ - $element = $this->getElement(); - $fontStyle = $element->getFontStyle(); - $styleWriter = new FontStyleWriter($xmlWriter, $fontStyle); - $styleWriter->setIsInline(true); - $styleWriter->write(); + $this->endElementP(); // w:p } } diff --git a/src/PhpWord/Writer/Word2007/Element/TextBox.php b/src/PhpWord/Writer/Word2007/Element/TextBox.php index 4ee5e68e..fe62c644 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Element/TextBox.php @@ -24,10 +24,12 @@ use PhpOffice\PhpWord\Writer\Word2007\Style\TextBox as TextBoxStyleWriter; * * @since 0.11.0 */ -class TextBox extends AbstractElement +class TextBox extends Image { /** - * Write element + * Write element. + * + * @return void */ public function write() { @@ -48,7 +50,10 @@ class TextBox extends AbstractElement $xmlWriter->startElement('w:pict'); $xmlWriter->startElement('v:shape'); $xmlWriter->writeAttribute('type', '#_x0000_t0202'); + $styleWriter->write(); + $styleWriter->writeBorder(); + $xmlWriter->startElement('v:textbox'); $styleWriter->writeInnerMargin(); @@ -59,13 +64,11 @@ class TextBox extends AbstractElement $xmlWriter->endElement(); // w:txbxContent $xmlWriter->endElement(); // v: textbox - $styleWriter->writeW10Wrap(); + $xmlWriter->endElement(); // v:shape $xmlWriter->endElement(); // w:pict $xmlWriter->endElement(); // w:r - if (!$this->withoutP) { - $xmlWriter->endElement(); // w:p - } + $this->endElementP(); } } diff --git a/src/PhpWord/Writer/Word2007/Element/TextBreak.php b/src/PhpWord/Writer/Word2007/Element/TextBreak.php index 5f4bd3ce..fb52b86e 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextBreak.php +++ b/src/PhpWord/Writer/Word2007/Element/TextBreak.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; class TextBreak extends Text { /** - * Write text break element + * Write text break element. + * + * @return void */ public function write() { @@ -37,13 +39,15 @@ class TextBreak extends Text if (!$this->withoutP) { $hasStyle = $element->hasStyle(); - $this->writeOpeningWP(); + $this->startElementP(); + if ($hasStyle) { $xmlWriter->startElement('w:pPr'); $this->writeFontStyle(); $xmlWriter->endElement(); // w:pPr } - $this->writeClosingWP(); + + $this->endElementP(); // w:p } else { $xmlWriter->writeElement('w:br'); } diff --git a/src/PhpWord/Writer/Word2007/Element/TextRun.php b/src/PhpWord/Writer/Word2007/Element/TextRun.php index 330e297c..844e0b6b 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextRun.php +++ b/src/PhpWord/Writer/Word2007/Element/TextRun.php @@ -25,18 +25,20 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; class TextRun extends Text { /** - * Write textrun element + * Write textrun element. + * + * @return void */ public function write() { $xmlWriter = $this->getXmlWriter(); $element = $this->getElement(); - $this->writeOpeningWP(); + $this->startElementP(); $containerWriter = new Container($xmlWriter, $element); $containerWriter->write(); - $this->writeClosingWP(); + $this->endElementP(); // w:p } } diff --git a/src/PhpWord/Writer/Word2007/Element/Title.php b/src/PhpWord/Writer/Word2007/Element/Title.php index 144e67ab..ce9aeea5 100644 --- a/src/PhpWord/Writer/Word2007/Element/Title.php +++ b/src/PhpWord/Writer/Word2007/Element/Title.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; class Title extends AbstractElement { /** - * Write title element + * Write title element. + * + * @return void */ public function write() { @@ -48,10 +50,11 @@ class Title extends AbstractElement } $rId = $element->getRelationId(); + $bookmarkRId = $element->getPhpWord()->addBookmark(); // Bookmark start for TOC $xmlWriter->startElement('w:bookmarkStart'); - $xmlWriter->writeAttribute('w:id', $rId); + $xmlWriter->writeAttribute('w:id', $bookmarkRId); $xmlWriter->writeAttribute('w:name', "_Toc{$rId}"); $xmlWriter->endElement(); @@ -64,7 +67,7 @@ class Title extends AbstractElement // Bookmark end $xmlWriter->startElement('w:bookmarkEnd'); - $xmlWriter->writeAttribute('w:id', $rId); + $xmlWriter->writeAttribute('w:id', $bookmarkRId); $xmlWriter->endElement(); $xmlWriter->endElement(); diff --git a/src/PhpWord/Writer/Word2007/Part/AbstractPart.php b/src/PhpWord/Writer/Word2007/Part/AbstractPart.php index 610a7616..e26853d7 100644 --- a/src/PhpWord/Writer/Word2007/Part/AbstractPart.php +++ b/src/PhpWord/Writer/Word2007/Part/AbstractPart.php @@ -46,9 +46,10 @@ abstract class AbstractPart abstract public function write(); /** - * Set parent writer + * Set parent writer. * * @param \PhpOffice\PhpWord\Writer\AbstractWriter $writer + * @return void */ public function setParentWriter(AbstractWriter $writer = null) { diff --git a/src/PhpWord/Writer/Word2007/Part/Chart.php b/src/PhpWord/Writer/Word2007/Part/Chart.php new file mode 100644 index 00000000..8423762c --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -0,0 +1,320 @@ + array('type' => 'pie', 'colors' => 1), + 'doughnut' => array('type' => 'doughnut', 'colors' => 1, 'hole' => 75, 'no3d' => true), + 'bar' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'bar'), + 'column' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'col'), + 'line' => array('type' => 'line', 'colors' => 0, 'axes' => true), + 'area' => array('type' => 'area', 'colors' => 0, 'axes' => true), + 'radar' => array('type' => 'radar', 'colors' => 0, 'axes' => true, 'radar' => 'standard', 'no3d' => true), + 'scatter' => array('type' => 'scatter', 'colors' => 0, 'axes' => true, 'scatter' => 'marker', 'no3d' => true), + ); + + /** + * Chart options + * + * @var array + */ + private $options = array(); + + /** + * Set chart element. + * + * @param \PhpOffice\PhpWord\Element\Chart $element + * @return void + */ + public function setElement(ChartElement $element) + { + $this->element = $element; + } + + /** + * Write part + * + * @return string + */ + public function write() + { + $xmlWriter = $this->getXmlWriter(); + + $xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); + $xmlWriter->startElement('c:chartSpace'); + $xmlWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); + $xmlWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); + $xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + + $this->writeChart($xmlWriter); + $this->writeShape($xmlWriter); + + $xmlWriter->endElement(); // c:chartSpace + + return $xmlWriter->getData(); + } + + /** + * Write chart + * + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_Chart.html + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @return void + */ + private function writeChart(XMLWriter $xmlWriter) + { + $xmlWriter->startElement('c:chart'); + + $xmlWriter->writeElementBlock('c:autoTitleDeleted', 'val', 1); + + $this->writePlotArea($xmlWriter); + + $xmlWriter->endElement(); // c:chart + } + + /** + * Write plot area. + * + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_PlotArea.html + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_PieChart.html + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_DoughnutChart.html + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_BarChart.html + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_LineChart.html + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_AreaChart.html + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_RadarChart.html + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_ScatterChart.html + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @return void + */ + private function writePlotArea(XMLWriter $xmlWriter) + { + $type = $this->element->getType(); + $style = $this->element->getStyle(); + $this->options = $this->types[$type]; + + $xmlWriter->startElement('c:plotArea'); + $xmlWriter->writeElement('c:layout'); + + // Chart + $chartType = $this->options['type']; + $chartType .= $style->is3d() && !isset($this->options['no3d'])? '3D' : ''; + $chartType .= 'Chart'; + $xmlWriter->startElement("c:{$chartType}"); + + $xmlWriter->writeElementBlock('c:varyColors', 'val', $this->options['colors']); + if ($type == 'area') { + $xmlWriter->writeElementBlock('c:grouping', 'val', 'standard'); + } + if (isset($this->options['hole'])) { + $xmlWriter->writeElementBlock('c:holeSize', 'val', $this->options['hole']); + } + if (isset($this->options['bar'])) { + $xmlWriter->writeElementBlock('c:barDir', 'val', $this->options['bar']); // bar|col + $xmlWriter->writeElementBlock('c:grouping', 'val', 'clustered'); // 3d; standard = percentStacked + } + if (isset($this->options['radar'])) { + $xmlWriter->writeElementBlock('c:radarStyle', 'val', $this->options['radar']); + } + if (isset($this->options['scatter'])) { + $xmlWriter->writeElementBlock('c:scatterStyle', 'val', $this->options['scatter']); + } + + // Series + $this->writeSeries($xmlWriter, isset($this->options['scatter'])); + + // Axes + if (isset($this->options['axes'])) { + $xmlWriter->writeElementBlock('c:axId', 'val', 1); + $xmlWriter->writeElementBlock('c:axId', 'val', 2); + } + + $xmlWriter->endElement(); // chart type + + // Axes + if (isset($this->options['axes'])) { + $this->writeAxis($xmlWriter, 'cat'); + $this->writeAxis($xmlWriter, 'val'); + } + + $xmlWriter->endElement(); // c:plotArea + } + + /** + * Write series. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param bool $scatter + * @return void + */ + private function writeSeries(XMLWriter $xmlWriter, $scatter = false) + { + $series = $this->element->getSeries(); + + $index = 0; + foreach ($series as $seriesItem) { + $categories = $seriesItem['categories']; + $values = $seriesItem['values']; + + $xmlWriter->startElement('c:ser'); + + $xmlWriter->writeElementBlock('c:idx', 'val', $index); + $xmlWriter->writeElementBlock('c:order', 'val', $index); + + if (isset($this->options['scatter'])) { + $this->writeShape($xmlWriter); + } + + if ($scatter === true) { + $this->writeSeriesItem($xmlWriter, 'xVal', $categories); + $this->writeSeriesItem($xmlWriter, 'yVal', $values); + } else { + $this->writeSeriesItem($xmlWriter, 'cat', $categories); + $this->writeSeriesItem($xmlWriter, 'val', $values); + } + + $xmlWriter->endElement(); // c:ser + $index++; + } + + } + + /** + * Write series items. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param string $type + * @param array $values + * @return void + */ + private function writeSeriesItem(XMLWriter $xmlWriter, $type, $values) + { + $types = array( + 'cat' => array('c:cat', 'c:strLit'), + 'val' => array('c:val', 'c:numLit'), + 'xVal' => array('c:xVal', 'c:strLit'), + 'yVal' => array('c:yVal', 'c:numLit'), + ); + list($itemType, $itemLit) = $types[$type]; + + $xmlWriter->startElement($itemType); + $xmlWriter->startElement($itemLit); + + $index = 0; + foreach ($values as $value) { + $xmlWriter->startElement('c:pt'); + $xmlWriter->writeAttribute('idx', $index); + + $xmlWriter->startElement('c:v'); + $xmlWriter->writeRaw($value); + $xmlWriter->endElement(); // c:v + + $xmlWriter->endElement(); // c:pt + $index++; + } + + $xmlWriter->endElement(); // $itemLit + $xmlWriter->endElement(); // $itemType + } + + /** + * Write axis + * + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_CatAx.html + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param string $type + * @return void + */ + private function writeAxis(XMLWriter $xmlWriter, $type) + { + $types = array( + 'cat' => array('c:catAx', 1, 'b', 2), + 'val' => array('c:valAx', 2, 'l', 1), + ); + list($axisType, $axisId, $axisPos, $axisCross) = $types[$type]; + + $xmlWriter->startElement($axisType); + + $xmlWriter->writeElementBlock('c:axId', 'val', $axisId); + $xmlWriter->writeElementBlock('c:axPos', 'val', $axisPos); + $xmlWriter->writeElementBlock('c:crossAx', 'val', $axisCross); + $xmlWriter->writeElementBlock('c:auto', 'val', 1); + + if (isset($this->options['axes'])) { + $xmlWriter->writeElementBlock('c:delete', 'val', 0); + $xmlWriter->writeElementBlock('c:majorTickMark', 'val', 'none'); + $xmlWriter->writeElementBlock('c:minorTickMark', 'val', 'none'); + $xmlWriter->writeElementBlock('c:tickLblPos', 'val', 'none'); // nextTo + $xmlWriter->writeElementBlock('c:crosses', 'val', 'autoZero'); + } + if (isset($this->options['radar'])) { + $xmlWriter->writeElement('c:majorGridlines'); + } + + $xmlWriter->startElement('c:scaling'); + $xmlWriter->writeElementBlock('c:orientation', 'val', 'minMax'); + $xmlWriter->endElement(); // c:scaling + + $this->writeShape($xmlWriter, true); + + $xmlWriter->endElement(); // $axisType + } + + /** + * Write shape + * + * @link http://www.datypic.com/sc/ooxml/t-a_CT_ShapeProperties.html + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param bool $line + * @return void + */ + private function writeShape(XMLWriter $xmlWriter, $line = false) + { + $xmlWriter->startElement('c:spPr'); + $xmlWriter->startElement('a:ln'); + if ($line === true) { + $xmlWriter->writeElement('a:solidFill'); + } else { + $xmlWriter->writeElement('a:noFill'); + } + $xmlWriter->endElement(); // a:ln + $xmlWriter->endElement(); // c:spPr + } +} diff --git a/src/PhpWord/Writer/Word2007/Part/ContentTypes.php b/src/PhpWord/Writer/Word2007/Part/ContentTypes.php index b6f23f47..6ae4e875 100644 --- a/src/PhpWord/Writer/Word2007/Part/ContentTypes.php +++ b/src/PhpWord/Writer/Word2007/Part/ContentTypes.php @@ -37,6 +37,7 @@ class ContentTypes extends AbstractPart $openXMLPrefix = 'application/vnd.openxmlformats-'; $wordMLPrefix = $openXMLPrefix . 'officedocument.wordprocessingml.'; + $drawingMLPrefix = $openXMLPrefix . 'officedocument.drawingml.'; $overrides = array( '/docProps/core.xml' => $openXMLPrefix . 'package.core-properties+xml', '/docProps/app.xml' => $openXMLPrefix . 'officedocument.extended-properties+xml', @@ -53,7 +54,11 @@ class ContentTypes extends AbstractPart $defaults = $contentTypes['default']; if (!empty($contentTypes['override'])) { foreach ($contentTypes['override'] as $key => $val) { - $overrides[$key] = $wordMLPrefix . $val . '+xml'; + if ($val == 'chart') { + $overrides[$key] = $drawingMLPrefix . $val . '+xml'; + } else { + $overrides[$key] = $wordMLPrefix . $val . '+xml'; + } } } @@ -77,6 +82,7 @@ class ContentTypes extends AbstractPart * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter XML Writer * @param array $parts * @param boolean $isDefault + * @return void */ private function writeContentType(XMLWriter $xmlWriter, $parts, $isDefault) { diff --git a/src/PhpWord/Writer/Word2007/Part/DocPropsApp.php b/src/PhpWord/Writer/Word2007/Part/DocPropsApp.php index 1e6549c5..421ceefe 100644 --- a/src/PhpWord/Writer/Word2007/Part/DocPropsApp.php +++ b/src/PhpWord/Writer/Word2007/Part/DocPropsApp.php @@ -41,8 +41,8 @@ class DocPropsApp extends AbstractPart $xmlWriter->writeAttribute('xmlns:vt', 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); $xmlWriter->writeElement('Application', 'PHPWord'); - $xmlWriter->writeElement('Company', $phpWord->getDocumentProperties()->getCompany()); - $xmlWriter->writeElement('Manager', $phpWord->getDocumentProperties()->getManager()); + $xmlWriter->writeElement('Company', $phpWord->getDocInfo()->getCompany()); + $xmlWriter->writeElement('Manager', $phpWord->getDocInfo()->getManager()); $xmlWriter->endElement(); // Properties diff --git a/src/PhpWord/Writer/Word2007/Part/DocPropsCore.php b/src/PhpWord/Writer/Word2007/Part/DocPropsCore.php index 38f6d235..252be01f 100644 --- a/src/PhpWord/Writer/Word2007/Part/DocPropsCore.php +++ b/src/PhpWord/Writer/Word2007/Part/DocPropsCore.php @@ -43,24 +43,24 @@ class DocPropsCore extends AbstractPart $xmlWriter->writeAttribute('xmlns:dcmitype', 'http://purl.org/dc/dcmitype/'); $xmlWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); - $xmlWriter->writeElement('dc:creator', $phpWord->getDocumentProperties()->getCreator()); - $xmlWriter->writeElement('dc:title', $phpWord->getDocumentProperties()->getTitle()); - $xmlWriter->writeElement('dc:description', $phpWord->getDocumentProperties()->getDescription()); - $xmlWriter->writeElement('dc:subject', $phpWord->getDocumentProperties()->getSubject()); - $xmlWriter->writeElement('cp:keywords', $phpWord->getDocumentProperties()->getKeywords()); - $xmlWriter->writeElement('cp:category', $phpWord->getDocumentProperties()->getCategory()); - $xmlWriter->writeElement('cp:lastModifiedBy', $phpWord->getDocumentProperties()->getLastModifiedBy()); + $xmlWriter->writeElement('dc:creator', $phpWord->getDocInfo()->getCreator()); + $xmlWriter->writeElement('dc:title', $phpWord->getDocInfo()->getTitle()); + $xmlWriter->writeElement('dc:description', $phpWord->getDocInfo()->getDescription()); + $xmlWriter->writeElement('dc:subject', $phpWord->getDocInfo()->getSubject()); + $xmlWriter->writeElement('cp:keywords', $phpWord->getDocInfo()->getKeywords()); + $xmlWriter->writeElement('cp:category', $phpWord->getDocInfo()->getCategory()); + $xmlWriter->writeElement('cp:lastModifiedBy', $phpWord->getDocInfo()->getLastModifiedBy()); // dcterms:created $xmlWriter->startElement('dcterms:created'); $xmlWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF'); - $xmlWriter->writeRaw(date($this->dateFormat, $phpWord->getDocumentProperties()->getCreated())); + $xmlWriter->writeRaw(date($this->dateFormat, $phpWord->getDocInfo()->getCreated())); $xmlWriter->endElement(); // dcterms:modified $xmlWriter->startElement('dcterms:modified'); $xmlWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF'); - $xmlWriter->writeRaw(date($this->dateFormat, $phpWord->getDocumentProperties()->getModified())); + $xmlWriter->writeRaw(date($this->dateFormat, $phpWord->getDocInfo()->getModified())); $xmlWriter->endElement(); $xmlWriter->endElement(); // cp:coreProperties diff --git a/src/PhpWord/Writer/Word2007/Part/DocPropsCustom.php b/src/PhpWord/Writer/Word2007/Part/DocPropsCustom.php index c5a3cf9e..ba6547d9 100644 --- a/src/PhpWord/Writer/Word2007/Part/DocPropsCustom.php +++ b/src/PhpWord/Writer/Word2007/Part/DocPropsCustom.php @@ -39,7 +39,7 @@ class DocPropsCustom extends AbstractPart $xmlWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/officeDocument/2006/custom-properties'); $xmlWriter->writeAttribute('xmlns:vt', 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); - $docProps = $phpWord->getDocumentProperties(); + $docProps = $phpWord->getDocInfo(); $properties = $docProps->getCustomProperties(); foreach ($properties as $key => $property) { $propertyValue = $docProps->getCustomPropertyValue($property); diff --git a/src/PhpWord/Writer/Word2007/Part/Document.php b/src/PhpWord/Writer/Word2007/Part/Document.php index 99570338..ea607f09 100644 --- a/src/PhpWord/Writer/Word2007/Part/Document.php +++ b/src/PhpWord/Writer/Word2007/Part/Document.php @@ -79,10 +79,11 @@ class Document extends AbstractPart } /** - * Write begin section + * Write begin section. * * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param \PhpOffice\PhpWord\Element\Section $section + * @return void */ private function writeSection(XMLWriter $xmlWriter, Section $section) { @@ -94,10 +95,11 @@ class Document extends AbstractPart } /** - * Write end section + * Write end section. * * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param \PhpOffice\PhpWord\Element\Section $section + * @return void */ private function writeSectionSettings(XMLWriter $xmlWriter, Section $section) { @@ -128,7 +130,7 @@ class Document extends AbstractPart } // Section settings - $styleWriter = new SectionStyleWriter($xmlWriter, $section->getSettings()); + $styleWriter = new SectionStyleWriter($xmlWriter, $section->getStyle()); $styleWriter->write(); $xmlWriter->endElement(); // w:sectPr diff --git a/src/PhpWord/Writer/Word2007/Part/FontTable.php b/src/PhpWord/Writer/Word2007/Part/FontTable.php index 49a47e7d..314cf586 100644 --- a/src/PhpWord/Writer/Word2007/Part/FontTable.php +++ b/src/PhpWord/Writer/Word2007/Part/FontTable.php @@ -26,7 +26,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Part; class FontTable extends AbstractPart { /** - * Write fontTable.xml + * Write fontTable.xml. + * + * @return string */ public function write() { diff --git a/src/PhpWord/Writer/Word2007/Part/Footnotes.php b/src/PhpWord/Writer/Word2007/Part/Footnotes.php index 903e5fe5..9ceefd82 100644 --- a/src/PhpWord/Writer/Word2007/Part/Footnotes.php +++ b/src/PhpWord/Writer/Word2007/Part/Footnotes.php @@ -133,10 +133,11 @@ class Footnotes extends AbstractPart } /** - * Write note item + * Write note item. * * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param \PhpOffice\PhpWord\Element\Footnote|\PhpOffice\PhpWord\Element\Endnote $element + * @return void */ protected function writeNote(XMLWriter $xmlWriter, $element) { diff --git a/src/PhpWord/Writer/Word2007/Part/Numbering.php b/src/PhpWord/Writer/Word2007/Part/Numbering.php index 8f735dd3..bbb8eeb4 100644 --- a/src/PhpWord/Writer/Word2007/Part/Numbering.php +++ b/src/PhpWord/Writer/Word2007/Part/Numbering.php @@ -18,9 +18,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Part; use PhpOffice\PhpWord\Shared\XMLWriter; -use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Style\Numbering as NumberingStyle; use PhpOffice\PhpWord\Style\NumberingLevel; +use PhpOffice\PhpWord\Style; /** * Word2007 numbering part writer: word/numbering.xml @@ -95,7 +95,11 @@ class Numbering extends AbstractPart } /** - * Write level + * Write level. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Style\NumberingLevel $level + * @return void */ private function writeLevel(XMLWriter $xmlWriter, NumberingLevel $level) { @@ -129,9 +133,13 @@ class Numbering extends AbstractPart } /** - * Write level paragraph + * Write level paragraph. * * @since 0.11.0 + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Style\NumberingLevel $level + * @return void * @todo Use paragraph style writer */ private function writeParagraph(XMLWriter $xmlWriter, NumberingLevel $level) @@ -158,9 +166,13 @@ class Numbering extends AbstractPart } /** - * Write level font + * Write level font. * * @since 0.11.0 + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Style\NumberingLevel $level + * @return void * @todo Use font style writer */ private function writeFont(XMLWriter $xmlWriter, NumberingLevel $level) diff --git a/src/PhpWord/Writer/Word2007/Part/Rels.php b/src/PhpWord/Writer/Word2007/Part/Rels.php index 562deb35..9a7f444b 100644 --- a/src/PhpWord/Writer/Word2007/Part/Rels.php +++ b/src/PhpWord/Writer/Word2007/Part/Rels.php @@ -47,12 +47,13 @@ class Rels extends AbstractPart } /** - * Write relationships + * Write relationships. * * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param array $xmlRels * @param array $mediaRels * @param int $relId + * @return void */ protected function writeRels(XMLWriter $xmlWriter, $xmlRels = array(), $mediaRels = array(), $relId = 1) { @@ -74,11 +75,12 @@ class Rels extends AbstractPart } /** - * Write media relationships + * Write media relationships. * * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param int $relId * @param array $mediaRel + * @return void */ private function writeMediaRel(XMLWriter $xmlWriter, $relId, $mediaRel) { @@ -87,8 +89,8 @@ class Rels extends AbstractPart $targetMapping = array('image' => 'media/', 'object' => 'embeddings/'); $mediaType = $mediaRel['type']; - $type = array_key_exists($mediaType, $typeMapping) ? $typeMapping[$mediaType] : $mediaType; - $targetPrefix = array_key_exists($mediaType, $targetMapping) ? $targetMapping[$mediaType] : ''; + $type = isset($typeMapping[$mediaType]) ? $typeMapping[$mediaType] : $mediaType; + $targetPrefix = isset($targetMapping[$mediaType]) ? $targetMapping[$mediaType] : ''; $target = $mediaRel['target']; $targetMode = ($type == 'hyperlink') ? 'External' : ''; @@ -96,7 +98,7 @@ class Rels extends AbstractPart } /** - * Write individual rels entry + * Write individual rels entry. * * Format: * @@ -106,6 +108,7 @@ class Rels extends AbstractPart * @param string $type Relationship type * @param string $target Relationship target * @param string $targetMode Relationship target mode + * @return void * @throws \PhpOffice\PhpWord\Exception\Exception */ private function writeRel(XMLWriter $xmlWriter, $relId, $type, $target, $targetMode = '') diff --git a/src/PhpWord/Writer/Word2007/Part/Settings.php b/src/PhpWord/Writer/Word2007/Part/Settings.php index 784a5d1e..50399c4a 100644 --- a/src/PhpWord/Writer/Word2007/Part/Settings.php +++ b/src/PhpWord/Writer/Word2007/Part/Settings.php @@ -24,6 +24,13 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Part; */ class Settings extends AbstractPart { + /** + * Settings value + * + * @var array + */ + private $settings = array(); + /** * Write part * @@ -31,68 +38,7 @@ class Settings extends AbstractPart */ public function write() { - $settings = array( - 'w:zoom' => array('@attributes' => array('w:percent' => '100')), - 'w:embedSystemFonts' => '', - 'w:defaultTabStop' => array('@attributes' => array('w:val' => '708')), - 'w:hyphenationZone' => array('@attributes' => array('w:val' => '425')), - 'w:doNotHyphenateCaps' => '', - 'w:characterSpacingControl' => array('@attributes' => array('w:val' => 'doNotCompress')), - 'w:doNotValidateAgainstSchema' => '', - 'w:doNotDemarcateInvalidXml' => '', - 'w:compat' => array( - 'w:useNormalStyleForList' => '', - 'w:doNotUseIndentAsNumberingTabStop' => '', - 'w:useAltKinsokuLineBreakRules' => '', - 'w:allowSpaceOfSameStyleInTable' => '', - 'w:doNotSuppressIndentation' => '', - 'w:doNotAutofitConstrainedTables' => '', - 'w:autofitToFirstFixedWidthCell' => '', - 'w:underlineTabInNumList' => '', - 'w:displayHangulFixedWidth' => '', - 'w:splitPgBreakAndParaMark' => '', - 'w:doNotVertAlignCellWithSp' => '', - 'w:doNotBreakConstrainedForcedTable' => '', - 'w:doNotVertAlignInTxbx' => '', - 'w:useAnsiKerningPairs' => '', - 'w:cachedColBalance' => '', - ), - 'm:mathPr' => array( - 'm:mathFont' => array('@attributes' => array('m:val' => 'Cambria Math')), - 'm:brkBin' => array('@attributes' => array('m:val' => 'before')), - 'm:brkBinSub' => array('@attributes' => array('m:val' => '--')), - 'm:smallFrac' => array('@attributes' => array('m:val' => 'off')), - 'm:dispDef' => '', - 'm:lMargin' => array('@attributes' => array('m:val' => '0')), - 'm:rMargin' => array('@attributes' => array('m:val' => '0')), - 'm:defJc' => array('@attributes' => array('m:val' => 'centerGroup')), - 'm:wrapIndent' => array('@attributes' => array('m:val' => '1440')), - 'm:intLim' => array('@attributes' => array('m:val' => 'subSup')), - 'm:naryLim' => array('@attributes' => array('m:val' => 'undOvr')), - ), - 'w:uiCompat97To2003' => '', - 'w:themeFontLang' => array('@attributes' => array('w:val' => 'de-DE')), - 'w:clrSchemeMapping' => array( - '@attributes' => array( - 'w:bg1' => 'light1', - 'w:t1' => 'dark1', - 'w:bg2' => 'light2', - 'w:t2' => 'dark2', - 'w:accent1' => 'accent1', - 'w:accent2' => 'accent2', - 'w:accent3' => 'accent3', - 'w:accent4' => 'accent4', - 'w:accent5' => 'accent5', - 'w:accent6' => 'accent6', - 'w:hyperlink' => 'hyperlink', - 'w:followedHyperlink' => 'followedHyperlink', - ), - ), - 'w:doNotIncludeSubdocsInStats' => '', - 'w:doNotAutoCompressPictures' => '', - 'w:decimalSymbol' => array('@attributes' => array('w:val' => ',')), - 'w:listSeparator' => array('@attributes' => array('w:val' => ';')), - ); + $this->getSettings(); $xmlWriter = $this->getXmlWriter(); @@ -106,7 +52,7 @@ class Settings extends AbstractPart $xmlWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml'); $xmlWriter->writeAttribute('xmlns:w10', 'urn:schemas-microsoft-com:office:word'); - foreach ($settings as $settingKey => $settingValue) { + foreach ($this->settings as $settingKey => $settingValue) { $this->writeSetting($xmlWriter, $settingKey, $settingValue); } @@ -116,11 +62,12 @@ class Settings extends AbstractPart } /** - * Write indivual setting, recursive to any child settings + * Write indivual setting, recursive to any child settings. * * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param string $settingKey * @param array|string $settingValue + * @return void */ protected function writeSetting($xmlWriter, $settingKey, $settingValue) { @@ -142,4 +89,92 @@ class Settings extends AbstractPart $xmlWriter->endElement(); } } + + /** + * Get settings. + * + * @return void + */ + private function getSettings() + { + // Default settings + $this->settings = array( + 'w:zoom' => array('@attributes' => array('w:percent' => '100')), + 'w:defaultTabStop' => array('@attributes' => array('w:val' => '708')), + 'w:hyphenationZone' => array('@attributes' => array('w:val' => '425')), + 'w:characterSpacingControl' => array('@attributes' => array('w:val' => 'doNotCompress')), + 'w:themeFontLang' => array('@attributes' => array('w:val' => 'en-US')), + 'w:decimalSymbol' => array('@attributes' => array('w:val' => '.')), + 'w:listSeparator' => array('@attributes' => array('w:val' => ';')), + 'w:compat' => '', + 'm:mathPr' => array( + 'm:mathFont' => array('@attributes' => array('m:val' => 'Cambria Math')), + 'm:brkBin' => array('@attributes' => array('m:val' => 'before')), + 'm:brkBinSub' => array('@attributes' => array('m:val' => '--')), + 'm:smallFrac' => array('@attributes' => array('m:val' => 'off')), + 'm:dispDef' => '', + 'm:lMargin' => array('@attributes' => array('m:val' => '0')), + 'm:rMargin' => array('@attributes' => array('m:val' => '0')), + 'm:defJc' => array('@attributes' => array('m:val' => 'centerGroup')), + 'm:wrapIndent' => array('@attributes' => array('m:val' => '1440')), + 'm:intLim' => array('@attributes' => array('m:val' => 'subSup')), + 'm:naryLim' => array('@attributes' => array('m:val' => 'undOvr')), + ), + 'w:clrSchemeMapping' => array( + '@attributes' => array( + 'w:bg1' => 'light1', + 'w:t1' => 'dark1', + 'w:bg2' => 'light2', + 'w:t2' => 'dark2', + 'w:accent1' => 'accent1', + 'w:accent2' => 'accent2', + 'w:accent3' => 'accent3', + 'w:accent4' => 'accent4', + 'w:accent5' => 'accent5', + 'w:accent6' => 'accent6', + 'w:hyperlink' => 'hyperlink', + 'w:followedHyperlink' => 'followedHyperlink', + ), + ), + ); + + // Other settings + $this->getProtection(); + $this->getCompatibility(); + } + + /** + * Get protection settings. + * + * @return void + */ + private function getProtection() + { + $protection = $this->getParentWriter()->getPhpWord()->getProtection(); + if ($protection->getEditing() !== null) { + $this->settings['w:documentProtection'] = array( + '@attributes' => array( + 'w:enforcement' => 1, + 'w:edit' => $protection->getEditing(), + ) + ); + } + } + + /** + * Get compatibility setting. + * + * @return void + */ + private function getCompatibility() + { + $compatibility = $this->getParentWriter()->getPhpWord()->getCompatibility(); + if ($compatibility->getOoxmlVersion() !== null) { + $this->settings['w:compat']['w:compatSetting'] = array('@attributes' => array( + 'w:name' => 'compatibilityMode', + 'w:uri' => 'http://schemas.microsoft.com/office/word', + 'w:val' => $compatibility->getOoxmlVersion(), + )); + } + } } diff --git a/src/PhpWord/Writer/Word2007/Part/Styles.php b/src/PhpWord/Writer/Word2007/Part/Styles.php index 0d688e36..01942229 100644 --- a/src/PhpWord/Writer/Word2007/Part/Styles.php +++ b/src/PhpWord/Writer/Word2007/Part/Styles.php @@ -75,10 +75,11 @@ class Styles extends AbstractPart } /** - * Write default font and other default styles + * Write default font and other default styles. * * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param \PhpOffice\PhpWord\Style\AbstractStyle[] $styles + * @return void */ private function writeDefaultStyles(XMLWriter $xmlWriter, $styles) { @@ -113,14 +114,14 @@ class Styles extends AbstractPart $xmlWriter->startElement('w:name'); $xmlWriter->writeAttribute('w:val', 'Normal'); $xmlWriter->endElement(); // w:name - if (array_key_exists('Normal', $styles)) { + if (isset($styles['Normal'])) { $styleWriter = new ParagraphStyleWriter($xmlWriter, $styles['Normal']); $styleWriter->write(); } $xmlWriter->endElement(); // w:style // FootnoteReference style - if (!array_key_exists('FootnoteReference', $styles)) { + if (!isset($styles['FootnoteReference'])) { $xmlWriter->startElement('w:style'); $xmlWriter->writeAttribute('w:type', 'character'); $xmlWriter->writeAttribute('w:styleId', 'FootnoteReference'); @@ -139,11 +140,12 @@ class Styles extends AbstractPart } /** - * Write font style + * Write font style. * * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param string $styleName * @param \PhpOffice\PhpWord\Style\Font $style + * @return void */ private function writeFontStyle(XMLWriter $xmlWriter, $styleName, FontStyle $style) { @@ -192,11 +194,12 @@ class Styles extends AbstractPart } /** - * Write paragraph style + * Write paragraph style. * * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param string $styleName * @param \PhpOffice\PhpWord\Style\Paragraph $style + * @return void */ private function writeParagraphStyle(XMLWriter $xmlWriter, $styleName, ParagraphStyle $style) { @@ -224,11 +227,12 @@ class Styles extends AbstractPart } /** - * Write table style + * Write table style. * * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param string $styleName * @param \PhpOffice\PhpWord\Style\Table $style + * @return void */ private function writeTableStyle(XMLWriter $xmlWriter, $styleName, TableStyle $style) { diff --git a/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php b/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php index 61c8bae8..16335680 100644 --- a/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php @@ -47,7 +47,7 @@ abstract class AbstractStyle abstract public function write(); /** - * Create new instance + * Create new instance. * * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param string|\PhpOffice\PhpWord\Style\AbstractStyle $style @@ -102,4 +102,41 @@ abstract class AbstractStyle return $value * $factor; } + + /** + * Write child style. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param string $name + * @param mixed $value + * @return void + */ + protected function writeChildStyle(XMLWriter $xmlWriter, $name, $value) + { + if ($value !== null) { + $class = "PhpOffice\\PhpWord\\Writer\\Word2007\\Style\\" . $name; + + /** @var \PhpOffice\PhpWord\Writer\Word2007\Style\AbstractStyle $writer */ + $writer = new $class($xmlWriter, $value); + $writer->write(); + } + } + + /** + * Assemble style array into style string + * + * @param array $styles + * @return string + */ + protected function assembleStyle($styles = array()) + { + $style = ''; + foreach ($styles as $key => $value) { + if (!is_null($value) && $value != '') { + $style .= "{$key}:{$value}; "; + } + } + + return trim($style); + } } diff --git a/src/PhpWord/Writer/Word2007/Style/Alignment.php b/src/PhpWord/Writer/Word2007/Style/Alignment.php index cefadb57..fabaf8ea 100644 --- a/src/PhpWord/Writer/Word2007/Style/Alignment.php +++ b/src/PhpWord/Writer/Word2007/Style/Alignment.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Style; class Alignment extends AbstractStyle { /** - * Write style + * Write style. + * + * @return void */ public function write() { diff --git a/src/PhpWord/Writer/Word2007/Style/Cell.php b/src/PhpWord/Writer/Word2007/Style/Cell.php index a4b1ae90..0f90b3aa 100644 --- a/src/PhpWord/Writer/Word2007/Style/Cell.php +++ b/src/PhpWord/Writer/Word2007/Style/Cell.php @@ -32,7 +32,9 @@ class Cell extends AbstractStyle private $width; /** - * Write style + * Write style. + * + * @return void */ public function write() { @@ -88,9 +90,10 @@ class Cell extends AbstractStyle } /** - * Set width + * Set width. * * @param int $value + * @return void */ public function setWidth($value = null) { diff --git a/src/PhpWord/Writer/Word2007/Style/Extrusion.php b/src/PhpWord/Writer/Word2007/Style/Extrusion.php new file mode 100644 index 00000000..ba1ee590 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Style/Extrusion.php @@ -0,0 +1,46 @@ +getStyle(); + if (!$style instanceof \PhpOffice\PhpWord\Style\Extrusion) { + return; + } + $xmlWriter = $this->getXmlWriter(); + + $xmlWriter->startElement("o:extrusion"); + $xmlWriter->writeAttribute('on', 't'); + $xmlWriter->writeAttributeIf($style->getType() !== null, 'type', $style->getType()); + $xmlWriter->writeAttributeIf($style->getColor() !== null, 'color', $style->getColor()); + $xmlWriter->endElement(); + } +} diff --git a/src/PhpWord/Writer/Word2007/Style/Fill.php b/src/PhpWord/Writer/Word2007/Style/Fill.php new file mode 100644 index 00000000..645f1ab0 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Style/Fill.php @@ -0,0 +1,43 @@ +getStyle(); + if (!$style instanceof \PhpOffice\PhpWord\Style\Fill) { + return; + } + $xmlWriter = $this->getXmlWriter(); + + $xmlWriter->writeAttribute('on', 't'); + $xmlWriter->writeAttributeIf($style->getColor() !== null, 'fillcolor', $style->getColor()); + } +} diff --git a/src/PhpWord/Writer/Word2007/Style/Font.php b/src/PhpWord/Writer/Word2007/Style/Font.php index 0ef22f08..9371f970 100644 --- a/src/PhpWord/Writer/Word2007/Style/Font.php +++ b/src/PhpWord/Writer/Word2007/Style/Font.php @@ -32,7 +32,9 @@ class Font extends AbstractStyle private $isInline = false; /** - * Write style + * Write style. + * + * @return void */ public function write() { @@ -51,7 +53,9 @@ class Font extends AbstractStyle } /** - * Write full style + * Write full style. + * + * @return void */ private function writeStyle() { @@ -64,8 +68,10 @@ class Font extends AbstractStyle $xmlWriter->startElement('w:rPr'); // Style name - $styleName = $style->getStyleName(); - $xmlWriter->writeElementIf(!is_null($styleName), 'w:rStyle', 'w:val', $styleName); + if ($this->isInline === true) { + $styleName = $style->getStyleName(); + $xmlWriter->writeElementIf($styleName !== null, 'w:rStyle', 'w:val', $styleName); + } // Font name/family $font = $style->getName(); @@ -103,31 +109,41 @@ class Font extends AbstractStyle $xmlWriter->writeElementIf($style->isAllCaps(), 'w:caps'); // Underline - $underline = $style->getUnderline(); - $xmlWriter->writeElementIf($underline != 'none', 'w:u', 'w:val', $underline); + $xmlWriter->writeElementIf($style->getUnderline() != 'none', 'w:u', 'w:val', $style->getUnderline()); // Foreground-Color - $fgColor = $style->getFgColor(); - $xmlWriter->writeElementIf(!is_null($fgColor), 'w:highlight', 'w:val', $fgColor); + $xmlWriter->writeElementIf($style->getFgColor() !== null, 'w:highlight', 'w:val', $style->getFgColor()); // Superscript/subscript $xmlWriter->writeElementIf($style->isSuperScript(), 'w:vertAlign', 'w:val', 'superscript'); $xmlWriter->writeElementIf($style->isSubScript(), 'w:vertAlign', 'w:val', 'subscript'); + // Spacing + $xmlWriter->writeElementIf($style->getScale() !== null, 'w:w', 'w:val', $style->getScale()); + $xmlWriter->writeElementIf($style->getSpacing() !== null, 'w:spacing', 'w:val', $style->getSpacing()); + $xmlWriter->writeElementIf($style->getKerning() !== null, 'w:kern', 'w:val', $style->getKerning() * 2); + // Background-Color $shading = $style->getShading(); if (!is_null($shading)) { $styleWriter = new Shading($xmlWriter, $shading); $styleWriter->write(); } + + // RTL + if ($this->isInline === true) { + $styleName = $style->getStyleName(); + $xmlWriter->writeElementIf($styleName === null && $style->isRTL(), 'w:rtl'); + } $xmlWriter->endElement(); } /** - * Set is inline + * Set is inline. * * @param bool $value + * @return void */ public function setIsInline($value) { diff --git a/src/PhpWord/Writer/Word2007/Style/Frame.php b/src/PhpWord/Writer/Word2007/Style/Frame.php new file mode 100644 index 00000000..28ebeaf5 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Style/Frame.php @@ -0,0 +1,161 @@ +getStyle(); + if (!$style instanceof FrameStyle) { + return; + } + $xmlWriter = $this->getXmlWriter(); + + $zIndices = array(FrameStyle::WRAP_INFRONT => PHP_INT_MAX, FrameStyle::WRAP_BEHIND => -PHP_INT_MAX); + + $properties = array( + 'width' => 'width', + 'height' => 'height', + 'left' => 'margin-left', + 'top' => 'margin-top', + ); + $sizeStyles = $this->getStyles($style, $properties, $style->getUnit()); + + $properties = array( + 'pos' => 'position', + 'hPos' => 'mso-position-horizontal', + 'vPos' => 'mso-position-vertical', + 'hPosRelTo' => 'mso-position-horizontal-relative', + 'vPosRelTo' => 'mso-position-vertical-relative', + ); + $posStyles = $this->getStyles($style, $properties); + + $styles = array_merge($sizeStyles, $posStyles); + + // zIndex for infront & behind wrap + $wrap = $style->getWrap(); + if ($wrap !== null && isset($zIndices[$wrap])) { + $styles['z-index'] = $zIndices[$wrap]; + $wrap = null; + } + + // Style attribute + $xmlWriter->writeAttribute('style', $this->assembleStyle($styles)); + + $this->writeWrap($xmlWriter, $style, $wrap); + } + + /** + * Write alignment. + * + * @return void + */ + public function writeAlignment() + { + $style = $this->getStyle(); + if (!$style instanceof FrameStyle) { + return; + } + + $xmlWriter = $this->getXmlWriter(); + $xmlWriter->startElement('w:pPr'); + $styleWriter = new Alignment($xmlWriter, new AlignmentStyle(array('value' => $style->getAlign()))); + $styleWriter->write(); + $xmlWriter->endElement(); // w:pPr + } + + /** + * Write alignment. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Style\Frame $style + * @param string $wrap + * @return void + */ + private function writeWrap(XMLWriter $xmlWriter, FrameStyle $style, $wrap) + { + if ($wrap !== null) { + $xmlWriter->startElement('w10:wrap'); + $xmlWriter->writeAttribute('type', $wrap); + + $relativePositions = array( + FrameStyle::POS_RELTO_MARGIN => 'margin', + FrameStyle::POS_RELTO_PAGE => 'page', + FrameStyle::POS_RELTO_TMARGIN => 'margin', + FrameStyle::POS_RELTO_BMARGIN => 'page', + FrameStyle::POS_RELTO_LMARGIN => 'margin', + FrameStyle::POS_RELTO_RMARGIN => 'page', + ); + $pos = $style->getPos(); + $hPos = $style->getHPosRelTo(); + $vPos = $style->getVPosRelTo(); + + if ($pos == FrameStyle::POS_ABSOLUTE) { + $xmlWriter->writeAttribute('anchorx', "page"); + $xmlWriter->writeAttribute('anchory', "page"); + } elseif ($pos == FrameStyle::POS_RELATIVE) { + if (isset($relativePositions[$hPos])) { + $xmlWriter->writeAttribute('anchorx', $relativePositions[$hPos]); + } + if (isset($relativePositions[$vPos])) { + $xmlWriter->writeAttribute('anchory', $relativePositions[$vPos]); + } + } + + $xmlWriter->endElement(); // w10:wrap + } + } + + /** + * Get style values in associative array + * + * @param \PhpOffice\PhpWord\Style\Frame $style + * @param array $properties + * @param string $suffix + * @return array + */ + private function getStyles(FrameStyle $style, $properties, $suffix = '') + { + $styles = array(); + + foreach ($properties as $key => $property) { + $method = "get{$key}"; + $value = $style->$method(); + if ($value !== null) { + $styles[$property] = $style->$method() . $suffix; + } + } + + return $styles; + } +} diff --git a/src/PhpWord/Writer/Word2007/Style/Image.php b/src/PhpWord/Writer/Word2007/Style/Image.php index 280b569a..cabf37ce 100644 --- a/src/PhpWord/Writer/Word2007/Style/Image.php +++ b/src/PhpWord/Writer/Word2007/Style/Image.php @@ -17,157 +17,11 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Style; -use PhpOffice\PhpWord\Style\Alignment as AlignmentStyle; -use PhpOffice\PhpWord\Style\Image as ImageStyle; - /** * Image style writer * * @since 0.10.0 */ -class Image extends AbstractStyle +class Image extends Frame { - /** - * w10 namespace wrapping type - * - * @var string - */ - protected $w10wrap; - - /** - * Write style - */ - public function write() - { - $style = $this->getStyle(); - if (!$style instanceof ImageStyle) { - return; - } - $this->writeStyle($style); - } - - /** - * Write style attribute - * - * @param \PhpOffice\PhpWord\Style\Image $style - */ - protected function writeStyle($style) - { - $xmlWriter = $this->getXmlWriter(); - - $styles = $this->getElementStyle($style); - $imageStyle = $this->assembleStyle($styles); - - $xmlWriter->writeAttribute('style', $imageStyle); - } - - /** - * Write alignment - */ - public function writeAlignment() - { - $style = $this->getStyle(); - if (!$style instanceof ImageStyle) { - return; - } - - $xmlWriter = $this->getXmlWriter(); - $xmlWriter->startElement('w:pPr'); - $styleWriter = new Alignment($xmlWriter, new AlignmentStyle(array('value' => $style->getAlign()))); - $styleWriter->write(); - $xmlWriter->endElement(); // w:pPr - } - - /** - * Write w10 wrapping - */ - public function writeW10Wrap() - { - if (is_null($this->w10wrap)) { - return; - } - - $xmlWriter = $this->getXmlWriter(); - $xmlWriter->startElement('w10:wrap'); - $xmlWriter->writeAttribute('type', $this->w10wrap); - $xmlWriter->endElement(); // w10:wrap - } - - /** - * Get element style - * - * @param \PhpOffice\PhpWord\Style\Image $style - * @return array - */ - protected function getElementStyle(ImageStyle $style) - { - $styles = array( - 'mso-width-percent' => '0', - 'mso-height-percent' => '0', - 'mso-width-relative' => 'margin', - 'mso-height-relative' => 'margin', - ); - - // Dimension - $dimensions = array( - 'width' => $style->getWidth(), - 'height' => $style->getHeight(), - 'margin-top' => $style->getMarginTop(), - 'margin-left' => $style->getMarginLeft() - ); - foreach ($dimensions as $key => $value) { - if ($value !== null) { - $styles[$key] = $value . 'px'; - } - } - - // Absolute/relative positioning - $positioning = $style->getPositioning(); - $styles['position'] = $positioning; - if ($positioning !== null) { - $styles['mso-position-horizontal'] = $style->getPosHorizontal(); - $styles['mso-position-vertical'] = $style->getPosVertical(); - $styles['mso-position-horizontal-relative'] = $style->getPosHorizontalRel(); - $styles['mso-position-vertical-relative'] = $style->getPosVerticalRel(); - } - - // Wrapping style - $wrapping = $style->getWrappingStyle(); - if ($wrapping == ImageStyle::WRAPPING_STYLE_INLINE) { - // Nothing to do when inline - } elseif ($wrapping == ImageStyle::WRAPPING_STYLE_BEHIND) { - $styles['z-index'] = -251658752; - } else { - $styles['z-index'] = 251659264; - $styles['mso-position-horizontal'] = 'absolute'; - $styles['mso-position-vertical'] = 'absolute'; - } - - // w10 wrapping - if ($wrapping == ImageStyle::WRAPPING_STYLE_SQUARE) { - $this->w10wrap = 'square'; - } elseif ($wrapping == ImageStyle::WRAPPING_STYLE_TIGHT) { - $this->w10wrap = 'tight'; - } - - return $styles; - } - - /** - * Assemble style array into style string - * - * @param array $styles - * @return string - */ - protected function assembleStyle($styles = array()) - { - $style = ''; - foreach ($styles as $key => $value) { - if (!is_null($value) && $value != '') { - $style .= "{$key}:{$value}; "; - } - } - - return trim($style); - } } diff --git a/src/PhpWord/Writer/Word2007/Style/Indentation.php b/src/PhpWord/Writer/Word2007/Style/Indentation.php index f9bb696f..a1b4d8d1 100644 --- a/src/PhpWord/Writer/Word2007/Style/Indentation.php +++ b/src/PhpWord/Writer/Word2007/Style/Indentation.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Style; class Indentation extends AbstractStyle { /** - * Write style + * Write style. + * + * @return void */ public function write() { diff --git a/src/PhpWord/Writer/Word2007/Style/Line.php b/src/PhpWord/Writer/Word2007/Style/Line.php index dfecb4b0..48e27492 100644 --- a/src/PhpWord/Writer/Word2007/Style/Line.php +++ b/src/PhpWord/Writer/Word2007/Style/Line.php @@ -23,50 +23,13 @@ use PhpOffice\PhpWord\Style\Line as LineStyle; * Line style writer * */ -class Line extends Image +class Line extends Frame { /** - * Write style - */ - public function write() - { - $style = $this->getStyle(); - if (!$style instanceof LineStyle) { - return; - } - $this->writeStyle($style); - } - - /** - * Write style attribute + * Write Line stroke. * - * @param \PhpOffice\PhpWord\Style\Line $style - */ - protected function writeStyle($style) - { - $xmlWriter = $this->getXmlWriter(); - - $styles = $this->getElementStyle($style); - if ($style->isFlip()) { - $styles['flip'] = 'y'; - } - $imageStyle = $this->assembleStyle($styles); - $xmlWriter->writeAttribute('style', $imageStyle); - - // Connector type - $xmlWriter->writeAttribute('o:connectortype', $style->getConnectorType()); - - // Weight - $weight = $style->getWeight(); - $xmlWriter->writeAttributeIf($weight !== null, 'strokeweight', $weight . 'pt'); - - // Color - $color = $style->getColor(); - $xmlWriter->writeAttributeIf($color !== null, 'strokecolor', $color); - } - - /** - * Write Line stroke + * @return void + * @todo Merge with `Stroke` style */ public function writeStroke() { @@ -77,8 +40,6 @@ class Line extends Image } $dash = $style->getDash(); - $beginArrow = $style->getBeginArrow(); - $endArrow = $style->getEndArrow(); $dashStyles = array( LineStyle::DASH_STYLE_DASH => 'dash', LineStyle::DASH_STYLE_ROUND_DOT => '1 1', @@ -89,22 +50,22 @@ class Line extends Image LineStyle::DASH_STYLE_LONG_DASH_DOT_DOT => 'longDashDotDot', ); - if (($dash !== null) || ($beginArrow !== null) || ($endArrow !== null)) { - $xmlWriter->startElement('v:stroke'); + $xmlWriter->startElement('v:stroke'); - $xmlWriter->writeAttributeIf($beginArrow !== null, 'startarrow', $beginArrow); - $xmlWriter->writeAttributeIf($endArrow !== null, 'endarrow', $endArrow); + $xmlWriter->writeAttributeIf($style->getWeight() !== null, 'weight', $style->getWeight() . 'pt'); + $xmlWriter->writeAttributeIf($style->getColor() !== null, 'color', $style->getColor()); + $xmlWriter->writeAttributeIf($style->getBeginArrow() !== null, 'startarrow', $style->getBeginArrow()); + $xmlWriter->writeAttributeIf($style->getEndArrow() !== null, 'endarrow', $style->getEndArrow()); - if ($dash !== null) { - if (array_key_exists($dash, $dashStyles)) { - $xmlWriter->writeAttribute('dashstyle', $dashStyles[$dash]); - } - if ($dash == LineStyle::DASH_STYLE_ROUND_DOT) { - $xmlWriter->writeAttribute('endcap', 'round'); - } + if ($dash !== null) { + if (isset($dashStyles[$dash])) { + $xmlWriter->writeAttribute('dashstyle', $dashStyles[$dash]); + } + if ($dash == LineStyle::DASH_STYLE_ROUND_DOT) { + $xmlWriter->writeAttribute('endcap', 'round'); } - - $xmlWriter->endElement(); //v:stroke } + + $xmlWriter->endElement(); //v:stroke } } diff --git a/src/PhpWord/Writer/Word2007/Style/LineNumbering.php b/src/PhpWord/Writer/Word2007/Style/LineNumbering.php index b3c103b6..d06fa2d6 100644 --- a/src/PhpWord/Writer/Word2007/Style/LineNumbering.php +++ b/src/PhpWord/Writer/Word2007/Style/LineNumbering.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Style; class LineNumbering extends AbstractStyle { /** - * Write style + * Write style. + * + * @return void * * The w:start seems to be zero based so we have to decrement by one */ diff --git a/src/PhpWord/Writer/Word2007/Style/MarginBorder.php b/src/PhpWord/Writer/Word2007/Style/MarginBorder.php index 88bb0109..30029112 100644 --- a/src/PhpWord/Writer/Word2007/Style/MarginBorder.php +++ b/src/PhpWord/Writer/Word2007/Style/MarginBorder.php @@ -48,17 +48,18 @@ class MarginBorder extends AbstractStyle private $attributes = array(); /** - * Write style + * Write style. + * + * @return void */ public function write() { $xmlWriter = $this->getXmlWriter(); $sides = array('top', 'left', 'right', 'bottom', 'insideH', 'insideV'); - $sizeCount = count($this->sizes) - 1; - for ($i = 0; $i < $sizeCount; $i++) { - if ($this->sizes[$i] !== null) { + foreach ($this->sizes as $i => $size) { + if ($size !== null) { $color = null; if (isset($this->colors[$i])) { $color = $this->colors[$i]; @@ -69,19 +70,20 @@ class MarginBorder extends AbstractStyle } /** - * Write side + * Write side. * * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param string $side * @param int $width * @param string $color + * @return void */ private function writeSide(XMLWriter $xmlWriter, $side, $width, $color = null) { $xmlWriter->startElement('w:' . $side); if (!empty($this->colors)) { if ($color === null && !empty($this->attributes)) { - if (array_key_exists('defaultColor', $this->attributes)) { + if (isset($this->attributes['defaultColor'])) { $color = $this->attributes['defaultColor']; } } @@ -89,7 +91,7 @@ class MarginBorder extends AbstractStyle $xmlWriter->writeAttribute('w:sz', $width); $xmlWriter->writeAttribute('w:color', $color); if (!empty($this->attributes)) { - if (array_key_exists('space', $this->attributes)) { + if (isset($this->attributes['space'])) { $xmlWriter->writeAttribute('w:space', $this->attributes['space']); } } @@ -101,9 +103,10 @@ class MarginBorder extends AbstractStyle } /** - * Set sizes + * Set sizes. * * @param integer[] $value + * @return void */ public function setSizes($value) { @@ -111,9 +114,10 @@ class MarginBorder extends AbstractStyle } /** - * Set colors + * Set colors. * * @param string[] $value + * @return void */ public function setColors($value) { @@ -121,9 +125,10 @@ class MarginBorder extends AbstractStyle } /** - * Set attributes + * Set attributes. * * @param array $value + * @return void */ public function setAttributes($value) { diff --git a/src/PhpWord/Writer/Word2007/Style/Outline.php b/src/PhpWord/Writer/Word2007/Style/Outline.php new file mode 100644 index 00000000..06064d18 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Style/Outline.php @@ -0,0 +1,51 @@ +getStyle(); + if (!$style instanceof \PhpOffice\PhpWord\Style\Outline) { + return; + } + $xmlWriter = $this->getXmlWriter(); + + $xmlWriter->startElement("v:stroke"); + $xmlWriter->writeAttribute('on', 't'); + $xmlWriter->writeAttributeIf($style->getColor() !== null, 'color', $style->getColor()); + $xmlWriter->writeAttributeIf($style->getWeight() !== null, 'weight', $style->getWeight() . $style->getUnit()); + $xmlWriter->writeAttributeIf($style->getDash() !== null, 'dashstyle', $style->getDash()); + $xmlWriter->writeAttributeIf($style->getLine() !== null, 'linestyle', $style->getLine()); + $xmlWriter->writeAttributeIf($style->getEndCap() !== null, 'endcap', $style->getEndCap()); + $xmlWriter->writeAttributeIf($style->getStartArrow() !== null, 'startarrow', $style->getStartArrow()); + $xmlWriter->writeAttributeIf($style->getEndArrow() !== null, 'endarrow', $style->getEndArrow()); + $xmlWriter->endElement(); + } +} diff --git a/src/PhpWord/Writer/Word2007/Style/Paragraph.php b/src/PhpWord/Writer/Word2007/Style/Paragraph.php index f3287700..039b78bf 100644 --- a/src/PhpWord/Writer/Word2007/Style/Paragraph.php +++ b/src/PhpWord/Writer/Word2007/Style/Paragraph.php @@ -18,9 +18,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Style; use PhpOffice\PhpWord\Shared\XMLWriter; -use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Style\Alignment as AlignmentStyle; use PhpOffice\PhpWord\Style\Paragraph as ParagraphStyle; +use PhpOffice\PhpWord\Style; /** * Paragraph style writer @@ -44,7 +44,9 @@ class Paragraph extends AbstractStyle private $isInline = false; /** - * Write style + * Write style. + * + * @return void */ public function write() { @@ -67,7 +69,9 @@ class Paragraph extends AbstractStyle } /** - * Write full style + * Write full style. + * + * @return void */ private function writeStyle() { @@ -83,7 +87,9 @@ class Paragraph extends AbstractStyle } // Style name - $xmlWriter->writeElementIf($styles['name'] !== null, 'w:pStyle', 'w:val', $styles['name']); + if ($this->isInline === true) { + $xmlWriter->writeElementIf($styles['name'] !== null, 'w:pStyle', 'w:val', $styles['name']); + } // Alignment $styleWriter = new Alignment($xmlWriter, new AlignmentStyle(array('value' => $styles['alignment']))); @@ -95,9 +101,10 @@ class Paragraph extends AbstractStyle $xmlWriter->writeElementIf($styles['pagination']['keepLines'] === true, 'w:keepLines', 'w:val', '1'); $xmlWriter->writeElementIf($styles['pagination']['pageBreak'] === true, 'w:pageBreakBefore', 'w:val', '1'); - // Indentation & spacing + // Child style: indentation, spacing, and shading $this->writeChildStyle($xmlWriter, 'Indentation', $styles['indentation']); $this->writeChildStyle($xmlWriter, 'Spacing', $styles['spacing']); + $this->writeChildStyle($xmlWriter, 'Shading', $styles['shading']); // Tabs $this->writeTabs($xmlWriter, $styles['tabs']); @@ -105,34 +112,29 @@ class Paragraph extends AbstractStyle // Numbering $this->writeNumbering($xmlWriter, $styles['numbering']); + // Border + if ($style->hasBorder()) { + $xmlWriter->startElement('w:pBdr'); + + $styleWriter = new MarginBorder($xmlWriter); + $styleWriter->setSizes($style->getBorderSize()); + $styleWriter->setColors($style->getBorderColor()); + $styleWriter->write(); + + $xmlWriter->endElement(); + } + if (!$this->withoutPPR) { $xmlWriter->endElement(); // w:pPr } } /** - * Write child style - * - * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter - * @param string $name - * @param mixed $value - */ - private function writeChildStyle(XMLWriter $xmlWriter, $name, $value) - { - if ($value !== null) { - $class = "PhpOffice\\PhpWord\\Writer\\Word2007\\Style\\" . $name; - - /** @var \PhpOffice\PhpWord\Writer\Word2007\Style\AbstractStyle $writer */ - $writer = new $class($xmlWriter, $value); - $writer->write(); - } - } - - /** - * Write tabs + * Write tabs. * * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param \PhpOffice\PhpWord\Style\Tab[] $tabs + * @return void */ private function writeTabs(XMLWriter $xmlWriter, $tabs) { @@ -147,10 +149,11 @@ class Paragraph extends AbstractStyle } /** - * Write numbering + * Write numbering. * * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param array $numbering + * @return void */ private function writeNumbering(XMLWriter $xmlWriter, $numbering) { @@ -176,9 +179,10 @@ class Paragraph extends AbstractStyle } /** - * Set without w:pPr + * Set without w:pPr. * * @param bool $value + * @return void */ public function setWithoutPPR($value) { @@ -186,9 +190,10 @@ class Paragraph extends AbstractStyle } /** - * Set is inline + * Set is inline. * * @param bool $value + * @return void */ public function setIsInline($value) { diff --git a/src/PhpWord/Writer/Word2007/Style/Row.php b/src/PhpWord/Writer/Word2007/Style/Row.php index 5517cc2b..98841dd8 100644 --- a/src/PhpWord/Writer/Word2007/Style/Row.php +++ b/src/PhpWord/Writer/Word2007/Style/Row.php @@ -30,7 +30,9 @@ class Row extends AbstractStyle private $height; /** - * Write style + * Write style. + * + * @return void */ public function write() { @@ -55,9 +57,10 @@ class Row extends AbstractStyle } /** - * Set height + * Set height. * * @param int $value + * @return void */ public function setHeight($value = null) { diff --git a/src/PhpWord/Writer/Word2007/Style/Section.php b/src/PhpWord/Writer/Word2007/Style/Section.php index fb32a39a..486d0ed2 100644 --- a/src/PhpWord/Writer/Word2007/Style/Section.php +++ b/src/PhpWord/Writer/Word2007/Style/Section.php @@ -27,7 +27,9 @@ use PhpOffice\PhpWord\Style\Section as SectionStyle; class Section extends AbstractStyle { /** - * Write style + * Write style. + * + * @return void */ public function write() { diff --git a/src/PhpWord/Writer/Word2007/Style/Shading.php b/src/PhpWord/Writer/Word2007/Style/Shading.php index 72054c20..8ef8c6b1 100644 --- a/src/PhpWord/Writer/Word2007/Style/Shading.php +++ b/src/PhpWord/Writer/Word2007/Style/Shading.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Style; class Shading extends AbstractStyle { /** - * Write style + * Write style. + * + * @return void */ public function write() { diff --git a/src/PhpWord/Writer/Word2007/Style/Shadow.php b/src/PhpWord/Writer/Word2007/Style/Shadow.php new file mode 100644 index 00000000..cc746059 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Style/Shadow.php @@ -0,0 +1,46 @@ +getStyle(); + if (!$style instanceof \PhpOffice\PhpWord\Style\Shadow) { + return; + } + $xmlWriter = $this->getXmlWriter(); + + $xmlWriter->startElement("v:shadow"); + $xmlWriter->writeAttribute('on', 't'); + $xmlWriter->writeAttributeIf($style->getColor() !== null, 'color', $style->getColor()); + $xmlWriter->writeAttributeIf($style->getOffset() !== null, 'offset', $style->getOffset()); + $xmlWriter->endElement(); + } +} diff --git a/src/PhpWord/Writer/Word2007/Style/Shape.php b/src/PhpWord/Writer/Word2007/Style/Shape.php new file mode 100644 index 00000000..ba8dce5b --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Style/Shape.php @@ -0,0 +1,47 @@ +getStyle(); + if (!$style instanceof \PhpOffice\PhpWord\Style\Shape) { + return; + } + + $xmlWriter = $this->getXmlWriter(); + + $childStyles = array('Frame', 'Fill', 'Outline', 'Shadow', 'Extrusion'); + foreach ($childStyles as $childStyle) { + $method = "get{$childStyle}"; + $this->writeChildStyle($xmlWriter, $childStyle, $style->$method()); + } + } +} diff --git a/src/PhpWord/Writer/Word2007/Style/Spacing.php b/src/PhpWord/Writer/Word2007/Style/Spacing.php index 5dfb5c43..2f7e122a 100644 --- a/src/PhpWord/Writer/Word2007/Style/Spacing.php +++ b/src/PhpWord/Writer/Word2007/Style/Spacing.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Style; class Spacing extends AbstractStyle { /** - * Write style + * Write style. + * + * @return void */ public function write() { diff --git a/src/PhpWord/Writer/Word2007/Style/Tab.php b/src/PhpWord/Writer/Word2007/Style/Tab.php index 865a5a9c..aa00acc7 100644 --- a/src/PhpWord/Writer/Word2007/Style/Tab.php +++ b/src/PhpWord/Writer/Word2007/Style/Tab.php @@ -25,7 +25,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Style; class Tab extends AbstractStyle { /** - * Write style + * Write style. + * + * @return void */ public function write() { diff --git a/src/PhpWord/Writer/Word2007/Style/Table.php b/src/PhpWord/Writer/Word2007/Style/Table.php index e89b121c..8bbad107 100644 --- a/src/PhpWord/Writer/Word2007/Style/Table.php +++ b/src/PhpWord/Writer/Word2007/Style/Table.php @@ -34,7 +34,9 @@ class Table extends AbstractStyle private $width; /** - * Write style + * Write style. + * + * @return void */ public function write() { @@ -56,7 +58,11 @@ class Table extends AbstractStyle } /** - * Write full style + * Write full style. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Style\Table $style + * @return void */ private function writeStyle(XMLWriter $xmlWriter, TableStyle $style) { @@ -83,11 +89,12 @@ class Table extends AbstractStyle } /** - * Write width + * Write width. * * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter * @param int $width * @param string $unit + * @return void */ private function writeWidth(XMLWriter $xmlWriter, $width, $unit) { @@ -98,7 +105,11 @@ class Table extends AbstractStyle } /** - * Write margin + * Write margin. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Style\Table $style + * @return void */ private function writeMargin(XMLWriter $xmlWriter, TableStyle $style) { @@ -114,7 +125,11 @@ class Table extends AbstractStyle } /** - * Write border + * Write border. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Style\Table $style + * @return void */ private function writeBorder(XMLWriter $xmlWriter, TableStyle $style) { @@ -131,7 +146,11 @@ class Table extends AbstractStyle } /** - * Write row style + * Write row style. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Style\Table $style + * @return void */ private function writeFirstRow(XMLWriter $xmlWriter, TableStyle $style) { @@ -147,7 +166,11 @@ class Table extends AbstractStyle } /** - * Write shading + * Write shading. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Style\Table $style + * @return void */ private function writeShading(XMLWriter $xmlWriter, TableStyle $style) { @@ -162,9 +185,10 @@ class Table extends AbstractStyle } /** - * Set width + * Set width. * * @param int $value + * @return void */ public function setWidth($value = null) { diff --git a/src/PhpWord/Writer/Word2007/Style/TextBox.php b/src/PhpWord/Writer/Word2007/Style/TextBox.php index 13f40256..20c68c74 100644 --- a/src/PhpWord/Writer/Word2007/Style/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Style/TextBox.php @@ -24,69 +24,12 @@ use PhpOffice\PhpWord\Style\TextBox as TextBoxStyle; * * @since 0.11.0 */ -class TextBox extends Image +class TextBox extends Frame { /** - * Write style - */ - public function write() - { - $style = $this->getStyle(); - if (!$style instanceof TextBoxStyle) { - return; - } - $this->writeStyle($style); - $this->writeBorder($style); - } - - /** - * Write w10 wrapping + * Writer inner margin. * - * @return array - */ - public function writeW10Wrap() - { - if (is_null($this->w10wrap)) { - return; - } - $style = $this->getStyle(); - if (!$style instanceof TextBoxStyle) { - return; - } - - $relativePositions = array( - TextBoxStyle::POSITION_RELATIVE_TO_MARGIN => 'margin', - TextBoxStyle::POSITION_RELATIVE_TO_PAGE => 'page', - TextBoxStyle::POSITION_RELATIVE_TO_TMARGIN => 'margin', - TextBoxStyle::POSITION_RELATIVE_TO_BMARGIN => 'page', - TextBoxStyle::POSITION_RELATIVE_TO_LMARGIN => 'margin', - TextBoxStyle::POSITION_RELATIVE_TO_RMARGIN => 'page', - ); - $pos = $style->getPositioning(); - $vPos = $style->getPosVerticalRel(); - $hPos = $style->getPosHorizontalRel(); - - $xmlWriter = $this->getXmlWriter(); - $xmlWriter->startElement('w10:wrap'); - $xmlWriter->writeAttribute('type', $this->w10wrap); - - if ($pos == TextBoxStyle::POSITION_ABSOLUTE) { - $xmlWriter->writeAttribute('anchorx', "page"); - $xmlWriter->writeAttribute('anchory', "page"); - } elseif ($pos == TextBoxStyle::POSITION_RELATIVE) { - if (array_key_exists($vPos, $relativePositions)) { - $xmlWriter->writeAttribute('anchory', $relativePositions[$vPos]); - } - if (array_key_exists($hPos, $relativePositions)) { - $xmlWriter->writeAttribute('anchorx', $relativePositions[$hPos]); - } - } - - $xmlWriter->endElement(); // w10:wrap - } - - /** - * Writer inner margin + * @return void */ public function writeInnerMargin() { @@ -97,29 +40,26 @@ class TextBox extends Image $xmlWriter = $this->getXmlWriter(); $margins = implode(', ', $style->getInnerMargin()); + $xmlWriter->writeAttribute('inset', $margins); } /** - * Writer border + * Writer border. + * + * @return void */ - private function writeBorder(TextBoxStyle $style) + public function writeBorder() { + $style = $this->getStyle(); + if (!$style instanceof TextBoxStyle) { + return; + } $xmlWriter = $this->getXmlWriter(); - // Border size - $borderSize = $style->getBorderSize(); - if ($borderSize !== null) { - $xmlWriter->writeAttribute('strokeweight', $borderSize . 'pt'); - } - - // Border color - $borderColor = $style->getBorderColor(); - if (empty($borderColor)) { - $xmlWriter->writeAttribute('stroked', 'f'); - } else { - $xmlWriter->writeAttribute('strokecolor', $borderColor); - } - //@todo + $xmlWriter->startElement('v:stroke'); + $xmlWriter->writeAttributeIf($style->getBorderSize() !== null, 'weight', $style->getBorderSize() . 'pt'); + $xmlWriter->writeAttributeIf($style->getBorderColor() !== null, 'color', $style->getBorderColor()); + $xmlWriter->endElement(); // v:stroke } } diff --git a/tests/PhpWord/Tests/AutoloaderTest.php b/tests/PhpWord/Tests/AutoloaderTest.php index 92423fc6..dace5bdb 100644 --- a/tests/PhpWord/Tests/AutoloaderTest.php +++ b/tests/PhpWord/Tests/AutoloaderTest.php @@ -43,12 +43,11 @@ class AutoloaderTest extends \PHPUnit_Framework_TestCase */ public function testAutoload() { - $declared = get_declared_classes(); - $declaredCount = count($declared); + $declaredCount = count(get_declared_classes()); Autoloader::autoload('Foo'); - $this->assertEquals( + $this->assertCount( $declaredCount, - count(get_declared_classes()), + get_declared_classes(), 'PhpOffice\\PhpWord\\Autoloader::autoload() is trying to load ' . 'classes outside of the PhpOffice\\PhpWord namespace' ); diff --git a/tests/PhpWord/Tests/Collection/CollectionTest.php b/tests/PhpWord/Tests/Collection/CollectionTest.php index e3d08da2..833b3e80 100644 --- a/tests/PhpWord/Tests/Collection/CollectionTest.php +++ b/tests/PhpWord/Tests/Collection/CollectionTest.php @@ -28,8 +28,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase $object->addItem(new Footnote()); // addItem #1 $this->assertEquals(2, $object->addItem(new Footnote())); // addItem #2. Should returns new item index - $this->assertEquals(2, $object->countItems()); // There are two items now - $this->assertEquals(2, count($object->getItems())); // getItems returns array + $this->assertCount(2, $object->getItems()); // getItems returns array $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Footnote', $object->getItem(1)); // getItem returns object $this->assertNull($object->getItem(3)); // getItem returns null when invalid index is referenced diff --git a/tests/PhpWord/Tests/Element/AbstractElementTest.php b/tests/PhpWord/Tests/Element/AbstractElementTest.php index c92469f3..180dd4d0 100644 --- a/tests/PhpWord/Tests/Element/AbstractElementTest.php +++ b/tests/PhpWord/Tests/Element/AbstractElementTest.php @@ -19,8 +19,6 @@ namespace PhpOffice\PhpWord\Tests\Element; /** * Test class for PhpOffice\PhpWord\Element\AbstractElement - * - * @runTestsInSeparateProcesses */ class AbstractElementTest extends \PHPUnit_Framework_TestCase { diff --git a/tests/PhpWord/Tests/Element/LineTest.php b/tests/PhpWord/Tests/Element/LineTest.php index 429f9df6..5add9a6b 100644 --- a/tests/PhpWord/Tests/Element/LineTest.php +++ b/tests/PhpWord/Tests/Element/LineTest.php @@ -37,17 +37,17 @@ class LineTest extends \PHPUnit_Framework_TestCase $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Line', $oLine); $this->assertEquals($oLine->getStyle(), null); } - + /** * Get style name */ public function testStyleText() { $oLine = new Line('lineStyle'); - + $this->assertEquals($oLine->getStyle(), 'lineStyle'); } - + /** * Get style array */ @@ -55,14 +55,14 @@ class LineTest extends \PHPUnit_Framework_TestCase { $oLine = new Line( array( - 'width' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(14), - 'height' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(4), + 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(14), + 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(4), 'positioning' => 'absolute', 'posHorizontalRel' => 'page', 'posVerticalRel' => 'page', 'flip' => true, - 'marginLeft' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(5), - 'marginTop' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(3), + 'marginLeft' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(5), + 'marginTop' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), 'wrappingStyle' => \PhpOffice\PhpWord\Style\Image::WRAPPING_STYLE_SQUARE, 'beginArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_BLOCK, 'endArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_OVAL, @@ -70,7 +70,7 @@ class LineTest extends \PHPUnit_Framework_TestCase 'weight' => 10 ) ); - + $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Line', $oLine->getStyle()); } } diff --git a/tests/PhpWord/Tests/Element/LinkTest.php b/tests/PhpWord/Tests/Element/LinkTest.php index 0e582b13..ada6a36a 100644 --- a/tests/PhpWord/Tests/Element/LinkTest.php +++ b/tests/PhpWord/Tests/Element/LinkTest.php @@ -36,8 +36,8 @@ class LinkTest extends \PHPUnit_Framework_TestCase $oLink = new Link('http://www.google.com'); $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Link', $oLink); - $this->assertEquals($oLink->getTarget(), 'http://www.google.com'); - $this->assertEquals($oLink->getText(), $oLink->getTarget()); + $this->assertEquals($oLink->getSource(), 'http://www.google.com'); + $this->assertEquals($oLink->getText(), $oLink->getSource()); $this->assertEquals($oLink->getFontStyle(), null); $this->assertEquals($oLink->getParagraphStyle(), null); } @@ -55,7 +55,7 @@ class LinkTest extends \PHPUnit_Framework_TestCase ); $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Link', $oLink); - $this->assertEquals($oLink->getTarget(), 'http://www.google.com'); + $this->assertEquals($oLink->getSource(), 'http://www.google.com'); $this->assertEquals($oLink->getText(), 'Search Engine'); $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Font', $oLink->getFontStyle()); $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $oLink->getParagraphStyle()); diff --git a/tests/PhpWord/Tests/Element/ListItemRunTest.php b/tests/PhpWord/Tests/Element/ListItemRunTest.php index 37d679f9..7bb0c25d 100644 --- a/tests/PhpWord/Tests/Element/ListItemRunTest.php +++ b/tests/PhpWord/Tests/Element/ListItemRunTest.php @@ -131,7 +131,7 @@ class ListItemRunTest extends \PHPUnit_Framework_TestCase $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Link', $element); $this->assertCount(1, $oListItemRun->getElements()); - $this->assertEquals($element->getTarget(), 'http://www.google.fr'); + $this->assertEquals($element->getSource(), 'http://www.google.fr'); } /** @@ -144,7 +144,7 @@ class ListItemRunTest extends \PHPUnit_Framework_TestCase $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Link', $element); $this->assertCount(1, $oListItemRun->getElements()); - $this->assertEquals($element->getTarget(), 'http://www.google.fr'); + $this->assertEquals($element->getSource(), 'http://www.google.fr'); $this->assertEquals($element->getText(), 'ééé'); } diff --git a/tests/PhpWord/Tests/Element/SDTTest.php b/tests/PhpWord/Tests/Element/SDTTest.php new file mode 100644 index 00000000..8c7b4bf3 --- /dev/null +++ b/tests/PhpWord/Tests/Element/SDTTest.php @@ -0,0 +1,69 @@ +setValue($value); + $object->setListItems($types); + + $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\SDT', $object); + $this->assertEquals($type, $object->getType()); + $this->assertEquals($types, $object->getListItems()); + $this->assertEquals($value, $object->getValue()); + } + + /** + * Test set type exception + * + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Invalid style value + */ + public function testSetTypeException() + { + $object = new SDT('comboBox'); + $object->setType('foo'); + } + + /** + * Test set type + */ + public function testSetTypeNull() + { + $object = new SDT('comboBox'); + $object->setType(' '); + + $this->assertEquals('comboBox', $object->getType()); + } +} diff --git a/tests/PhpWord/Tests/Element/SectionTest.php b/tests/PhpWord/Tests/Element/SectionTest.php index af7595e2..853ebc5d 100644 --- a/tests/PhpWord/Tests/Element/SectionTest.php +++ b/tests/PhpWord/Tests/Element/SectionTest.php @@ -31,12 +31,12 @@ use PhpOffice\PhpWord\Style; class SectionTest extends \PHPUnit_Framework_TestCase { /** - * Get settings + * Get style */ - public function testGetSettings() + public function testGetStyle() { $oSection = new Section(0); - $this->assertAttributeEquals($oSection->getSettings(), 'settings', new Section(0)); + $this->assertAttributeEquals($oSection->getStyle(), 'style', new Section(0)); } /** @@ -69,12 +69,12 @@ class SectionTest extends \PHPUnit_Framework_TestCase /** * Set settings */ - public function testSetSettings() + public function testSetStyle() { $expected = 'landscape'; $object = new Section(0); - $object->setSettings(array('orientation' => $expected, 'foo' => null)); - $this->assertEquals($expected, $object->getSettings()->getOrientation()); + $object->setStyle(array('orientation' => $expected, 'foo' => null)); + $this->assertEquals($expected, $object->getStyle()->getOrientation()); } /** diff --git a/tests/PhpWord/Tests/Element/TextBoxTest.php b/tests/PhpWord/Tests/Element/TextBoxTest.php index c3c89ed4..2c6da465 100644 --- a/tests/PhpWord/Tests/Element/TextBoxTest.php +++ b/tests/PhpWord/Tests/Element/TextBoxTest.php @@ -55,11 +55,11 @@ class TextBoxTest extends \PHPUnit_Framework_TestCase { $oTextBox = new TextBox( array( - 'width' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(4.5), - 'height' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(17.5), + 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(4.5), + 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(17.5), 'positioning' => 'absolute', - 'marginLeft' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(15.4), - 'marginTop' => \PhpOffice\PhpWord\Shared\Drawing::centimetersToPixels(9.9), + 'marginLeft' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(15.4), + 'marginTop' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(9.9), 'stroke' => 0, 'innerMargin' => 0, 'borderSize' => 1, diff --git a/tests/PhpWord/Tests/Element/TextRunTest.php b/tests/PhpWord/Tests/Element/TextRunTest.php index 870214dd..de62a920 100644 --- a/tests/PhpWord/Tests/Element/TextRunTest.php +++ b/tests/PhpWord/Tests/Element/TextRunTest.php @@ -99,7 +99,7 @@ class TextRunTest extends \PHPUnit_Framework_TestCase $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Link', $element); $this->assertCount(1, $oTextRun->getElements()); - $this->assertEquals($element->getTarget(), 'http://www.google.fr'); + $this->assertEquals($element->getSource(), 'http://www.google.fr'); } /** @@ -112,7 +112,7 @@ class TextRunTest extends \PHPUnit_Framework_TestCase $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Link', $element); $this->assertCount(1, $oTextRun->getElements()); - $this->assertEquals($element->getTarget(), 'http://www.google.fr'); + $this->assertEquals($element->getSource(), 'http://www.google.fr'); $this->assertEquals($element->getText(), 'ééé'); } diff --git a/tests/PhpWord/Tests/Exception/CopyFileExceptionTest.php b/tests/PhpWord/Tests/Exception/CopyFileExceptionTest.php new file mode 100644 index 00000000..3d92595f --- /dev/null +++ b/tests/PhpWord/Tests/Exception/CopyFileExceptionTest.php @@ -0,0 +1,39 @@ +assertEquals(Media::countElements('section'), 0); + $this->assertEquals(0, Media::countElements('section')); } /** @@ -57,7 +57,7 @@ class MediaTest extends \PHPUnit_Framework_TestCase Media::addElement('section', 'object', $object); Media::addElement('section', 'object', $object); - $this->assertEquals(3, Media::countElements('section')); + $this->assertCount(3, Media::getElements('section')); } /** @@ -69,8 +69,7 @@ class MediaTest extends \PHPUnit_Framework_TestCase $actual = Media::addElement('section', 'link', 'http://test.com'); $this->assertEquals($expected, $actual); - $this->assertEquals(1, Media::countElements('section', 'link')); - $this->assertEquals(1, count(Media::getElements('section', 'link'))); + $this->assertCount(1, Media::getElements('section', 'link')); } /** @@ -84,8 +83,7 @@ class MediaTest extends \PHPUnit_Framework_TestCase Media::addElement('header1', 'image', $local, new Image($local)); Media::addElement('header1', 'image', $remote, new Image($remote)); - $this->assertEquals(2, Media::countElements('header1')); - $this->assertEquals(2, count(Media::getElements('header1'))); + $this->assertCount(2, Media::getElements('header1')); $this->assertEmpty(Media::getElements('header2')); } @@ -100,10 +98,10 @@ class MediaTest extends \PHPUnit_Framework_TestCase Media::addElement('footer1', 'image', $local, new Image($local)); Media::addElement('footer1', 'image', $remote, new Image($remote)); - $this->assertEquals(2, Media::countElements('footer1')); + $this->assertCount(2, Media::getElements('footer1')); Media::resetElements(); - $this->assertEquals(0, Media::countElements('footer1')); + $this->assertCount(0, Media::getElements('footer1')); } /** diff --git a/tests/PhpWord/Tests/DocumentPropertiesTest.php b/tests/PhpWord/Tests/Metadata/DocInfoTest.php similarity index 67% rename from tests/PhpWord/Tests/DocumentPropertiesTest.php rename to tests/PhpWord/Tests/Metadata/DocInfoTest.php index 30b2a7bc..c860a0d9 100644 --- a/tests/PhpWord/Tests/DocumentPropertiesTest.php +++ b/tests/PhpWord/Tests/Metadata/DocInfoTest.php @@ -15,23 +15,23 @@ * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ -namespace PhpOffice\PhpWord\Tests; +namespace PhpOffice\PhpWord\Tests\Metadata; -use PhpOffice\PhpWord\DocumentProperties; +use PhpOffice\PhpWord\Metadata\DocInfo; /** - * Test class for PhpOffice\PhpWord\DocumentProperties + * Test class for PhpOffice\PhpWord\Metadata\DocInfo * * @runTestsInSeparateProcesses */ -class DocumentPropertiesTest extends \PHPUnit_Framework_TestCase +class DocInfoTest extends \PHPUnit_Framework_TestCase { /** * Creator */ public function testCreator() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setCreator(); $this->assertEquals('', $oProperties->getCreator()); @@ -44,7 +44,7 @@ class DocumentPropertiesTest extends \PHPUnit_Framework_TestCase */ public function testLastModifiedBy() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setLastModifiedBy(); $this->assertEquals('', $oProperties->getLastModifiedBy()); @@ -57,7 +57,7 @@ class DocumentPropertiesTest extends \PHPUnit_Framework_TestCase */ public function testCreated() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setCreated(); $this->assertEquals(time(), $oProperties->getCreated()); @@ -71,7 +71,7 @@ class DocumentPropertiesTest extends \PHPUnit_Framework_TestCase */ public function testModified() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setModified(); $this->assertEquals(time(), $oProperties->getModified()); @@ -85,7 +85,7 @@ class DocumentPropertiesTest extends \PHPUnit_Framework_TestCase */ public function testTitle() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setTitle(); $this->assertEquals('', $oProperties->getTitle()); @@ -98,7 +98,7 @@ class DocumentPropertiesTest extends \PHPUnit_Framework_TestCase */ public function testDescription() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setDescription(); $this->assertEquals('', $oProperties->getDescription()); @@ -111,7 +111,7 @@ class DocumentPropertiesTest extends \PHPUnit_Framework_TestCase */ public function testSubject() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setSubject(); $this->assertEquals('', $oProperties->getSubject()); @@ -124,7 +124,7 @@ class DocumentPropertiesTest extends \PHPUnit_Framework_TestCase */ public function testKeywords() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setKeywords(); $this->assertEquals('', $oProperties->getKeywords()); @@ -137,7 +137,7 @@ class DocumentPropertiesTest extends \PHPUnit_Framework_TestCase */ public function testCategory() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setCategory(); $this->assertEquals('', $oProperties->getCategory()); @@ -150,7 +150,7 @@ class DocumentPropertiesTest extends \PHPUnit_Framework_TestCase */ public function testCompany() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setCompany(); $this->assertEquals('', $oProperties->getCompany()); @@ -163,7 +163,7 @@ class DocumentPropertiesTest extends \PHPUnit_Framework_TestCase */ public function testManager() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setManager(); $this->assertEquals('', $oProperties->getManager()); @@ -176,30 +176,30 @@ class DocumentPropertiesTest extends \PHPUnit_Framework_TestCase */ public function testCustomProperty() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setCustomProperty('key1', null); $oProperties->setCustomProperty('key2', true); $oProperties->setCustomProperty('key3', 3); $oProperties->setCustomProperty('key4', 4.4); $oProperties->setCustomProperty('key5', 'value5'); $this->assertEquals( - DocumentProperties::PROPERTY_TYPE_STRING, + DocInfo::PROPERTY_TYPE_STRING, $oProperties->getCustomPropertyType('key1') ); $this->assertEquals( - DocumentProperties::PROPERTY_TYPE_BOOLEAN, + DocInfo::PROPERTY_TYPE_BOOLEAN, $oProperties->getCustomPropertyType('key2') ); $this->assertEquals( - DocumentProperties::PROPERTY_TYPE_INTEGER, + DocInfo::PROPERTY_TYPE_INTEGER, $oProperties->getCustomPropertyType('key3') ); $this->assertEquals( - DocumentProperties::PROPERTY_TYPE_FLOAT, + DocInfo::PROPERTY_TYPE_FLOAT, $oProperties->getCustomPropertyType('key4') ); $this->assertEquals( - DocumentProperties::PROPERTY_TYPE_STRING, + DocInfo::PROPERTY_TYPE_STRING, $oProperties->getCustomPropertyType('key5') ); $this->assertEquals(null, $oProperties->getCustomPropertyType('key6')); @@ -225,50 +225,50 @@ class DocumentPropertiesTest extends \PHPUnit_Framework_TestCase */ public function testConvertProperty() { - $this->assertEquals('', DocumentProperties::convertProperty('a', 'empty')); - $this->assertEquals(null, DocumentProperties::convertProperty('a', 'null')); - $this->assertEquals(8, DocumentProperties::convertProperty('8', 'int')); - $this->assertEquals(8, DocumentProperties::convertProperty('8.3', 'uint')); - $this->assertEquals(8.3, DocumentProperties::convertProperty('8.3', 'decimal')); - $this->assertEquals('8.3', DocumentProperties::convertProperty('8.3', 'lpstr')); - $this->assertEquals(strtotime('10/11/2013'), DocumentProperties::convertProperty('10/11/2013', 'date')); - $this->assertEquals(true, DocumentProperties::convertProperty('true', 'bool')); - $this->assertEquals(false, DocumentProperties::convertProperty('1', 'bool')); - $this->assertEquals('1', DocumentProperties::convertProperty('1', 'array')); - $this->assertEquals('1', DocumentProperties::convertProperty('1', '')); + $this->assertEquals('', DocInfo::convertProperty('a', 'empty')); + $this->assertEquals(null, DocInfo::convertProperty('a', 'null')); + $this->assertEquals(8, DocInfo::convertProperty('8', 'int')); + $this->assertEquals(8, DocInfo::convertProperty('8.3', 'uint')); + $this->assertEquals(8.3, DocInfo::convertProperty('8.3', 'decimal')); + $this->assertEquals('8.3', DocInfo::convertProperty('8.3', 'lpstr')); + $this->assertEquals(strtotime('10/11/2013'), DocInfo::convertProperty('10/11/2013', 'date')); + $this->assertEquals(true, DocInfo::convertProperty('true', 'bool')); + $this->assertEquals(false, DocInfo::convertProperty('1', 'bool')); + $this->assertEquals('1', DocInfo::convertProperty('1', 'array')); + $this->assertEquals('1', DocInfo::convertProperty('1', '')); $this->assertEquals( - DocumentProperties::PROPERTY_TYPE_INTEGER, - DocumentProperties::convertPropertyType('int') + DocInfo::PROPERTY_TYPE_INTEGER, + DocInfo::convertPropertyType('int') ); $this->assertEquals( - DocumentProperties::PROPERTY_TYPE_INTEGER, - DocumentProperties::convertPropertyType('uint') + DocInfo::PROPERTY_TYPE_INTEGER, + DocInfo::convertPropertyType('uint') ); $this->assertEquals( - DocumentProperties::PROPERTY_TYPE_FLOAT, - DocumentProperties::convertPropertyType('decimal') + DocInfo::PROPERTY_TYPE_FLOAT, + DocInfo::convertPropertyType('decimal') ); $this->assertEquals( - DocumentProperties::PROPERTY_TYPE_STRING, - DocumentProperties::convertPropertyType('lpstr') + DocInfo::PROPERTY_TYPE_STRING, + DocInfo::convertPropertyType('lpstr') ); $this->assertEquals( - DocumentProperties::PROPERTY_TYPE_DATE, - DocumentProperties::convertPropertyType('date') + DocInfo::PROPERTY_TYPE_DATE, + DocInfo::convertPropertyType('date') ); $this->assertEquals( - DocumentProperties::PROPERTY_TYPE_BOOLEAN, - DocumentProperties::convertPropertyType('bool') + DocInfo::PROPERTY_TYPE_BOOLEAN, + DocInfo::convertPropertyType('bool') ); $this->assertEquals( - DocumentProperties::PROPERTY_TYPE_UNKNOWN, - DocumentProperties::convertPropertyType('array') + DocInfo::PROPERTY_TYPE_UNKNOWN, + DocInfo::convertPropertyType('array') ); $this->assertEquals( - DocumentProperties::PROPERTY_TYPE_UNKNOWN, - DocumentProperties::convertPropertyType('') + DocInfo::PROPERTY_TYPE_UNKNOWN, + DocInfo::convertPropertyType('') ); } } diff --git a/tests/PhpWord/Tests/PhpWordTest.php b/tests/PhpWord/Tests/PhpWordTest.php index 6a9e6b26..85c6a7f2 100644 --- a/tests/PhpWord/Tests/PhpWordTest.php +++ b/tests/PhpWord/Tests/PhpWordTest.php @@ -17,7 +17,7 @@ namespace PhpOffice\PhpWord\Tests; -use PhpOffice\PhpWord\DocumentProperties; +use PhpOffice\PhpWord\Metadata\DocInfo; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Style; @@ -35,24 +35,11 @@ class PhpWordTest extends \PHPUnit_Framework_TestCase public function testConstruct() { $phpWord = new PhpWord(); - $this->assertEquals(new DocumentProperties(), $phpWord->getDocumentProperties()); + $this->assertEquals(new DocInfo(), $phpWord->getDocInfo()); $this->assertEquals(Settings::DEFAULT_FONT_NAME, $phpWord->getDefaultFontName()); $this->assertEquals(Settings::DEFAULT_FONT_SIZE, $phpWord->getDefaultFontSize()); } - /** - * Test set/get document properties - */ - public function testSetGetDocumentProperties() - { - $phpWord = new PhpWord(); - $creator = 'PhpWord'; - $properties = $phpWord->getDocumentProperties(); - $properties->setCreator($creator); - $phpWord->setDocumentProperties($properties); - $this->assertEquals($creator, $phpWord->getDocumentProperties()->getCreator()); - } - /** * Test create/get section */ @@ -60,7 +47,7 @@ class PhpWordTest extends \PHPUnit_Framework_TestCase { $phpWord = new PhpWord(); $phpWord->addSection(); - $this->assertEquals(1, count($phpWord->getSections())); + $this->assertCount(1, $phpWord->getSections()); } /** @@ -132,6 +119,8 @@ class PhpWordTest extends \PHPUnit_Framework_TestCase /** * Test load template + * + * @deprecated 0.12.0 */ public function testLoadTemplate() { @@ -139,7 +128,7 @@ class PhpWordTest extends \PHPUnit_Framework_TestCase $phpWord = new PhpWord(); $this->assertInstanceOf( - 'PhpOffice\\PhpWord\\Template', + 'PhpOffice\\PhpWord\\TemplateProcessor', $phpWord->loadTemplate($templateFqfn) ); } @@ -147,6 +136,8 @@ class PhpWordTest extends \PHPUnit_Framework_TestCase /** * Test load template exception * + * @deprecated 0.12.0 + * * @expectedException \PhpOffice\PhpWord\Exception\Exception */ public function testLoadTemplateException() @@ -158,4 +149,28 @@ class PhpWordTest extends \PHPUnit_Framework_TestCase $phpWord = new PhpWord(); $phpWord->loadTemplate($templateFqfn); } + + /** + * Test save + */ + public function testSave() + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $section->addText('Hello world!'); + + $this->assertTrue($phpWord->save('test.docx', 'Word2007', true)); + } + + /** + * Test calling undefined method + * + * @expectedException \BadMethodCallException + * @expectedExceptionMessage is not defined + */ + public function testCallUndefinedMethod() + { + $phpWord = new PhpWord(); + $phpWord->undefinedMethod(); + } } diff --git a/tests/PhpWord/Tests/SettingsTest.php b/tests/PhpWord/Tests/SettingsTest.php index 61364034..0d3d66ae 100644 --- a/tests/PhpWord/Tests/SettingsTest.php +++ b/tests/PhpWord/Tests/SettingsTest.php @@ -22,6 +22,7 @@ use PhpOffice\PhpWord\Settings; /** * Test class for PhpOffice\PhpWord\Settings * + * @coversDefaultClass \PhpOffice\PhpWord\Settings * @runTestsInSeparateProcesses */ class SettingsTest extends \PHPUnit_Framework_TestCase @@ -70,6 +71,31 @@ class SettingsTest extends \PHPUnit_Framework_TestCase $this->assertFalse(Settings::setMeasurementUnit('foo')); } + /** + * @covers ::getTempDir + * @test + */ + public function testPhpTempDirIsUsedByDefault() + { + $this->assertEquals(sys_get_temp_dir(), Settings::getTempDir()); + } + + + /** + * @covers ::setTempDir + * @covers ::getTempDir + * @depends testPhpTempDirIsUsedByDefault + * @test + */ + public function testTempDirCanBeSet() + { + $userDefinedTempDir = 'C:\PhpWordTemp'; + Settings::setTempDir($userDefinedTempDir); + $currentTempDir = Settings::getTempDir(); + $this->assertEquals($userDefinedTempDir, $currentTempDir); + $this->assertNotEquals(sys_get_temp_dir(), $currentTempDir); + } + /** * Test set/get default font name */ diff --git a/tests/PhpWord/Tests/Shared/ConverterTest.php b/tests/PhpWord/Tests/Shared/ConverterTest.php new file mode 100644 index 00000000..002e2e33 --- /dev/null +++ b/tests/PhpWord/Tests/Shared/ConverterTest.php @@ -0,0 +1,117 @@ +assertEquals($value / 2.54 * 1440, $result); + + $result = Converter::cmToInch($value); + $this->assertEquals($value / 2.54, $result); + + $result = Converter::cmToPixel($value); + $this->assertEquals($value / 2.54 * 96, $result); + + $result = Converter::cmToPoint($value); + $this->assertEquals($value / 2.54 * 72, $result); + + $result = Converter::cmToEmu($value); + $this->assertEquals(round($value / 2.54 * 96 * 9525), $result); + + $result = Converter::inchToTwip($value); + $this->assertEquals($value * 1440, $result); + + $result = Converter::inchToCm($value); + $this->assertEquals($value * 2.54, $result); + + $result = Converter::inchToPixel($value); + $this->assertEquals($value * 96, $result); + + $result = Converter::inchToPoint($value); + $this->assertEquals($value * 72, $result); + + $result = Converter::inchToEmu($value); + $this->assertEquals(round($value * 96 * 9525), $result); + + $result = Converter::pixelToTwip($value); + $this->assertEquals($value / 96 * 1440, $result); + + $result = Converter::pixelToCm($value); + $this->assertEquals($value / 96 * 2.54, $result); + + $result = Converter::pixelToPoint($value); + $this->assertEquals($value / 96 * 72, $result); + + $result = Converter::pixelToEMU($value); + $this->assertEquals(round($value * 9525), $result); + + $result = Converter::pointToTwip($value); + $this->assertEquals($value * 20, $result); + + $result = Converter::pointToPixel($value); + $this->assertEquals($value / 72 * 96, $result); + + $result = Converter::pointToEMU($value); + $this->assertEquals(round($value / 72 * 96 * 9525), $result); + + $result = Converter::emuToPixel($value); + $this->assertEquals(round($value / 9525), $result); + + $result = Converter::degreeToAngle($value); + $this->assertEquals((int)round($value * 60000), $result); + + $result = Converter::angleToDegree($value); + $this->assertEquals(round($value / 60000), $result); + } + } + + /** + * Test htmlToRGB() + */ + public function testHtmlToRGB() + { + // Prepare test values [ original, expected ] + $values[] = array('#FF99DD', array(255, 153, 221)); // With # + $values[] = array('FF99DD', array(255, 153, 221)); // 6 characters + $values[] = array('F9D', array(255, 153, 221)); // 3 characters + $values[] = array('0F9D', false); // 4 characters + // Conduct test + foreach ($values as $value) { + $result = Converter::htmlToRGB($value[0]); + $this->assertEquals($value[1], $result); + } + } +} diff --git a/tests/PhpWord/Tests/Shared/DrawingTest.php b/tests/PhpWord/Tests/Shared/DrawingTest.php deleted file mode 100644 index 25fd3a38..00000000 --- a/tests/PhpWord/Tests/Shared/DrawingTest.php +++ /dev/null @@ -1,82 +0,0 @@ -assertEquals(round($value * 9525), $result); - - $result = Drawing::emuToPixels($value); - $this->assertEquals(round($value / 9525), $result); - - $result = Drawing::pixelsToPoints($value); - $this->assertEquals($value * 0.75, $result); - - $result = Drawing::pointsToPixels($value); - $this->assertEquals($value * 1.333333333, $result); - - $result = Drawing::degreesToAngle($value); - $this->assertEquals((int)round($value * 60000), $result); - - $result = Drawing::angleToDegrees($value); - $this->assertEquals(round($value / 60000), $result); - - $result = Drawing::pixelsToCentimeters($value); - $this->assertEquals($value * 0.026458333, $result); - - $result = Drawing::centimetersToPixels($value); - $this->assertEquals($value / 0.026458333, $result); - } - } - - /** - * Test htmlToRGB() - */ - public function testHtmlToRGB() - { - // Prepare test values [ original, expected ] - $values[] = array('#FF99DD', array(255, 153, 221)); // With # - $values[] = array('FF99DD', array(255, 153, 221)); // 6 characters - $values[] = array('F9D', array(255, 153, 221)); // 3 characters - $values[] = array('0F9D', false); // 4 characters - // Conduct test - foreach ($values as $value) { - $result = Drawing::htmlToRGB($value[0]); - $this->assertEquals($value[1], $result); - } - } -} diff --git a/tests/PhpWord/Tests/Shared/FontTest.php b/tests/PhpWord/Tests/Shared/FontTest.php deleted file mode 100644 index c10f7739..00000000 --- a/tests/PhpWord/Tests/Shared/FontTest.php +++ /dev/null @@ -1,58 +0,0 @@ -assertEquals($original * 16 / 12, $result); - - $result = Font::inchSizeToPixels($original); - $this->assertEquals($original * 96, $result); - - $result = Font::centimeterSizeToPixels($original); - $this->assertEquals($original * 37.795275591, $result); - - $result = Font::centimeterSizeToTwips($original); - $this->assertEquals($original * 565.217, $result); - - $result = Font::inchSizeToTwips($original); - $this->assertEquals($original * 565.217 * 2.54, $result); - - $result = Font::pixelSizeToTwips($original); - $this->assertEquals($original * 565.217 / 37.795275591, $result); - - $result = Font::pointSizeToTwips($original); - $this->assertEquals($original * 20, $result); - } -} diff --git a/tests/PhpWord/Tests/Shared/HtmlTest.php b/tests/PhpWord/Tests/Shared/HtmlTest.php index 730600d7..c4c0fc9d 100644 --- a/tests/PhpWord/Tests/Shared/HtmlTest.php +++ b/tests/PhpWord/Tests/Shared/HtmlTest.php @@ -34,7 +34,7 @@ class HtmlTest extends \PHPUnit_Framework_TestCase // Default $section = new Section(1); - $this->assertEquals(0, $section->countElements()); + $this->assertCount(0, $section->getElements()); // Heading $styles = array('strong', 'em', 'sup', 'sub'); @@ -52,7 +52,7 @@ class HtmlTest extends \PHPUnit_Framework_TestCase // Add HTML Html::addHtml($section, $content); - $this->assertEquals(7, $section->countElements()); + $this->assertCount(7, $section->getElements()); // Other parts $section = new Section(1); @@ -60,6 +60,12 @@ class HtmlTest extends \PHPUnit_Framework_TestCase $content .= '
HeaderContent
'; $content .= '
  • Bullet
    • Bullet
'; $content .= '
  1. Bullet
'; + $content .= "'Single Quoted Text'"; + $content .= '"Double Quoted Text"'; + $content .= '& Ampersand'; + $content .= '<>“‘’«»‹›'; + $content .= '&•°…™©®—'; + $content .= '–   ²³¼½¾'; Html::addHtml($section, $content); } } diff --git a/tests/PhpWord/Tests/Shared/StringTest.php b/tests/PhpWord/Tests/Shared/StringTest.php index bf5862fb..a3524ede 100644 --- a/tests/PhpWord/Tests/Shared/StringTest.php +++ b/tests/PhpWord/Tests/Shared/StringTest.php @@ -64,4 +64,12 @@ class StringTest extends \PHPUnit_Framework_TestCase $this->assertEquals('\uc0{\u8364}', String::toUnicode('€')); $this->assertEquals('\uc0{\u233}', String::toUnicode('é')); } + + /** + * Test remove underscore prefix + */ + public function testRemoveUnderscorePrefix() + { + $this->assertEquals('item', String::removeUnderscorePrefix('_item')); + } } diff --git a/tests/PhpWord/Tests/Style/FontTest.php b/tests/PhpWord/Tests/Style/FontTest.php index 432b29fb..c21ea4ce 100644 --- a/tests/PhpWord/Tests/Style/FontTest.php +++ b/tests/PhpWord/Tests/Style/FontTest.php @@ -46,6 +46,7 @@ class FontTest extends \PHPUnit_Framework_TestCase $this->assertEquals('text', $object->getStyleType()); $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $object->getParagraphStyle()); + $this->assertTrue(is_array($object->getStyleValues())); } /** @@ -71,6 +72,9 @@ class FontTest extends \PHPUnit_Framework_TestCase 'allCaps' => false, 'fgColor' => null, 'bgColor' => null, + 'scale' => null, + 'spacing' => null, + 'kerning' => null, ); foreach ($attributes as $key => $default) { $get = is_bool($default) ? "is{$key}" : "get{$key}"; @@ -106,6 +110,9 @@ class FontTest extends \PHPUnit_Framework_TestCase 'fgColor' => Font::FGCOLOR_YELLOW, 'bgColor' => 'FFFF00', 'lineHeight' => 2, + 'scale' => 150, + 'spacing' => 240, + 'kerning' => 10, ); $object->setStyleByArray($attributes); foreach ($attributes as $key => $value) { diff --git a/tests/PhpWord/Tests/Style/ParagraphTest.php b/tests/PhpWord/Tests/Style/ParagraphTest.php index 12aa51ce..73540b0c 100644 --- a/tests/PhpWord/Tests/Style/ParagraphTest.php +++ b/tests/PhpWord/Tests/Style/ParagraphTest.php @@ -119,7 +119,7 @@ class ParagraphTest extends \PHPUnit_Framework_TestCase { $object = new Paragraph(); $object->setTabs(array(new Tab('left', 1550), new Tab('right', 5300))); - $this->assertEquals(2, count($object->getTabs())); + $this->assertCount(2, $object->getTabs()); } /** diff --git a/tests/PhpWord/Tests/Style/SectionTest.php b/tests/PhpWord/Tests/Style/SectionTest.php index dd7273cb..e5becd72 100644 --- a/tests/PhpWord/Tests/Style/SectionTest.php +++ b/tests/PhpWord/Tests/Style/SectionTest.php @@ -35,13 +35,14 @@ class SettingsTest extends \PHPUnit_Framework_TestCase $oSettings = new Section(); $this->assertEquals('portrait', $oSettings->getOrientation()); - $this->assertEquals(11906, $oSettings->getPageSizeW()); - $this->assertEquals(16838, $oSettings->getPageSizeH()); + $this->assertEquals(Section::DEFAULT_WIDTH, $oSettings->getPageSizeW()); + $this->assertEquals(Section::DEFAULT_HEIGHT, $oSettings->getPageSizeH()); + $this->assertEquals('A4', $oSettings->getPaperSize()); $oSettings->setSettingValue('orientation', 'landscape'); $this->assertEquals('landscape', $oSettings->getOrientation()); - $this->assertEquals(16838, $oSettings->getPageSizeW()); - $this->assertEquals(11906, $oSettings->getPageSizeH()); + $this->assertEquals(Section::DEFAULT_HEIGHT, $oSettings->getPageSizeW()); + $this->assertEquals(Section::DEFAULT_WIDTH, $oSettings->getPageSizeH()); $iVal = rand(1, 1000); $oSettings->setSettingValue('borderSize', $iVal); @@ -96,6 +97,34 @@ class SettingsTest extends \PHPUnit_Framework_TestCase $this->assertEquals($iVal, $oSettings->getMarginRight()); } + /** + * Set/get page width + */ + public function testPageWidth() + { + // Section Settings + $oSettings = new Section(); + + $this->assertEquals(Section::DEFAULT_WIDTH, $oSettings->getPageSizeW()); + $iVal = rand(1, 1000); + $oSettings->setSettingValue('pageSizeW', $iVal); + $this->assertEquals($iVal, $oSettings->getPageSizeW()); + } + + /** + * Set/get page height + */ + public function testPageHeight() + { + // Section Settings + $oSettings = new Section(); + + $this->assertEquals(Section::DEFAULT_HEIGHT, $oSettings->getPageSizeH()); + $iVal = rand(1, 1000); + $oSettings->setSettingValue('pageSizeH', $iVal); + $this->assertEquals($iVal, $oSettings->getPageSizeH()); + } + /** * Set/get landscape orientation */ @@ -106,8 +135,8 @@ class SettingsTest extends \PHPUnit_Framework_TestCase $oSettings->setLandscape(); $this->assertEquals('landscape', $oSettings->getOrientation()); - $this->assertEquals(16838, $oSettings->getPageSizeW()); - $this->assertEquals(11906, $oSettings->getPageSizeH()); + $this->assertEquals(Section::DEFAULT_HEIGHT, $oSettings->getPageSizeW()); + $this->assertEquals(Section::DEFAULT_WIDTH, $oSettings->getPageSizeH()); } /** @@ -120,8 +149,8 @@ class SettingsTest extends \PHPUnit_Framework_TestCase $oSettings->setPortrait(); $this->assertEquals('portrait', $oSettings->getOrientation()); - $this->assertEquals(11906, $oSettings->getPageSizeW()); - $this->assertEquals(16838, $oSettings->getPageSizeH()); + $this->assertEquals(Section::DEFAULT_WIDTH, $oSettings->getPageSizeW()); + $this->assertEquals(Section::DEFAULT_HEIGHT, $oSettings->getPageSizeH()); } /** diff --git a/tests/PhpWord/Tests/StyleTest.php b/tests/PhpWord/Tests/StyleTest.php index f446ecdf..6165e4fd 100644 --- a/tests/PhpWord/Tests/StyleTest.php +++ b/tests/PhpWord/Tests/StyleTest.php @@ -22,43 +22,63 @@ use PhpOffice\PhpWord\Style; /** * Test class for PhpOffice\PhpWord\Style * + * @coversDefaultClass \PhpOffice\PhpWord\Style * @runTestsInSeparateProcesses */ class StyleTest extends \PHPUnit_Framework_TestCase { /** * Add and get paragraph, font, link, title, and table styles + * + * @covers ::addParagraphStyle + * @covers ::addFontStyle + * @covers ::addLinkStyle + * @covers ::addTitleStyle + * @covers ::addTableStyle + * @covers ::setDefaultParagraphStyle + * @covers ::countStyles + * @covers ::getStyle + * @covers ::resetStyles + * @covers ::getStyles + * @test */ public function testStyles() { $paragraph = array('align' => 'center'); $font = array('italic' => true, '_bold' => true); $table = array('bgColor' => 'CCCCCC'); - $styles = array('Paragraph' => 'Paragraph', 'Font' => 'Font', - 'Link' => 'Font', 'Table' => 'Table', - 'Heading_1' => 'Font', 'Normal' => 'Paragraph'); - $elementCount = 6; + $styles = array( + 'Paragraph' => 'Paragraph', + 'Font' => 'Font', + 'Link' => 'Font', + 'Table' => 'Table', + 'Heading_1' => 'Font', + 'Normal' => 'Paragraph', + ); Style::addParagraphStyle('Paragraph', $paragraph); Style::addFontStyle('Font', $font); Style::addLinkStyle('Link', $font); - Style::addTableStyle('Table', $table); + // @todo Style::addNumberingStyle Style::addTitleStyle(1, $font); + Style::addTableStyle('Table', $table); Style::setDefaultParagraphStyle($paragraph); - $this->assertEquals($elementCount, count(Style::getStyles())); + $this->assertCount(count($styles), Style::getStyles()); foreach ($styles as $name => $style) { $this->assertInstanceOf("PhpOffice\\PhpWord\\Style\\{$style}", Style::getStyle($name)); } $this->assertNull(Style::getStyle('Unknown')); Style::resetStyles(); - $this->assertEquals(0, count(Style::getStyles())); - + $this->assertCount(0, Style::getStyles()); } /** - * Set default paragraph style + * Test default paragraph style + * + * @covers ::setDefaultParagraphStyle + * @test */ public function testDefaultParagraphStyle() { diff --git a/tests/PhpWord/Tests/TemplateTest.php b/tests/PhpWord/Tests/TemplateProcessorTest.php similarity index 64% rename from tests/PhpWord/Tests/TemplateTest.php rename to tests/PhpWord/Tests/TemplateProcessorTest.php index 57ee229e..04d1e777 100644 --- a/tests/PhpWord/Tests/TemplateTest.php +++ b/tests/PhpWord/Tests/TemplateProcessorTest.php @@ -17,35 +17,33 @@ namespace PhpOffice\PhpWord\Tests; -use PhpOffice\PhpWord\Template; +use PhpOffice\PhpWord\TemplateProcessor; /** - * Test class for PhpOffice\PhpWord\Template - * - * @covers \PhpOffice\PhpWord\Template - * @coversDefaultClass \PhpOffice\PhpWord\Template + * @covers \PhpOffice\PhpWord\TemplateProcessor + * @coversDefaultClass \PhpOffice\PhpWord\TemplateProcessor * @runTestsInSeparateProcesses */ -final class TemplateTest extends \PHPUnit_Framework_TestCase +final class TemplateProcessorTest extends \PHPUnit_Framework_TestCase { /** - * Template can be saved in temporary location + * Template can be saved in temporary location. * * @covers ::save * @test */ final public function testTemplateCanBeSavedInTemporaryLocation() { - $templateFqfn = __DIR__ . "/_files/templates/with_table_macros.docx"; + $templateFqfn = __DIR__ . '/_files/templates/with_table_macros.docx'; - $document = new Template($templateFqfn); + $templateProcessor = new TemplateProcessor($templateFqfn); $xslDOMDocument = new \DOMDocument(); $xslDOMDocument->load(__DIR__ . "/_files/xsl/remove_tables_by_needle.xsl"); foreach (array('${employee.', '${scoreboard.') as $needle) { - $document->applyXslStyleSheet($xslDOMDocument, array('needle' => $needle)); + $templateProcessor->applyXslStyleSheet($xslDOMDocument, array('needle' => $needle)); } - $documentFqfn = $document->save(); + $documentFqfn = $templateProcessor->save(); $this->assertNotEmpty($documentFqfn, 'FQFN of the saved document is empty.'); $this->assertFileExists($documentFqfn, "The saved document \"{$documentFqfn}\" doesn't exist."); @@ -70,9 +68,10 @@ final class TemplateTest extends \PHPUnit_Framework_TestCase } /** - * XSL stylesheet can be applied + * XSL stylesheet can be applied. * * @param string $actualDocumentFqfn + * @throws \Exception * @covers ::applyXslStyleSheet * @depends testTemplateCanBeSavedInTemporaryLocation * @test @@ -99,7 +98,7 @@ final class TemplateTest extends \PHPUnit_Framework_TestCase } /** - * XSL stylesheet cannot be applied on failure in setting parameter value + * XSL stylesheet cannot be applied on failure in setting parameter value. * * @covers ::applyXslStyleSheet * @expectedException \PhpOffice\PhpWord\Exception\Exception @@ -108,20 +107,20 @@ final class TemplateTest extends \PHPUnit_Framework_TestCase */ final public function testXslStyleSheetCanNotBeAppliedOnFailureOfSettingParameterValue() { - $template = new Template(__DIR__ . "/_files/templates/blank.docx"); + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); $xslDOMDocument = new \DOMDocument(); - $xslDOMDocument->load(__DIR__ . "/_files/xsl/passthrough.xsl"); + $xslDOMDocument->load(__DIR__ . '/_files/xsl/passthrough.xsl'); /* * We have to use error control below, because \XSLTProcessor::setParameter omits warning on failure. * This warning fails the test. */ - @$template->applyXslStyleSheet($xslDOMDocument, array(1 => 'somevalue')); + @$templateProcessor->applyXslStyleSheet($xslDOMDocument, array(1 => 'somevalue')); } /** - * XSL stylesheet can be applied on failure of loading XML from template + * XSL stylesheet can be applied on failure of loading XML from template. * * @covers ::applyXslStyleSheet * @expectedException \PhpOffice\PhpWord\Exception\Exception @@ -130,83 +129,88 @@ final class TemplateTest extends \PHPUnit_Framework_TestCase */ final public function testXslStyleSheetCanNotBeAppliedOnFailureOfLoadingXmlFromTemplate() { - $template = new Template(__DIR__ . "/_files/templates/corrupted_main_document_part.docx"); + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/corrupted_main_document_part.docx'); $xslDOMDocument = new \DOMDocument(); - $xslDOMDocument->load(__DIR__ . "/_files/xsl/passthrough.xsl"); + $xslDOMDocument->load(__DIR__ . '/_files/xsl/passthrough.xsl'); /* * We have to use error control below, because \DOMDocument::loadXML omits warning on failure. * This warning fails the test. */ - @$template->applyXslStyleSheet($xslDOMDocument); + @$templateProcessor->applyXslStyleSheet($xslDOMDocument); } /** - * Get variables and clone row + * @civers ::setValue + * @covers ::cloneRow + * @covers ::saveAs + * @test */ public function testCloneRow() { - $template = __DIR__ . "/_files/templates/clone-merge.docx"; - $expectedVar = array('tableHeader', 'userId', 'userName', 'userLocation'); - $docName = 'clone-test-result.docx'; + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-merge.docx'); - $document = new Template($template); - $actualVar = $document->getVariables(); - $document->setValue('tableHeader', utf8_decode('ééé')); - $document->cloneRow('userId', 1); - $document->setValue('userId#1', 'Test'); - $document->saveAs($docName); + $this->assertEquals( + array('tableHeader', 'userId', 'userName', 'userLocation'), + $templateProcessor->getVariables() + ); + + $docName = 'clone-test-result.docx'; + $templateProcessor->setValue('tableHeader', utf8_decode('ééé')); + $templateProcessor->cloneRow('userId', 1); + $templateProcessor->setValue('userId#1', 'Test'); + $templateProcessor->saveAs($docName); $docFound = file_exists($docName); unlink($docName); - - $this->assertEquals($expectedVar, $actualVar); $this->assertTrue($docFound); } /** - * Replace variables in header and footer + * @covers ::setValue + * @covers ::saveAs + * @test */ public function testVariablesCanBeReplacedInHeaderAndFooter() { - $template = __DIR__ . "/_files/templates/header-footer.docx"; - $expectedVar = array('documentContent', 'headerValue', 'footerValue'); - $docName = 'header-footer-test-result.docx'; + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/header-footer.docx'); - $document = new Template($template); - $actualVar = $document->getVariables(); - $document->setValue('headerValue', 'Header Value'); - $document->setValue('documentContent', 'Document text.'); - $document->setValue('footerValue', 'Footer Value'); - $document->saveAs($docName); + $this->assertEquals( + array('documentContent', 'headerValue', 'footerValue'), + $templateProcessor->getVariables() + ); + + $docName = 'header-footer-test-result.docx'; + $templateProcessor->setValue('headerValue', 'Header Value'); + $templateProcessor->setValue('documentContent', 'Document text.'); + $templateProcessor->setValue('footerValue', 'Footer Value'); + $templateProcessor->saveAs($docName); $docFound = file_exists($docName); unlink($docName); - - $this->assertEquals($expectedVar, $actualVar); $this->assertTrue($docFound); - } /** - * Clone and delete block + * @covers ::cloneBlock + * @covers ::deleteBlock + * @covers ::saveAs + * @test */ public function testCloneDeleteBlock() { - $template = __DIR__ . "/_files/templates/clone-delete-block.docx"; - $expectedVar = array('DELETEME', '/DELETEME', 'CLONEME', '/CLONEME'); + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-delete-block.docx'); + + $this->assertEquals( + array('DELETEME', '/DELETEME', 'CLONEME', '/CLONEME'), + $templateProcessor->getVariables() + ); + $docName = 'clone-delete-block-result.docx'; - - $document = new Template($template); - $actualVar = $document->getVariables(); - - $document->cloneBlock('CLONEME', 3); - $document->deleteBlock('DELETEME'); - - $document->saveAs($docName); + $templateProcessor->cloneBlock('CLONEME', 3); + $templateProcessor->deleteBlock('DELETEME'); + $templateProcessor->saveAs($docName); $docFound = file_exists($docName); unlink($docName); - - $this->assertEquals($expectedVar, $actualVar); $this->assertTrue($docFound); } } diff --git a/tests/PhpWord/Tests/Writer/HTMLTest.php b/tests/PhpWord/Tests/Writer/HTMLTest.php index f9b8e6ba..c3339d1a 100644 --- a/tests/PhpWord/Tests/Writer/HTMLTest.php +++ b/tests/PhpWord/Tests/Writer/HTMLTest.php @@ -61,7 +61,7 @@ class HTMLTest extends \PHPUnit_Framework_TestCase $phpWord = new PhpWord(); - $docProps = $phpWord->getDocumentProperties(); + $docProps = $phpWord->getDocInfo(); $docProps->setTitle('HTML Test'); $phpWord->addTitleStyle(1, array('bold' => true)); diff --git a/tests/PhpWord/Tests/Writer/ODText/Part/ContentTest.php b/tests/PhpWord/Tests/Writer/ODText/Part/ContentTest.php index 27b2427f..85ddada6 100644 --- a/tests/PhpWord/Tests/Writer/ODText/Part/ContentTest.php +++ b/tests/PhpWord/Tests/Writer/ODText/Part/ContentTest.php @@ -47,7 +47,7 @@ class ContentTest extends \PHPUnit_Framework_TestCase $phpWord = new PhpWord(); - $docProps = $phpWord->getDocumentProperties(); + $docProps = $phpWord->getDocInfo(); $docProps->setCustomProperty('Company', 'PHPWord'); $phpWord->setDefaultFontName('Verdana'); diff --git a/tests/PhpWord/Tests/Writer/PDF/DomPDFTest.php b/tests/PhpWord/Tests/Writer/PDF/DomPDFTest.php index a22cb530..476c9011 100644 --- a/tests/PhpWord/Tests/Writer/PDF/DomPDFTest.php +++ b/tests/PhpWord/Tests/Writer/PDF/DomPDFTest.php @@ -71,7 +71,7 @@ class DomPDFTest extends \PHPUnit_Framework_TestCase $writer->setOrientation(); $this->assertEquals('default', $writer->getOrientation()); - $writer->setTempDir(sys_get_temp_dir()); - $this->assertEquals(sys_get_temp_dir(), $writer->getTempDir()); + $writer->setTempDir(Settings::getTempDir()); + $this->assertEquals(Settings::getTempDir(), $writer->getTempDir()); } } diff --git a/tests/PhpWord/Tests/Writer/RTF/StyleTest.php b/tests/PhpWord/Tests/Writer/RTF/StyleTest.php index 8b4a4441..542e34fe 100644 --- a/tests/PhpWord/Tests/Writer/RTF/StyleTest.php +++ b/tests/PhpWord/Tests/Writer/RTF/StyleTest.php @@ -28,7 +28,7 @@ class StyleTest extends \PHPUnit_Framework_TestCase */ public function testEmptyStyles() { - $styles = array('Font', 'Paragraph'); + $styles = array('Font', 'Paragraph', 'Section'); foreach ($styles as $style) { $objectClass = 'PhpOffice\\PhpWord\\Writer\\RTF\\Style\\' . $style; $object = new $objectClass(); diff --git a/tests/PhpWord/Tests/Writer/RTFTest.php b/tests/PhpWord/Tests/Writer/RTFTest.php index c1448106..5b983b35 100644 --- a/tests/PhpWord/Tests/Writer/RTFTest.php +++ b/tests/PhpWord/Tests/Writer/RTFTest.php @@ -91,7 +91,7 @@ class RTFTest extends \PHPUnit_Framework_TestCase $this->assertTrue(file_exists($file)); - unlink($file); + @unlink($file); } /** diff --git a/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php b/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php index da7504b5..92a74c15 100644 --- a/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php @@ -41,7 +41,7 @@ class ElementTest extends \PHPUnit_Framework_TestCase $elements = array( 'CheckBox', 'Container', 'Footnote', 'Image', 'Link', 'ListItem', 'ListItemRun', 'Object', 'PreserveText', 'Table', 'Text', 'TextBox', 'TextBreak', 'Title', 'TOC', - 'Field', 'Line' + 'Field', 'Line', 'Shape', 'Chart', 'FormField', 'SDT' ); foreach ($elements as $element) { $objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $element; @@ -61,10 +61,159 @@ class ElementTest extends \PHPUnit_Framework_TestCase { $phpWord = new PhpWord(); $section = $phpWord->addSection(); + $section->addLine(array('width' => 1000, 'height' => 1000, 'positioning' => 'absolute', 'flip' => true)); $doc = TestHelperDOCX::getDocument($phpWord); $element = "/w:document/w:body/w:p/w:r/w:pict/v:shapetype"; $this->assertTrue($doc->elementExists($element)); } + + /** + * Test shape elements + */ + public function testShapeElements() + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + + // Arc + $section->addShape( + 'arc', + array( + 'points' => '-90 20', + 'frame' => array('width' => 120, 'height' => 120), + 'outline' => array('color' => '#333333', 'weight' => 2, 'startArrow' => 'oval', 'endArrow' => 'open'), + ) + ); + + // Curve + $section->addShape( + 'curve', + array( + 'points' => '1,100 200,1 1,50 200,50', 'connector' => 'elbow', + 'outline' => array('color' => '#66cc00', 'weight' => 2, 'dash' => 'dash', + 'startArrow' => 'diamond', 'endArrow' => 'block'), + ) + ); + + // Line + $section->addShape( + 'line', + array( + 'points' => '1,1 150,30', + 'outline' => array('color' => '#cc00ff', 'line' => 'thickThin', 'weight' => 3, + 'startArrow' => 'oval', 'endArrow' => 'classic', 'endCap' => 'round'), + ) + ); + + // Polyline + $section->addShape( + 'polyline', + array( + 'points' => '1,30 20,10 55,20 75,10 100,40 115,50, 120,15 200,50', + 'outline' => array('color' => '#cc6666', 'weight' => 2, + 'startArrow' => 'none', 'endArrow' => 'classic'), + ) + ); + + // Rectangle + $section->addShape( + 'rect', + array( + 'roundness' => 0.2, + 'frame' => array('width' => 100, 'height' => 100, 'left' => 1, 'top' => 1), + 'fill' => array('color' => '#FFCC33'), + 'outline' => array('color' => '#990000', 'weight' => 1), + 'shadow' => array('color' => '#EEEEEE', 'offset' => '3pt,3pt'), + ) + ); + + // Oval + $section->addShape( + 'oval', + array( + 'frame' => array('width' => 100, 'height' => 70, 'left' => 1, 'top' => 1), + 'fill' => array('color' => '#33CC99'), + 'outline' => array('color' => '#333333', 'weight' => 2), + 'extrusion' => array('type' => 'perspective', 'color' => '#EEEEEE'), + ) + ); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $elements = array('arc', 'curve', 'line', 'polyline', 'roundrect', 'oval'); + foreach ($elements as $element) { + $path = "/w:document/w:body/w:p/w:r/w:pict/v:{$element}"; + $this->assertTrue($doc->elementExists($path)); + } + } + + /** + * Test shape elements + */ + public function testChartElements() + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $style = array('width' => 1000000, 'height' => 1000000); + + $chartTypes = array('pie', 'doughnut', 'bar', 'line', 'area', 'scatter', 'radar'); + $categories = array('A', 'B', 'C', 'D', 'E'); + $series1 = array(1, 3, 2, 5, 4); + foreach ($chartTypes as $chartType) { + $section->addChart($chartType, $categories, $series1, $style); + } + $section->addChart('pie', $categories, $series1, array('3d' => true)); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $index = 0; + foreach ($chartTypes as $chartType) { + $index++; + $file = "word/charts/chart{$index}.xml"; + $path = "/c:chartSpace/c:chart/c:plotArea/c:{$chartType}Chart"; + $this->assertTrue($doc->elementExists($path, $file)); + } + } + + /** + * Test form fields + */ + public function testFormFieldElements() + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + + $section->addFormField('textinput')->setName('MyTextBox'); + $section->addFormField('checkbox')->setDefault(true)->setValue('Your name'); + $section->addFormField('dropdown')->setEntries(array('Choice 1', 'Choice 2', 'Choice 3')); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $path = "/w:document/w:body/w:p/w:r/w:fldChar/w:ffData"; + $this->assertTrue($doc->elementExists($path . '/w:textInput')); + $this->assertTrue($doc->elementExists($path . '/w:checkBox')); + $this->assertTrue($doc->elementExists($path . '/w:ddList')); + } + + /** + * Test SDT elements + */ + public function testSDTElements() + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + + $section->addSDT('comboBox'); + $section->addSDT('dropDownList'); + $section->addSDT('date'); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $path = "/w:document/w:body/w:p/w:sdt/w:sdtPr"; + $this->assertTrue($doc->elementExists($path . '/w:comboBox')); + $this->assertTrue($doc->elementExists($path . '/w:dropDownList')); + $this->assertTrue($doc->elementExists($path . '/w:date')); + } } diff --git a/tests/PhpWord/Tests/Writer/Word2007/Part/DocumentTest.php b/tests/PhpWord/Tests/Writer/Word2007/Part/DocumentTest.php index e27d072a..ef36e0dd 100644 --- a/tests/PhpWord/Tests/Writer/Word2007/Part/DocumentTest.php +++ b/tests/PhpWord/Tests/Writer/Word2007/Part/DocumentTest.php @@ -45,11 +45,11 @@ class DocumentTest extends \PHPUnit_Framework_TestCase $section = $phpWord->addSection(); $section->addHeader(); $section->addHeader('first'); - $settings = $section->getSettings(); - $settings->setLandscape(); - $settings->setPageNumberingStart(2); - $settings->setBorderSize(240); - $settings->setBreakType('nextPage'); + $style = $section->getStyle(); + $style->setLandscape(); + $style->setPageNumberingStart(2); + $style->setBorderSize(240); + $style->setBreakType('nextPage'); $doc = TestHelperDOCX::getDocument($phpWord); $element = $doc->getElement('/w:document/w:body/w:sectPr/w:pgNumType'); @@ -114,15 +114,15 @@ class DocumentTest extends \PHPUnit_Framework_TestCase $this->assertEquals('page', $element->getAttribute('w:type')); // Title - $element = $doc->getElement('/w:document/w:body/w:p[5]/w:pPr/w:pStyle'); + $element = $doc->getElement('/w:document/w:body/w:p[6]/w:pPr/w:pStyle'); $this->assertEquals('Heading1', $element->getAttribute('w:val')); // List item - $element = $doc->getElement('/w:document/w:body/w:p[6]/w:pPr/w:numPr/w:numId'); + $element = $doc->getElement('/w:document/w:body/w:p[7]/w:pPr/w:numPr/w:numId'); $this->assertEquals(3, $element->getAttribute('w:val')); // Object - $element = $doc->getElement('/w:document/w:body/w:p[11]/w:r/w:object/o:OLEObject'); + $element = $doc->getElement('/w:document/w:body/w:p[12]/w:r/w:object/o:OLEObject'); $this->assertEquals('Embed', $element->getAttribute('Type')); } @@ -135,8 +135,14 @@ class DocumentTest extends \PHPUnit_Framework_TestCase $tabs = array(new \PhpOffice\PhpWord\Style\Tab('right', 9090)); $phpWord = new PhpWord(); - $phpWord->addParagraphStyle('pStyle', array('align' => 'center', 'tabs' => $tabs)); // Style #1 - $phpWord->addFontStyle('fStyle', array('size' => '20', 'bold' => true, 'allCaps' => true)); // Style #2 + $phpWord->addParagraphStyle('pStyle', array( + 'align' => 'center', + 'tabs' => $tabs, + 'shading' => array('fill' => 'FFFF99'), + 'borderSize' => 4, + )); // Style #1 + $phpWord->addFontStyle('fStyle', array('size' => '20', 'bold' => true, 'allCaps' => true, + 'scale' => 200, 'spacing' => 240, 'kerning' => 10)); // Style #2 $phpWord->addTitleStyle(1, array('color' => '333333', 'doubleStrikethrough' => true)); // Style #3 $phpWord->addTableStyle('tStyle', array('borderSize' => 1)); $fontStyle = new Font('text', array('align' => 'center')); diff --git a/tests/PhpWord/Tests/Writer/Word2007/Part/SettingsTest.php b/tests/PhpWord/Tests/Writer/Word2007/Part/SettingsTest.php new file mode 100644 index 00000000..7d4d1849 --- /dev/null +++ b/tests/PhpWord/Tests/Writer/Word2007/Part/SettingsTest.php @@ -0,0 +1,68 @@ +getProtection()->setEditing('forms'); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $file = 'word/settings.xml'; + + $path = '/w:settings/w:documentProtection'; + $this->assertTrue($doc->elementExists($path, $file)); + } + + /** + * Test compatibility + */ + public function testCompatibility() + { + $phpWord = new PhpWord(); + $phpWord->getCompatibility()->setOoxmlVersion(15); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $file = 'word/settings.xml'; + + $path = '/w:settings/w:compat/w:compatSetting'; + $this->assertTrue($doc->elementExists($path, $file)); + } +} diff --git a/tests/PhpWord/Tests/Writer/Word2007/Style/FontTest.php b/tests/PhpWord/Tests/Writer/Word2007/Style/FontTest.php new file mode 100644 index 00000000..af11c054 --- /dev/null +++ b/tests/PhpWord/Tests/Writer/Word2007/Style/FontTest.php @@ -0,0 +1,54 @@ +addSection(); + $textrun = $section->addTextRun(); + $textrun->addText('سلام این یک پاراگراف راست به چپ است', array('rtl' => true)); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $file = 'word/document.xml'; + $path = '/w:document/w:body/w:p/w:r/w:rPr/w:rtl'; + $this->assertTrue($doc->elementExists($path, $file)); + } +} diff --git a/tests/PhpWord/Tests/Writer/Word2007/StyleTest.php b/tests/PhpWord/Tests/Writer/Word2007/StyleTest.php index 71cbc300..8dd229c3 100644 --- a/tests/PhpWord/Tests/Writer/Word2007/StyleTest.php +++ b/tests/PhpWord/Tests/Writer/Word2007/StyleTest.php @@ -31,7 +31,7 @@ class StyleTest extends \PHPUnit_Framework_TestCase $styles = array( 'Alignment', 'Cell', 'Font', 'Image', 'Indentation', 'LineNumbering', 'Paragraph', 'Row', 'Section', 'Shading', 'Spacing', 'Tab', 'Table', - 'TextBox', 'Line' + 'TextBox', 'Line', 'Shape', 'Frame', 'Outline', 'Fill', 'Shadow', 'Extrusion', ); foreach ($styles as $style) { $objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Style\\' . $style; @@ -49,8 +49,9 @@ class StyleTest extends \PHPUnit_Framework_TestCase public function testMethodExceptions() { $styles = array( - 'Image' => 'writeAlignment', - 'Line' => 'writeStroke', + 'Frame' => 'writeAlignment', + 'Line' => 'writeStroke', + 'TextBox' => 'writeBorder', ); foreach ($styles as $style => $method) { $objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Style\\' . $style; diff --git a/tests/PhpWord/Tests/_includes/TestHelperDOCX.php b/tests/PhpWord/Tests/_includes/TestHelperDOCX.php index 7998cbdc..2a0043d5 100644 --- a/tests/PhpWord/Tests/_includes/TestHelperDOCX.php +++ b/tests/PhpWord/Tests/_includes/TestHelperDOCX.php @@ -17,8 +17,10 @@ namespace PhpOffice\PhpWord\Tests; +use PhpOffice\PhpWord\Exception\CreateTemporaryFileException; use PhpOffice\PhpWord\IOFactory; use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Settings; /** * Test helper class @@ -35,15 +37,22 @@ class TestHelperDOCX /** * Get document content * + * @since 0.12.0 Throws CreateTemporaryFileException. + * * @param \PhpOffice\PhpWord\PhpWord $phpWord * @param string $writerName * @return \PhpOffice\PhpWord\Tests\XmlDocument + * @throws \PhpOffice\PhpWord\Exception\CreateTemporaryFileException */ public static function getDocument(PhpWord $phpWord, $writerName = 'Word2007') { - self::$file = tempnam(sys_get_temp_dir(), 'PhpWord'); - if (!is_dir(sys_get_temp_dir() . '/PhpWord_Unit_Test/')) { - mkdir(sys_get_temp_dir() . '/PhpWord_Unit_Test/'); + self::$file = tempnam(Settings::getTempDir(), 'PhpWord'); + if (false === self::$file) { + throw new CreateTemporaryFileException(); + } + + if (!is_dir(Settings::getTempDir() . '/PhpWord_Unit_Test/')) { + mkdir(Settings::getTempDir() . '/PhpWord_Unit_Test/'); } $xmlWriter = IOFactory::createWriter($phpWord, $writerName); @@ -52,11 +61,11 @@ class TestHelperDOCX $zip = new \ZipArchive; $res = $zip->open(self::$file); if ($res === true) { - $zip->extractTo(sys_get_temp_dir() . '/PhpWord_Unit_Test/'); + $zip->extractTo(Settings::getTempDir() . '/PhpWord_Unit_Test/'); $zip->close(); } - return new XmlDocument(sys_get_temp_dir() . '/PhpWord_Unit_Test/'); + return new XmlDocument(Settings::getTempDir() . '/PhpWord_Unit_Test/'); } /** @@ -67,8 +76,8 @@ class TestHelperDOCX if (file_exists(self::$file)) { unlink(self::$file); } - if (is_dir(sys_get_temp_dir() . '/PhpWord_Unit_Test/')) { - self::deleteDir(sys_get_temp_dir() . '/PhpWord_Unit_Test/'); + if (is_dir(Settings::getTempDir() . '/PhpWord_Unit_Test/')) { + self::deleteDir(Settings::getTempDir() . '/PhpWord_Unit_Test/'); } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index d0dcdba7..4932a21b 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -23,16 +23,10 @@ if (!defined('PHPWORD_TESTS_BASE_DIR')) { } $vendor = realpath(__DIR__ . '/../vendor'); - -if (file_exists($vendor . "/autoload.php")) { - require $vendor . "/autoload.php"; +if (file_exists($vendor . '/autoload.php')) { + require $vendor . '/autoload.php'; } else { - $vendor = realpath(__DIR__ . '/../../../'); - if (file_exists($vendor . "/autoload.php")) { - require $vendor . "/autoload.php"; - } else { - throw new Exception("Unable to load dependencies"); - } + throw new Exception('Unable to load dependencies'); } spl_autoload_register(function ($class) { @@ -49,5 +43,5 @@ spl_autoload_register(function ($class) { } }); -require_once __DIR__ . "/../src/PhpWord/Autoloader.php"; +require_once __DIR__ . '/../src/PhpWord/Autoloader.php'; \PhpOffice\PhpWord\Autoloader::register();