diff --git a/.gitignore b/.gitignore index 810a7b0ae1..e5deb64387 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 73dd68ec83..22f45d9b2e 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 59cbba6cf4..93ab0127a9 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 34985610b0..335ad2d519 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 ecbe135440..8f499a8ebb 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 -$phpWord = new \PhpOffice\PhpWord\PhpWord(); - -// Every element you want to append to the word document is placed in a section. -// To create a basic section: -$section = $phpWord->addSection(); - -// After creating a section, you can append elements: -$section->addText('Hello world!'); +addText('Hello world! I am formatted.', - array('name'=>'Tahoma', 'size'=>16, 'bold'=>true)); +// Creating the new document... +$phpWord = new \PhpOffice\PhpWord\PhpWord(); -// 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'); +/* Note: any element you append to a document must reside inside of a Section. */ -// You can also put the appended element to local object like this: +// Adding an empty Section to the document... +$section = $phpWord->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)' + ) +); + +/* + * 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. + */ + +// 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) +); + +// 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 +); + +// 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 027934ea1a..d33c3a2128 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 2f9a0915b0..b55d8340ca 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 172e564ef9..47351b0efd 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": "herrera-io/json", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/herrera-io/php-json.git", + "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1" + }, + "dist": { + "type": "zip", + "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.0", + "version": "1.5.1", "source": { "type": "git", "url": "https://github.com/schmittjoh/metadata.git", - "reference": "88ffa28bc987e4c26229fc84a2e541b6ed4e1459" + "reference": "22b72455559a25777cfd28c4ffda81ff7639f353" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/88ffa28bc987e4c26229fc84a2e541b6ed4e1459", - "reference": "88ffa28bc987e4c26229fc84a2e541b6ed4e1459", + "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,94 +602,143 @@ "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": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Christophe Coevoet", - "email": "stof@notk.org" + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" }, { - "name": "KnpLabs", - "homepage": "http://knplabs.com" + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" }, { - "name": "Symfony Community", - "homepage": "https://github.com/KnpLabs/KnpMenu/contributors" + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com" } ], - "description": "An object oriented menu library", - "homepage": "http://knplabs.com", + "description": "A library to validate a json schema.", + "homepage": "https://github.com/justinrainbow/json-schema", "keywords": [ - "menu", - "tree" + "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/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kevin Herrera", + "email": "me@kevingh.com", + "homepage": "http://www.kevingh.com/" + } ], - "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,32 +2201,249 @@ "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": { - "ext-tokenizer": "*", - "php": ">=5.1.2" + "symfony/finder": ">=2.2.0", + "theseer/fdomdocument": ">=1.3.1" }, - "suggest": { - "phpunit/php-timer": "dev-master" - }, - "bin": [ - "scripts/phpcs" - ], "type": "library", - "extra": { - "branch-alias": { + "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": { + "ext-tokenizer": "*", + "php": ">=5.1.2" + }, + "suggest": { + "phpunit/php-timer": "dev-master" + }, + "bin": [ + "scripts/phpcs" + ], + "type": "library", + "extra": { + "branch-alias": { "dev-phpcs-fixer": "2.0.x-dev" } }, @@ -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,55 +2584,56 @@ "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/dependency-injection": "", - "symfony/http-kernel": "" + "symfony/config": "", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.5-dev" } }, "autoload": { "psr-0": { - "Symfony\\Component\\EventDispatcher\\": "" + "Symfony\\Component\\DependencyInjection\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -2128,48 +2641,57 @@ "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", + "description": "Symfony DependencyInjection Component", "homepage": "http://symfony.com", - "time": "2014-04-16 10:34:31" + "time": "2014-12-02 21:48:32" }, { - "name": "symfony/filesystem", - "version": "v2.4.4", - "target-dir": "Symfony/Component/Filesystem", + "name": "symfony/event-dispatcher", + "version": "v2.6.1", + "target-dir": "Symfony/Component/EventDispatcher", "source": { "type": "git", - "url": "https://github.com/symfony/Filesystem.git", - "reference": "a3af8294bcce4a7c1b2892363b0c9d8109affad4" + "url": "https://github.com/symfony/EventDispatcher.git", + "reference": "720fe9bca893df7ad1b4546649473b5afddf0216" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/a3af8294bcce4a7c1b2892363b0c9d8109affad4", - "reference": "a3af8294bcce4a7c1b2892363b0c9d8109affad4", + "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": "", + "symfony/http-kernel": "" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.6-dev" } }, "autoload": { "psr-0": { - "Symfony\\Component\\Filesystem\\": "" + "Symfony\\Component\\EventDispatcher\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -2177,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 Filesystem Component", + "description": "Symfony EventDispatcher Component", "homepage": "http://symfony.com", - "time": "2014-04-16 10:34:31" + "time": "2014-12-02 20:19:20" }, { - "name": "symfony/finder", - "version": "v2.4.4", - "target-dir": "Symfony/Component/Finder", + "name": "symfony/filesystem", + "version": "v2.5.8", + "target-dir": "Symfony/Component/Filesystem", "source": { "type": "git", - "url": "https://github.com/symfony/Finder.git", - "reference": "25e1e7d5e7376f8a92ae3b1d714d956edf33a730" + "url": "https://github.com/symfony/Filesystem.git", + "reference": "e5fc05a3a1dbb4ea0bed80fe7bd21ba3cab88c42" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/25e1e7d5e7376f8a92ae3b1d714d956edf33a730", - "reference": "25e1e7d5e7376f8a92ae3b1d714d956edf33a730", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/e5fc05a3a1dbb4ea0bed80fe7bd21ba3cab88c42", + "reference": "e5fc05a3a1dbb4ea0bed80fe7bd21ba3cab88c42", "shasum": "" }, "require": { @@ -2213,12 +2733,12 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.5-dev" } }, "autoload": { "psr-0": { - "Symfony\\Component\\Finder\\": "" + "Symfony\\Component\\Filesystem\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -2226,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 Finder Component", + "description": "Symfony Filesystem Component", "homepage": "http://symfony.com", - "time": "2014-04-27 13:34:57" + "time": "2014-12-02 20:15:53" }, { - "name": "symfony/process", - "version": "v2.4.4", - "target-dir": "Symfony/Component/Process", + "name": "symfony/finder", + "version": "v2.6.1", + "target-dir": "Symfony/Component/Finder", "source": { "type": "git", - "url": "https://github.com/symfony/Process.git", - "reference": "8721f1476d5d38a43c7d6ccb6435b351cf8f3bb7" + "url": "https://github.com/symfony/Finder.git", + "reference": "0d3ef7f6ec55a7af5eca7914eaa0dacc04ccc721" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/8721f1476d5d38a43c7d6ccb6435b351cf8f3bb7", - "reference": "8721f1476d5d38a43c7d6ccb6435b351cf8f3bb7", + "url": "https://api.github.com/repos/symfony/Finder/zipball/0d3ef7f6ec55a7af5eca7914eaa0dacc04ccc721", + "reference": "0d3ef7f6ec55a7af5eca7914eaa0dacc04ccc721", "shasum": "" }, "require": { @@ -2262,12 +2780,12 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.6-dev" } }, "autoload": { "psr-0": { - "Symfony\\Component\\Process\\": "" + "Symfony\\Component\\Finder\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -2275,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 Process Component", + "description": "Symfony Finder Component", "homepage": "http://symfony.com", - "time": "2014-04-27 13:34:57" + "time": "2014-12-02 20:19:20" }, { - "name": "symfony/property-access", - "version": "v2.4.4", - "target-dir": "Symfony/Component/PropertyAccess", + "name": "symfony/process", + "version": "v2.6.1", + "target-dir": "Symfony/Component/Process", "source": { "type": "git", - "url": "https://github.com/symfony/PropertyAccess.git", - "reference": "0456222bc00c40c1365065b603f7c397fb9a7134" + "url": "https://github.com/symfony/Process.git", + "reference": "bf0c9bd625f13b0b0bbe39919225cf145dfb935a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/PropertyAccess/zipball/0456222bc00c40c1365065b603f7c397fb9a7134", - "reference": "0456222bc00c40c1365065b603f7c397fb9a7134", + "url": "https://api.github.com/repos/symfony/Process/zipball/bf0c9bd625f13b0b0bbe39919225cf145dfb935a", + "reference": "bf0c9bd625f13b0b0bbe39919225cf145dfb935a", "shasum": "" }, "require": { @@ -2311,12 +2827,12 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.6-dev" } }, "autoload": { "psr-0": { - "Symfony\\Component\\PropertyAccess\\": "" + "Symfony\\Component\\Process\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -2324,45 +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 PropertyAccess Component", + "description": "Symfony Process 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": "theseer/fdomdocument", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://github.com/theseer/fDOMDocument.git", + "reference": "d08cf070350f884c63fc9078d27893c2ab6c7cef" + }, + "dist": { + "type": "zip", + "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.15.1", + "version": "v1.16.2", "source": { "type": "git", - "url": "https://github.com/fabpot/Twig.git", - "reference": "1fb5784662f438d7d96a541e305e28b812e2eeed" + "url": "https://github.com/twigphp/Twig.git", + "reference": "42f758d9fe2146d1f0470604fc05ee43580873fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fabpot/Twig/zipball/1fb5784662f438d7d96a541e305e28b812e2eeed", - "reference": "1fb5784662f438d7d96a541e305e28b812e2eeed", + "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 f5c38581f1..de645350d0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -41,14 +41,14 @@ # 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 30566df647..f165a58981 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 ec158356e7..79652ae025 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 f08e29badd..34d3af2477 100644 --- a/docs/general.rst +++ b/docs/general.rst @@ -12,46 +12,82 @@ folder `__. .. code-block:: php + addSection(); + /* Note: any element you append to a document must reside inside of a Section. */ - // After creating a section, you can append elements: - $section->addText('Hello world!'); + // Adding an empty Section to the document... + $section = $phpWord->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)' + ) + ); - // 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)); + /* + * 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. + */ + + // 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 fd3a3fa910..671c32a64c 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 e5d61b4ea1..6599590460 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 aca5b24153..d2decd7c94 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 d5678a520e..0be6b4e06a 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 84522c1b5f..1a59e94230 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(); +/* Note: any element you append to a document must reside inside of a Section. */ -// After creating a section, you can append elements: -$section->addText('Hello world!'); +// Adding an empty Section to the document... +$section = $phpWord->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)' + ) +); -// 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)); +/* + * 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. + */ + +// 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 + +To be completed. + +## Charts + +To be completed. + +## Form fields + +To be completed. -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. +# 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 0000000000..f4c1e8ebd4 --- /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 0000000000..6a65ea0d57 --- /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 b1d9d205e1..0000000000 --- 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 f0b62b2d6e..5eb348ecfe 100644 --- a/phpmd.xml.dist +++ b/phpmd.xml.dist @@ -18,7 +18,7 @@ - + diff --git a/phpword.ini.dist b/phpword.ini.dist index 4a51ee11ce..f8eafb6a78 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 311f33508f..f7aaece30a 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 @@ $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 d6e4cdbc87..46d91cec34 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 bfbc84afda..a95b15d644 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 e41f4ddbac..7ebf6e3365 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 @@ // 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 f47370605e..b93ab344c1 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 1bec44e447..c7f3d8c0bc 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 @@ $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 899bc82bbf..60edacb5a7 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); - -$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'); - -$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->cloneRow('rowValue', 10); + +$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')); + +$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 d3f0c1fb3c..dd364562d0 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('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('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('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( + '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( + '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 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 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('Keep scrolling. More below.')); + +$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 882653bc71..5c305c8342 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 @@ $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 @@ $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 @@ $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 44bca8a63b..f3553bfef2 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 0000000000..68a30d362d --- /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 0fd56edc0a..dc4fc129cb 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->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 @@ // 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 dd0c88012d..d13912119b 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 @@ $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 3a3d34abc5..3a29e3fdee 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 @@ // 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 1bd61e79c6..dd06670e65 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 af23a00f02..2a216c2378 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 b18b1bc9ae..8f8889b83c 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(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 @@ $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 @@ // 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 313cfbed49..f630bdf22d 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 @@ $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 a209ce3906..fc0e5419b0 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 @@ $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 892cd8b2a5..ebee8544fa 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 b600ec006e..df3162c33c 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 e7aae5bad2..b5d4a7a5a8 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 8ee8fc6d01..2b7e9f6856 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 0a659ddb3d..afeb863d1c 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 92b3aa498c..4235c94650 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -20,4 +20,4 @@ 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 fd75037275..9bdbef8243 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 @@ // 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 5a955702b7..8bb192cfc8 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 @@ // 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 0000000000..3df71b4cc8 --- /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 0000000000..b61a646fde --- /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 0000000000..9f356810dc --- /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 0000000000..19ac42fe34 --- /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 0000000000..1b907f8724 --- /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 0000000000..ec326ae025 --- /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 f7e2305f14..95ac693fc3 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 7af23c94d2..22d27a4a6b 100644 --- a/samples/Sample_Header.php +++ b/samples/Sample_Header.php @@ -1,10 +1,13 @@ '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 @@ * @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 420c542019..a65d8fd90e 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 @@

 

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 0000000000..a5ce295d8a 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 c467f836c3..68da845de3 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 ae1b6efbe5..41e40e2e9e 100644 --- a/src/PhpWord/Collection/AbstractCollection.php +++ b/src/PhpWord/Collection/AbstractCollection.php @@ -57,10 +57,11 @@ public function getItem($index) } /** - * 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 0000000000..cb9d74d53f --- /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 @@ protected function addElement($elementName) /** @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 @@ public function countElements() 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 @@ private function setElementRelationId(AbstractElement $element, $elementName, $s */ 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 @@ private function checkValidity($method) '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 @@ private function checkValidity($method) ); // 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 @@ private function checkValidity($method) 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 ca45ef23f9..99a7a1becc 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 @@ public function getPhpWord() } /** - * 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 @@ public function getSectionId() } /** - * Set doc part + * Set doc part. * * @param string $docPart * @param int $docPartId + * @return void */ public function setDocPart($docPart, $docPartId = 1) { @@ -155,6 +179,21 @@ public function getDocPartId() 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 @@ public function getElementIndex() } /** - * Set element index + * Set element index. * * @param int $value + * @return void */ public function setElementIndex($value) { @@ -186,7 +226,9 @@ public function getElementId() } /** - * 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 @@ public function getRelationId() } /** - * Set relation Id + * Set relation Id. * * @param int $value + * @return void */ public function setRelationId($value) { @@ -224,13 +267,79 @@ public function getNestedLevel() } /** - * 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 setParentContainer(AbstractElement $container) + { + $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 */ - public function setNestedLevel($value) + private function setMediaRelation() { - $this->nestedLevel = $value; + 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 @@ public function isInSection() } /** - * 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 @@ protected function setStyle($styleObject, $styleValue = null, $returnObject = fa 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 0000000000..d5b8ff6fba --- /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 ea49bc7bc8..cac37a7804 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 0000000000..66c59ff52c --- /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 a5620580fe..d3b2a3c6f4 100644 --- a/src/PhpWord/Element/CheckBox.php +++ b/src/PhpWord/Element/CheckBox.php @@ -21,6 +21,8 @@ /** * 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 20278898f8..1000055520 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 50f0522fb1..1eaa6f242f 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -100,7 +100,7 @@ public function __construct($type = null, $properties = array(), $options = arra 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 @@ public function setProperties($properties = array()) { 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 @@ public function setOptions($options = array()) { 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 142ccfda1a..8e19eaf7db 100644 --- a/src/PhpWord/Element/Footer.php +++ b/src/PhpWord/Element/Footer.php @@ -59,10 +59,12 @@ public function __construct($sectionId, $containerId = 1, $type = self::AUTO) } /** - * Set type + * Set type. * - * @param string $value * @since 0.10.0 + * + * @param string $value + * @return void */ public function setType($value = self::AUTO) { diff --git a/src/PhpWord/Element/Footnote.php b/src/PhpWord/Element/Footnote.php index 76311c6bbd..162a703ed5 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 0000000000..7bd61be1e7 --- /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 a1cb8250f7..cab2527a4e 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 @@ public function __construct($source, $style = null, $watermark = false) { $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 @@ public function getTarget() } /** - * Set target file name + * Set target file name. * * @param string $value + * @return void */ public function setTarget($value) { @@ -270,9 +280,10 @@ public function getMediaIndex() } /** - * Set media index + * Set media index. * * @param integer $value + * @return void */ public function setMediaIndex($value) { @@ -304,8 +315,8 @@ public function getImageStringData($base64 = false) 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 @@ public function getImageStringData($base64 = false) } /** - * 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 @@ private function checkImage($source) } /** - * Set source type + * Set source type. * * @param string $source + * @return void */ private function setSourceType($source) { @@ -409,15 +422,22 @@ private function setSourceType($source) /** * 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 @@ private function getArchiveImageSize($source) $imageContent = $zip->getFromName($imageFilename); if ($imageContent !== false) { file_put_contents($tempFilename, $imageContent); - $imageData = @getimagesize($tempFilename); + $imageData = getimagesize($tempFilename); unlink($tempFilename); } } @@ -436,7 +456,9 @@ private function getArchiveImageSize($source) } /** - * Set image functions and extensions + * Set image functions and extensions. + * + * @return void */ private function setFunctions() { @@ -469,10 +491,11 @@ private function setFunctions() } /** - * 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 4acca8eda3..b76ac4fb32 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 3ffe58d4a4..9d0eb76662 100644 --- a/src/PhpWord/Element/Link.php +++ b/src/PhpWord/Element/Link.php @@ -27,11 +27,11 @@ 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 @@ public function getParagraphStyle() 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 @@ public function getParagraphStyle() */ public function getLinkSrc() { - return $this->getTarget(); + return $this->getSource(); } /** @@ -136,4 +161,14 @@ public function getLinkName() { 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 59bd83917c..4cb8d33952 100644 --- a/src/PhpWord/Element/ListItem.php +++ b/src/PhpWord/Element/ListItem.php @@ -64,7 +64,7 @@ public function __construct($text, $depth = 0, $fontStyle = null, $listStyle = n 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 fb219f91fb..1b77830db3 100644 --- a/src/PhpWord/Element/ListItemRun.php +++ b/src/PhpWord/Element/ListItemRun.php @@ -59,13 +59,15 @@ public function __construct($depth = 0, $listStyle = null, $paragraphStyle = nul 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 @@ public function getStyle() } /** - * 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 a63c186936..31943ba68a 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 @@ public function __construct($source, $style = null) } $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 @@ public function getImageRelationId() } /** - * 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 100385c93e..44aef3b40e 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 d7dcea3443..e2df632551 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 @@ public function __construct($height = null, $style = null) 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 0000000000..c69ed42772 --- /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 b7cee6a2df..d746f69bb3 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() - { - 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) + public function getStyle() { - return $this->addElement('TOC', $fontStyle, $tocStyle, $minDepth, $maxDepth); + return $this->style; } /** @@ -218,6 +180,30 @@ private function addHeaderFooter($type = Header::AUTO, $header = true) } + /** + * 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 0000000000..a7a96d1884 --- /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 9ac745545c..a56d9ffe40 100644 --- a/src/PhpWord/Element/TOC.php +++ b/src/PhpWord/Element/TOC.php @@ -129,9 +129,10 @@ public function getStyleFont() } /** - * Set max depth + * Set max depth. * * @param int $value + * @return void */ public function setMaxDepth($value) { @@ -149,9 +150,10 @@ public function getMaxDepth() } /** - * 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 ace634607d..5f0b8f7953 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 @@ public function __construct($style = null) 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 @@ public function getWidth() } /** - * 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 06c9518167..d929bf35db 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 7583710404..c356cfa8e1 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 d5206879dc..cf1d49c81a 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 0000000000..97a900e3b2 --- /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 @@ public static function load($filename, $readerName = 'Word2007') 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 7f35841c43..59735cea4c 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 @@ public static function countElements($container, $mediaType = null) { $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 @@ public static function getElements($container, $type = null) } 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 0000000000..d78b97f1f9 --- /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 5644c3d96c..9643685f25 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 0000000000..3556ce8c2c --- /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 c54faa3615..99c95c7912 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,146 +61,151 @@ 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(); + } - /** - * Get document properties object - * - * @return DocumentProperties - */ - public function getDocumentProperties() - { - return $this->documentProperties; + // Metadata + $metadata = array('DocInfo', 'Protection', 'Compatibility'); + foreach ($metadata as $meta) { + $class = 'PhpOffice\\PhpWord\\Metadata\\' . $meta; + $this->metadata[$meta] = new $class(); + } } /** - * Set document properties object + * Dynamic function call to reduce static dependency * - * @param DocumentProperties $documentProperties - * @return self + * @param mixed $function + * @param mixed $args + * @throws \BadMethodCallException + * @return mixed + * @since 0.12.0 */ - public function setDocumentProperties(DocumentProperties $documentProperties) + public function __call($function, $args) { - $this->documentProperties = $documentProperties; + $function = strtolower($function); - return $this; - } + $getCollection = array(); + $addCollection = array(); + $addStyle = array(); - /** - * Get all sections - * - * @return \PhpOffice\PhpWord\Element\Section[] - */ - public function getSections() - { - return $this->sections; - } + $collections = array('Bookmark', 'Title', 'Footnote', 'Endnote', 'Chart'); + foreach ($collections as $collection) { + $getCollection[] = strtolower("get{$collection}s"); + $addCollection[] = strtolower("add{$collection}"); + } - /** - * Create new section - * - * @param array $settings - * @return \PhpOffice\PhpWord\Element\Section - */ - public function addSection($settings = null) - { - $section = new Section(count($this->sections) + 1, $settings); - $section->setPhpWord($this); - $this->sections[] = $section; + $styles = array('Paragraph', 'Font', 'Table', 'Numbering', 'Link', 'Title'); + foreach ($styles as $style) { + $addStyle[] = strtolower("add{$style}Style"); + } - return $section; - } + // Run get collection method + if (in_array($function, $getCollection)) { + $key = ucfirst(str_replace('get', '', $function)); - /** - * Get titles - * - * @return \PhpOffice\PhpWord\Collection\Titles - */ - public function getTitles() - { - return $this->titles; + 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."); } /** - * Add new title + * Get document properties object * - * @param \PhpOffice\PhpWord\Element\Title $title - * @return int + * @return \PhpOffice\PhpWord\Metadata\DocInfo */ - public function addTitle($title) + public function getDocInfo() { - return $this->titles->addItem($title); + return $this->metadata['DocInfo']; } /** - * Get footnotes + * Get protection * - * @return \PhpOffice\PhpWord\Collection\Footnotes + * @return \PhpOffice\PhpWord\Metadata\Protection + * @since 0.12.0 */ - public function getFootnotes() + public function getProtection() { - return $this->footnotes; + return $this->metadata['Protection']; } /** - * Add new footnote + * Get compatibility * - * @param \PhpOffice\PhpWord\Element\Footnote $footnote - * @return int + * @return \PhpOffice\PhpWord\Metadata\Compatibility + * @since 0.12.0 */ - public function addFootnote($footnote) + public function getCompatibility() { - return $this->footnotes->addItem($footnote); + return $this->metadata['Compatibility']; } /** - * Get endnotes + * Get all sections * - * @return \PhpOffice\PhpWord\Collection\Endnotes + * @return \PhpOffice\PhpWord\Element\Section[] */ - public function getEndnotes() + public function getSections() { - return $this->endnotes; + return $this->sections; } /** - * Add new endnote + * Create new section * - * @param \PhpOffice\PhpWord\Element\Endnote $endnote - * @return int + * @param array $style + * @return \PhpOffice\PhpWord\Element\Section */ - public function addEndnote($endnote) + public function addSection($style = null) { - return $this->endnotes->addItem($endnote); + $section = new Section(count($this->sections) + 1, $style); + $section->setPhpWord($this); + $this->sections[] = $section; + + return $section; } /** @@ -207,9 +219,10 @@ public function getDefaultFontName() } /** - * Set default font name + * Set default font name. * * @param string $fontName + * @return void */ public function setDefaultFontName($fontName) { @@ -227,9 +240,10 @@ public function getDefaultFontSize() } /** - * Set default font size + * Set default font size. * * @param int $fontSize + * @return void */ public function setDefaultFontSize($fontSize) { @@ -248,106 +262,97 @@ public function setDefaultParagraphStyle($styles) } /** - * Adds a paragraph style definition to styles.xml + * Load template by filename * - * @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 + * @deprecated 0.12.0 Use `new TemplateProcessor($documentTemplate)` instead. * - * @param string $styleName - * @param mixed $fontStyle - * @param mixed $paragraphStyle - * @return \PhpOffice\PhpWord\Style\Font + * @param string $filename Fully qualified filename. + * @return TemplateProcessor + * @throws \PhpOffice\PhpWord\Exception\Exception */ - public function addFontStyle($styleName, $fontStyle, $paragraphStyle = null) + public function loadTemplate($filename) { - return Style::addFontStyle($styleName, $fontStyle, $paragraphStyle); + if (file_exists($filename)) { + return new TemplateProcessor($filename); + } else { + throw new Exception("Template file {$filename} not found."); + } } /** - * Adds a table style definition to styles.xml + * Save to file or download * - * @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 + * All exceptions should already been handled by the writers * - * @param string $styleName - * @param mixed $styles - * @return \PhpOffice\PhpWord\Style\Numbering + * @param string $filename + * @param string $format + * @param bool $download + * @return bool */ - public function addNumberingStyle($styleName, $styles) + public function save($filename, $format = 'Word2007', $download = false) { - return Style::addNumberingStyle($styleName, $styles); - } + $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 + } - /** - * 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); + $writer->save($filename); + + return true; } /** - * Adds a heading style definition to styles.xml + * Create new section * - * @param int $depth - * @param mixed $fontStyle - * @param mixed $paragraphStyle - * @return \PhpOffice\PhpWord\Style\Font + * @param array $settings + * @return \PhpOffice\PhpWord\Element\Section + * @deprecated 0.10.0 + * @codeCoverageIgnore */ - public function addTitleStyle($depth, $fontStyle, $paragraphStyle = null) + public function createSection($settings = null) { - return Style::addTitleStyle($depth, $fontStyle, $paragraphStyle); + return $this->addSection($settings); } /** - * Load template by filename + * Get document properties object * - * @param string $filename Fully qualified filename. - * @return Template - * @throws \PhpOffice\PhpWord\Exception\Exception + * @return \PhpOffice\PhpWord\Metadata\DocInfo + * @deprecated 0.12.0 + * @codeCoverageIgnore */ - public function loadTemplate($filename) + public function getDocumentProperties() { - if (file_exists($filename)) { - return new Template($filename); - } else { - throw new Exception("Template file {$filename} not found."); - } + return $this->getDocInfo(); } /** - * Create new section + * Set document properties object * - * @param array $settings - * @return \PhpOffice\PhpWord\Element\Section - * @deprecated 0.10.0 + * @param \PhpOffice\PhpWord\Metadata\DocInfo $documentProperties + * @return self + * @deprecated 0.12.0 * @codeCoverageIgnore */ - public function createSection($settings = null) + public function setDocumentProperties($documentProperties) { - return $this->addSection($settings); + $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 0000000000..c63d8d9e22 --- /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 19efdc5170..d992f7fd3c 100644 --- a/src/PhpWord/Reader/ODText.php +++ b/src/PhpWord/Reader/ODText.php @@ -51,15 +51,16 @@ public function load($docFile) } /** - * 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 @@ private function readPart(PhpWord &$phpWord, $relationships, $partName, $docFile $part->setRels($relationships); $part->read($phpWord); } - } /** diff --git a/src/PhpWord/Reader/ODText/Content.php b/src/PhpWord/Reader/ODText/Content.php index 12b39f74d3..cf2fd65368 100644 --- a/src/PhpWord/Reader/ODText/Content.php +++ b/src/PhpWord/Reader/ODText/Content.php @@ -28,11 +28,12 @@ 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 @@ public function read(PhpWord &$phpWord) $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 f7f4542dbc..d08ce3a679 100644 --- a/src/PhpWord/Reader/ODText/Meta.php +++ b/src/PhpWord/Reader/ODText/Meta.php @@ -28,16 +28,17 @@ 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 cb082fdc63..3f63e3398e 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 @@ public function read(PhpWord &$phpWord) $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 @@ public function read(PhpWord &$phpWord) } /** - * Mark opening braket `{` character + * Mark opening braket `{` character. + * + * @return void */ private function markOpening() { @@ -190,7 +193,9 @@ private function markOpening() } /** - * Mark closing braket `}` character + * Mark closing braket `}` character. + * + * @return void */ private function markClosing() { @@ -199,7 +204,9 @@ private function markClosing() } /** - * Mark backslash `\` character + * Mark backslash `\` character. + * + * @return void */ private function markBackslash() { @@ -214,7 +221,9 @@ private function markBackslash() } /** - * 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 @@ private function markNewline() } /** - * Flush control word or text + * Flush control word or text. * * @param bool $isControl + * @return void */ private function flush($isControl = false) { @@ -238,9 +248,10 @@ private function flush($isControl = false) } /** - * Flush control word + * Flush control word. * * @param bool $isControl + * @return void */ private function flushControl($isControl = false) { @@ -255,7 +266,9 @@ private function flushControl($isControl = false) } /** - * Flush text in queue + * Flush text in queue. + * + * @return void */ private function flushText() { @@ -279,9 +292,10 @@ private function flushText() } /** - * 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 @@ private function setControl($value) } /** - * Push text into queue + * Push text into queue. * * @param string $char + * @return void */ private function pushText($char) { @@ -306,10 +321,11 @@ private function pushText($char) } /** - * Parse control + * Parse control. * * @param string $control * @param string $parameter + * @return void */ private function parseControl($control, $parameter) { @@ -335,7 +351,7 @@ private function parseControl($control, $parameter) '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 @@ private function parseControl($control, $parameter) } /** - * Read paragraph + * Read paragraph. * * @param array $directives + * @return void */ private function readParagraph($directives) { @@ -358,9 +375,10 @@ private function readParagraph($directives) } /** - * Read style + * Read style. * * @param array $directives + * @return void */ private function readStyle($directives) { @@ -369,9 +387,10 @@ private function readStyle($directives) } /** - * Read skip + * Read skip. * * @param array $directives + * @return void */ private function readSkip($directives) { @@ -381,7 +400,9 @@ private function readSkip($directives) } /** - * Read text + * Read text. + * + * @return void */ private function readText() { diff --git a/src/PhpWord/Reader/Word2007.php b/src/PhpWord/Reader/Word2007.php index 70d5f60b77..ebe6c4f765 100644 --- a/src/PhpWord/Reader/Word2007.php +++ b/src/PhpWord/Reader/Word2007.php @@ -63,7 +63,7 @@ public function load($docFile) $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 @@ public function load($docFile) } /** - * 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 a7261d6d9d..021bdba11e 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 @@ public function __construct($docFile, $xmlFile) } /** - * Set relationships + * Set relationships. * * @param array $value + * @return void */ public function setRels($value) { @@ -89,23 +90,24 @@ public function setRels($value) } /** - * 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 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, &$p 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 @@ protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, &$parent, } /** - * 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 @@ protected function readTable(XMLReader $xmlReader, \DOMElement $domNode, &$paren } /** - * Read w:pPr + * Read w:pPr. * * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader * @param \DOMElement $domNode @@ -337,7 +341,7 @@ protected function readParagraphStyle(XMLReader $xmlReader, \DOMElement $domNode * * @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 @@ protected function readFontStyle(XMLReader $xmlReader, \DOMElement $domNode) '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 @@ private function readStyleDef($method, $attributeValue, $expected) $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 @@ private function readStyleDef($method, $attributeValue, $expected) 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 0b92b64dcd..54537525b6 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 efbbfaa5c8..eb725b2ec3 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 @@ 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 @@ public function read(PhpWord &$phpWord) $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 be804531d3..e1beed0666 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 @@ public function read(PhpWord &$phpWord) 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 @@ public function read(PhpWord &$phpWord) } /** - * 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 @@ private function readHeaderFooter($settings, Section &$section) $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 @@ private function readSectionStyle(XMLReader $xmlReader, \DOMElement $domNode) } /** - * 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 @@ private function readWPNode(XMLReader $xmlReader, \DOMElement $node, Section &$s } /** - * 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 47713cfbb7..6f6adc879e 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 @@ public function read(PhpWord &$phpWord) // 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 2dd3f5217b..872d45033b 100644 --- a/src/PhpWord/Reader/Word2007/Numbering.php +++ b/src/PhpWord/Reader/Word2007/Numbering.php @@ -28,11 +28,12 @@ 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 7dc4b6eaac..299fe1df77 100644 --- a/src/PhpWord/Reader/Word2007/Styles.php +++ b/src/PhpWord/Reader/Word2007/Styles.php @@ -28,11 +28,12 @@ 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 cb74389a20..67b1dbedbd 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 @@ public static function setPdfRenderer($libraryName, $libraryBaseDir) } /** - * Return the PDF Rendering Library + * Return the PDF Rendering Library. + * + * @return string */ public static function getPdfRendererName() { @@ -214,7 +223,9 @@ public static function setPdfRendererName($libraryName) /** - * 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 @@ public static function getPdfRendererPath() */ 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 @@ public static function setMeasurementUnit($value) 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 0000000000..c6727edd55 --- /dev/null +++ b/src/PhpWord/Shared/Converter.php @@ -0,0 +1,278 @@ +' . $html . ''; } @@ -83,12 +89,13 @@ protected static function parseInlineStyle($node, $styles = array()) } /** - * 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 @@ protected static function parseNode($node, $element, $styles = array(), $data = $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 @@ protected static function parseNode($node, $element, $styles = array(), $data = } /** - * 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 @@ private static function parseChildNodes($node, $element, $styles, $data) * * @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 @@ private static function parseParagraph($node, $element, &$styles) * 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 @@ private static function parseHeading($element, &$styles, $argument1) * * @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 @@ private static function parseText($node, $element, &$styles) /** * 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 @@ private static function parseProperty(&$styles, $argument1, $argument2) * * @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 @@ private static function parseTable($node, $element, &$styles, $argument1) /** * 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 @@ private static function parseList(&$styles, &$data, $argument1) * * @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 0000000000..82815afc4b --- /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 1e4504cc01..be04fd0ec7 100644 --- a/src/PhpWord/Shared/String.php +++ b/src/PhpWord/Shared/String.php @@ -178,7 +178,9 @@ public static function removeUnderscorePrefix($value) } /** - * 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 153152ee63..ca6869eb3c 100644 --- a/src/PhpWord/Shared/XMLReader.php +++ b/src/PhpWord/Shared/XMLReader.php @@ -96,7 +96,11 @@ public function getElements($path, \DOMElement $contextNode = null) $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 cb00c70b74..2134f62a9d 100644 --- a/src/PhpWord/Shared/XMLWriter.php +++ b/src/PhpWord/Shared/XMLWriter.php @@ -66,12 +66,12 @@ public function __construct($tempLocation = self::STORAGE_MEMORY, $tempFolder = $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 @@ public function getData() } } + /** + * 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 @@ public function getData() * @param string $element * @param string $attribute * @param mixed $value + * @return void */ public function writeElementIf($condition, $element, $attribute = null, $value = null) { @@ -166,6 +191,7 @@ public function writeElementIf($condition, $element, $attribute = null, $value = * @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 cbfcb07127..157959e8e9 100644 --- a/src/PhpWord/Shared/ZipArchive.php +++ b/src/PhpWord/Shared/ZipArchive.php @@ -83,7 +83,7 @@ public function __construct() $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 @@ public function open($filename, $flags = null) $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 @@ public function close() { 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 @@ public function pclzipAddFile($filename, $localname = null) { /** @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 @@ public function pclzipAddFile($filename, $localname = null) $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 @@ public function pclzipAddFromString($localname, $contents) $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 @@ public function pclzipGetFromName($filename) $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 @@ public function pclzipLocateName($filename) $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 d56c73feca..ab03106fce 100644 --- a/src/PhpWord/Style.php +++ b/src/PhpWord/Style.php @@ -123,8 +123,11 @@ public static function countStyles() } /** - * Reset styles + * Reset styles. + * * @since 0.10.0 + * + * @return void */ public static function resetStyles() { @@ -160,7 +163,7 @@ public static function getStyles() */ 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 @@ public static function getStyle($styleName) */ 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 13ef8f9b26..ab1a1ee729 100644 --- a/src/PhpWord/Style/AbstractStyle.php +++ b/src/PhpWord/Style/AbstractStyle.php @@ -126,6 +126,24 @@ public function setAuto($value = true) 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 @@ protected function setIntVal($value, $default = null) 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 @@ protected function setFloatVal($value, $default = null) 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 @@ protected function setEnumVal($value = null, $enum = array(), $default = null) * * @param mixed $value * @param string $styleName - * @param mixed $style + * @param mixed &$style * @return mixed */ protected function setObjectVal($value, $styleName, &$style) @@ -296,6 +316,24 @@ protected function setObjectVal($value, $styleName, &$style) 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 2d1b88d08f..11290c8752 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 @@ public function setVAlign($value = null) } /** - * Get text direction + * Get text direction. + * + * @return string */ public function getTextDirection() { @@ -163,7 +167,9 @@ public function setBgColor($value = null) } /** - * Get grid span (colspan) + * Get grid span (colspan). + * + * @return integer */ public function getGridSpan() { @@ -184,7 +190,9 @@ public function setGridSpan($value = null) } /** - * 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 0000000000..13b72a33f5 --- /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 0000000000..ccbb26505b --- /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 0000000000..08c7a85739 --- /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 0775b8b33b..8980258b43 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 @@ public function __construct($type = 'text', $paragraph = null) $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 @@ public function getName() /** * Set font name * - * @param string $value + * @param string $value * @return self */ public function setName($value = null) @@ -259,7 +327,7 @@ public function getHint() /** * Set Font Content Type * - * @param string $value + * @param string $value * @return self */ public function setHint($value = null) @@ -272,7 +340,7 @@ public function setHint($value = null) /** * Get font size * - * @return int|float + * @return int|float */ public function getSize() { @@ -282,7 +350,7 @@ public function getSize() /** * Set font size * - * @param int|float $value + * @param int|float $value * @return self */ public function setSize($value = null) @@ -305,7 +373,7 @@ public function getColor() /** * Set font color * - * @param string $value + * @param string $value * @return self */ public function setColor($value = null) @@ -328,7 +396,7 @@ public function isBold() /** * Set bold * - * @param bool $value + * @param bool $value * @return self */ public function setBold($value = true) @@ -351,7 +419,7 @@ public function isItalic() /** * Set italic * - * @param bool $value + * @param bool $value * @return self */ public function setItalic($value = true) @@ -374,7 +442,7 @@ public function getUnderline() /** * Set underline * - * @param string $value + * @param string $value * @return self */ public function setUnderline($value = self::UNDERLINE_NONE) @@ -397,12 +465,12 @@ public function isSuperScript() /** * 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 @@ public function isSubScript() /** * 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 @@ public function isStrikethrough() /** * 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 @@ public function isDoubleStrikethrough() /** * 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 @@ public function isSmallCaps() /** * 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 @@ public function isAllCaps() /** * 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 @@ public function getFgColor() /** * Set foreground/highlight color * - * @param string $value + * @param string $value * @return self */ public function setFgColor($value = null) @@ -540,11 +608,7 @@ public function setFgColor($value = null) */ public function getBgColor() { - if ($this->shading !== null) { - return $this->shading->getFill(); - } else { - return null; - } + return $this->getChildStyleValue($this->shading, 'fill'); } /** @@ -558,6 +622,75 @@ public function setBgColor($value = null) $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 @@ public function getLineHeight() /** * Set lineheight * - * @param int|float|string $value + * @param int|float|string $value * @return self */ public function setLineHeight($value) @@ -605,42 +738,47 @@ public function setParagraph($value = null) } /** - * Get shading + * Get rtl * - * @return \PhpOffice\PhpWord\Style\Shading + * @return bool */ - public function getShading() + public function isRTL() { - return $this->shading; + return $this->rtl; } /** - * Set shading + * Set rtl * - * @param mixed $value + * @param bool $value * @return self */ - public function setShading($value = null) + public function setRTL($value = true) { - $this->setObjectVal($value, 'Shading', $this->shading); + $this->rtl = $this->setBoolVal($value, $this->rtl); return $this; } /** - * Set $property value and set $pairProperty = false when $value = true + * Get shading * - * @param bool $property - * @param bool $pairProperty - * @param bool $value + * @return \PhpOffice\PhpWord\Style\Shading + */ + public function getShading() + { + return $this->shading; + } + + /** + * Set shading + * + * @param mixed $value * @return self */ - private function setPairedProperty(&$property, &$pairProperty, $value) + public function setShading($value = null) { - $property = $this->setBoolVal($value, $property); - if ($value == true) { - $pairProperty = false; - } + $this->setObjectVal($value, 'Shading', $this->shading); return $this; } diff --git a/src/PhpWord/Style/Frame.php b/src/PhpWord/Style/Frame.php new file mode 100644 index 0000000000..5fef5f0182 --- /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 3798c1a22f..babfa6798e 100644 --- a/src/PhpWord/Style/Image.php +++ b/src/PhpWord/Style/Image.php @@ -19,217 +19,56 @@ /** * 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(); - } - - /** - * 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; + parent::__construct(); + $this->setUnit('px'); + + // 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 @@ public function setAlign($value = null) */ public function getMarginTop() { - return $this->marginTop; + return $this->getTop(); } /** @@ -251,7 +90,7 @@ public function getMarginTop() */ public function setMarginTop($value = 0) { - $this->marginTop = $this->setNumericVal($value, 0); + $this->setTop($value); return $this; } @@ -263,7 +102,7 @@ public function setMarginTop($value = 0) */ public function getMarginLeft() { - return $this->marginLeft; + return $this->getLeft(); } /** @@ -275,7 +114,7 @@ public function getMarginLeft() */ public function setMarginLeft($value = 0) { - $this->marginLeft = $this->setNumericVal($value, 0); + $this->setLeft($value); return $this; } @@ -287,7 +126,7 @@ public function setMarginLeft($value = 0) */ public function getWrappingStyle() { - return $this->wrappingStyle; + return $this->getWrap(); } /** @@ -299,12 +138,7 @@ public function getWrappingStyle() */ 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 @@ public function setWrappingStyle($wrappingStyle) */ public function getPositioning() { - return $this->positioning; + return $this->getPos(); } /** @@ -328,8 +162,7 @@ public function getPositioning() */ 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 @@ public function setPositioning($positioning) */ public function getPosHorizontal() { - return $this->posHorizontal; + return $this->getHPos(); } /** @@ -353,11 +186,7 @@ public function getPosHorizontal() */ 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 @@ public function setPosHorizontal($alignment) */ public function getPosVertical() { - return $this->posVertical; + return $this->getVPos(); } /** @@ -381,12 +210,7 @@ public function getPosVertical() */ 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 @@ public function setPosVertical($alignment) */ public function getPosHorizontalRel() { - return $this->posHorizontalRel; + return $this->getHPosRelTo(); } /** @@ -410,13 +234,7 @@ public function getPosHorizontalRel() */ 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 @@ public function setPosHorizontalRel($relto) */ public function getPosVerticalRel() { - return $this->posVerticalRel; + return $this->getVPosRelTo(); } /** @@ -440,13 +258,7 @@ public function getPosVerticalRel() */ 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 0000000000..bfd14a1457 --- /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 0000000000..642666b5f1 --- /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 8167358663..964a4ec960 100644 --- a/src/PhpWord/Style/Paragraph.php +++ b/src/PhpWord/Style/Paragraph.php @@ -47,7 +47,7 @@ * * @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 @@ public function getStyleValues() 'level' => $this->getNumLevel(), ), 'tabs' => $this->getTabs(), + 'shading' => $this->getShading(), ); return $styles; @@ -313,11 +321,7 @@ public function setIndentation($value = null) */ public function getIndent() { - if ($this->indentation !== null) { - return $this->indentation->getLeft(); - } else { - return null; - } + return $this->getChildStyleValue($this->indentation, 'left'); } /** @@ -338,11 +342,7 @@ public function setIndent($value = null) */ public function getHanging() { - if ($this->indentation !== null) { - return $this->indentation->getHanging(); - } else { - return null; - } + return $this->getChildStyleValue($this->indentation, 'hanging'); } /** @@ -388,11 +388,7 @@ public function setSpace($value = null) */ public function getSpaceBefore() { - if ($this->spacing !== null) { - return $this->spacing->getBefore(); - } else { - return null; - } + return $this->getChildStyleValue($this->spacing, 'before'); } /** @@ -413,11 +409,7 @@ public function setSpaceBefore($value = null) */ public function getSpaceAfter() { - if ($this->spacing !== null) { - return $this->spacing->getAfter(); - } else { - return null; - } + return $this->getChildStyleValue($this->spacing, 'after'); } /** @@ -438,11 +430,7 @@ public function setSpaceAfter($value = null) */ public function getSpacing() { - if ($this->spacing !== null) { - return $this->spacing->getLine(); - } else { - return null; - } + return $this->getChildStyleValue($this->spacing, 'line'); } /** @@ -694,4 +682,27 @@ public function getPageBreakBefore() { 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 fd59f1b419..128e8e6b21 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 @@ public function setLandscape() /** * 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 0000000000..deafbff0f8 --- /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 0000000000..c9809920bb --- /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 9f0a1ddec7..6220b74096 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 @@ public function getInnerMarginTop() } /** - * Set margin left + * Set margin left. * * @param int $value + * @return void */ public function setInnerMarginLeft($value = null) { @@ -107,9 +109,10 @@ public function getInnerMarginLeft() } /** - * Set margin right + * Set margin right. * * @param int $value + * @return void */ public function setInnerMarginRight($value = null) { @@ -127,9 +130,10 @@ public function getInnerMarginRight() } /** - * Set margin bottom + * Set margin bottom. * * @param int $value + * @return void */ public function setInnerMarginBottom($value = null) { @@ -147,9 +151,10 @@ public function getInnerMarginBottom() } /** - * 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 @@ public function hasInnerMargins() } /** - * Set border size + * Set border size. * * @param int $value Size in points + * @return void */ public function setBorderSize($value = null) { @@ -208,9 +214,10 @@ public function getBorderSize() } /** - * 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 21e8b98886..f6ad790eab 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 0000000000..cbed973011 --- /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 346e9b66ba..599d8a6fdd 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 @@ public function setTempDir($value) 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 @@ protected function getTempFile($filename) } /** - * 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 @@ protected function cleanupTempFile() } /** - * Clear temporary directory + * Clear temporary directory. + * + * @return void */ protected function clearTempDir() { @@ -311,13 +315,15 @@ protected function openFile($filename) } /** - * 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 @@ protected function writeFile(&$fileHandle, $content) } /** - * 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 @@ protected function addFilesToPackage(ZipArchive $zip, $elements) $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 @@ protected function addFilesToPackage(ZipArchive $zip, $elements) } /** - * 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 @@ protected function addFileToPackage($zipPackage, $source, $target) } /** - * 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 29173ff23c..5c58acfc9d 100644 --- a/src/PhpWord/Writer/HTML.php +++ b/src/PhpWord/Writer/HTML.php @@ -61,15 +61,15 @@ public function __construct(PhpWord $phpWord = null) } /** - * 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 @@ public function getNotes() } /** - * 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 53b994df09..73f88d3d8d 100644 --- a/src/PhpWord/Writer/HTML/Element/AbstractElement.php +++ b/src/PhpWord/Writer/HTML/Element/AbstractElement.php @@ -68,9 +68,10 @@ public function __construct(AbstractWriter $parentWriter, Element $element, $wit } /** - * 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 d1256eb066..4e99810c7b 100644 --- a/src/PhpWord/Writer/HTML/Element/Link.php +++ b/src/PhpWord/Writer/HTML/Element/Link.php @@ -37,7 +37,7 @@ public function write() $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 79a3b393d2..ef8eb34d75 100644 --- a/src/PhpWord/Writer/HTML/Element/ListItem.php +++ b/src/PhpWord/Writer/HTML/Element/ListItem.php @@ -35,7 +35,7 @@ public function write() 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 a3fb1f3b5c..774ed9d23c 100644 --- a/src/PhpWord/Writer/HTML/Element/PageBreak.php +++ b/src/PhpWord/Writer/HTML/Element/PageBreak.php @@ -24,4 +24,21 @@ */ 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 c8813a67f9..9027603b8f 100644 --- a/src/PhpWord/Writer/HTML/Element/Table.php +++ b/src/PhpWord/Writer/HTML/Element/Table.php @@ -51,7 +51,7 @@ public function write() $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 52e7a6b5a5..0c31df3632 100644 --- a/src/PhpWord/Writer/HTML/Element/Text.php +++ b/src/PhpWord/Writer/HTML/Element/Text.php @@ -72,7 +72,7 @@ public function write() $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 @@ public function write() } /** - * Set opening text + * Set opening text. * * @param string $value + * @return void */ public function setOpeningText($value) { @@ -91,9 +92,10 @@ public function setOpeningText($value) } /** - * Set closing text + * Set closing text. * * @param string $value + * @return void */ public function setClosingText($value) { @@ -164,7 +166,9 @@ private function getParagraphStyle() } /** - * 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 20747bf9ec..c054ccf98b 100644 --- a/src/PhpWord/Writer/HTML/Element/Title.php +++ b/src/PhpWord/Writer/HTML/Element/Title.php @@ -36,7 +36,7 @@ public function write() } $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 319aa20fbf..124cc15a8a 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 4fd61a834f..b91ca3ad2d 100644 --- a/src/PhpWord/Writer/HTML/Part/Body.php +++ b/src/PhpWord/Writer/HTML/Part/Body.php @@ -72,7 +72,7 @@ private function writeNotes() $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 edbc8dcf7f..503f75b879 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 @@ public function write() $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 @@ public function write() return $content; } + /** * Get styles * @@ -96,6 +97,14 @@ private function writeStyles() '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 cd37174aed..07ef16184c 100644 --- a/src/PhpWord/Writer/HTML/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/HTML/Style/AbstractStyle.php @@ -26,6 +26,13 @@ */ abstract class AbstractStyle { + /** + * Parent writer + * + * @var \PhpOffice\PhpWord\Writer\AbstractWriter + */ + private $parentWriter; + /** * Style * @@ -48,6 +55,27 @@ public function __construct($style = null) $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 18f2828751..8645a1f402 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 f9c8d5d453..8fa364bec9 100644 --- a/src/PhpWord/Writer/ODText.php +++ b/src/PhpWord/Writer/ODText.php @@ -60,9 +60,10 @@ public function __construct(PhpWord $phpWord = null) } /** - * 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 3229b59c67..3cbb38542a 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 @@ public function write() $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 79d3aa246f..adb64f8599 100644 --- a/src/PhpWord/Writer/ODText/Element/Link.php +++ b/src/PhpWord/Writer/ODText/Element/Link.php @@ -41,7 +41,7 @@ public function write() $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 31118ef993..edc8d07f4f 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 @@ protected function writeCommonRootAttributes(XMLWriter $xmlWriter) } /** - * 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 f16937a0e2..4bde66ee97 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -106,9 +106,12 @@ public function write() } /** - * 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 @@ private function writeAutoStyles(XMLWriter $xmlWriter) } /** - * Write automatic styles + * Write automatic styles. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @return void */ private function writeTextStyles(XMLWriter $xmlWriter) { @@ -160,7 +166,10 @@ private function writeTextStyles(XMLWriter $xmlWriter) } /** - * Get automatic styles + * Get automatic styles. + * + * @param \PhpOffice\PhpWord\PhpWord $phpWord + * @return void */ private function getAutoStyles(PhpWord $phpWord) { @@ -168,7 +177,7 @@ private function getAutoStyles(PhpWord $phpWord) $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 @@ private function getAutoStyles(PhpWord $phpWord) * 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 @@ private function getContainerStyle($container, &$paragraphStyleCount, &$fontStyl /** * 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 c9e729add5..15c81a4e9c 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 @@ public function write() * @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 b7864fe339..7522872d7e 100644 --- a/src/PhpWord/Writer/ODText/Part/Styles.php +++ b/src/PhpWord/Writer/ODText/Part/Styles.php @@ -61,7 +61,10 @@ public function write() } /** - * Write default styles + * Write default styles. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @return void */ private function writeDefault(XMLWriter $xmlWriter) { @@ -103,7 +106,10 @@ private function writeDefault(XMLWriter $xmlWriter) } /** - * Write named styles + * Write named styles. + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @return void */ private function writeNamed(XMLWriter $xmlWriter) { @@ -122,7 +128,10 @@ private function writeNamed(XMLWriter $xmlWriter) } } /** - * 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 @@ private function writePageLayout(XMLWriter $xmlWriter) $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 acab0ee5c1..4518450555 100644 --- a/src/PhpWord/Writer/ODText/Style/Font.php +++ b/src/PhpWord/Writer/ODText/Style/Font.php @@ -25,7 +25,9 @@ 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 de97f474ea..21b9c4ee93 100644 --- a/src/PhpWord/Writer/ODText/Style/Image.php +++ b/src/PhpWord/Writer/ODText/Style/Image.php @@ -25,7 +25,9 @@ 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 133b8cdf7b..03e605a196 100644 --- a/src/PhpWord/Writer/ODText/Style/Paragraph.php +++ b/src/PhpWord/Writer/ODText/Style/Paragraph.php @@ -25,7 +25,9 @@ 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 3d910157a2..fa432856c7 100644 --- a/src/PhpWord/Writer/ODText/Style/Section.php +++ b/src/PhpWord/Writer/ODText/Style/Section.php @@ -25,7 +25,9 @@ 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 b32349af05..dbfb94ed84 100644 --- a/src/PhpWord/Writer/ODText/Style/Table.php +++ b/src/PhpWord/Writer/ODText/Style/Table.php @@ -25,7 +25,9 @@ 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 d4288c8a3f..572e4b1dfd 100644 --- a/src/PhpWord/Writer/PDF/AbstractRenderer.php +++ b/src/PhpWord/Writer/PDF/AbstractRenderer.php @@ -190,6 +190,7 @@ protected function prepareForSave($filename = null) * 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 a40e2ceac3..47054c4a48 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 9d4e050c87..46d456d4f7 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 @@ public function save($filename = null) // 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 669a2cddee..36849e24ad 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 @@ public function save($filename = null) // 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 d7fed942dc..58210c997f 100644 --- a/src/PhpWord/Writer/RTF.php +++ b/src/PhpWord/Writer/RTF.php @@ -55,15 +55,15 @@ public function __construct(PhpWord $phpWord = null) } /** - * 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 @@ private function getContent() } /** - * Get font table + * Get font table. + * + * @return array */ public function getFontTable() { @@ -94,7 +96,9 @@ public function getFontTable() } /** - * Get color table + * Get color table. + * + * @return array */ public function getColorTable() { @@ -102,7 +106,9 @@ public function getColorTable() } /** - * Get last paragraph style + * Get last paragraph style. + * + * @return mixed */ public function getLastParagraphStyle() { @@ -110,9 +116,10 @@ public function getLastParagraphStyle() } /** - * 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 79e139471b..73da5cbddb 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 1daae2a0f3..52e705e9e2 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 @@ public function write() $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 22b085886c..adbc7976ce 100644 --- a/src/PhpWord/Writer/RTF/Element/Link.php +++ b/src/PhpWord/Writer/RTF/Element/Link.php @@ -39,7 +39,7 @@ public function write() $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 b48e084f46..7c4329f719 100644 --- a/src/PhpWord/Writer/RTF/Element/Table.php +++ b/src/PhpWord/Writer/RTF/Element/Table.php @@ -66,6 +66,7 @@ public function write() /** * Write column * + * @param \PhpOffice\PhpWord\Element\Row $row * @return string */ private function writeRowDef(RowElement $row) @@ -89,6 +90,7 @@ private function writeRowDef(RowElement $row) /** * Write row * + * @param \PhpOffice\PhpWord\Element\Row $row * @return string */ private function writeRow(RowElement $row) @@ -106,6 +108,7 @@ private function writeRow(RowElement $row) /** * 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 71565044b2..edcdbd84a4 100644 --- a/src/PhpWord/Writer/RTF/Part/Document.php +++ b/src/PhpWord/Writer/RTF/Part/Document.php @@ -19,11 +19,13 @@ 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 @@ public function write() */ 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 @@ private function writeInfo() $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 @@ private function writeFormatting() */ 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 15a0c303e8..31fbb7f4af 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 @@ public function getFontTable() } /** - * Get color table + * Get color table. + * + * @return array */ public function getColorTable() { @@ -141,10 +153,10 @@ private function writeColorTable() $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 @@ private function writeGenerator() } /** - * 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 @@ private function registerFont() $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 @@ private function registerFont() } /** - * 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 @@ private function registerFontItems($style) $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 0000000000..88c517ad79 --- /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 9634b566cb..20c47aee08 100644 --- a/src/PhpWord/Writer/RTF/Style/Font.php +++ b/src/PhpWord/Writer/RTF/Style/Font.php @@ -66,9 +66,11 @@ public function write() } /** - * Set font name index + * Set font name index. + * * * @param int $value + * @return void */ public function setNameIndex($value = 0) { @@ -76,9 +78,10 @@ public function setNameIndex($value = 0) } /** - * 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 b166cc2790..1a7de0a35b 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -73,9 +73,10 @@ public function write() } /** - * 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 0000000000..4169b630cc --- /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 751b58b607..09d095093f 100644 --- a/src/PhpWord/Writer/Word2007.php +++ b/src/PhpWord/Writer/Word2007.php @@ -71,6 +71,7 @@ public function __construct(PhpWord $phpWord = null) 'Footer' => '', 'Footnotes' => '', 'Endnotes' => '', + 'Chart' => '', ); foreach (array_keys($this->parts) as $partName) { $partClass = get_class($this) . '\\Part\\' . $partName; @@ -87,9 +88,10 @@ public function __construct(PhpWord $phpWord = null) } /** - * Save document by name + * Save document by name. * * @param string $filename + * @return void */ public function save($filename = null) { @@ -127,6 +129,7 @@ public function save($filename = null) $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 @@ public function getRelationships() } /** - * 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 @@ private function addHeaderFooterMedia(ZipArchive $zip, $docPart) } /** - * 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 @@ private function addHeaderFooterContent(Section &$section, ZipArchive $zip, $elm * 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 @@ private function addNotes(ZipArchive $zip, &$rId, $noteType = 'footnote') } /** - * 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 @@ private function registerContentTypes($media) $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 52b4c62e9c..3b6432ed6a 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 @@ protected function getElement() } /** - * Has page break before + * Start w:p DOM element. + * + * @uses \PhpOffice\PhpWord\Writer\Word2007\Element\PageBreak::write() + * @return void + */ + protected function startElementP() + { + if (!$this->withoutP) { + $this->xmlWriter->startElement('w:p'); + // Paragraph style + if (method_exists($this->element, 'getParagraphStyle')) { + $this->writeParagraphStyle(); + } + } + } + + /** + * End w:p DOM element. + * + * @return void + */ + protected function endElementP() + { + if (!$this->withoutP) { + $this->xmlWriter->endElement(); // w:p + } + } + + /** + * Write ending. * - * @return bool + * @return void */ - public function hasPageBreakBefore() + protected function writeParagraphStyle() { - return $this->pageBreakBefore; + $this->writeTextStyle('Paragraph'); } /** - * Set page break before + * Write ending. * - * @param bool $value + * @return void */ - public function setPageBreakBefore($value = true) + protected function writeFontStyle() { - $this->pageBreakBefore = (bool)$value; + $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 @@ public function setPageBreakBefore($value = true) */ 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 0000000000..df5a104a18 --- /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 0000000000..ccd8cd77db --- /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 ea13b8f943..deafbd1de3 100644 --- a/src/PhpWord/Writer/Word2007/Element/CheckBox.php +++ b/src/PhpWord/Writer/Word2007/Element/CheckBox.php @@ -25,7 +25,9 @@ class CheckBox extends Text { /** - * Write element + * Write element. + * + * @return void */ public function write() { @@ -35,7 +37,7 @@ public function write() return; } - $this->writeOpeningWP(); + $this->startElementP(); $xmlWriter->startElement('w:r'); $xmlWriter->startElement('w:fldChar'); @@ -66,7 +68,7 @@ public function write() $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 @@ public function write() $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 3dad824df1..771fe5c34e 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 @@ private function writeElement(XMLWriter $xmlWriter, Element $element, $withoutP) $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 68c4c40c2c..b9c3c34b81 100644 --- a/src/PhpWord/Writer/Word2007/Element/Field.php +++ b/src/PhpWord/Writer/Word2007/Element/Field.php @@ -25,7 +25,9 @@ class Field extends Text { /** - * Write field element + * Write field element. + * + * @return void */ public function write() { @@ -67,7 +69,8 @@ public function write() } } - $this->writeOpeningWP(); + $this->startElementP(); + $xmlWriter->startElement('w:fldSimple'); $xmlWriter->writeAttribute('w:instr', $instruction); $xmlWriter->startElement('w:r'); @@ -82,6 +85,6 @@ public function write() $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 240a8a00a8..5640a90db4 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 @@ public function write() return; } - $this->writeOpeningWP(); + $this->startElementP(); $xmlWriter->startElement('w:r'); $xmlWriter->startElement('w:rPr'); @@ -55,6 +57,6 @@ public function write() $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 0000000000..432dc9c23b --- /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 a882040eac..7398842397 100644 --- a/src/PhpWord/Writer/Word2007/Element/Image.php +++ b/src/PhpWord/Writer/Word2007/Element/Image.php @@ -29,7 +29,9 @@ class Image extends AbstractElement { /** - * Write element + * Write element. + * + * @return void */ public function write() { @@ -47,7 +49,9 @@ public function write() } /** - * Write image element + * Write image element. + * + * @return void */ private function writeImage(XMLWriter $xmlWriter, ImageElement $element) { @@ -59,26 +63,30 @@ private function writeImage(XMLWriter $xmlWriter, ImageElement $element) $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 @@ private function writeWatermark(XMLWriter $xmlWriter, ImageElement $element) $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 1ae1069495..a6c7c24081 100644 --- a/src/PhpWord/Writer/Word2007/Element/Line.php +++ b/src/PhpWord/Writer/Word2007/Element/Line.php @@ -27,7 +27,9 @@ class Line extends AbstractElement { /** - * Write element + * Write element. + * + * @return void */ public function write() { @@ -37,16 +39,19 @@ public function write() 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 @@ public function write() $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 ec531bacaa..2cb8407f5b 100644 --- a/src/PhpWord/Writer/Word2007/Element/Link.php +++ b/src/PhpWord/Writer/Word2007/Element/Link.php @@ -25,7 +25,9 @@ class Link extends Text { /** - * Write link element + * Write link element. + * + * @return void */ public function write() { @@ -37,10 +39,14 @@ public function write() $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 @@ public function write() $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 7b86efaeb8..0f559a4e1d 100644 --- a/src/PhpWord/Writer/Word2007/Element/ListItem.php +++ b/src/PhpWord/Writer/Word2007/Element/ListItem.php @@ -27,7 +27,9 @@ 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 747c262525..289cb05476 100644 --- a/src/PhpWord/Writer/Word2007/Element/ListItemRun.php +++ b/src/PhpWord/Writer/Word2007/Element/ListItemRun.php @@ -27,7 +27,9 @@ 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 ae03f04f5b..a9cc449abf 100644 --- a/src/PhpWord/Writer/Word2007/Element/Object.php +++ b/src/PhpWord/Writer/Word2007/Element/Object.php @@ -27,7 +27,9 @@ class Object extends AbstractElement { /** - * Write object element + * Write object element. + * + * @return void */ public function write() { @@ -41,6 +43,7 @@ public function write() $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 @@ public function write() $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 @@ public function write() $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 6974777a45..fb831ca7ac 100644 --- a/src/PhpWord/Writer/Word2007/Element/PageBreak.php +++ b/src/PhpWord/Writer/Word2007/Element/PageBreak.php @@ -20,27 +20,26 @@ /** * 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 dd5d900874..894b3050f3 100644 --- a/src/PhpWord/Writer/Word2007/Element/PreserveText.php +++ b/src/PhpWord/Writer/Word2007/Element/PreserveText.php @@ -25,7 +25,9 @@ class PreserveText extends Text { /** - * Write preserve text element + * Write preserve text element. + * + * @return void */ public function write() { @@ -40,7 +42,7 @@ public function write() $texts = array($texts); } - $this->writeOpeningWP(); + $this->startElementP(); foreach ($texts as $text) { if (substr($text, 0, 1) == '{') { @@ -86,6 +88,6 @@ public function write() } } - $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 0000000000..79d7004dd6 --- /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 0000000000..bd9320a258 --- /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 1db2efddbd..db2a65d07b 100644 --- a/src/PhpWord/Writer/Word2007/Element/TOC.php +++ b/src/PhpWord/Writer/Word2007/Element/TOC.php @@ -32,7 +32,9 @@ class TOC extends AbstractElement { /** - * Write element + * Write element. + * + * @return void */ public function write() { @@ -68,6 +70,7 @@ public function write() * @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 @@ private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, $title, $ * @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 @@ private function writeStyle(XMLWriter $xmlWriter, TOCElement $element, $indent) } /** - * 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 8cadfc384d..f090d05c89 100644 --- a/src/PhpWord/Writer/Word2007/Element/Table.php +++ b/src/PhpWord/Writer/Word2007/Element/Table.php @@ -35,7 +35,9 @@ class Table extends AbstractElement { /** - * Write element + * Write element. + * + * @return void */ public function write() { @@ -69,7 +71,11 @@ public function write() } /** - * 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 @@ private function writeColumns(XMLWriter $xmlWriter, TableElement $element) } /** - * 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 @@ private function writeRow(XMLWriter $xmlWriter, RowElement $row) } /** - * 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 64c4b766cb..cfb991c2d0 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 @@ class Text extends AbstractElement { /** - * Write text element + * Write text element. + * + * @return void */ public function write() { @@ -39,7 +37,7 @@ public function write() return; } - $this->writeOpeningWP(); + $this->startElementP(); $xmlWriter->startElement('w:r'); @@ -51,72 +49,6 @@ public function write() $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 4ee5e68e61..fe62c644f3 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Element/TextBox.php @@ -24,10 +24,12 @@ * * @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 @@ public function write() $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 @@ public function write() $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 5f4bd3ce59..fb52b86e62 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextBreak.php +++ b/src/PhpWord/Writer/Word2007/Element/TextBreak.php @@ -25,7 +25,9 @@ class TextBreak extends Text { /** - * Write text break element + * Write text break element. + * + * @return void */ public function write() { @@ -37,13 +39,15 @@ public function write() 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 330e297c13..844e0b6bbb 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextRun.php +++ b/src/PhpWord/Writer/Word2007/Element/TextRun.php @@ -25,18 +25,20 @@ 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 144e67abe8..ce9aeea529 100644 --- a/src/PhpWord/Writer/Word2007/Element/Title.php +++ b/src/PhpWord/Writer/Word2007/Element/Title.php @@ -25,7 +25,9 @@ class Title extends AbstractElement { /** - * Write title element + * Write title element. + * + * @return void */ public function write() { @@ -48,10 +50,11 @@ public function write() } $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 @@ public function write() // 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 610a761621..e26853d737 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 0000000000..8423762c30 --- /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 b6f23f4726..6ae4e8758e 100644 --- a/src/PhpWord/Writer/Word2007/Part/ContentTypes.php +++ b/src/PhpWord/Writer/Word2007/Part/ContentTypes.php @@ -37,6 +37,7 @@ public function write() $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 @@ public function write() $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 @@ public function write() * @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 1e6549c52e..421ceefec2 100644 --- a/src/PhpWord/Writer/Word2007/Part/DocPropsApp.php +++ b/src/PhpWord/Writer/Word2007/Part/DocPropsApp.php @@ -41,8 +41,8 @@ public function write() $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 38f6d2351f..252be01f02 100644 --- a/src/PhpWord/Writer/Word2007/Part/DocPropsCore.php +++ b/src/PhpWord/Writer/Word2007/Part/DocPropsCore.php @@ -43,24 +43,24 @@ public function write() $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 c5a3cf9e43..ba6547d9b9 100644 --- a/src/PhpWord/Writer/Word2007/Part/DocPropsCustom.php +++ b/src/PhpWord/Writer/Word2007/Part/DocPropsCustom.php @@ -39,7 +39,7 @@ public function write() $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 9957033859..ea607f09b7 100644 --- a/src/PhpWord/Writer/Word2007/Part/Document.php +++ b/src/PhpWord/Writer/Word2007/Part/Document.php @@ -79,10 +79,11 @@ public function write() } /** - * 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 @@ private function writeSection(XMLWriter $xmlWriter, Section $section) } /** - * 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 @@ private function writeSectionSettings(XMLWriter $xmlWriter, Section $section) } // 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 49a47e7dcc..314cf58679 100644 --- a/src/PhpWord/Writer/Word2007/Part/FontTable.php +++ b/src/PhpWord/Writer/Word2007/Part/FontTable.php @@ -26,7 +26,9 @@ 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 903e5fe55d..9ceefd82ee 100644 --- a/src/PhpWord/Writer/Word2007/Part/Footnotes.php +++ b/src/PhpWord/Writer/Word2007/Part/Footnotes.php @@ -133,10 +133,11 @@ public function setElements($elements) } /** - * 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 8f735dd324..bbb8eeb455 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 @@ public function write() } /** - * 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 @@ private function writeLevel(XMLWriter $xmlWriter, NumberingLevel $level) } /** - * 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 @@ private function writeParagraph(XMLWriter $xmlWriter, NumberingLevel $level) } /** - * 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 562deb35b5..9a7f444bd4 100644 --- a/src/PhpWord/Writer/Word2007/Part/Rels.php +++ b/src/PhpWord/Writer/Word2007/Part/Rels.php @@ -47,12 +47,13 @@ public function write() } /** - * 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 @@ protected function writeRels(XMLWriter $xmlWriter, $xmlRels = array(), $mediaRel } /** - * 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 @@ private function writeMediaRel(XMLWriter $xmlWriter, $relId, $mediaRel) $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 @@ private function writeMediaRel(XMLWriter $xmlWriter, $relId, $mediaRel) } /** - * Write individual rels entry + * Write individual rels entry. * * Format: * @@ -106,6 +108,7 @@ private function writeMediaRel(XMLWriter $xmlWriter, $relId, $mediaRel) * @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 784a5d1e35..50399c4aa0 100644 --- a/src/PhpWord/Writer/Word2007/Part/Settings.php +++ b/src/PhpWord/Writer/Word2007/Part/Settings.php @@ -24,6 +24,13 @@ */ 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 @@ public function write() $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 @@ public function write() } /** - * 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 @@ protected function writeSetting($xmlWriter, $settingKey, $settingValue) $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 0d688e366f..0194222948 100644 --- a/src/PhpWord/Writer/Word2007/Part/Styles.php +++ b/src/PhpWord/Writer/Word2007/Part/Styles.php @@ -75,10 +75,11 @@ public function write() } /** - * 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 @@ private function writeDefaultStyles(XMLWriter $xmlWriter, $styles) $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 @@ private function writeDefaultStyles(XMLWriter $xmlWriter, $styles) } /** - * 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 @@ private function writeFontStyle(XMLWriter $xmlWriter, $styleName, FontStyle $sty } /** - * 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 @@ private function writeParagraphStyle(XMLWriter $xmlWriter, $styleName, Paragraph } /** - * 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 61c8bae808..16335680f0 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 @@ protected function convertTwip($value, $default = 0) 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 cefadb5740..fabaf8eac4 100644 --- a/src/PhpWord/Writer/Word2007/Style/Alignment.php +++ b/src/PhpWord/Writer/Word2007/Style/Alignment.php @@ -25,7 +25,9 @@ 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 a4b1ae90da..0f90b3aa91 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 @@ public function write() } /** - * 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 0000000000..ba1ee590ec --- /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 0000000000..645f1ab053 --- /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 0ef22f08f9..9371f97003 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 @@ public function write() } /** - * Write full style + * Write full style. + * + * @return void */ private function writeStyle() { @@ -64,8 +68,10 @@ private function writeStyle() $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 @@ private function writeStyle() $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 0000000000..28ebeaf52e --- /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 280b569a4a..cabf37ce3b 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 f9bb696f1b..a1b4d8d113 100644 --- a/src/PhpWord/Writer/Word2007/Style/Indentation.php +++ b/src/PhpWord/Writer/Word2007/Style/Indentation.php @@ -25,7 +25,9 @@ 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 dfecb4b0e8..48e27492ac 100644 --- a/src/PhpWord/Writer/Word2007/Style/Line.php +++ b/src/PhpWord/Writer/Word2007/Style/Line.php @@ -23,50 +23,13 @@ * 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 @@ public function writeStroke() } $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 @@ public function writeStroke() 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 b3c103b6d4..d06fa2d697 100644 --- a/src/PhpWord/Writer/Word2007/Style/LineNumbering.php +++ b/src/PhpWord/Writer/Word2007/Style/LineNumbering.php @@ -25,7 +25,9 @@ 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 88bb010972..30029112f8 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 @@ public function write() } /** - * 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 @@ private function writeSide(XMLWriter $xmlWriter, $side, $width, $color = null) $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 @@ private function writeSide(XMLWriter $xmlWriter, $side, $width, $color = null) } /** - * Set sizes + * Set sizes. * * @param integer[] $value + * @return void */ public function setSizes($value) { @@ -111,9 +114,10 @@ public function setSizes($value) } /** - * Set colors + * Set colors. * * @param string[] $value + * @return void */ public function setColors($value) { @@ -121,9 +125,10 @@ public function setColors($value) } /** - * 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 0000000000..06064d188a --- /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 f328770083..039b78bfad 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 @@ public function write() } /** - * Write full style + * Write full style. + * + * @return void */ private function writeStyle() { @@ -83,7 +87,9 @@ private function writeStyle() } // 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 @@ private function writeStyle() $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 @@ private function writeStyle() // Numbering $this->writeNumbering($xmlWriter, $styles['numbering']); - if (!$this->withoutPPR) { - $xmlWriter->endElement(); // w:pPr - } - } + // Border + if ($style->hasBorder()) { + $xmlWriter->startElement('w:pBdr'); - /** - * 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; + $styleWriter = new MarginBorder($xmlWriter); + $styleWriter->setSizes($style->getBorderSize()); + $styleWriter->setColors($style->getBorderColor()); + $styleWriter->write(); - /** @var \PhpOffice\PhpWord\Writer\Word2007\Style\AbstractStyle $writer */ - $writer = new $class($xmlWriter, $value); - $writer->write(); + $xmlWriter->endElement(); + } + + if (!$this->withoutPPR) { + $xmlWriter->endElement(); // w:pPr } } /** - * 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 @@ private function writeTabs(XMLWriter $xmlWriter, $tabs) } /** - * 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 @@ private function writeNumbering(XMLWriter $xmlWriter, $numbering) } /** - * Set without w:pPr + * Set without w:pPr. * * @param bool $value + * @return void */ public function setWithoutPPR($value) { @@ -186,9 +190,10 @@ public function setWithoutPPR($value) } /** - * 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 5517cc2b82..98841dd846 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 @@ public function write() } /** - * 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 fb32a39a05..486d0ed228 100644 --- a/src/PhpWord/Writer/Word2007/Style/Section.php +++ b/src/PhpWord/Writer/Word2007/Style/Section.php @@ -27,7 +27,9 @@ 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 72054c207b..8ef8c6b184 100644 --- a/src/PhpWord/Writer/Word2007/Style/Shading.php +++ b/src/PhpWord/Writer/Word2007/Style/Shading.php @@ -25,7 +25,9 @@ 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 0000000000..cc74605994 --- /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 0000000000..ba8dce5bd1 --- /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 5dfb5c43cf..2f7e122a22 100644 --- a/src/PhpWord/Writer/Word2007/Style/Spacing.php +++ b/src/PhpWord/Writer/Word2007/Style/Spacing.php @@ -25,7 +25,9 @@ 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 865a5a9c6e..aa00acc788 100644 --- a/src/PhpWord/Writer/Word2007/Style/Tab.php +++ b/src/PhpWord/Writer/Word2007/Style/Tab.php @@ -25,7 +25,9 @@ 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 e89b121c87..8bbad107c3 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 @@ public function write() } /** - * 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 @@ private function writeStyle(XMLWriter $xmlWriter, TableStyle $style) } /** - * 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 @@ private function writeWidth(XMLWriter $xmlWriter, $width, $unit) } /** - * 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 @@ private function writeMargin(XMLWriter $xmlWriter, TableStyle $style) } /** - * 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 @@ private function writeBorder(XMLWriter $xmlWriter, TableStyle $style) } /** - * 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 @@ private function writeFirstRow(XMLWriter $xmlWriter, TableStyle $style) } /** - * 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 @@ private function writeShading(XMLWriter $xmlWriter, TableStyle $style) } /** - * 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 13f40256f1..20c68c7421 100644 --- a/src/PhpWord/Writer/Word2007/Style/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Style/TextBox.php @@ -24,69 +24,12 @@ * * @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 @@ public function writeInnerMargin() $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() { - $xmlWriter = $this->getXmlWriter(); - - // Border size - $borderSize = $style->getBorderSize(); - if ($borderSize !== null) { - $xmlWriter->writeAttribute('strokeweight', $borderSize . 'pt'); + $style = $this->getStyle(); + if (!$style instanceof TextBoxStyle) { + return; } + $xmlWriter = $this->getXmlWriter(); - // 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 92423fc62f..dace5bdb49 100644 --- a/tests/PhpWord/Tests/AutoloaderTest.php +++ b/tests/PhpWord/Tests/AutoloaderTest.php @@ -43,12 +43,11 @@ public function testRegister() */ 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 e3d08da276..833b3e8072 100644 --- a/tests/PhpWord/Tests/Collection/CollectionTest.php +++ b/tests/PhpWord/Tests/Collection/CollectionTest.php @@ -28,8 +28,7 @@ public function testCollection() $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 c92469f348..180dd4d0b6 100644 --- a/tests/PhpWord/Tests/Element/AbstractElementTest.php +++ b/tests/PhpWord/Tests/Element/AbstractElementTest.php @@ -19,8 +19,6 @@ /** * 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 429f9df69c..5add9a6b07 100644 --- a/tests/PhpWord/Tests/Element/LineTest.php +++ b/tests/PhpWord/Tests/Element/LineTest.php @@ -37,17 +37,17 @@ public function testConstruct() $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 @@ public function testStyleArray() { $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 @@ public function testStyleArray() '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 0e582b13ca..ada6a36a9f 100644 --- a/tests/PhpWord/Tests/Element/LinkTest.php +++ b/tests/PhpWord/Tests/Element/LinkTest.php @@ -36,8 +36,8 @@ public function testConstructDefault() $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 @@ public function testConstructWithParamsArray() ); $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 37d679f93b..7bb0c25d71 100644 --- a/tests/PhpWord/Tests/Element/ListItemRunTest.php +++ b/tests/PhpWord/Tests/Element/ListItemRunTest.php @@ -131,7 +131,7 @@ public function testAddLink() $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 @@ public function testAddLinkWithName() $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 0000000000..8c7b4bf328 --- /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 af7595e208..853ebc5d3f 100644 --- a/tests/PhpWord/Tests/Element/SectionTest.php +++ b/tests/PhpWord/Tests/Element/SectionTest.php @@ -31,12 +31,12 @@ 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 @@ public function testGetHeaders() /** * 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 c3c89ed4cb..2c6da4655d 100644 --- a/tests/PhpWord/Tests/Element/TextBoxTest.php +++ b/tests/PhpWord/Tests/Element/TextBoxTest.php @@ -55,11 +55,11 @@ public function testStyleArray() { $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 870214dde1..de62a920da 100644 --- a/tests/PhpWord/Tests/Element/TextRunTest.php +++ b/tests/PhpWord/Tests/Element/TextRunTest.php @@ -99,7 +99,7 @@ public function testAddLink() $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 @@ public function testAddLinkWithName() $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 0000000000..3d92595f25 --- /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 @@ public function testAddSectionMediaElement() 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 @@ public function testAddSectionLinkElement() $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 @@ public function testAddHeaderMediaElement() 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 @@ public function testAddFooterMediaElement() 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 30b2a7bc48..c860a0d9a9 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 @@ public function testCreator() */ public function testLastModifiedBy() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setLastModifiedBy(); $this->assertEquals('', $oProperties->getLastModifiedBy()); @@ -57,7 +57,7 @@ public function testLastModifiedBy() */ public function testCreated() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setCreated(); $this->assertEquals(time(), $oProperties->getCreated()); @@ -71,7 +71,7 @@ public function testCreated() */ public function testModified() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setModified(); $this->assertEquals(time(), $oProperties->getModified()); @@ -85,7 +85,7 @@ public function testModified() */ public function testTitle() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setTitle(); $this->assertEquals('', $oProperties->getTitle()); @@ -98,7 +98,7 @@ public function testTitle() */ public function testDescription() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setDescription(); $this->assertEquals('', $oProperties->getDescription()); @@ -111,7 +111,7 @@ public function testDescription() */ public function testSubject() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setSubject(); $this->assertEquals('', $oProperties->getSubject()); @@ -124,7 +124,7 @@ public function testSubject() */ public function testKeywords() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setKeywords(); $this->assertEquals('', $oProperties->getKeywords()); @@ -137,7 +137,7 @@ public function testKeywords() */ public function testCategory() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setCategory(); $this->assertEquals('', $oProperties->getCategory()); @@ -150,7 +150,7 @@ public function testCategory() */ public function testCompany() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setCompany(); $this->assertEquals('', $oProperties->getCompany()); @@ -163,7 +163,7 @@ public function testCompany() */ public function testManager() { - $oProperties = new DocumentProperties(); + $oProperties = new DocInfo(); $oProperties->setManager(); $this->assertEquals('', $oProperties->getManager()); @@ -176,30 +176,30 @@ public function testManager() */ 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 @@ public function testCustomProperty() */ 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 6a9e6b2649..85c6a7f291 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 @@ public function testCreateGetSections() { $phpWord = new PhpWord(); $phpWord->addSection(); - $this->assertEquals(1, count($phpWord->getSections())); + $this->assertCount(1, $phpWord->getSections()); } /** @@ -132,6 +119,8 @@ public function testAddTitleStyle() /** * Test load template + * + * @deprecated 0.12.0 */ public function testLoadTemplate() { @@ -139,7 +128,7 @@ public function testLoadTemplate() $phpWord = new PhpWord(); $this->assertInstanceOf( - 'PhpOffice\\PhpWord\\Template', + 'PhpOffice\\PhpWord\\TemplateProcessor', $phpWord->loadTemplate($templateFqfn) ); } @@ -147,6 +136,8 @@ public function testLoadTemplate() /** * Test load template exception * + * @deprecated 0.12.0 + * * @expectedException \PhpOffice\PhpWord\Exception\Exception */ public function testLoadTemplateException() @@ -158,4 +149,28 @@ public function testLoadTemplateException() $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 6136403449..0d3d66aecc 100644 --- a/tests/PhpWord/Tests/SettingsTest.php +++ b/tests/PhpWord/Tests/SettingsTest.php @@ -22,6 +22,7 @@ /** * Test class for PhpOffice\PhpWord\Settings * + * @coversDefaultClass \PhpOffice\PhpWord\Settings * @runTestsInSeparateProcesses */ class SettingsTest extends \PHPUnit_Framework_TestCase @@ -70,6 +71,31 @@ public function testSetGetMeasurementUnit() $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 0000000000..002e2e33bf --- /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 25fd3a3886..0000000000 --- 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 c10f773959..0000000000 --- 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 730600d743..c4c0fc9d5a 100644 --- a/tests/PhpWord/Tests/Shared/HtmlTest.php +++ b/tests/PhpWord/Tests/Shared/HtmlTest.php @@ -34,7 +34,7 @@ public function testAddHtml() // 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 @@ public function testAddHtml() // 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 @@ public function testAddHtml() $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 bf5862fbc0..a3524eded8 100644 --- a/tests/PhpWord/Tests/Shared/StringTest.php +++ b/tests/PhpWord/Tests/Shared/StringTest.php @@ -64,4 +64,12 @@ public function testToUnicode() $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 432b29fb22..c21ea4ce3e 100644 --- a/tests/PhpWord/Tests/Style/FontTest.php +++ b/tests/PhpWord/Tests/Style/FontTest.php @@ -46,6 +46,7 @@ public function testInitiation() $this->assertEquals('text', $object->getStyleType()); $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Paragraph', $object->getParagraphStyle()); + $this->assertTrue(is_array($object->getStyleValues())); } /** @@ -71,6 +72,9 @@ public function testSetStyleValueWithNullOrEmpty() '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 @@ public function testSetStyleValueNormal() '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 12aa51ceb6..73540b0c7b 100644 --- a/tests/PhpWord/Tests/Style/ParagraphTest.php +++ b/tests/PhpWord/Tests/Style/ParagraphTest.php @@ -119,7 +119,7 @@ public function testTabs() { $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 dd7273cb0f..e5becd7296 100644 --- a/tests/PhpWord/Tests/Style/SectionTest.php +++ b/tests/PhpWord/Tests/Style/SectionTest.php @@ -35,13 +35,14 @@ public function testSettingValue() $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 @@ public function testMargin() $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 @@ public function testOrientationLandscape() $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 @@ public function testOrientationPortrait() $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 f446ecdf9a..6165e4fd3b 100644 --- a/tests/PhpWord/Tests/StyleTest.php +++ b/tests/PhpWord/Tests/StyleTest.php @@ -22,43 +22,63 @@ /** * 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 57ee229e62..04d1e77715 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 public function testTemplateCanBeSavedInTemporaryLocation() } /** - * 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 public function testXslStyleSheetCanBeApplied($actualDocumentFqfn) } /** - * 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 public function testXslStyleSheetCanBeApplied($actualDocumentFqfn) */ 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 public function testXslStyleSheetCanNotBeAppliedOnFailureOfSettingParamete */ 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'); + + $this->assertEquals( + array('documentContent', 'headerValue', 'footerValue'), + $templateProcessor->getVariables() + ); - $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); + $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'); - $docName = 'clone-delete-block-result.docx'; - - $document = new Template($template); - $actualVar = $document->getVariables(); + $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/clone-delete-block.docx'); - $document->cloneBlock('CLONEME', 3); - $document->deleteBlock('DELETEME'); + $this->assertEquals( + array('DELETEME', '/DELETEME', 'CLONEME', '/CLONEME'), + $templateProcessor->getVariables() + ); - $document->saveAs($docName); + $docName = 'clone-delete-block-result.docx'; + $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 f9b8e6ba91..c3339d1a4f 100644 --- a/tests/PhpWord/Tests/Writer/HTMLTest.php +++ b/tests/PhpWord/Tests/Writer/HTMLTest.php @@ -61,7 +61,7 @@ public function testSave() $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 27b2427f9b..85ddada6ba 100644 --- a/tests/PhpWord/Tests/Writer/ODText/Part/ContentTest.php +++ b/tests/PhpWord/Tests/Writer/ODText/Part/ContentTest.php @@ -47,7 +47,7 @@ public function testWriteContent() $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 a22cb53051..476c9011dc 100644 --- a/tests/PhpWord/Tests/Writer/PDF/DomPDFTest.php +++ b/tests/PhpWord/Tests/Writer/PDF/DomPDFTest.php @@ -71,7 +71,7 @@ public function testSetGetAbstractRendererProperties() $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 8b4a4441ba..542e34fe7c 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 c144810674..5b983b3578 100644 --- a/tests/PhpWord/Tests/Writer/RTFTest.php +++ b/tests/PhpWord/Tests/Writer/RTFTest.php @@ -91,7 +91,7 @@ public function testSave() $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 da7504b5c1..92a74c1544 100644 --- a/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php @@ -41,7 +41,7 @@ public function testUnmatchedElements() $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 @@ public function testLineElement() { $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 e27d072a37..ef36e0dd72 100644 --- a/tests/PhpWord/Tests/Writer/Word2007/Part/DocumentTest.php +++ b/tests/PhpWord/Tests/Writer/Word2007/Part/DocumentTest.php @@ -45,11 +45,11 @@ public function testWriteEndSectionPageNumbering() $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 @@ public function testElements() $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 @@ public function testElementStyles() $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 0000000000..7d4d1849c6 --- /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 0000000000..af11c054ff --- /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 71cbc30068..8dd229c311 100644 --- a/tests/PhpWord/Tests/Writer/Word2007/StyleTest.php +++ b/tests/PhpWord/Tests/Writer/Word2007/StyleTest.php @@ -31,7 +31,7 @@ public function testEmptyStyles() $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 @@ public function testEmptyStyles() 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 7998cbdc8a..2a0043d5c8 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 @@ public static function getDocument(PhpWord $phpWord, $writerName = 'Word2007') $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 @@ public static function clear() 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 d0dcdba7ff..4932a21b26 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -23,16 +23,10 @@ } $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 @@ } }); -require_once __DIR__ . "/../src/PhpWord/Autoloader.php"; +require_once __DIR__ . '/../src/PhpWord/Autoloader.php'; \PhpOffice\PhpWord\Autoloader::register();